/****************************************************************************** __ ____ __ / / ___ ____ _/ __/_____________ _/ /__ / / / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \ / /___/ __/ /_/ / __(__ ) /__/ /_/ / / __/ /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/ (C)opyright 2025, Leafscale, LLC - https://www.leafscale.com Project: Zygaena Filename: outdated.reef Authors: Chris Tusa License: Description: Outdated command - show packages with available updates ******************************************************************************/ module commands.outdated import sys.args import core.str import core.database import core.port import types import util.color import exitcodes as ec export fn execute(): int end export fn execute(): int color.print_action("Checking for available updates...") println("") // Get list of installed packages mut installed: [string] = new [string](512) let installed_count = database.list_installed(installed, 512) if installed_count == 0 color.print_info("No packages installed") return ec.EXIT_SUCCESS() end if // Check each package for updates mut outdated_count = 0 mut i = 0 while i < installed_count let pkg_name = installed[i] let installed_pkg = database.get_installed(pkg_name) // Find port let port_result = port.find(pkg_name) if port_result.success let p = port_result.port // Compare versions let cmp = compare_versions(installed_pkg.info.version, p.info.version) if cmp < 0 // Outdated if outdated_count == 0 color.print_info("Outdated packages:") println("") end if print(" ") print(pkg_name) print(" ") print(installed_pkg.info.version) print("-") print(int_to_str(installed_pkg.info.release)) print(" -> ") print(p.info.version) print("-") println(int_to_str(p.info.release)) outdated_count = outdated_count + 1 end if end if i = i + 1 end while if outdated_count == 0 color.print_success("All packages are up to date") // Return special code for scripting - no updates available if args.has_flag("check") return ec.EXIT_NO_UPDATES() end if return ec.EXIT_SUCCESS() else println("") color.print_info(int_to_str(outdated_count) + " package(s) can be upgraded") println("") color.print_info("Run 'coral upgrade' to upgrade all packages") color.print_info("Run 'coral upgrade ' to upgrade specific packages") // Return special code for scripting - updates available if args.has_flag("check") return ec.EXIT_UPDATE_AVAILABLE() end if return ec.EXIT_SUCCESS() end if end execute // Compare two version strings // Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2 fn compare_versions(v1: string, v2: string): int // Split versions into parts mut parts1: [string] = new [string](10) mut parts2: [string] = new [string](10) let count1 = str.split(v1, '.', parts1, 10) let count2 = str.split(v2, '.', parts2, 10) // Compare each part mut i = 0 let max_parts = max_int(count1, count2) while i < max_parts mut n1 = 0 mut n2 = 0 if i < count1 n1 = parse_int(parts1[i]) end if if i < count2 n2 = parse_int(parts2[i]) end if if n1 < n2 return 0 - 1 elif n1 > n2 return 1 end if i = i + 1 end while return 0 end compare_versions fn max_int(a: int, b: int): int if a > b return a end if return b end max_int // Parse integer from string fn parse_int(s: string): int let len = str.length(s) if len == 0 return 0 end if mut result = 0 mut i = 0 while i < len let c = s[i] if c >= '0' and c <= '9' result = result * 10 + (c - '0') else // Stop at non-digit return result end if i = i + 1 end while return result end parse_int // Helper: convert int to string fn int_to_str(n: int): string if n == 0 return "0" end if mut negative = false mut value = n if n < 0 negative = true value = 0 - n end if mut result = "" while value > 0 let digit = value % 10 result = str.concat(str.substring("0123456789", digit, 1), result) value = value / 10 end while if negative result = str.concat("-", result) end if return result end int_to_str end module