summaryrefslogtreecommitdiffstats
path: root/cnucnu.py
blob: cc99cc8daecf3685bdbb8e21b35f3e7eed9081a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/python -ttu
# vim: fileencoding=utf8 foldmethod=marker
#{{{ License header: GPLv2+
#    This file is part of cnucnu.
#
#    Cnucnu 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.
#
#    Cnucnu 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 cnucnu.  If not, see <http://www.gnu.org/licenses/>.
#}}}

import logging
import sys
import os
import pprint as pprint_module
pp = pprint_module.PrettyPrinter(indent=4)
pprint = pp.pprint

import cnucnu
import cnucnu.errors as cc_errors
from cnucnu.config import global_config
from cnucnu.package_list import Repository, PackageList
from cnucnu.checkshell import CheckShell
from cnucnu.bugzilla_reporter import BugzillaReporter
from cnucnu.scm import SCM


log = logging.getLogger('cnucnu')


class Actions(object):
    def action_report_outdated(self, args):
        """ file bugs for outdated packages """
        br = BugzillaReporter(global_config.bugzilla_config)
        repo = Repository(**global_config.config["repo"])
        scm = SCM(**global_config.config["scm"])

        pl = PackageList(repo=repo, scm=scm, br=br,
                         **global_config.config["package list"])
        package_count = len(pl)
        log.info("Checking '%i' packages", package_count)
        for number, package in enumerate(pl, start=1):
            if package.name >= args.start_with:
                log.info("checking package '%s' (%i/%i)", package.name, number,
                         package_count)
                try:
                    if package.upstream_newer:
                        print "package '%s' outdated (%s < %s)" % (
                            package.name,
                            package.repo_version,
                            package.latest_upstream
                        )
                        bug_url = package.report_outdated(dry_run=args.dry_run)
                        if bug_url:
                            print bug_url
                except cc_errors.UpstreamVersionRetrievalError, e:
                    log.error("Failed to fetch upstream information for "
                              "package '%s' (%s)" % (package.name, e.message))
                except cc_errors.PackageNotFoundError, e:
                    log.error(e)
                except Exception, e:
                    log.exception("Exception occured while processing "
                                  "package '%s':\n%s" % (package.name,
                                                         pp.pformat(e)))
            else:
                log.info("skipping package '%s'", package.name)

    def action_dump_config(self, args):
        """ dump config to stdout """
        sys.stdout.write(global_config.yaml)
        sys.exit(0)

    def action_dump_default_config(self, args):
        """ dump default config to stdout """
        sys.stdout.write(cnucnu.config.Config().yaml)
        sys.exit(0)

    def action_shell(self, args):
        """ run interactive shell """
        shell = CheckShell(config=global_config)
        while True:
            if not shell.cmdloop():
                break

    @property
    def possible(self):
        """ possible actions """
        possible_actions = {}
        for method in dir(self):
            if method.startswith("action_"):
                possible_actions[
                    method[len("action_"):].replace("_", "-")
                ] = getattr(self, method).__doc__
        return possible_actions

    def action(self, action):
        action = action.replace("-", "_")
        return getattr(self, "action_" + action)

    def do(self, action, args):
        return self.action(action)(args)


if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    actions = Actions()

    parser.add_argument("--config", dest="config_filename",
                        help="config_filename, e.g. for bugzilla credentials")
    parser.add_argument("--dry-run", dest="dry_run",
                        help="Do not file or change bugs",
                        default=False, action="store_true")
    parser.add_argument("--loglevel", dest="loglevel",
                        help="Specify loglevel, default: %(default)s",
                        choices=("DEBUG", "INFO", "WARNING", "ERROR",
                                 "CRITICAL"),
                        default="WARNING")
    parser.add_argument("--start-with", dest="start_with",
                        help="Start with this package when reporting bugs",
                        metavar="PACKAGE", default="")

    subparsers = parser.add_subparsers(dest="action",
                                       help='command to perform')
    possible_actions = actions.possible.items()
    possible_actions.sort()
    for action, help_text in possible_actions:
        command_parser = subparsers.add_parser(action, help=help_text)

    args = parser.parse_args()

    logging.basicConfig(level=getattr(logging, args.loglevel.upper()))

    # default to ./cnucnu.yaml if it exists and no config file is specified on
    # the commandline
    yaml_file = args.config_filename
    if not yaml_file:
        new_yaml_file = "./cnucnu.yaml"
        if os.access(new_yaml_file, os.R_OK):
            yaml_file = new_yaml_file

    if yaml_file:
        global_config.update_yaml_file(yaml_file)

    actions.do(args.action, args)