chiark / gitweb /
Centralise management of srclib metadata
[fdroidserver.git] / fdroidserver / scanner.py
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
3 #
4 # scanner.py - part of the FDroid server tools
5 # Copyright (C) 2010-13, Ciaran Gultnieks, ciaran@ciarang.com
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Affero General Public License for more details.
16 #
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 import os
21 import traceback
22 from optparse import OptionParser
23 import logging
24
25 import common
26 import metadata
27 from common import BuildException
28 from common import VCSException
29
30 config = None
31 options = None
32
33
34 def main():
35
36     global config, options
37
38     # Parse command line...
39     parser = OptionParser(usage="Usage: %prog [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
40     parser.add_option("-v", "--verbose", action="store_true", default=False,
41                       help="Spew out even more information than normal")
42     parser.add_option("-q", "--quiet", action="store_true", default=False,
43                       help="Restrict output to warnings and errors")
44     parser.add_option("--nosvn", action="store_true", default=False,
45                       help="Skip svn repositories - for test purposes, because they are too slow.")
46     (options, args) = parser.parse_args()
47
48     config = common.read_config(options)
49
50     # Read all app and srclib metadata
51     allapps = metadata.read_metadata()
52     apps = common.read_app_args(args, allapps, True)
53     metadata.read_srclibs()
54
55     problems = []
56
57     build_dir = 'build'
58     if not os.path.isdir(build_dir):
59         logging.info("Creating build directory")
60         os.makedirs(build_dir)
61     srclib_dir = os.path.join(build_dir, 'srclib')
62     extlib_dir = os.path.join(build_dir, 'extlib')
63
64     for app in apps:
65
66         if app['Disabled']:
67             logging.info("Skipping %s: disabled" % app['id'])
68             continue
69         if not app['builds']:
70             logging.info("Skipping %s: no builds specified" % app['id'])
71             continue
72         elif options.nosvn and app['Repo Type'] == 'svn':
73             continue
74
75         logging.info("Processing " + app['id'])
76
77         try:
78
79             build_dir = 'build/' + app['id']
80
81             # Set up vcs interface and make sure we have the latest code...
82             vcs = common.getvcs(app['Repo Type'], app['Repo'], build_dir)
83
84             for thisbuild in app['builds']:
85
86                 if 'disable' in thisbuild:
87                     logging.info("...skipping version %s - %s" % (
88                         thisbuild['version'], thisbuild.get('disable', thisbuild['commit'][1:])))
89                 else:
90                     logging.info("...scanning version " + thisbuild['version'])
91
92                     # Prepare the source code...
93                     root_dir, _ = common.prepare_source(vcs, app, thisbuild,
94                                                         build_dir, srclib_dir,
95                                                         extlib_dir, False)
96
97                     # Do the scan...
98                     buildprobs = common.scan_source(build_dir, root_dir, thisbuild)
99                     for problem in buildprobs:
100                         problems.append(problem + ' in ' + app['id']
101                                         + ' ' + thisbuild['version'])
102
103         except BuildException as be:
104             msg = "Could not scan app %s due to BuildException: %s" % (app['id'], be)
105             problems.append(msg)
106         except VCSException as vcse:
107             msg = "VCS error while scanning app %s: %s" % (app['id'], vcse)
108             problems.append(msg)
109         except Exception:
110             msg = "Could not scan app %s due to unknown error: %s" % (app['id'], traceback.format_exc())
111             problems.append(msg)
112
113     logging.info("Finished:")
114     for problem in problems:
115         print problem
116     print str(len(problems)) + ' problems.'
117
118 if __name__ == "__main__":
119     main()