Files
SaraSuite/Cli.py
T

110 lines
4.4 KiB
Python

"""Command-line mode, for machines without a desktop (e.g. a Fedora Server box):
SaraSuite list
SaraSuite install <Name> [--set Id=Value ...] [--option Id=on|off ...]
SaraSuite update <Name>
SaraSuite options <Name> [--option Id=on|off ...] (no --option: list them)
SaraSuite remove <Name> [--configs] [--keep-runtime]
SaraSuite self-update (AppImage only)
Install starts from your defaults (Settings, or the manifest's) unless set.
"""
import argparse
import SelfUpdate
from Catalog import UpdateCatalog
from Core import AppVersion
from Installer import Apply, DefaultAnswers, DefaultOptions, FetchCommit, GetStatus, Remove
from Manifests import LoadPrograms
def _Pairs(Items: list[str]) -> dict[str, str]:
Pairs = {}
for Item in Items:
Key, Separator, Value = Item.partition("=")
if not Separator:
raise SystemExit(f"Expected Id=Value, got {Item!r}")
Pairs[Key] = Value
return Pairs
def _Switches(Items: list[str]) -> dict[str, bool]:
return {Key: Value.lower() in ("on", "yes", "true", "1") for Key, Value in _Pairs(Items).items()}
def Run(Arguments: list[str]) -> int:
Parser = argparse.ArgumentParser(prog="SaraSuite")
Commands = Parser.add_subparsers(dest="Command", required=True)
Commands.add_parser("list")
Install = Commands.add_parser("install")
Install.add_argument("Name")
Install.add_argument("--set", action="append", default=[], dest="Answers")
Install.add_argument("--option", action="append", default=[], dest="Options")
Commands.add_parser("update").add_argument("Name")
OptionsCommand = Commands.add_parser("options")
OptionsCommand.add_argument("Name")
OptionsCommand.add_argument("--option", action="append", default=[], dest="Options")
RemoveCommand = Commands.add_parser("remove")
RemoveCommand.add_argument("Name")
RemoveCommand.add_argument("--configs", action="store_true")
RemoveCommand.add_argument("--keep-runtime", action="store_true")
Commands.add_parser("self-update")
Args = Parser.parse_args(Arguments)
if Args.Command == "self-update":
Latest = SelfUpdate.LatestRelease()
if Latest is None or not SelfUpdate.IsNewer(Latest.Version):
print(f"SaraSuite {AppVersion} is the latest.")
return 0
SelfUpdate.Install(Latest, print)
return 0
UpdateCatalog(print) # the program list from the SaraSuite repo (AppImage only)
Programs = {Program.Name.lower(): Program for Program in LoadPrograms()}
if Args.Command == "list":
for Program in Programs.values():
Current = GetStatus(Program)
State = "update available" if Current.UpdateAvailable else "installed" if Current.Installed else "not installed"
Name = f" {Program.Name}" if Program.Parent else Program.Name
print(f"{Name:12} {State:16} {Current.Error}")
return 0
Program = Programs.get(Args.Name.lower())
if Program is None:
print(f"Unknown program {Args.Name!r}. Known: {', '.join(P.Name for P in Programs.values())}")
return 1
Current = GetStatus(Program)
Installed = Current.Installed
if Args.Command == "install":
if Installed:
print(f"{Program.Name} is already installed; use update.")
return 1
Options = DefaultOptions(Program)
Options.update(_Switches(Args.Options))
Answers = DefaultAnswers(Program)
Answers.update(_Pairs(Args.Answers))
Apply(Program, print, Options, Answers)
elif Args.Command == "update":
if not Installed:
print(f"{Program.Name} isn't installed.")
return 1
Apply(Program, print)
elif Args.Command == "options":
if not Installed:
print(f"{Program.Name} isn't installed.")
return 1
if not Args.Options:
for Option in Program.Options:
State = "on" if Current.Receipt.Options.get(Option.Id) else "off"
print(f"{Option.Id:20} {State:4} {Option.Label}")
return 0
Options = dict(Current.Receipt.Options)
Options.update(_Switches(Args.Options))
Apply(Program, print, Options, Source=FetchCommit(Program, Current.Receipt.Commit, print))
elif Args.Command == "remove":
Remove(Program, Args.configs, not Args.keep_runtime, print)
return 0