255 lines
7.2 KiB
Nim
255 lines
7.2 KiB
Nim
#!/usr/bin/env nim
|
|
# Copyright (c) 2026 Nexus Foundation
|
|
# Licensed under the Libertaria Sovereign License (LSL-1.0)
|
|
# See legal/LICENSE_SOVEREIGN.md for details.
|
|
|
|
# NIP MVP - Minimal Viable Product CLI
|
|
# Simple, focused package grafting from Nix, PKGSRC, and Pacman
|
|
|
|
import std/[os, strutils, strformat]
|
|
import src/nimpak/cli/graft_commands
|
|
import src/nimpak/cli/bootstrap_commands
|
|
import src/nimpak/cli/store_commands
|
|
|
|
const
|
|
Version = "0.1.0-mvp"
|
|
Banner = """
|
|
🌱 NIP v$1 - Universal Package Grafting
|
|
Graft packages from Nix, PKGSRC, and Pacman
|
|
""" % [Version]
|
|
|
|
proc showHelp() =
|
|
echo Banner
|
|
echo """
|
|
USAGE:
|
|
nip <command> [arguments] [options]
|
|
|
|
COMMANDS:
|
|
graft <package> Graft a package (auto-detect source)
|
|
graft <source>:<pkg> Graft from specific source
|
|
remove <package> Remove an installed package
|
|
list List installed packages
|
|
list --source=<src> List packages from specific source
|
|
info <package> Show package information
|
|
status Show system status
|
|
doctor Check system health
|
|
setup Setup system integration (PATH, libraries)
|
|
bootstrap Build tool management (nix, pkgsrc, gentoo)
|
|
store Interact with Content-Addressable Storage (CAS)
|
|
config [show|init] Show or initialize configuration
|
|
logs [lines] Show recent log entries (default: 50)
|
|
search <query> Search for packages (coming soon)
|
|
|
|
SOURCES:
|
|
nix Nix/nixpkgs packages
|
|
pkgsrc NetBSD PKGSRC packages
|
|
pacman Arch Linux Pacman packages
|
|
|
|
OPTIONS:
|
|
--verbose, -v Verbose output
|
|
--help, -h Show this help
|
|
--version Show version
|
|
|
|
EXAMPLES:
|
|
nip graft nix:firefox # Graft Firefox from Nix
|
|
nip graft pkgsrc:vim # Graft Vim from PKGSRC
|
|
nip graft hello # Auto-detect source for hello
|
|
nip list # List all installed packages
|
|
nip list --source=nix # List Nix packages only
|
|
nip info firefox # Show Firefox info
|
|
nip remove firefox # Remove Firefox
|
|
nip status # Show system status
|
|
nip doctor # Check system health
|
|
|
|
DIRECTORIES:
|
|
/Programs/<Name>/<Version>/ Package installation
|
|
/System/Links/Executables/ Binaries (in PATH)
|
|
/System/Links/Libraries/ Shared libraries
|
|
/var/nip/db/packages.json Package database
|
|
|
|
MORE INFO:
|
|
https://git.maiwald.work/Nexus/NexusToolKit
|
|
"""
|
|
|
|
proc showVersion() =
|
|
echo fmt"NIP version {Version}"
|
|
|
|
proc main() =
|
|
let args = commandLineParams()
|
|
|
|
if args.len == 0:
|
|
showHelp()
|
|
quit(0)
|
|
|
|
# Parse global options
|
|
var verbose = false
|
|
var remainingArgs: seq[string] = @[]
|
|
|
|
for arg in args:
|
|
case arg
|
|
of "--verbose", "-v":
|
|
verbose = true
|
|
of "--help", "-h":
|
|
showHelp()
|
|
quit(0)
|
|
of "--version":
|
|
showVersion()
|
|
quit(0)
|
|
else:
|
|
remainingArgs.add(arg)
|
|
|
|
if remainingArgs.len == 0:
|
|
showHelp()
|
|
quit(0)
|
|
|
|
let command = remainingArgs[0].toLower()
|
|
let commandArgs = if remainingArgs.len > 1: remainingArgs[1..^1] else: @[]
|
|
|
|
# Dispatch command
|
|
var exitCode = 0
|
|
|
|
try:
|
|
# Handle commands that don't need initialization
|
|
if command == "setup":
|
|
exitCode = setupCommand(verbose)
|
|
quit(exitCode)
|
|
|
|
if command == "config":
|
|
let action = if commandArgs.len > 0: commandArgs[0] else: "show"
|
|
exitCode = configCommand(action, verbose)
|
|
quit(exitCode)
|
|
|
|
if command == "platform":
|
|
exitCode = platformCommand(verbose)
|
|
quit(exitCode)
|
|
|
|
# Initialize graft commands for other commands
|
|
initGraftCommands(verbose)
|
|
|
|
case command
|
|
of "graft", "install":
|
|
if commandArgs.len == 0:
|
|
echo "Error: Package name required"
|
|
echo "Usage: nip graft <package> or nip graft <source>:<package>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = graftCommand(commandArgs[0], verbose)
|
|
|
|
of "remove", "uninstall":
|
|
if commandArgs.len == 0:
|
|
echo "Error: Package name required"
|
|
echo "Usage: nip remove <package>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = removeCommand(commandArgs[0], verbose)
|
|
|
|
of "list", "ls":
|
|
var source = ""
|
|
for arg in commandArgs:
|
|
if arg.startsWith("--source="):
|
|
source = arg.split("=", 1)[1]
|
|
exitCode = listCommand(source, verbose)
|
|
|
|
of "info", "show":
|
|
if commandArgs.len == 0:
|
|
echo "Error: Package name required"
|
|
echo "Usage: nip info <package>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = infoCommand(commandArgs[0], verbose)
|
|
|
|
of "status":
|
|
exitCode = statusCommand(verbose)
|
|
|
|
of "doctor", "check":
|
|
exitCode = doctorCommand(verbose)
|
|
|
|
of "search":
|
|
if commandArgs.len == 0:
|
|
echo "Error: Search query required"
|
|
echo "Usage: nip search <query>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = searchCommand(commandArgs[0], "", verbose)
|
|
|
|
of "logs":
|
|
let lines = if commandArgs.len > 0:
|
|
try: parseInt(commandArgs[0])
|
|
except: 50
|
|
else: 50
|
|
exitCode = logsCommand(lines, verbose)
|
|
|
|
of "help":
|
|
showHelp()
|
|
exitCode = 0
|
|
|
|
of "bootstrap":
|
|
if commandArgs.len == 0:
|
|
bootstrapHelpCommand()
|
|
exitCode = 0
|
|
else:
|
|
let subCmd = commandArgs[0].toLower()
|
|
let subArgs = if commandArgs.len > 1: commandArgs[1..^1] else: @[]
|
|
case subCmd
|
|
of "list":
|
|
exitCode = bootstrapListCommand()
|
|
of "install":
|
|
if subArgs.len == 0:
|
|
echo "Error: Tool name required"
|
|
echo "Usage: nip bootstrap install <tool>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = bootstrapInstallCommand(subArgs[0])
|
|
of "remove":
|
|
if subArgs.len == 0:
|
|
echo "Error: Tool name required"
|
|
echo "Usage: nip bootstrap remove <tool>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = bootstrapRemoveCommand(subArgs[0])
|
|
of "info":
|
|
if subArgs.len == 0:
|
|
echo "Error: Tool name required"
|
|
echo "Usage: nip bootstrap info <tool>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = bootstrapInfoCommand(subArgs[0])
|
|
of "recipes":
|
|
exitCode = bootstrapListRecipesCommand()
|
|
of "update-recipes":
|
|
exitCode = bootstrapUpdateRecipesCommand()
|
|
of "validate":
|
|
if subArgs.len == 0:
|
|
echo "Error: Tool name required"
|
|
echo "Usage: nip bootstrap validate <tool>"
|
|
exitCode = 1
|
|
else:
|
|
exitCode = bootstrapValidateRecipeCommand(subArgs[0])
|
|
of "help":
|
|
bootstrapHelpCommand()
|
|
exitCode = 0
|
|
else:
|
|
echo fmt"Error: Unknown bootstrap subcommand '{subCmd}'"
|
|
bootstrapHelpCommand()
|
|
exitCode = 1
|
|
|
|
of "store":
|
|
exitCode = dispatchStoreCommand(commandArgs, verbose)
|
|
|
|
else:
|
|
echo fmt"Error: Unknown command '{command}'"
|
|
echo "Run 'nip --help' for usage information"
|
|
exitCode = 1
|
|
|
|
except Exception as e:
|
|
echo fmt"Fatal error: {e.msg}"
|
|
if verbose:
|
|
echo "Stack trace:"
|
|
echo e.getStackTrace()
|
|
exitCode = 1
|
|
|
|
quit(exitCode)
|
|
|
|
when isMainModule:
|
|
main()
|