summaryrefslogblamecommitdiff
path: root/pkgver_test.py
blob: 0a39f90884c7c433adc45475be17a61c4691c043 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                    
                        
                   
                                                        
 
                            
                                                           
 
                                                         
                                           












                                                      

                                                                           
 





                                                                      
 
                                                 
 

                                
 


                                                          
 

                                                                 
 


                                                                    
 








                                                                      
             












                                                                          
                 












                                                       
 
                     





















                                                                      



                                                    








                                                

                                              





                                                           
                                      





                                                                  

                            
                                 
     
#!/usr/bin/env python3
# Adélie Linux architecture package tester
# Ensure all packages are all on arches
#
# Copyright © 2018-2020 Adélie Linux team.  All rights reserved.
# NCSA license.
#
import argparse
import os
import sys
from pathlib import Path

from apkkit.base.index import Index

from output import FORMATTERS, Yes, No, YES_MISSING, PARTIAL_MISSING
from version import is_older

def analyze(opts, repo):
    newest = dict()
    arch_newest = {arch: dict() for arch in opts.arches}

    for arch in opts.arches:
        print(f"Loading {repo}/{arch}...", file=sys.stderr)

        url = f"{opts.url}/{repo}/{arch}/APKINDEX.tar.gz"
        for pkg in Index(url=url).packages:
            if pkg.name != pkg.origin:
                continue
            new = pkg.version

            for mydict in (newest, arch_newest[arch]):
                curr = mydict.get(pkg.name, None)
                if curr is None:
                    mydict[pkg.name] = new
                elif is_older(curr, new):
                    mydict[pkg.name] = new

    return newest, arch_newest

def order_arch(opts):
    yield ["repo", "arch", "package", "version for arch", "newest version"]

    for repo in opts.repos:
        if Path(repo + "-specific").is_file():
            with open(repo + '-specific', 'r') as ignore_file:
                ign = set(pkg[:-1] for pkg in ignore_file.readlines())
        else:
            ign = set()

        newest, arch_newest = analyze(opts, repo)

        for arch in opts.arches:
            old = list()

            for pkg in newest.keys():
                ver = newest[pkg]
                archver = arch_newest[arch].get(pkg, None)

                if archver is None and pkg not in ign:
                    yield [repo, arch, pkg, PARTIAL_MISSING, ver]

                elif archver is not None and is_older(archver, ver):
                    if opts.only_missing:
                        continue

                    yield [repo, arch, pkg, archver, ver]

def order_pkg(opts):
    yield ["repo", "package", *opts.arches]

    for repo in opts.repos:
        if Path(repo + "-specific").is_file():
            with open(repo + '-specific', 'r') as ignore_file:
                ign = set(pkg[:-1] for pkg in ignore_file.readlines())
        else:
            ign = set()

        newest, arch_newest = analyze(opts, repo)

        for pkg in sorted(newest.keys()):
            for i in opts.arches:
                archver = arch_newest[i].get(pkg, None)
                if archver is None:
                    break
                if opts.only_missing:
                    continue
                if archver is not None and is_older(archver, newest[pkg]):
                    break
            else:
                continue

            row = [repo, pkg]
            for i in opts.arches:
                archver = arch_newest[i].get(pkg, None)
                if archver is None and pkg in ign:
                    row.append(YES_MISSING)
                elif archver is None:
                    row.append(PARTIAL_MISSING)
                elif is_older(archver, newest[pkg]):
                    row.append(No(archver))
                else:
                    row.append(Yes(archver))

            yield row

ORDERS = {
    "pkg": order_pkg,
    "arch": order_arch,
}

if __name__ == "__main__":
    opts = argparse.ArgumentParser(
        description="""Scan the REPO/ARCH repositories under URL and
        look for outdated or missing packages when comparing across
        architectures. This script only examines main packages, not
        subpackages.

        At least two architectures must be given in order to make a
        comparison."""
    )
    opts.add_argument(
        "-f", "--format", choices=FORMATTERS.keys(),
        default="pretty" if os.isatty(sys.stdout.fileno()) else "tab",
        help="display format",
    )
    opts.add_argument(
        "-m", "--only-missing", action="store_true",
        help="show only missing packages",
    )
    opts.add_argument(
        "-o", "--order", choices=ORDERS.keys(),
        default="pkg",
        help="display order",
    )
    opts.add_argument(
        "url", metavar="URL",
        help="base URL (no repository or arch)",
    )
    opts.add_argument(
        "repos", metavar="REPOS",
        help="repositories (comma separated)",
    )
    opts.add_argument(
        "arches", metavar="ARCHES",
        help="architectures (comma separated, at least 2)",
    )
    opts = opts.parse_args()
    opts.repos = opts.repos.split(",")
    opts.arches = opts.arches.split(",")

    if len(opts.arches) < 2:
        print("At least two arches are required", file=sys.stderr)
        sys.exit(1)

    FORMATTERS[opts.format](
        opts,
        ORDERS[opts.order](opts),
    )