chiark / gitweb /
47bf119aa97e97053ca1edd111f3e46fd1b39f1f
[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
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 thisbuild['disable']:
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,
94                                                         extlib_dir, False)
95
96                     # Do the scan...
97                     buildprobs = common.scan_source(build_dir, root_dir, thisbuild)
98                     for problem in buildprobs:
99                         problems.append(problem + ' in ' + app['id']
100                                         + ' ' + thisbuild['version'])
101
102         except BuildException as be:
103             msg = "Could not scan app %s due to BuildException: %s" % (app['id'], be)
104             problems.append(msg)
105         except VCSException as vcse:
106             msg = "VCS error while scanning app %s: %s" % (app['id'], vcse)
107             problems.append(msg)
108         except Exception:
109             msg = "Could not scan app %s due to unknown error: %s" % (app['id'], traceback.format_exc())
110             problems.append(msg)
111
112     logging.info("Finished:")
113     for problem in problems:
114         print problem
115     print str(len(problems)) + ' problems.'
116
117 if __name__ == "__main__":
118     main()