chiark / gitweb /
fix PEP8 "W391 blank line at end of file"
[fdroidserver.git] / fdroidserver / verify.py
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
3 #
4 # verify.py - part of the FDroid server tools
5 # Copyright (C) 2013, 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 sys
21 import os
22 import shutil
23 import subprocess
24 import glob
25 from optparse import OptionParser
26 import logging
27
28 import common
29 from common import FDroidPopen
30
31 options = None
32 config = None
33
34
35 def main():
36
37     global options, config
38
39     # Parse command line...
40     parser = OptionParser(usage="Usage: %prog [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
41     parser.add_option("-v", "--verbose", action="store_true", default=False,
42                       help="Spew out even more information than normal")
43     parser.add_option("-q", "--quiet", action="store_true", default=False,
44                       help="Restrict output to warnings and errors")
45     (options, args) = parser.parse_args()
46
47     config = common.read_config(options)
48
49     tmp_dir = 'tmp'
50     if not os.path.isdir(tmp_dir):
51         logging.info("Creating temporary directory")
52         os.makedirs(tmp_dir)
53
54     unsigned_dir = 'unsigned'
55     if not os.path.isdir(unsigned_dir):
56         logging.error("No unsigned directory - nothing to do")
57         sys.exit(0)
58
59     verified = 0
60     notverified = 0
61
62     vercodes = common.read_pkg_args(args, True)
63
64     for apkfile in sorted(glob.glob(os.path.join(unsigned_dir, '*.apk'))):
65
66         apkfilename = os.path.basename(apkfile)
67         appid, vercode = common.apknameinfo(apkfile)
68
69         if vercodes and appid not in vercodes:
70             continue
71         if vercodes[appid] and vercode not in vercodes[appid]:
72             continue
73
74         try:
75
76             logging.info("Processing " + apkfilename)
77
78             remoteapk = os.path.join(tmp_dir, apkfilename)
79             if os.path.exists(remoteapk):
80                 os.remove(remoteapk)
81             url = 'https://f-droid.org/repo/' + apkfilename
82             logging.info("...retrieving " + url)
83             p = FDroidPopen(['wget', url], cwd=tmp_dir)
84             if p.returncode != 0:
85                 raise Exception("Failed to get " + apkfilename)
86
87             thisdir = os.path.join(tmp_dir, 'this_apk')
88             thatdir = os.path.join(tmp_dir, 'that_apk')
89             for d in [thisdir, thatdir]:
90                 if os.path.exists(d):
91                     shutil.rmtree(d)
92                 os.mkdir(d)
93
94             if subprocess.call(['jar', 'xf',
95                 os.path.join("..", "..", unsigned_dir, apkfilename)],
96                 cwd=thisdir) != 0:
97                 raise Exception("Failed to unpack local build of " + apkfilename)
98             if subprocess.call(['jar', 'xf', os.path.join("..", "..", remoteapk)],
99                 cwd=thatdir) != 0:
100                 raise Exception("Failed to unpack remote build of " + apkfilename)
101
102             p = FDroidPopen(['diff', '-r', 'this_apk', 'that_apk'], cwd=tmp_dir)
103             lines = p.stdout.splitlines()
104             if len(lines) != 1 or 'META-INF' not in lines[0]:
105                 raise Exception("Unexpected diff output - " + p.stdout)
106
107             logging.info("...successfully verified")
108             verified += 1
109
110         except Exception, e:
111             logging.info("...NOT verified - {0}".format(e))
112             notverified += 1
113
114     logging.info("Finished")
115     logging.info("{0} successfully verified".format(verified))
116     logging.info("{0} NOT verified".format(notverified))
117
118 if __name__ == "__main__":
119     main()