/****************************************************************************** __ ____ __ / / ___ ____ _/ __/_____________ _/ /__ / / / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \ / /___/ __/ /_/ / __(__ ) /__/ /_/ / / __/ /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/ (C)opyright 2025, Leafscale, LLC - https://www.leafscale.com Project: Zygaena Filename: main.reef Authors: Chris Tusa License: Description: Entry point for Coral package manager ******************************************************************************/ import sys.args import sys.process import sys.env import io.file import io.dir import core.str import types import exitcodes as ec import commands.build as cmd_build import commands.install as cmd_install import commands.remove as cmd_remove import commands.upgrade as cmd_upgrade import commands.info as cmd_info import commands.list as cmd_list import commands.files as cmd_files import commands.owner as cmd_owner import commands.search as cmd_search import commands.depends as cmd_depends import commands.sync as cmd_sync import commands.outdated as cmd_outdated import commands.repo as cmd_repo import commands.key as cmd_key import commands.db as cmd_db import commands.clean as cmd_clean import commands.ports as cmd_ports import commands.verify as cmd_verify import util.color fn version(): string return "0.4.2" end version proc print_usage() println("coral " + version() + " - Package manager for Zygaena") println("") println("USAGE:") println(" coral [options] [packages...]") println("") println("COMMANDS:") println(" Package Management:") println(" install Install packages") println(" reinstall Reinstall packages (same as install --force)") println(" remove Remove packages") println(" upgrade Upgrade packages") println("") println(" Query Commands:") println(" info Show package info") println(" list List installed packages") println(" files List package files") println(" owner Find file owner") println(" search Search packages") println(" depends Show dependencies") println(" outdated Show available updates") println(" verify Verify package integrity") println("") println(" Build Commands:") println(" build Build package from port") println(" sync Update ports tree") println(" clean Remove build artifacts (sources|packages|build|all)") println("") println(" System Commands:") println(" db Manage package database (init|rebuild|status)") println(" ports Port development tools (new|cache)") println(" repo Manage repositories") println(" key Manage signing keys") println("") println("OPTIONS:") println(" -h, --help Show this help") println(" --version Show version") println(" -y, --yes Don't ask for confirmation") println(" -f, --force Force operation") println(" -v, --verbose Verbose output") println(" -n, --dry-run Show what would be done") println(" -q, --quiet Minimal output") println(" --no-color Disable colored output") println(" --root Use alternative root directory") println(" --prefix Installation prefix (default: /usr)") println("") println("EXIT CODES:") println(" 0 Success") println(" 1 General error") println(" 2 Usage/syntax error") println(" 10-19 Package errors") println(" 20-29 Build errors") println(" 30-39 Network errors") println(" 50-59 Permission errors") println(" 60-69 Dependency errors") println(" 100+ Informational (scripting)") end print_usage // Find the index of the command argument, skipping global flags fn find_command_index(): int let argc = args.count() mut i = 1 while i < argc let arg = args.get(i) // Skip flags that take a value if arg == "--root" or arg == "--prefix" i = i + 2 // Skip flag and its value continue end if // Skip boolean flags if arg == "-y" or arg == "--yes" or arg == "-f" or arg == "--force" or arg == "-v" or arg == "--verbose" or arg == "-n" or arg == "--dry-run" or arg == "-q" or arg == "--quiet" or arg == "--no-color" i = i + 1 continue end if // Found the command return i end while return -1 end find_command_index // Parse global options from command line arguments fn parse_global_options(): types.GlobalOptions mut opts = types.new_global_options() opts.yes = args.has_flag("y") or args.has_flag("yes") opts.force = args.has_flag("f") or args.has_flag("force") opts.verbose = args.has_flag("v") or args.has_flag("verbose") opts.dry_run = args.has_flag("n") or args.has_flag("dry-run") opts.quiet = args.has_flag("q") or args.has_flag("quiet") // Check for --root option if args.has_flag("root") opts.root = args.get_flag_value("root") end if // Check for --prefix option if args.has_flag("prefix") opts.prefix = args.get_flag_value("prefix") end if return opts end parse_global_options // Check if we are running as root (UID 0) // Uses file test to check write permission on system directory fn is_root(): bool // Try to create a temp file in /var/lib/coral - only root can write there let test_file = "/var/lib/coral/.root_check" if file.writeFile(test_file, "1") // Successfully wrote - we have root-level access // File will be overwritten next time, no need to delete return true end if return false end is_root // Check if a command is a query command (doesn't require root) fn is_query_command(cmd: string): bool // Query commands that don't modify the system if cmd == "info" return true elif cmd == "list" return true elif cmd == "files" return true elif cmd == "owner" return true elif cmd == "search" return true elif cmd == "depends" return true elif cmd == "outdated" return true elif cmd == "verify" return true elif cmd == "build" // Building packages doesn't require root - only writes to build directories return true elif cmd == "--help" or cmd == "-h" return true elif cmd == "--version" or cmd == "version" return true end if return false end is_query_command fn main(): int let argc = args.count() if argc < 2 print_usage() return ec.EXIT_USAGE() end if // Check for --help and --version before finding command // (these can appear anywhere) if args.has_flag("help") or args.has_flag("h") print_usage() return ec.EXIT_SUCCESS() end if if args.has_flag("version") println("coral " + version()) return ec.EXIT_SUCCESS() end if // Find the actual command, skipping global flags let cmd_index = find_command_index() if cmd_index < 0 print_usage() return ec.EXIT_USAGE() end if let cmd = args.get(cmd_index) // Parse global options and set command index mut opts = parse_global_options() opts.cmd_index = cmd_index // Check for root privileges if required if not is_query_command(cmd) if not is_root() color.print_error("This command requires root privileges") println("Run 'coral " + cmd + "' as root or with sudo") return ec.EXIT_ROOT_REQUIRED() end if end if // Dispatch to command handlers // Commands return exit codes if cmd == "build" return cmd_build.execute(opts) elif cmd == "install" return cmd_install.execute(opts) elif cmd == "reinstall" // Reinstall is install with force flag enabled mut reinstall_opts = opts reinstall_opts.force = true return cmd_install.execute(reinstall_opts) elif cmd == "remove" return cmd_remove.execute(opts) elif cmd == "upgrade" return cmd_upgrade.execute(opts) elif cmd == "info" return cmd_info.execute(opts) elif cmd == "list" return cmd_list.execute(opts) elif cmd == "files" return cmd_files.execute(opts) elif cmd == "owner" return cmd_owner.execute(opts) elif cmd == "search" return cmd_search.execute() elif cmd == "depends" return cmd_depends.execute() elif cmd == "sync" return cmd_sync.execute() elif cmd == "outdated" return cmd_outdated.execute() elif cmd == "repo" return cmd_repo.execute() elif cmd == "key" return cmd_key.execute() elif cmd == "db" return cmd_db.execute(opts) elif cmd == "clean" return cmd_clean.execute() elif cmd == "ports" return cmd_ports.execute(opts) elif cmd == "verify" return cmd_verify.execute(opts) elif cmd == "version" println(version()) return ec.EXIT_SUCCESS() else color.print_error("unknown command '" + cmd + "'") println("Run 'coral --help' for usage.") return ec.EXIT_USAGE() end if end main