diff options
| -rw-r--r-- | notes.txt | 141 | ||||
| -rw-r--r-- | src/__main__.py | 3 | ||||
| -rw-r--r-- | src/options.py | 95 | ||||
| -rw-r--r-- | src/xi.py | 117 | 
4 files changed, 271 insertions, 85 deletions
| diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..962ba2b --- /dev/null +++ b/notes.txt @@ -0,0 +1,141 @@ +/etc/xi/xipkg.conf +    for xipkg config + +in config define repo sources like this: +    <source name>: <url or filepath> + +eg: +    davidovski: https://xi.davidovski.xyz/repo/ + + +then specify repos that should be loaded: +    repos: core extra other + +/var/lib/xipkg +    to contain all working files: + +/var/lib/xipkg/packages +    "working dir" to keep xipkg files and xipkg.info +    will look something like this: +        packages/ +                    core/ +                    extra/ + + +/var/lib/xipkg/keychain +place to store publickeys for sources. + +/var/lib/xipkg/installed/<pkg name> +                                    /info       - info about the package that has been installed to the system +                                    /files      - text file with all the files that it installed to the sysetm (for later removal purposes) + + +sync +------- +download all xipkg.info and keys from repos, done before all other commands + +just go to each source +and each repo +one by one take each xipkg.info +temporarily save each xipkg.info somewhere, per source + +find the latest xipkg.info and get the VER_HASH for that build +find all of the xipkg.info with that VER_HASH and compare their checksums +the most common CHECKSUM will win, so place that xipkg.info in the correct place + +? maybe make a warning about any sources that have outdated / different CHECKSUMS for that version hash (possibly malicious?) + +A database should be made: + +Packages: +    [name (String), repo (String)] + +Sources: +    [name (String)], url (String) + +PackageSources: +    package (String), repo (String), source (String) + +This database should solve the problem of of which package infos come from which sources + + +??? +File: +    path (String), package (String), repo (String) +??? + +install +------- + +if a xipkg file is specified and there is a corresponding .info as well, it will install it directly +if its a url, then download the xipkg file and its .info + +if its a package name: +    check if it exists, +    if that package name exists in multiple repos, then prompt to ask which repo to take from  + +to check a package is already installed, search for its name in /var/lib/xipkg/installed + +to install package need to: +    - find the package in a place in /var/lib/xipkg/packages  +    - find all dependencies and subdependecies in a tree, and repeat install for any that are missing + +    - aquire .xipkg from correct source (look for the xipkg.info.source) + +    - verify that the hash of xipkg is right + +    - check against every publickey in /var/lib/xipkg/keychain (maybe better ideas?) + +    - untar the xipkg +    - list all package's files in xipkg into /var/lib/xipkg/installed/<pkg name>/files +    - copy the pkginfo to /var/lib/xipkg/installed/<pkg name>  +            ( do not use a symlink since later syncs can make the information inacurate) +    - copy all the files into their place on the system +            (actually install the package) +         +    - make an install reciept that contains: +        * the source that the package was downloaded from +        * the key that was used to validate the package +        * the date the package was installed +        * the user that installed the package +        * if the package was installed as a dependency +        * other info? + +    - ?? run some post install scripts?? +    - ?? clean up?? + +remove +------ + +find the package's installed files in /var/lib/xipkg/installed/<pkg name>/files and remove them from the system +(? maybe check if other packages need them, and dont remove then?) + +remove all the info from /var/lib/xipkg/installed/<pkg name> + +(? check ) +     +upgrade +------- +do a sync +if a package is specified, only upgrade that one package + +create a dependency tree and try upgrade core packages first (shouldnt matter really, since upgrading shouldnt have any dependencies other than xipkg and its subdependencies) + +to upgrade a package find that package in the repo and compare its pkginfo with the installed's package info + +if the VERSION_HASH is different then upgrade (guessing newer) +if the CHECKSUM is different AND the date is newer then upgrade (a different checksum with an older date could be a mistake) + +(cant rely only on version hash, because the way that the package was built can be changed) + + +force-upgrade +------------ +(! needs a better name) + +just removes the package and then installs it again + +file +------ +searches for a file to install +(!!! REQUIRES SOME KIND OF FILE DATABASE) diff --git a/src/__main__.py b/src/__main__.py index d1abc56..43d8cb7 100644 --- a/src/__main__.py +++ b/src/__main__.py @@ -1,6 +1,5 @@  import xi  if __name__ == "__main__": -    pass - +    xi.main() diff --git a/src/options.py b/src/options.py new file mode 100644 index 0000000..9064369 --- /dev/null +++ b/src/options.py @@ -0,0 +1,95 @@ +import sys + +options = { +        "h": { +                "name": "help", +                "flag" : True, +                "desc" : "prints the command usage and exists the program", +            } +        "y" : { +                "name" : "no-confirm", +                "flag" : True, +                "desc": "will not prompt the user" +            }, +        "r" : { +                "name" : "root", +                "flag" : False, +                "desc" : "specify the directory to use as the system root", +                "default" : "/" +            }, +        "l": { +                "name" : "no-sync", +                "flag" : True, +                "desc" : "skip syncing with repo sources (not recommended)" +            } +        } + +def parse_args(): + +    # re-organise the options by name rather than by single letter +    # a dict with "name": option_leter +    names = { v["name"] if v["name"] else k : k for k,v in options.items()} + +    args = sys.argv +    index = 1 + +    # save all of the options into a "parsed" dictionary +    parsed = {"args" : []} + +    while index < len(args): +        arg = args[index] + +        if len(arg) > 1 and arg[0] == "-": +            option = None + +            # is a named argument with a -- +            if arg[1] == "-" and len(arg) > 2 and arg[2:].split("=")[0] in names: +                option = names[arg[2:].split("=")[0]] +            # is a single letter argument with a - +            elif arg[1] in options: +                option = arg[1] +            else: +                parsed["args"].append(arg) + +            # add the option and any values ot the parsed dict +            if option is not None: +                if options[option]["flag"]: +                    parsed[option] = True +                else: +                    if "=" in arg: +                        parsed[option] = arg.split("=")[1] +                    else: +                        index += 1 +                        parsed[option] = args[index] +        else: +            parsed["args"].append(arg) +     + +        index += 1 + +    # add all default values to the parsed options +    for option in options: +        if not option in parsed: +            if options[option]["flag"]: +                parsed[option] = False +            else: +                parsed[option] = options[option]["default"] + +    return parsed + +def print_usage(): +    for option,o in options.items(): +        name = o["name"] +        description = o["desc"] +        d = ("[default=" + o["default"] + "]") if not o["flag"] else "" + +        print(f"\t-{option}, --{name}\t{d}") +        print(f"\t\t{description}\n") + +        if "verbs" in globals(): +            print("Available actions:") +            for verb in verbs: +                print(f"\t{verb}") + + + @@ -1,88 +1,39 @@ -import sys +import options -options = { -        "y" : { -                "name" : "no-confirm", -                "flag" : True, -                "desc": "will not prompt the user" -            }, -        "r" : { -                "name" : "root", -                "flag" : False, -                "desc" : "specify the directory to use as the system root", -                "default" : "/" -            }, -        "h": { -                "name": "help", -                "flag" : True, -                "desc" : "prints the command usage and exists the program", -            } -        } - -def parse_args(): - -    # re-organise the options by name rather than by single letter -    # a dict with "name": option_leter -    names = { v["name"] if v["name"] else k : k for k,v in options.items()} - -    args = sys.argv -    index = 1 - -    # save all of the options into a "parsed" dictionary -    parsed = {"other" : []} - -    while index < len(args): -        arg = args[index] - -        if len(arg) > 1 and arg[0] == "-": -            option = None +def search(terms): +    print(f"searching for {terms}") +    pass -            # is a named argument with a -- -            if arg[1] == "-" and len(arg) > 2 and arg[2:].split("=")[0] in names: -                option = names[arg[2:].split("=")[0]] -            # is a single letter argument with a - -            elif arg[1] in options: -                option = arg[1] -            else: -                parsed["other"].append(arg) +def install(terms): +    print(f"installing for {terms}") +    pass -            # add the option and any values ot the parsed dict -            if option is not None: -                if options[option]["flag"]: -                    parsed[option] = True -                else: -                    if "=" in arg: -                        parsed[option] = arg.split("=")[1] -                    else: -                        index += 1 -                        parsed[option] = args[index] -        else: -            parsed["other"].append(arg) -     +def remove(terms): +    print(f"removing for {terms}") +    pass -        index += 1 - -    # add all default values to the parsed options -    for option in options: -        if not option in parsed: -            if options[option]["flag"]: -                parsed[option] = False -            else: -                parsed[option] = options[option]["default"] - -    return parsed - -def print_usage(): -    for option,o in options.items(): -        name = o["name"] -        description = o["desc"] -        d = ("[default=" + o["default"] + "]") if not o["flag"] else "" - -        print(f"\t-{option}, --{name}\t{d}") -        print(f"\t\t{description}\n") - - -opts = parse_args() -if opts["h"]: -    print_usage() +verbs = { v: globals()[v] for v in [ +                "search", +                "install" +                "remove" +            ] +        } +def main(): +    opts = options.parse_args() +    args = opts["args"] + +    if opts["h"]: +        options.print_usage() +        return + +    if len(args) > 0: +        verb = args[0].lower() +        ( +            verbs[verb] if verb in verbs else search +        )( +            args[1:] if len(args) > 1 else [] +        ) +    else: +        options.print_usage() +        return | 
