diff options
Diffstat (limited to 'devel/management')
-rw-r--r-- | devel/management/commands/import_signatures.py | 104 | ||||
-rw-r--r-- | devel/management/commands/reporead.py | 11 |
2 files changed, 109 insertions, 6 deletions
diff --git a/devel/management/commands/import_signatures.py b/devel/management/commands/import_signatures.py new file mode 100644 index 00000000..8a4ce873 --- /dev/null +++ b/devel/management/commands/import_signatures.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +""" +import_signatures command + +Import signatures from a given GPG keyring. + +Usage: ./manage.py generate_keyring <keyring_path> +""" + +from datetime import datetime +import logging +import subprocess +import sys + +from django.core.management.base import BaseCommand, CommandError +from django.db import transaction + +from devel.models import PGPSignature + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s -> %(levelname)s: %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + stream=sys.stderr) +logger = logging.getLogger() + +class Command(BaseCommand): + args = "<keyring_path>" + help = "Import signatures from a given GPG keyring." + + def handle(self, *args, **options): + v = int(options.get('verbosity', None)) + if v == 0: + logger.level = logging.ERROR + elif v == 1: + logger.level = logging.INFO + elif v == 2: + logger.level = logging.DEBUG + + if len(args) < 1: + raise CommandError("keyring_path must be provided") + + import_signatures(args[0]) + +def parse_sigdata(data): + nodes = {} + edges = [] + current_pubkey = None + + # parse all of the output from our successful GPG command + logger.info("parsing command output") + for line in data.split('\n'): + parts = line.split(':') + if parts[0] == 'pub': + current_pubkey = parts[4] + nodes[current_pubkey] = None + if parts[0] == 'uid': + uid = parts[9] + # only set uid if this is the first one encountered + if nodes[current_pubkey] is None: + nodes[current_pubkey] = uid + if parts[0] == 'sig': + created = datetime.utcfromtimestamp(int(parts[5])) + expires = None + if parts[6]: + expires = datetime.utcfromtimestamp(int(parts[6])) + valid = parts[1] != '-' + edge = (parts[4], current_pubkey, created, expires, valid) + edges.append(edge) + + return nodes, edges + + +def import_signatures(keyring): + gpg_cmd = ["gpg", "--no-default-keyring", "--keyring", keyring, + "--list-sigs", "--with-colons", "--fixed-list-mode"] + logger.info("running command: %r", gpg_cmd) + proc = subprocess.Popen(gpg_cmd, stdout=subprocess.PIPE) + outdata, errdata = proc.communicate() + if proc.returncode != 0: + logger.error(errdata) + raise subprocess.CalledProcessError(proc.returncode, gpg_cmd) + + nodes, edges = parse_sigdata(outdata) + + # now prune the data down to what we actually want. + # prune edges not in nodes, remove duplicates, and self-sigs + pruned_edges = set(edge for edge in edges + if edge[0] in nodes and edge[0] != edge[1]) + + logger.info("creating or finding %d signatures", len(pruned_edges)) + created_ct = 0 + with transaction.commit_on_success(): + for edge in pruned_edges: + _, created = PGPSignature.objects.get_or_create( + signer=edge[0], signee=edge[1], + created=edge[2], expires=edge[3], + defaults={ 'valid': edge[4] }) + if created: + created_ct += 1 + + logger.info("created %d signatures", created_ct) + +# vim: set ts=4 sw=4 et: diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py index 66df7b97..4dd26091 100644 --- a/devel/management/commands/reporead.py +++ b/devel/management/commands/reporead.py @@ -376,10 +376,9 @@ def db_update(archname, reponame, pkgs, force=False): timestamp = None # for a force, we don't want to update the timestamp. # for a non-force, we don't want to do anything at all. - if pkg_same_version(pkg, dbpkg): - if not force: - continue - else: + if not force and pkg_same_version(pkg, dbpkg): + continue + elif not force: timestamp = datetime.utcnow() # The odd select_for_update song and dance here are to ensure @@ -388,7 +387,7 @@ def db_update(archname, reponame, pkgs, force=False): with transaction.commit_on_success(): # TODO Django 1.4 select_for_update() will work once released dbpkg = select_pkg_for_update(dbpkg) - if pkg_same_version(pkg, dbpkg): + if not force and pkg_same_version(pkg, dbpkg): logger.debug("Package %s was already updated", pkg.name) continue logger.info("Updating package %s", pkg.name) @@ -415,7 +414,7 @@ def filesonly_update(archname, reponame, pkgs, force=False): with transaction.commit_on_success(): if not dbpkg.files_last_update or not dbpkg.last_update: pass - elif dbpkg.files_last_update > dbpkg.last_update: + elif not force and dbpkg.files_last_update > dbpkg.last_update: logger.debug("Files for %s are up to date", pkg.name) continue # TODO Django 1.4 select_for_update() will work once released |