commit e00a529ba9f8fe0f51d1c93b1210211f34ee0b10 Author: Ryan Hughes Date: Mon Aug 25 05:45:19 2025 +0200 Probably should have committed a long time ago... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6d650b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +x86_64/ +src/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..758c8bc --- /dev/null +++ b/README.md @@ -0,0 +1,244 @@ +# Omarchy Repository + +A custom Arch Linux repository for managing and distributing packages. + +## Directory Structure + +``` +omarchy-repo/ +├── x86_64/ # Repository packages and database +├── src/ # AUR package build sources +├── build/ # Docker build files +├── bin/ # Management scripts +└── packages # Package list +``` + +## Quick Start + +1. **Add packages to track:** + - Edit `packages` file (system auto-detects if official or AUR) + +2. **Build packages in Docker:** + ```bash + ./bin/build + ``` + +3. **Update repository database:** + ```bash + ./bin/update-repo + ``` + +## Configuration + +### Local Usage + +Add this to `/etc/pacman.conf` (before other repositories for priority): + +```ini +[omarchy] +SigLevel = Optional TrustAll +Server = file:///home/ryan/Dev/omarchy-repo/x86_64 +``` + +### Remote Server Setup + +To serve this repository over HTTP: + +1. **Using Python (temporary):** + ```bash + cd /home/ryan/Dev/omarchy-repo/x86_64 + python -m http.server 8080 + ``` + +2. **Using nginx (permanent):** + ```nginx + server { + listen 80; + server_name repo.yourdomain.com; + root /home/ryan/Dev/omarchy-repo/x86_64; + autoindex on; + } + ``` + +3. **Client configuration:** + ```ini + [omarchy] + SigLevel = Optional TrustAll + Server = http://repo.yourdomain.com + ``` + +## Scripts Usage + +### build + +Builds all packages in Docker container (no local installation). + +```bash +# Build everything +./bin/build + +# Options: +./bin/build --only "yay walker-bin" # Build specific packages +./bin/build --skip-pgp # Skip PGP signature verification +./bin/build --force # Force rebuild even if no updates +./bin/build --keep-image # Keep Docker image after build +``` + +### update-repo + +Updates the repository database with all packages in x86_64/. + +```bash +# Update database +./bin/update-repo + +# Options: +./bin/update-repo --verify # Only verify the database +./bin/update-repo --sign # Sign database with GPG +./bin/update-repo --stats # Show repository statistics +``` + +### clean-repo + +Maintains the repository by removing old packages. + +```bash +# Keep only latest 2 versions +./bin/clean-repo + +# Options: +./bin/clean-repo --keep 3 # Keep 3 versions +./bin/clean-repo --dry-run # Preview what would be removed +./bin/clean-repo --all # Remove all packages (dangerous!) +``` + +### sync-repo + +Syncs repository to remote server. + +```bash +# Sync to configured remote +./bin/sync-repo ./x86_64 +``` + +## ISO Integration + +To include this repository in an Arch ISO: + +1. Copy the entire `x86_64/` directory to the ISO +2. Add the repository configuration to the ISO's `pacman.conf` +3. The packages will be available during installation + +## Package Management + +### Adding Packages + +1. Add package name to `packages.official` or `packages.aur` +2. Run `./scripts/build-packages.sh` +3. Run `./scripts/update-repo.sh` + +### Removing Packages + +1. Remove package name from the list files +2. Delete the package file from `x86_64/` +3. Run `./scripts/update-repo.sh` + +### Updating Packages + +Simply run the build script again - it will download/build the latest versions: + +```bash +./scripts/build-packages.sh +./scripts/update-repo.sh +``` + +## Security + +### Package Signing (Optional) + +1. **Create a GPG key:** + ```bash + gpg --gen-key + ``` + +2. **Export public key:** + ```bash + gpg --export --armor "Your Name" > omarchy-repo.key + ``` + +3. **Sign packages during build:** + ```bash + ./scripts/update-repo.sh --sign + ``` + +4. **Client configuration:** + ```ini + [omarchy] + SigLevel = Required + Server = file:///home/ryan/Dev/omarchy-repo/x86_64 + ``` + +## Maintenance + +### Regular Updates + +Create a systemd timer or cron job for automatic updates: + +```bash +# /etc/cron.daily/omarchy-repo-update +#!/bin/bash +cd /home/ryan/Dev/omarchy-repo +./scripts/build-packages.sh +./scripts/update-repo.sh +./scripts/clean-repo.sh --keep 2 +``` + +### Backup + +Important files to backup: +- `packages.official` +- `packages.aur` +- `x86_64/*.pkg.tar.*` +- GPG keys (if using signing) + +## Troubleshooting + +### Common Issues + +1. **"No packages found"** + - Run `./scripts/build-packages.sh` first + +2. **AUR build failures** + - Check build dependencies + - Try manual mode: `./scripts/build-packages.sh --manual` + +3. **Repository not recognized by pacman** + - Ensure the repository is listed before other repos in `/etc/pacman.conf` + - Run `sudo pacman -Sy` to sync databases + +4. **Permission errors** + - Some operations need sudo (downloading official packages) + - Ensure scripts are executable: `chmod +x scripts/*.sh` + +## Advanced Usage + +### Mirror Synchronization + +To sync with another omarchy instance: + +```bash +rsync -av --delete \ + user@remote:/path/to/omarchy-repo/x86_64/ \ + /home/ryan/Dev/omarchy-repo/x86_64/ +``` + +### Custom Build Flags + +For AUR packages, edit `/etc/makepkg.conf` to customize: +- `CFLAGS` / `CXXFLAGS` for optimization +- `MAKEFLAGS` for parallel compilation +- `PACKAGER` for package attribution + +## License + +This repository structure and scripts are provided as-is for personal use. diff --git a/bin/build b/bin/build new file mode 100755 index 0000000..ff63702 --- /dev/null +++ b/bin/build @@ -0,0 +1,231 @@ +#!/bin/bash +# Omarchy Repository Package Builder - Docker Isolated +# Builds packages in Docker without affecting the host system + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Repository paths +REPO_DIR="/home/ryan/Dev/omarchy-repo" +ARCH_DIR="$REPO_DIR/x86_64" +BUILD_DIR="$REPO_DIR/build" + +# Create directories if they don't exist +mkdir -p "$ARCH_DIR" "$BUILD_DIR" + +# Function to print colored messages +print_msg() { + local color=$1 + local msg=$2 + echo -e "${color}${msg}${NC}" +} + + +# Function to build Docker image +build_docker_image() { + print_msg "$BLUE" "==> Building Docker image..." + + # Check if Dockerfile exists + if [[ ! -f "$BUILD_DIR/Dockerfile" ]]; then + print_msg "$RED" "Error: Dockerfile not found at $BUILD_DIR/Dockerfile" + exit 1 + fi + + # Prepare package list for Docker build + if [[ -n "$ONLY_PACKAGES" ]]; then + print_msg "$YELLOW" " -> Filtering packages: $ONLY_PACKAGES" + + # Create temporary filtered list + > "$BUILD_DIR/packages" + + # Check each package against the main list + for pkg in $ONLY_PACKAGES; do + # Check if in package list (handle options like skip-pgp) + if [[ -f "$REPO_DIR/packages" ]]; then + grep "^$pkg\( \|$\)" "$REPO_DIR/packages" >> "$BUILD_DIR/packages" && { + print_msg "$GREEN" " -> $pkg" + } || { + print_msg "$YELLOW" " -> $pkg (not found in package list)" + } + fi + done + else + # Copy full packages list to build directory + cp "$REPO_DIR/packages" "$BUILD_DIR/packages" + fi + + # Build image + cd "$BUILD_DIR" + docker build -t omarchy-builder . || { + print_msg "$RED" "Failed to build Docker image" + exit 1 + } + + print_msg "$GREEN" " -> Docker image built successfully!" +} + +# Function to run build in Docker +run_docker_build() { + print_msg "$BLUE" "==> Running package build in Docker..." + + # Create src directory if it doesn't exist + mkdir -p "$REPO_DIR/src" + + # Build docker run command with options + DOCKER_ENV="" + if [[ "$SKIP_PGP" == true ]]; then + print_msg "$YELLOW" " -> Skipping PGP signature verification" + DOCKER_ENV="$DOCKER_ENV -e SKIP_PGP=true" + fi + if [[ "$FORCE_REBUILD" == true ]]; then + print_msg "$YELLOW" " -> Forcing rebuild of all packages" + DOCKER_ENV="$DOCKER_ENV -e FORCE_REBUILD=true" + fi + + docker run --rm \ + $DOCKER_ENV \ + -v "$ARCH_DIR:/output" \ + -v "$ARCH_DIR:/var/cache/pacman/pkg" \ + -v "$REPO_DIR/src:/src" \ + omarchy-builder || { + print_msg "$RED" "Docker build failed" + exit 1 + } + + print_msg "$GREEN" " -> Package build complete!" +} + +# Function to clean Docker resources +clean_docker() { + print_msg "$BLUE" "==> Cleaning Docker resources..." + + # Remove image + docker rmi omarchy-builder 2>/dev/null || true + + # Clean temporary packages file from build directory + rm -f "$BUILD_DIR/packages" + + print_msg "$GREEN" " -> Cleanup complete!" +} + +# Main execution +main() { + print_msg "$BLUE" "================================" + print_msg "$BLUE" "Omarchy Repository Docker Builder" + print_msg "$BLUE" "================================" + + # Check for Docker + if ! command -v docker &> /dev/null; then + print_msg "$RED" "Error: Docker is not installed" + print_msg "$YELLOW" "Please install Docker first:" + print_msg "$YELLOW" " sudo pacman -S docker" + print_msg "$YELLOW" " sudo systemctl start docker" + print_msg "$YELLOW" " sudo usermod -aG docker $USER" + exit 1 + fi + + # Check if Docker daemon is running + if ! docker info &> /dev/null; then + print_msg "$RED" "Error: Docker daemon is not running" + print_msg "$YELLOW" "Start Docker with: sudo systemctl start docker" + exit 1 + fi + + # Parse command line arguments + CLEAN_ONLY=false + KEEP_IMAGE=false + ONLY_PACKAGES="" + SKIP_PGP=false + FORCE_REBUILD=false + + while [[ $# -gt 0 ]]; do + case $1 in + --clean) + CLEAN_ONLY=true + shift + ;; + --keep-image) + KEEP_IMAGE=true + shift + ;; + --only) + ONLY_PACKAGES="$2" + shift 2 + ;; + --skip-pgp) + SKIP_PGP=true + shift + ;; + --force) + FORCE_REBUILD=true + shift + ;; + -h|--help) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --clean Clean Docker resources only" + echo " --keep-image Keep Docker image after build" + echo " --only \"pkg1 pkg2\" Only build specific packages" + echo " --skip-pgp Skip PGP signature verification" + echo " --force Force rebuild even if no updates" + echo " -h, --help Show this help message" + echo "" + echo "Examples:" + echo " $0 # Build all packages" + echo " $0 --only \"yay walker-bin\" # Only build yay and walker-bin" + echo " $0 --skip-pgp # Build without PGP checks" + echo "" + echo "This script builds all packages listed in:" + echo " - packages.official (downloaded from Arch repos)" + echo " - packages.aur (built from AUR)" + echo "" + echo "All builds happen inside a Docker container." + echo "No packages are installed on your host system." + exit 0 + ;; + *) + print_msg "$RED" "Unknown option: $1" + exit 1 + ;; + esac + done + + # Execute based on options + if [[ "$CLEAN_ONLY" == true ]]; then + clean_docker + else + # Build packages + build_docker_image + run_docker_build + + # Clean up unless keeping image + if [[ "$KEEP_IMAGE" != true ]]; then + clean_docker + else + print_msg "$YELLOW" "Docker image kept: omarchy-builder" + print_msg "$YELLOW" "Remove with: docker rmi omarchy-builder" + fi + + # Show results + print_msg "$BLUE" "\n==> Build Summary:" + local count=$(ls -1 "$ARCH_DIR"/*.pkg.tar.* 2>/dev/null | wc -l) + if [[ $count -gt 0 ]]; then + print_msg "$GREEN" " -> Built/downloaded $count package(s)" + print_msg "$GREEN" " -> Packages are in: $ARCH_DIR" + print_msg "$YELLOW" "\nNext step: Run ./scripts/update-repo.sh" + else + print_msg "$YELLOW" " -> No packages were built" + print_msg "$YELLOW" " -> Check your package lists" + fi + fi +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/bin/clean-repo b/bin/clean-repo new file mode 100755 index 0000000..ef2f3fc --- /dev/null +++ b/bin/clean-repo @@ -0,0 +1,245 @@ +#!/bin/bash +# Omarchy Repository Cleaner +# Removes old package versions keeping only the latest + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Repository configuration +REPO_DIR="/home/ryan/Dev/omarchy-repo" +ARCH_DIR="$REPO_DIR/x86_64" +KEEP_VERSIONS=2 + +# Function to print colored messages +print_msg() { + local color=$1 + local msg=$2 + echo -e "${color}${msg}${NC}" +} + +# Function to clean old packages +clean_packages() { + local keep=$1 + local dry_run=$2 + + print_msg "$BLUE" "==> Cleaning old packages (keeping $keep versions)..." + + cd "$ARCH_DIR" + + # Group packages by name + declare -A packages + + for pkg in *.pkg.tar.*; do + [[ -f "$pkg" ]] || continue + + # Skip signature files + [[ "$pkg" == *.sig ]] && continue + + # Extract package name (remove version and architecture) + # Format: name-version-release-arch.pkg.tar.* + local pkgname=$(echo "$pkg" | sed -E 's/-[0-9]+.*-(any|x86_64|i686)\.pkg\.tar\..*//') + + # Add to array + if [[ -n "${packages[$pkgname]}" ]]; then + packages[$pkgname]="${packages[$pkgname]} $pkg" + else + packages[$pkgname]="$pkg" + fi + done + + # Process each package group + local total_removed=0 + local space_freed=0 + + for pkgname in "${!packages[@]}"; do + # Convert string to array and sort by modification time (newest first) + IFS=' ' read -ra pkg_files <<< "${packages[$pkgname]}" + + # Sort by modification time + local sorted_files=($(ls -t "${pkg_files[@]}" 2>/dev/null)) + local count=${#sorted_files[@]} + + if [[ $count -gt $keep ]]; then + print_msg "$GREEN" " -> Processing $pkgname ($count versions found)" + + # Remove old versions + for ((i=$keep; i<$count; i++)); do + local file="${sorted_files[$i]}" + local size=$(stat -c%s "$file" 2>/dev/null || echo 0) + space_freed=$((space_freed + size)) + + if [[ "$dry_run" == true ]]; then + print_msg "$YELLOW" " Would remove: $file ($(numfmt --to=iec-i --suffix=B $size))" + else + print_msg "$RED" " Removing: $file ($(numfmt --to=iec-i --suffix=B $size))" + rm -f "$file" + rm -f "${file}.sig" 2>/dev/null || true + fi + + total_removed=$((total_removed + 1)) + done + fi + done + + # Summary + if [[ $total_removed -gt 0 ]]; then + if [[ "$dry_run" == true ]]; then + print_msg "$BLUE" "\n -> Would remove $total_removed old package(s)" + print_msg "$BLUE" " -> Would free $(numfmt --to=iec-i --suffix=B $space_freed)" + else + print_msg "$GREEN" "\n -> Removed $total_removed old package(s)" + print_msg "$GREEN" " -> Freed $(numfmt --to=iec-i --suffix=B $space_freed)" + fi + else + print_msg "$YELLOW" " -> No old packages to remove" + fi +} + +# Function to remove all packages +remove_all_packages() { + local dry_run=$1 + + print_msg "$RED" "==> WARNING: Removing ALL packages from repository!" + + if [[ "$dry_run" != true ]]; then + read -p "Are you sure? Type 'yes' to confirm: " confirm + if [[ "$confirm" != "yes" ]]; then + print_msg "$YELLOW" "Cancelled." + exit 0 + fi + fi + + cd "$ARCH_DIR" + + local count=$(ls -1 *.pkg.tar.* 2>/dev/null | wc -l) + + if [[ $count -eq 0 ]]; then + print_msg "$YELLOW" "No packages found to remove" + return + fi + + if [[ "$dry_run" == true ]]; then + print_msg "$YELLOW" "Would remove $count package(s):" + ls -1 *.pkg.tar.* 2>/dev/null | while read -r pkg; do + echo " - $pkg" + done + else + rm -f *.pkg.tar.* + rm -f *.db* *.files* + print_msg "$GREEN" "Removed $count package(s) and database files" + fi +} + +# Function to show repository disk usage +show_disk_usage() { + print_msg "$BLUE" "\n==> Repository Disk Usage:" + + cd "$ARCH_DIR" + + local total_size=$(du -sh . 2>/dev/null | cut -f1) + local package_count=$(ls -1 *.pkg.tar.* 2>/dev/null | grep -v '\.sig$' | wc -l) + + print_msg "$GREEN" " -> Total size: $total_size" + print_msg "$GREEN" " -> Package count: $package_count" + + if [[ $package_count -gt 0 ]]; then + print_msg "$GREEN" " -> Average package size: $(du -b *.pkg.tar.* 2>/dev/null | awk '{sum+=$1; count++} END {print sum/count}' | numfmt --to=iec-i --suffix=B)" + fi +} + +# Main execution +main() { + print_msg "$BLUE" "================================" + print_msg "$BLUE" "Omarchy Repository Cleaner" + print_msg "$BLUE" "================================" + + # Parse command line arguments + DRY_RUN=false + REMOVE_ALL=false + SHOW_USAGE=false + + while [[ $# -gt 0 ]]; do + case $1 in + --keep) + KEEP_VERSIONS="$2" + shift 2 + ;; + --dry-run) + DRY_RUN=true + shift + ;; + --all) + REMOVE_ALL=true + shift + ;; + --usage) + SHOW_USAGE=true + shift + ;; + -h|--help) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --keep N Keep N versions of each package (default: 2)" + echo " --dry-run Preview what would be removed without removing" + echo " --all Remove ALL packages (dangerous!)" + echo " --usage Show disk usage statistics" + echo " -h, --help Show this help message" + echo "" + echo "Examples:" + echo " $0 # Keep 2 versions (default)" + echo " $0 --keep 3 # Keep 3 versions" + echo " $0 --dry-run # Preview cleanup" + echo " $0 --all --dry-run # Preview complete removal" + exit 0 + ;; + *) + print_msg "$RED" "Unknown option: $1" + exit 1 + ;; + esac + done + + # Validate keep versions + if ! [[ "$KEEP_VERSIONS" =~ ^[0-9]+$ ]] || [[ "$KEEP_VERSIONS" -lt 1 ]]; then + print_msg "$RED" "Error: --keep must be a positive integer" + exit 1 + fi + + # Show dry run notice + if [[ "$DRY_RUN" == true ]]; then + print_msg "$YELLOW" "DRY RUN MODE - No changes will be made" + fi + + # Execute based on options + if [[ "$SHOW_USAGE" == true ]]; then + show_disk_usage + elif [[ "$REMOVE_ALL" == true ]]; then + remove_all_packages "$DRY_RUN" + else + clean_packages "$KEEP_VERSIONS" "$DRY_RUN" + + # Update database after cleaning (unless dry run) + if [[ "$DRY_RUN" != true ]]; then + print_msg "$BLUE" "\n==> Updating repository database..." + "$REPO_DIR/scripts/update-repo.sh" >/dev/null 2>&1 && { + print_msg "$GREEN" " -> Database updated successfully!" + } || { + print_msg "$YELLOW" " -> Database update failed (may need manual update)" + } + fi + + show_disk_usage + fi + + print_msg "$GREEN" "\n==> Cleanup complete!" +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/bin/sync-repo b/bin/sync-repo new file mode 100755 index 0000000..424b770 --- /dev/null +++ b/bin/sync-repo @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ $# -eq 0 ]; then + echo "Usage: sync-repo.sh [directory]" + exit 1 +fi + +rclone sync "$1" "pkgs.omarchy.org:omarchy-pkgs/$(basename $1)" --checksum --progress --copy-links --delete-after -v diff --git a/bin/update-repo b/bin/update-repo new file mode 100755 index 0000000..09e43ab --- /dev/null +++ b/bin/update-repo @@ -0,0 +1,186 @@ +#!/bin/bash +# Omarchy Repository Database Manager +# Updates the repository database with all packages + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Repository configuration +REPO_DIR="/home/ryan/Dev/omarchy-repo" +ARCH_DIR="$REPO_DIR/x86_64" +REPO_NAME="omarchy" +DB_FILE="$ARCH_DIR/${REPO_NAME}.db.tar.zst" +FILES_FILE="$ARCH_DIR/${REPO_NAME}.files.tar.zst" + +# Function to print colored messages +print_msg() { + local color=$1 + local msg=$2 + echo -e "${color}${msg}${NC}" +} + +# Function to update repository database +update_database() { + print_msg "$BLUE" "==> Updating repository database..." + + # Change to architecture directory + cd "$ARCH_DIR" + + # Remove old database files and symlinks + rm -f "${REPO_NAME}.db" "${REPO_NAME}.db.tar.zst" + rm -f "${REPO_NAME}.files" "${REPO_NAME}.files.tar.zst" + rm -f "${REPO_NAME}.db.tar.zst.old" "${REPO_NAME}.files.tar.zst.old" + + # Check if there are any packages + if ! ls *.pkg.tar.* 1> /dev/null 2>&1; then + print_msg "$YELLOW" "Warning: No packages found in $ARCH_DIR" + print_msg "$YELLOW" "Run ./scripts/build-packages.sh first to build packages" + exit 1 + fi + + # Add all packages to the database (excluding signature files) + print_msg "$GREEN" " -> Adding packages to database..." + # Process packages in smaller batches to avoid command line limits + # Use -n 5 to process 5 packages at a time + find . -maxdepth 1 -name "*.pkg.tar.*" ! -name "*.sig" -exec basename {} \; | xargs -n 5 repo-add "$DB_FILE" || { + print_msg "$RED" "Error: Failed to update repository database" + exit 1 + } + + # Create symlinks for compatibility + ln -sf "${REPO_NAME}.db.tar.zst" "${REPO_NAME}.db" + ln -sf "${REPO_NAME}.files.tar.zst" "${REPO_NAME}.files" + + # Count packages + PACKAGE_COUNT=$(ls -1 *.pkg.tar.* 2>/dev/null | wc -l) + + print_msg "$GREEN" " -> Database updated successfully!" + print_msg "$BLUE" " -> Total packages in repository: $PACKAGE_COUNT" +} + +# Function to verify database +verify_database() { + print_msg "$BLUE" "\n==> Verifying repository database..." + + if [[ -f "$DB_FILE" ]]; then + # List packages in database + print_msg "$GREEN" " -> Packages in database:" + tar -tf "$DB_FILE" 2>/dev/null | grep -E "^[^/]+/$" | sed 's|/$||' | sort -u | while read -r pkg; do + echo " - $pkg" + done + + print_msg "$GREEN" " -> Database verification complete!" + else + print_msg "$RED" "Error: Database file not found!" + exit 1 + fi +} + +# Function to sign database (optional) +sign_database() { + print_msg "$BLUE" "\n==> Signing repository database..." + + # Check if GPG key is available + if ! gpg --list-secret-keys 2>/dev/null | grep -q "sec"; then + print_msg "$YELLOW" "Warning: No GPG key found, skipping signing" + print_msg "$YELLOW" "To enable signing, create a GPG key and configure it" + return + fi + + # Sign the database + gpg --detach-sign --use-agent "$DB_FILE" 2>/dev/null && { + print_msg "$GREEN" " -> Database signed successfully!" + } || { + print_msg "$YELLOW" " -> Database signing failed (optional)" + } +} + +# Function to generate repository statistics +generate_stats() { + print_msg "$BLUE" "\n==> Repository Statistics:" + + cd "$ARCH_DIR" + + # Count packages by type + local total_packages=$(ls -1 *.pkg.tar.* 2>/dev/null | wc -l) + local total_size=$(du -sh . 2>/dev/null | cut -f1) + + print_msg "$GREEN" " -> Total packages: $total_packages" + print_msg "$GREEN" " -> Repository size: $total_size" + + # List largest packages + if [[ $total_packages -gt 0 ]]; then + print_msg "$GREEN" " -> Largest packages:" + ls -lhS *.pkg.tar.* 2>/dev/null | head -5 | awk '{print " " $9 " (" $5 ")"}' + fi +} + +# Main execution +main() { + print_msg "$BLUE" "================================" + print_msg "$BLUE" "Omarchy Repository Database Manager" + print_msg "$BLUE" "================================" + + # Parse command line arguments + VERIFY_ONLY=false + SIGN_DB=false + STATS_ONLY=false + + while [[ $# -gt 0 ]]; do + case $1 in + --verify) + VERIFY_ONLY=true + shift + ;; + --sign) + SIGN_DB=true + shift + ;; + --stats) + STATS_ONLY=true + shift + ;; + -h|--help) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --verify Only verify the database" + echo " --sign Sign the database with GPG" + echo " --stats Show repository statistics only" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + print_msg "$RED" "Unknown option: $1" + exit 1 + ;; + esac + done + + # Execute based on options + if [[ "$STATS_ONLY" == true ]]; then + generate_stats + elif [[ "$VERIFY_ONLY" == true ]]; then + verify_database + else + update_database + + if [[ "$SIGN_DB" == true ]]; then + sign_database + fi + + verify_database + generate_stats + fi + + print_msg "$GREEN" "\n==> Repository update complete!" +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 0000000..4191450 --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,27 @@ +FROM archlinux:latest + +# Update system and install build tools +RUN pacman -Syu --noconfirm && \ + pacman -S --noconfirm base-devel git sudo wget + +# Create build user +RUN useradd -m -G wheel builder && \ + echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +# Create output directory +RUN mkdir -p /output && chown builder:builder /output + +USER builder +WORKDIR /home/builder + +# Copy package list +COPY --chown=builder:builder packages ./ + +# Copy build scripts +COPY --chown=builder:builder build-packages.sh ./ +COPY --chown=builder:builder build-aur.sh ./ + +# Make scripts executable +RUN chmod +x build-packages.sh build-aur.sh + +CMD ["./build-packages.sh"] diff --git a/build/build-aur.sh b/build/build-aur.sh new file mode 100644 index 0000000..e4cbf9e --- /dev/null +++ b/build/build-aur.sh @@ -0,0 +1,126 @@ +#!/bin/bash +# AUR package building functions + +# Simple function to build an AUR package +build_aur_package() { + local pkg="$1" + local opts="$2" + + echo " -> Building $pkg..." + cd /src + + # Case 1: Directory exists with PKGBUILD - check for updates + if [[ -d "$pkg" ]] && [[ -f "$pkg/PKGBUILD" ]]; then + cd "$pkg" + + # Store current commit before pull + OLD_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "none") + + # Try to pull updates + git pull --quiet + + # Get new commit after pull + NEW_COMMIT=$(git rev-parse HEAD 2>/dev/null || echo "none") + + # Determine if we need to build + if [[ "$FORCE_REBUILD" == "true" ]]; then + echo " Forcing rebuild..." + elif [[ "$OLD_COMMIT" != "$NEW_COMMIT" ]]; then + echo " Updates found, rebuilding..." + else + echo " No updates found, skipping" + return 0 + fi + + # Case 2: Directory exists but no PKGBUILD - reclone + elif [[ -d "$pkg" ]]; then + echo " Incomplete clone detected, removing and recloning..." + rm -rf "$pkg" + git clone "https://aur.archlinux.org/${pkg}.git" || { + echo " Failed to clone $pkg" + FAILED_PACKAGES="$FAILED_PACKAGES $pkg" + return 1 + } + cd "$pkg" + + # Case 3: Directory doesn't exist - clone + else + git clone "https://aur.archlinux.org/${pkg}.git" || { + echo " Failed to clone $pkg" + FAILED_PACKAGES="$FAILED_PACKAGES $pkg" + return 1 + } + cd "$pkg" + fi + + # Build package + MAKEPKG_FLAGS="-sc --noconfirm" + + # Check for skip-pgp in options or global SKIP_PGP + if [[ "$SKIP_PGP" == "true" ]] || [[ "$opts" == *"skip-pgp"* ]]; then + MAKEPKG_FLAGS="$MAKEPKG_FLAGS --skippgpcheck" + echo " (skipping PGP verification)" + fi + + if gpg --list-secret-keys 2>/dev/null | grep -q "sec"; then + makepkg $MAKEPKG_FLAGS --sign || { + echo " Failed to build $pkg" + FAILED_PACKAGES="$FAILED_PACKAGES $pkg" + cd /src + return 1 + } + else + makepkg $MAKEPKG_FLAGS || { + echo " Failed to build $pkg" + FAILED_PACKAGES="$FAILED_PACKAGES $pkg" + cd /src + return 1 + } + fi + + # Copy to output and add to temporary build repo + for pkg_file in *.pkg.tar.*; do + if [[ -f "$pkg_file" ]] && [[ "$pkg_file" != *.sig ]]; then + cp "$pkg_file" /output/ + # Add to temporary repo database (pointing to /output files) + repo-add /tmp/build-repo/omarchy-build.db.tar.gz "/output/$pkg_file" + fi + done + + # Update pacman database to see new packages + sudo pacman -Sy + + echo " Successfully built $pkg" + cd /src +} + +build_aur_packages() { + # Work in the mounted src directory + cd /src + + FAILED_PACKAGES="" + + if [[ -s /tmp/packages.aur ]]; then + echo "==> Building AUR packages..." + while IFS= read -r line || [ -n "$line" ]; do + [[ "$line" =~ ^#.*$ ]] && continue + [[ -z "$line" ]] && continue + + # Parse package name and options + package=$(echo "$line" | awk '{print $1}') + options=$(echo "$line" | awk '{$1=""; print $0}' | xargs) + + # Build the package + build_aur_package "$package" "$options" + done < /tmp/packages.aur + + # Report failures at the end + if [[ -n "$FAILED_PACKAGES" ]]; then + echo "" + echo "==> Failed packages:" + for pkg in $FAILED_PACKAGES; do + echo " - $pkg" + done + fi + fi +} \ No newline at end of file diff --git a/build/build-packages.sh b/build/build-packages.sh new file mode 100644 index 0000000..99eb2f8 --- /dev/null +++ b/build/build-packages.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# Main build script that runs inside Docker container +set -e + +echo "==> Setting up local repository..." +# Create a temporary repo directory for build dependencies +mkdir -p /tmp/build-repo + +# Add local repo to pacman.conf so AUR packages can find their dependencies +sudo tee -a /etc/pacman.conf > /dev/null << EOF + +[omarchy-build] +SigLevel = Optional TrustAll +Server = file:///tmp/build-repo +EOF + +# Create initial empty database +repo-add /tmp/build-repo/omarchy-build.db.tar.gz 2>/dev/null || true + +# Sync pacman to recognize the new repo +sudo pacman -Sy + +echo "==> Processing package list..." +FAILED_PACKAGES="" +PROCESSED_PACKAGES="" + +# Separate packages into official and AUR +> /tmp/packages.official +> /tmp/packages.aur + +if [[ -f /home/builder/packages ]]; then + while IFS= read -r line || [ -n "$line" ]; do + [[ "$line" =~ ^#.*$ ]] && continue + [[ -z "$line" ]] && continue + + # Parse package name and options + package=$(echo "$line" | awk '{print $1}') + options=$(echo "$line" | awk '{$1=""; print $0}' | xargs) + + # Check if it's in official repos + if pacman -Si "$package" &>/dev/null; then + echo "$package" >> /tmp/packages.official + else + echo "$line" >> /tmp/packages.aur # Keep options for AUR packages + fi + done < /home/builder/packages +fi + +# Show package counts +echo "==> Package breakdown:" +echo " -> Official packages: $(wc -l < /tmp/packages.official 2>/dev/null || echo 0)" +echo " -> AUR packages: $(wc -l < /tmp/packages.aur 2>/dev/null || echo 0)" + +# Debug: Show AUR packages if any +if [[ -s /tmp/packages.aur ]]; then + echo "==> AUR packages to build:" + cat /tmp/packages.aur | while read line; do + echo " - $line" + done +fi + +echo "==> Downloading official packages..." +if [[ -s /tmp/packages.official ]]; then + while IFS= read -r package || [ -n "$package" ]; do + echo " -> Downloading $package..." + + # Download package without installing (will use default cache which is now /output) + sudo pacman -Sw --noconfirm "$package" || { + # Fallback to direct download + url=$(pacman -Sp "$package" 2>/dev/null) + if [[ -n "$url" ]]; then + wget -q -P /output "$url" || echo " -> Failed: $package" + fi + } + done < /tmp/packages.official +fi + +# Source the AUR build functions +source /home/builder/build-aur.sh + +# Build AUR packages +build_aur_packages + +echo "==> Build complete!" \ No newline at end of file diff --git a/packages b/packages new file mode 100644 index 0000000..40da773 --- /dev/null +++ b/packages @@ -0,0 +1,166 @@ +# Omarchy Repository Package List +# Format: packagename [options] +# Options: skip-pgp +# Lines starting with # are comments +# Empty lines are ignored + +1password-beta skip-pgp +1password-cli skip-pgp +alacritty +autoconf-archive +avahi +base +base-devel +bash-completion +bat +blueberry +brightnessctl +btop +btrfs-progs +chromium +clang +cups +cups-browsed +cups-filters +cups-pdf +dart +docker +docker-buildx +docker-compose +dust +egl-wayland +evince +eza +fastfetch +fcitx5 +fcitx5-gtk +fcitx5-qt +fd +ffmpegthumbnailer +fzf +gcc14 +git +github-cli +gnome-calculator +gnome-keyring +gnome-themes-extra +grub +gst-plugin-pipewire +gtk4-layer-shell +gum +gvfs-mtp +htop +hypridle +hyprland +hyprland-qtutils +hyprlock +hyprpicker +hyprshot +hyprsunset +imagemagick +impala +imv +inetutils +intltool +iwd +jdk-openjdk +jq +kdenlive +kvantum-qt5 +lazydocker +lazygit +less +libpulse +libqalculate +libreoffice-fresh +libsass +libva-nvidia-driver +limine-mkinitcpio-hook +limine-snapper-sync +linux +linux-firmware +linux-headers +llvm +localsend-bin +luarocks +mako +man-db +mariadb-libs +mise +mpv +nautilus +neovim +noto-fonts +noto-fonts-cjk +noto-fonts-emoji +noto-fonts-extra +nss-mdns +nvidia-dkms +nvidia-open-dkms +nvidia-utils +obs-studio +obsidian +omarchy-chromium-bin +pamixer +pinta +pipewire +pipewire-alsa +pipewire-jack +pipewire-pulse +playerctl +plocate +plymouth +polkit-gnome +postgresql-libs +power-profiles-daemon +python-gobject +python-poetry-core +python-terminaltexteffects +qt5-remoteobjects +qt5-wayland +qt6-wayland +ripgrep +sassc +satty +signal-desktop +slurp +snapper +spotify +starship +sushi +swaybg +swayosd +system-config-printer +tldr +tree-sitter-cli +ttf-cascadia-mono-nerd +ttf-font-awesome +ttf-ia-writer +ttf-jetbrains-mono +typora +tzupdate +ufw +ufw-docker +unzip +uwsm +walker-bin +waybar +webp-pixbuf-loader +wf-recorder +wget +whois +wiremix +wireplumber +wl-clip-persist +wl-clipboard +wl-screenrec +woff2-font-awesome +xdg-desktop-portal-gtk +xdg-desktop-portal-hyprland +xmlstarlet +xournalpp +yaru-icon-theme +yay +yay-debug +zoxide +zram-generator