Skip to content
archversion 7.49 KiB
Newer Older
Seblu's avatar
Seblu committed
#!/usr/bin/python3
Seblu's avatar
Seblu committed
# coding: utf-8

# archversion - Archlinux Version Controller
# Copyright © 2012 Sébastien Luttringer
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

'''Archlinux Version Controller'''

Seblu's avatar
Seblu committed
from archversion import VERSION, DEFAULT_CONFIG_FILENAME, DEFAULT_CACHE_FILENAME
Seblu's avatar
Seblu committed
from archversion.config import BaseConfigFile
from archversion.database import JsonDatabase
Seblu's avatar
Seblu committed
from archversion.error import BaseError, MissingConfigFile, NoSuchFile
Seblu's avatar
Seblu committed
from archversion.error import ERR_FATAL, ERR_ABORT, ERR_UNKNOWN
Seblu's avatar
Seblu committed
from archversion.pacman import parse_pkgbuild, pkgbuild_set_version, pkgbuild_update_checksums
from archversion.version import VersionController
Seblu's avatar
Seblu committed
from collections import OrderedDict
import argparse
import logging
Seblu's avatar
Seblu committed
import os
Seblu's avatar
Seblu committed

def parse_argv():
    '''Parse command line arguments'''
    p_main = argparse.ArgumentParser()
    p_main.add_argument("--version", action="version",
                        version="%(prog)s version %s" + VERSION)
Seblu's avatar
Seblu committed
    p_main.add_argument("--debug", action="store_true",
                        help="debug mode")
    p_main.add_argument("-c", "--config", default=None,
                        help="config file path")
    p_main.add_argument("-C", "--cache", default=None,
                        help="cache file path")
    sp_main = p_main.add_subparsers()
    # check parser
Seblu's avatar
Seblu committed
    p_check = sp_main.add_parser("check", aliases=["ck"],
                                 help="check packages versions")
Seblu's avatar
Seblu committed
    p_check.add_argument("-c", "--diff-cache", action="store_true",
                         help="doesn't display cached versions")
    p_check.add_argument("-n", "--diff-new", action="store_true",
                         help="only display new versions")
    p_check.add_argument("-s", "--sort", action="store_true",
                         help="sort packages by name")
    p_check.add_argument("-S", "--no-cache", action="store_true",
                         help="don't save version in cache")
    p_check.add_argument("packages", nargs='*',
                         help="only check this packages")
    p_check.set_defaults(func=command_check)
    # list parser
Seblu's avatar
Seblu committed
    p_list = sp_main.add_parser("list", aliases=["ls"],
                                help="list various informations")
Seblu's avatar
Seblu committed
    p_list.add_argument("-s", "--sort", action="store_true",
                        help="sort listing")
    p_list.add_argument("what", choices=("config", "cache", "modes"),
                        help="config: list configured packages. "
                        "cache: list packages in cache. "
                        "modes: list comparaison modes. ")
    p_list.set_defaults(func=command_list)
Seblu's avatar
Seblu committed
    # update parser
Seblu's avatar
Seblu committed
    p_update = sp_main.add_parser("update", aliases=["up"],
                                  help="update a PKGBUILD with latest version")
Seblu's avatar
Seblu committed
    p_update.add_argument("-p", "--path", default="PKGBUILD",
                          help="name of the file to update. Default PKGBUILD")
    p_update.add_argument("-c", "--checksum", action="store_true",
                          help="run updpkgsums after update")
    p_update.add_argument("-C", "--cache", action="store_true",
                          help="use cache")
    p_update.set_defaults(func=command_update)
    # do parse
    namespace = p_main.parse_args()
    # Ensure subparser was choosen
    if "func" not in namespace:
        p_main.error("missing argument")
    return namespace
Seblu's avatar
Seblu committed

def command_check(args, vctrl):
    '''Handle check command call'''
    # filter packages
    if len(args.packages) > 0:
        for pkg in list(vctrl.packages):
            if pkg not in args.packages:
                vctrl.packages.pop(pkg, None)
    # sort packages if asked
    if args.sort:
        vctrl.packages = OrderedDict(sorted(vctrl.packages.items(),
                                            key=lambda t: t[0]))
    # start checking
    try:
        vctrl.print_versions(args.diff_new, args.diff_cache)
    finally:
        # save version database
        if not args.no_cache:
            vctrl.cache.save(args.cache, DEFAULT_CACHE_FILENAME)

def command_list(args, vctrl):
    '''Handle list command call'''
    # sort if asked
    if args.sort:
        # sort packages
        vctrl.packages = OrderedDict(sorted(vctrl.packages.items(),
                                            key=lambda t: t[0]))
        # sort cache
        vctrl.cache = OrderedDict(sorted(vctrl.cache.items(),
                                         key=lambda t: t[0]))
    # call the right action
    if args.what == "config":
        vctrl.print_names()
    elif args.what == "cache":
        vctrl.print_cache()
    elif args.what == "modes":
        vctrl.print_modes()

Seblu's avatar
Seblu committed
def command_update(args, vctrl):
    '''Handle update command call'''
    if not os.path.exists(args.path):
        raise NoSuchFile(args.path)
    if os.getresuid()[1] == 0:
        logging.warn("Warning: You should not run this as root")
    pkgdict = parse_pkgbuild(args.path)
    pkgname = pkgdict.get("pkgname0", pkgdict.get("pkgbase", None))
Seblu's avatar
Seblu committed
    pkgver = pkgdict.get("pkgver", None)
    # some sanity checks
    if "pkgname" is None:
        raise BaseError("Unable to detect pkgname in %s" % args.path)
    if "pkgver" is None:
        raise BaseError("Unable to detect pkgver in %s" % args.path)
    # get upstream version
    vctrl.packages = [ pkgname ]
    if not args.cache:
        vctrl.check_versions()
    upver = vctrl.cache.get(pkgname, None)
    if upver is None:
        raise BaseError("Unable to detect upstream version of %s" % pkgname)
    # print what we detect
    print("Package name: %s" % pkgname)
    print("PKGBUILD version: %s" % pkgver)
    print("Upstream version: %s" % vctrl.cache[pkgname])
    # compare version
    if pkgver == upver:
        print("Version are the same.")
        return
    # update version with upstream
    pkgbuild_set_version(args.path, upver)
    # update checksum
    if args.checksum:
        pkgbuild_update_checksums(args.path)

Seblu's avatar
Seblu committed
def main():
    '''Program entry point'''
    try:
        # parse command line
        args = parse_argv()
        # set global debug mode
        if args.debug:
            logging.getLogger().setLevel(logging.DEBUG)
        # load configuration
        packages = BaseConfigFile(args.config, DEFAULT_CONFIG_FILENAME)
        # load cache database
        cachedb = JsonDatabase()
        cachedb.load(args.cache, DEFAULT_CACHE_FILENAME)
        # load checking controller
        vctrl = VersionController(packages, cachedb)
        # call command function
        return args.func(args, vctrl)
    except KeyboardInterrupt:
        exit(ERR_ABORT)
    except BaseError as exp:
        logging.error(exp)
Seblu's avatar
Seblu committed
        exit(ERR_FATAL)
    except Exception as exp:
        logging.error("Unknown error. Please report it with --debug.")
        logging.error(exp)
        if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
            raise
Seblu's avatar
Seblu committed
        exit(ERR_UNKNOWN)

if __name__ == '__main__':
    main()

# vim:set ts=4 sw=4 et ai: