chiark / gitweb /
Merge branch 'master' into 'master'
[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     # Get all apps...
51     allapps = metadata.read_metadata()
52     apps = common.read_app_args(args, allapps, True)
53
54     problems = []
55
56     build_dir = 'build'
57     if not os.path.isdir(build_dir):
58         logging.info("Creating build directory")
59         os.makedirs(build_dir)
60     srclib_dir = os.path.join(build_dir, 'srclib')
61     extlib_dir = os.path.join(build_dir, 'extlib')
62
63     for app in apps:
64
65         if app['Disabled']:
66             logging.info("Skipping %s: disabled" % app['id'])
67             continue
68         if not app['builds']:
69             logging.info("Skipping %s: no builds specified" % app['id'])
70             continue
71         elif options.nosvn and app['Repo Type'] == 'svn':
72             continue
73
74         logging.info("Processing " + app['id'])
75
76         try:
77
78             build_dir = 'build/' + app['id']
79
80             # Set up vcs interface and make sure we have the latest code...
81             vcs = common.getvcs(app['Repo Type'], app['Repo'], build_dir)
82
83             for thisbuild in app['builds']:
84
85                 if 'disable' in thisbuild:
86                     logging.info("...skipping version %s - %s" % (
87                         thisbuild['version'], thisbuild.get('disable', thisbuild['commit'][1:])))
88                 else:
89                     logging.info("...scanning version " + thisbuild['version'])
90
91                     # Prepare the source code...
92                     root_dir, _ = common.prepare_source(vcs, app, thisbuild,
93                             build_dir, srclib_dir, extlib_dir, False)
94
95                     # Do the scan...
96                     buildprobs = common.scan_source(build_dir, root_dir, thisbuild)
97                     for problem in buildprobs:
98                         problems.append(problem +
99                             ' in ' + app['id'] + ' ' + thisbuild['version'])
100
101         except BuildException as be:
102             msg = "Could not scan app %s due to BuildException: %s" % (app['id'], be)
103             problems.append(msg)
104         except VCSException as vcse:
105             msg = "VCS error while scanning app %s: %s" % (app['id'], vcse)
106             problems.append(msg)
107         except Exception:
108             msg = "Could not scan app %s due to unknown error: %s" % (app['id'], traceback.format_exc())
109             problems.append(msg)
110
111     logging.info("Finished:")
112     for problem in problems:
113         print problem
114     print str(len(problems)) + ' problems.'
115
116 if __name__ == "__main__":
117     main()