diff --git a/examples/config.py b/examples/config.py index e04f8a93..b651ca7d 100644 --- a/examples/config.py +++ b/examples/config.py @@ -141,6 +141,6 @@ build_server_always = False # Limit in number of characters that fields can take up # Only the fields listed here are supported, defaults shown char_limits = { - 'Summary' : 50, - 'Description' : 1500 + 'Summary': 50, + 'Description': 1500 } diff --git a/fdroid b/fdroid index 91f50644..9a22f571 100755 --- a/fdroid +++ b/fdroid @@ -38,14 +38,16 @@ commands = { "server": "Interact with the repo HTTP server", } + def print_help(): print "usage: fdroid [-h|--help] []" print print "Valid commands are:" - for cmd,summary in commands.items(): + for cmd, summary in commands.items(): print " " + cmd + ' '*(15-len(cmd)) + summary print + def main(): if len(sys.argv) <= 1: @@ -85,4 +87,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/build.py b/fdroidserver/build.py index ccb84605..4c7a5bd8 100644 --- a/fdroidserver/build.py +++ b/fdroidserver/build.py @@ -37,8 +37,9 @@ from common import BuildException, VCSException, FDroidPopen, SilentPopen try: import paramiko -except: - paramiko = None +except ImportError: + pass + def get_builder_vm_id(): vd = os.path.join('builder', '.vagrant') @@ -244,7 +245,9 @@ def release_vm(): def build_server(app, thisbuild, vcs, build_dir, output_dir, force): """Do a build on the build server.""" - if not paramiko: + try: + paramiko + except NameError: raise BuildException("Paramiko is required to use the buildserver") if options.verbose: logging.getLogger("paramiko").setLevel(logging.DEBUG) diff --git a/fdroidserver/checkupdates.py b/fdroidserver/checkupdates.py index d20ebefc..51247e48 100644 --- a/fdroidserver/checkupdates.py +++ b/fdroidserver/checkupdates.py @@ -30,7 +30,8 @@ import HTMLParser from distutils.version import LooseVersion import logging -import common, metadata +import common +import metadata from common import BuildException from common import VCSException from metadata import MetaDataException @@ -79,6 +80,7 @@ def check_http(app): msg = "Could not complete http check for app {0} due to unknown error: {1}".format(app['id'], traceback.format_exc()) return (None, msg) + # Check for a new version by looking at the tags in the source repo. # Whether this can be used reliably or not depends on # the development procedures used by the project's developers. Use it with @@ -157,6 +159,7 @@ def check_tags(app, pattern): msg = "Could not scan app {0} due to unknown error: {1}".format(app['id'], traceback.format_exc()) return (None, msg, None) + # Check for a new version by looking at the AndroidManifest.xml at the HEAD # of the source repo. Whether this can be used reliably or not depends on # the development procedures used by the project's developers. Use it with @@ -212,9 +215,9 @@ def check_repomanifest(app, branch=None): if package != appid: return (None, "Package ID mismatch") if not version: - return (None,"Couldn't find latest version name") + return (None, "Couldn't find latest version name") if not vercode: - return (None,"Couldn't find latest version code") + return (None, "Couldn't find latest version code") vercode = str(int(vercode)) @@ -232,6 +235,7 @@ def check_repomanifest(app, branch=None): msg = "Could not scan app {0} due to unknown error: {1}".format(app['id'], traceback.format_exc()) return (None, msg) + def check_repotrunk(app, branch=None): try: @@ -262,13 +266,14 @@ def check_repotrunk(app, branch=None): msg = "Could not scan app {0} due to unknown error: {1}".format(app['id'], traceback.format_exc()) return (None, msg) + # Check for a new version by looking at the Google Play Store. # Returns (None, "a message") if this didn't work, or (version, None) for # the details of the current version. def check_gplay(app): time.sleep(15) url = 'https://play.google.com/store/apps/details?id=' + app['id'] - headers = {'User-Agent' : 'Mozilla/5.0 (X11; Linux i686; rv:18.0) Gecko/20100101 Firefox/18.0'} + headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux i686; rv:18.0) Gecko/20100101 Firefox/18.0'} req = urllib2.Request(url, None, headers) try: resp = urllib2.urlopen(req, None, 20) @@ -296,6 +301,7 @@ def check_gplay(app): config = None options = None + def main(): global config, options @@ -348,7 +354,6 @@ def main(): common.getappname(app), version)) return - for app in apps: if options.autoonly and app['Auto Update Mode'] in ('None', 'Static'): @@ -515,4 +520,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/common.py b/fdroidserver/common.py index e30d188c..5cea12b3 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -17,7 +17,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import os, sys, re +import os +import sys +import re import shutil import glob import stat @@ -34,6 +36,7 @@ import metadata config = None options = None + def get_default_config(): return { 'sdk_path': os.getenv("ANDROID_HOME"), @@ -50,12 +53,13 @@ def get_default_config(): 'keystore': '$HOME/.local/share/fdroidserver/keystore.jks', 'smartcardoptions': [], 'char_limits': { - 'Summary' : 50, - 'Description' : 1500 + 'Summary': 50, + 'Description': 1500 }, - 'keyaliases': { }, + 'keyaliases': {}, } + def read_config(opts, config_file='config.py'): """Read the repository config @@ -120,8 +124,9 @@ def read_config(opts, config_file='config.py'): return config + def test_sdk_exists(c): - if c['sdk_path'] == None: + if c['sdk_path'] is None: # c['sdk_path'] is set to the value of ANDROID_HOME by default logging.critical('No Android SDK found! ANDROID_HOME is not set and sdk_path is not in config.py!') logging.info('You can use ANDROID_HOME to set the path to your SDK, i.e.:') @@ -138,6 +143,7 @@ def test_sdk_exists(c): return False return True + def write_password_file(pwtype, password=None): ''' writes out passwords to a protected file instead of passing passwords as @@ -145,13 +151,14 @@ def write_password_file(pwtype, password=None): ''' filename = '.fdroid.' + pwtype + '.txt' fd = os.open(filename, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0600) - if password == None: + if password is None: os.write(fd, config[pwtype]) else: os.write(fd, password) os.close(fd) config[pwtype + 'file'] = filename + # Given the arguments in the form of multiple appid:[vc] strings, this returns # a dictionary with the set of vercodes specified for each package. def read_pkg_args(args, allow_vercodes=False): @@ -173,6 +180,7 @@ def read_pkg_args(args, allow_vercodes=False): return vercodes + # On top of what read_pkg_args does, this returns the whole app metadata, but # limiting the builds list to the builds matching the vercodes specified. def read_app_args(args, allapps, allow_vercodes=False): @@ -211,6 +219,7 @@ def read_app_args(args, allapps, allow_vercodes=False): return apps + def has_extension(filename, extension): name, ext = os.path.splitext(filename) ext = ext.lower()[1:] @@ -218,6 +227,7 @@ def has_extension(filename, extension): apk_regex = None + def apknameinfo(filename): global apk_regex filename = os.path.basename(filename) @@ -230,12 +240,15 @@ def apknameinfo(filename): raise Exception("Invalid apk name: %s" % filename) return result + def getapkname(app, build): return "%s_%s.apk" % (app['id'], build['vercode']) + def getsrcname(app, build): return "%s_%s_src.tar.gz" % (app['id'], build['vercode']) + def getappname(app): if app['Name']: return app['Name'] @@ -243,9 +256,11 @@ def getappname(app): return app['Auto Name'] return app['id'] + def getcvname(app): return '%s (%s)' % (app['Current Version'], app['Current Version Code']) + def getvcs(vcstype, remote, local): if vcstype == 'git': return vcs_git(remote, local) @@ -263,12 +278,14 @@ def getvcs(vcstype, remote, local): return getsrclib(remote, 'build/srclib', raw=True) raise VCSException("Invalid vcs type " + vcstype) + def getsrclibvcs(name): srclib_path = os.path.join('srclibs', name + ".txt") if not os.path.exists(srclib_path): raise VCSException("Missing srclib " + name) return metadata.parse_srclib(srclib_path)['Repo Type'] + class vcs: def __init__(self, remote, local): @@ -354,6 +371,7 @@ class vcs: def getsrclib(self): return self.srclib + class vcs_git(vcs): def repotype(self): @@ -527,7 +545,7 @@ class vcs_gitsvn(vcs): svn_rev = rev_split[1] else: - # if no branch is specified, then assume trunk (ie. 'master' + # if no branch is specified, then assume trunk (ie. 'master' # branch): treeish = 'master' svn_rev = rev @@ -562,6 +580,7 @@ class vcs_gitsvn(vcs): return None return p.stdout.strip() + class vcs_svn(vcs): def repotype(self): @@ -604,6 +623,7 @@ class vcs_svn(vcs): return line[18:] return None + class vcs_hg(vcs): def repotype(self): @@ -676,6 +696,7 @@ class vcs_bzr(vcs): return [tag.split(' ')[0].strip() for tag in p.stdout.splitlines()] + def retrieve_string(app_dir, string, xmlfiles=None): res_dirs = [ @@ -686,9 +707,9 @@ def retrieve_string(app_dir, string, xmlfiles=None): if xmlfiles is None: xmlfiles = [] for res_dir in res_dirs: - for r,d,f in os.walk(res_dir): + for r, d, f in os.walk(res_dir): if r.endswith('/values'): - xmlfiles += [os.path.join(r,x) for x in f if x.endswith('.xml')] + xmlfiles += [os.path.join(r, x) for x in f if x.endswith('.xml')] string_search = None if string.startswith('@string/'): @@ -704,15 +725,16 @@ def retrieve_string(app_dir, string, xmlfiles=None): return retrieve_string(app_dir, matches.group(1), xmlfiles) return None - return string.replace("\\'","'") + return string.replace("\\'", "'") + # Return list of existing files that will be used to find the highest vercode def manifest_paths(app_dir, flavour): - possible_manifests = [ os.path.join(app_dir, 'AndroidManifest.xml'), + possible_manifests = [os.path.join(app_dir, 'AndroidManifest.xml'), os.path.join(app_dir, 'src', 'main', 'AndroidManifest.xml'), os.path.join(app_dir, 'src', 'AndroidManifest.xml'), - os.path.join(app_dir, 'build.gradle') ] + os.path.join(app_dir, 'build.gradle')] if flavour: possible_manifests.append( @@ -720,6 +742,7 @@ def manifest_paths(app_dir, flavour): return [path for path in possible_manifests if os.path.isfile(path)] + # Retrieve the package name. Returns the name, or None if not found. def fetch_real_name(app_dir, flavour): app_search = re.compile(r'.* ') - if re.match('^\s*$', s) != None: + if re.match('^\s*$', s) is not None: test_config['sdk_path'] = default_sdk_path else: test_config['sdk_path'] = s @@ -211,7 +213,7 @@ def main(): if options.distinguished_name: keydname = options.distinguished_name write_to_config('keydname', keydname) - if keystore == 'NONE': # we're using a smartcard + if keystore == 'NONE': # we're using a smartcard write_to_config('repo_keyalias', '1') # seems to be the default disable_in_config('keypass', 'never used with smartcard') write_to_config('smartcardoptions', @@ -246,7 +248,7 @@ def main(): password = genpassword() write_to_config('keystorepass', password) write_to_config('keypass', password) - if options.repo_keyalias == None: + if options.repo_keyalias is None: repo_keyalias = socket.getfqdn() write_to_config('repo_keyalias', repo_keyalias) if not options.distinguished_name: @@ -260,7 +262,7 @@ def main(): logging.info(' Android SDK Build Tools:\t' + os.path.dirname(aapt)) logging.info(' Android NDK (optional):\t' + ndk_path) logging.info(' Keystore for signing key:\t' + keystore) - if repo_keyalias != None: + if repo_keyalias is not None: logging.info(' Alias for key in store:\t' + repo_keyalias) logging.info('\nTo complete the setup, add your APKs to "' + os.path.join(fdroiddir, 'repo') + '"' + diff --git a/fdroidserver/install.py b/fdroidserver/install.py index ebdae6b7..840fa295 100644 --- a/fdroidserver/install.py +++ b/fdroidserver/install.py @@ -30,6 +30,7 @@ from common import FDroidPopen options = None config = None + def devices(): p = FDroidPopen(["adb", "devices"]) if p.returncode != 0: @@ -68,7 +69,7 @@ def main(): if args: vercodes = common.read_pkg_args(args, True) - apks = { appid : None for appid in vercodes } + apks = {appid: None for appid in vercodes} # Get the signed apk with the highest vercode for apkfile in sorted(glob.glob(os.path.join(output_dir, '*.apk'))): @@ -86,8 +87,8 @@ def main(): else: - apks = { common.apknameinfo(apkfile)[0] : apkfile for apkfile in - sorted(glob.glob(os.path.join(output_dir, '*.apk'))) } + apks = {common.apknameinfo(apkfile)[0]: apkfile for apkfile in + sorted(glob.glob(os.path.join(output_dir, '*.apk')))} for appid, apk in apks.iteritems(): # Get device list each time to avoid device not found errors @@ -97,8 +98,8 @@ def main(): logging.info("Installing %s..." % apk) for dev in devs: logging.info("Installing %s on %s..." % (apk, dev)) - p = FDroidPopen(["adb", "-s", dev, "install", apk ]) - fail= "" + p = FDroidPopen(["adb", "-s", dev, "install", apk]) + fail = "" for line in p.stdout.splitlines(): if line.startswith("Failure"): fail = line[9:-1] @@ -115,4 +116,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/lint.py b/fdroidserver/lint.py index 5c76cd04..8cc70859 100644 --- a/fdroidserver/lint.py +++ b/fdroidserver/lint.py @@ -20,7 +20,8 @@ from optparse import OptionParser import re import logging -import common, metadata +import common +import metadata config = None options = None @@ -118,6 +119,7 @@ regex_pedantic = { ], } + def main(): global config, options, appid, app_count, warn_count @@ -171,7 +173,7 @@ def main(): lastcommit, app['Update Check Mode'])) # No proper license - if app['License'] in ('Unknown','None',''): + if app['License'] in ('Unknown', 'None', ''): warn("License was not set") # Summary size limit @@ -240,4 +242,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/metadata.py b/fdroidserver/metadata.py index cb034812..cd44cbc1 100644 --- a/fdroidserver/metadata.py +++ b/fdroidserver/metadata.py @@ -17,10 +17,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import os, re, glob +import os +import re +import glob import cgi import logging + class MetaDataException(Exception): def __init__(self, value): self.value = value @@ -120,67 +123,68 @@ class FieldType(): # Generic value types valuetypes = { - 'int' : FieldType("Integer", + 'int': FieldType("Integer", r'^[1-9][0-9]*$', None, - [ 'FlattrID' ], - [ 'vercode' ]), + ['FlattrID'], + ['vercode']), - 'http' : FieldType("HTTP link", + 'http': FieldType("HTTP link", r'^http[s]?://', None, - [ "Web Site", "Source Code", "Issue Tracker", "Donate" ], []), + ["Web Site", "Source Code", "Issue Tracker", "Donate"], []), - 'bitcoin' : FieldType("Bitcoin address", + 'bitcoin': FieldType("Bitcoin address", r'^[a-zA-Z0-9]{27,34}$', None, - [ "Bitcoin" ], - [ ]), + ["Bitcoin"], + []), - 'litecoin' : FieldType("Litecoin address", + 'litecoin': FieldType("Litecoin address", r'^L[a-zA-Z0-9]{33}$', None, - [ "Litecoin" ], - [ ]), + ["Litecoin"], + []), - 'dogecoin' : FieldType("Dogecoin address", + 'dogecoin': FieldType("Dogecoin address", r'^D[a-zA-Z0-9]{33}$', None, - [ "Dogecoin" ], - [ ]), + ["Dogecoin"], + []), - 'Bool' : FieldType("Boolean", + 'Bool': FieldType("Boolean", ['Yes', 'No'], None, - [ "Requires Root" ], - [ ]), + ["Requires Root"], + []), - 'bool' : FieldType("Boolean", + 'bool': FieldType("Boolean", ['yes', 'no'], None, - [ ], - [ 'submodules', 'oldsdkloc', 'forceversion', 'forcevercode', - 'novcheck' ]), + [], + ['submodules', 'oldsdkloc', 'forceversion', 'forcevercode', + 'novcheck']), - 'Repo Type' : FieldType("Repo Type", - [ 'git', 'git-svn', 'svn', 'hg', 'bzr', 'srclib' ], None, - [ "Repo Type" ], - [ ]), + 'Repo Type': FieldType("Repo Type", + ['git', 'git-svn', 'svn', 'hg', 'bzr', 'srclib'], None, + ["Repo Type"], + []), - 'archive' : FieldType("Archive Policy", + 'archive': FieldType("Archive Policy", r'^[0-9]+ versions$', None, - [ "Archive Policy" ], - [ ]), + ["Archive Policy"], + []), - 'antifeatures' : FieldType("Anti-Feature", - [ "Ads", "Tracking", "NonFreeNet", "NonFreeDep", "NonFreeAdd", "UpstreamNonFree" ], ',', - [ "AntiFeatures" ], - [ ]), + 'antifeatures': FieldType("Anti-Feature", + ["Ads", "Tracking", "NonFreeNet", "NonFreeDep", "NonFreeAdd", "UpstreamNonFree"], ',', + ["AntiFeatures"], + []), - 'autoupdatemodes' : FieldType("Auto Update Mode", + 'autoupdatemodes': FieldType("Auto Update Mode", r"^(Version .+|None)$", None, - [ "Auto Update Mode" ], - [ ]), + ["Auto Update Mode"], + []), - 'updatecheckmodes' : FieldType("Update Check Mode", + 'updatecheckmodes': FieldType("Update Check Mode", r"^(Tags|Tags .+|RepoManifest|RepoManifest/.+|RepoTrunk|HTTP|Static|None)$", None, - [ "Update Check Mode" ], - [ ]) + ["Update Check Mode"], + []) } + # Check an app's metadata information for integrity errors def check_metadata(info): for k, t in valuetypes.iteritems(): @@ -198,6 +202,7 @@ def check_metadata(info): elif k == 'bool': build[attr] = False + # Formatter for descriptions. Create an instance, and call parseline() with # each line of the description source from the metadata. At the end, call # end() and then text_plain, text_wiki and text_html will contain the result. @@ -213,8 +218,10 @@ class DescriptionFormatter: text_wiki = '' text_html = '' linkResolver = None + def __init__(self, linkres): self.linkResolver = linkres + def endcur(self, notstates=None): if notstates and self.state in notstates: return @@ -224,13 +231,16 @@ class DescriptionFormatter: self.endul() elif self.state == self.stOL: self.endol() + def endpara(self): self.text_plain += '\n' self.text_html += '

' self.state = self.stNONE + def endul(self): self.text_html += '' self.state = self.stNONE + def endol(self): self.text_html += '' self.state = self.stNONE @@ -262,7 +272,6 @@ class DescriptionFormatter: self.ital = not self.ital txt = txt[2:] - def linkify(self, txt): linkified_plain = '' linkified_html = '' @@ -326,7 +335,7 @@ class DescriptionFormatter: self.text_html += '
    ' self.state = self.stOL self.text_html += '
  1. ' - self.text_plain += '* ' #TODO: lazy - put the numbers in! + self.text_plain += '* ' # TODO: lazy - put the numbers in! self.addtext(line[1:]) self.text_html += '
  2. ' else: @@ -342,6 +351,7 @@ class DescriptionFormatter: def end(self): self.endcur() + # Parse multiple lines of description as written in a metadata file, returning # a single string in plain text format. def description_plain(lines, linkres): @@ -351,6 +361,7 @@ def description_plain(lines, linkres): ps.end() return ps.text_plain + # Parse multiple lines of description as written in a metadata file, returning # a single string in wiki format. Used for the Maintainer Notes field as well, # because it's the same format. @@ -361,15 +372,17 @@ def description_wiki(lines): ps.end() return ps.text_wiki + # Parse multiple lines of description as written in a metadata file, returning # a single string in HTML format. -def description_html(lines,linkres): +def description_html(lines, linkres): ps = DescriptionFormatter(linkres) for line in lines: ps.parseline(line) ps.end() return ps.text_html + def parse_srclib(metafile, **kw): thisinfo = {} @@ -394,7 +407,7 @@ def parse_srclib(metafile, **kw): continue try: - field, value = line.split(':',1) + field, value = line.split(':', 1) except ValueError: raise MetaDataException("Invalid metadata in %s:%d" % (line, n)) @@ -405,6 +418,7 @@ def parse_srclib(metafile, **kw): return thisinfo + # Read all metadata. Returns a list of 'app' objects (which are dictionaries as # returned by the parse_metadata function. def read_metadata(xref=True, package=None, store=True): @@ -437,6 +451,7 @@ def read_metadata(xref=True, package=None, store=True): return apps + # Get the type expected for a given metadata field. def metafieldtype(name): if name in ['Description', 'Maintainer Notes']: @@ -453,6 +468,7 @@ def metafieldtype(name): return 'unknown' return 'string' + def flagtype(name): if name in ['extlibs', 'srclibs', 'patch', 'rm', 'buildjni', 'update', 'scanignore', 'scandelete']: @@ -461,6 +477,7 @@ def flagtype(name): return 'script' return 'string' + # Parse metadata for a single application. # # 'metafile' - the filename to read. The package id for the application comes @@ -507,7 +524,7 @@ def parse_metadata(metafile): t = flagtype(pk) if t == 'list': # Port legacy ';' separators - thisbuild[pk] = [v.strip() for v in pv.replace(';',',').split(',')] + thisbuild[pk] = [v.strip() for v in pv.replace(';', ',').split(',')] elif t == 'string': thisbuild[pk] = pv elif t == 'script': @@ -610,7 +627,7 @@ def parse_metadata(metafile): curcomments.append(line) continue try: - field, value = line.split(':',1) + field, value = line.split(':', 1) except ValueError: raise MetaDataException("Invalid metadata in "+linedesc) if field != field.strip() or value != value.strip(): @@ -633,7 +650,7 @@ def parse_metadata(metafile): elif fieldtype == 'string': thisinfo[field] = value elif fieldtype == 'list': - thisinfo[field] = [v.strip() for v in value.replace(';',',').split(',')] + thisinfo[field] = [v.strip() for v in value.replace(';', ',').split(',')] elif fieldtype == 'build': if value.endswith("\\"): mode = 2 @@ -687,6 +704,7 @@ def parse_metadata(metafile): return thisinfo + # Write a metadata file. # # 'dest' - The path to the output file @@ -753,7 +771,7 @@ def write_metadata(dest, app): mf.write('\n') for build in app['builds']: writecomments('build:' + build['version']) - mf.write("Build:%s,%s\n" % ( build['version'], build['vercode'])) + mf.write("Build:%s,%s\n" % (build['version'], build['vercode'])) def write_builditem(key, value): if key in ['version', 'vercode', 'origlines', 'type']: @@ -786,7 +804,6 @@ def write_metadata(dest, app): mf.write('.\n') mf.write('\n') - if app['Archive Policy']: writefield('Archive Policy') writefield('Auto Update Mode') @@ -804,5 +821,3 @@ def write_metadata(dest, app): mf.write('\n') writecomments(None) mf.close() - - diff --git a/fdroidserver/publish.py b/fdroidserver/publish.py index 8a9c8aeb..863610d4 100644 --- a/fdroidserver/publish.py +++ b/fdroidserver/publish.py @@ -26,12 +26,14 @@ import glob from optparse import OptionParser import logging -import common, metadata +import common +import metadata from common import FDroidPopen, BuildException config = None options = None + def main(): global config, options @@ -128,7 +130,7 @@ def main(): p = FDroidPopen(['keytool', '-list', '-alias', keyalias, '-keystore', config['keystore'], '-storepass:file', config['keystorepassfile']]) - if p.returncode !=0: + if p.returncode != 0: logging.info("Key does not exist - generating...") p = FDroidPopen(['keytool', '-genkey', '-keystore', config['keystore'], '-alias', keyalias, @@ -152,7 +154,7 @@ def main(): raise BuildException("Failed to sign application") # Zipalign it... - p = FDroidPopen([os.path.join(config['sdk_path'],'tools','zipalign'), + p = FDroidPopen([os.path.join(config['sdk_path'], 'tools', 'zipalign'), '-v', '4', apkfile, os.path.join(output_dir, apkfilename)]) if p.returncode != 0: @@ -170,4 +172,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/readmeta.py b/fdroidserver/readmeta.py index e9665130..ff3533a6 100644 --- a/fdroidserver/readmeta.py +++ b/fdroidserver/readmeta.py @@ -17,7 +17,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import os, metadata +import os +import metadata + def main(): @@ -28,4 +30,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/rewritemeta.py b/fdroidserver/rewritemeta.py index 74c185b1..058461b2 100644 --- a/fdroidserver/rewritemeta.py +++ b/fdroidserver/rewritemeta.py @@ -20,11 +20,13 @@ import os from optparse import OptionParser import logging -import common, metadata +import common +import metadata config = None options = None + def main(): global config, options @@ -51,4 +53,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/scanner.py b/fdroidserver/scanner.py index 34293ebb..455691ac 100644 --- a/fdroidserver/scanner.py +++ b/fdroidserver/scanner.py @@ -22,13 +22,15 @@ import traceback from optparse import OptionParser import logging -import common, metadata +import common +import metadata from common import BuildException from common import VCSException config = None options = None + def main(): global config, options @@ -113,4 +115,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/server.py b/fdroidserver/server.py index 0875d8dc..efec939d 100644 --- a/fdroidserver/server.py +++ b/fdroidserver/server.py @@ -28,6 +28,7 @@ import common config = None options = None + def update_awsbucket(repo_section): ''' Upload the contents of the directory `repo_section` (including @@ -91,7 +92,7 @@ def update_awsbucket(repo_section): if upload: if options.verbose: logging.info(' uploading "' + file_to_upload + '"...') - extra = { 'acl': 'public-read' } + extra = {'acl': 'public-read'} if file_to_upload.endswith('.sig'): extra['content_type'] = 'application/pgp-signature' elif file_to_upload.endswith('.asc'): @@ -113,6 +114,7 @@ def update_awsbucket(repo_section): else: logging.info(' skipping ' + s3url) + def update_serverwebroot(repo_section): rsyncargs = ['rsync', '-u', '-r', '--delete'] if options.verbose: @@ -133,6 +135,7 @@ def update_serverwebroot(repo_section): [indexjar, config['serverwebroot'] + repo_section]) != 0: sys.exit(1) + def main(): global config, options @@ -154,7 +157,7 @@ def main(): logging.critical("The only commands currently supported are 'init' and 'update'") sys.exit(1) - if config.get('nonstandardwebroot') == True: + if config.get('nonstandardwebroot') is True: standardwebroot = False else: standardwebroot = True diff --git a/fdroidserver/update.py b/fdroidserver/update.py index d2b02b7b..cf90c61e 100644 --- a/fdroidserver/update.py +++ b/fdroidserver/update.py @@ -32,29 +32,36 @@ import time from PIL import Image import logging -import common, metadata +import common +import metadata from common import FDroidPopen from metadata import MetaDataException + def get_densities(): return ['640', '480', '320', '240', '160', '120'] + def dpi_to_px(density): return (int(density) * 48) / 160 + def px_to_dpi(px): return (int(px) * 160) / 48 + def get_icon_dir(repodir, density): if density is None: return os.path.join(repodir, "icons") return os.path.join(repodir, "icons-%s" % density) + def get_icon_dirs(repodir): for density in get_densities(): yield get_icon_dir(repodir, density) yield os.path.join(repodir, "icons") + def update_wiki(apps, apks): """Update the wiki @@ -77,7 +84,7 @@ def update_wiki(apps, apks): if app['AntiFeatures']: for af in app['AntiFeatures'].split(','): wikidata += '{{AntiFeature|' + af + '}}\n' - wikidata += '{{App|id=%s|name=%s|added=%s|lastupdated=%s|source=%s|tracker=%s|web=%s|donate=%s|flattr=%s|bitcoin=%s|litecoin=%s|dogecoin=%s|license=%s|root=%s}}\n'%( + wikidata += '{{App|id=%s|name=%s|added=%s|lastupdated=%s|source=%s|tracker=%s|web=%s|donate=%s|flattr=%s|bitcoin=%s|litecoin=%s|dogecoin=%s|license=%s|root=%s}}\n' % ( app['id'], app['Name'], time.strftime('%Y-%m-%d', app['added']) if 'added' in app else '', @@ -256,6 +263,7 @@ def update_wiki(apps, apks): # Purge server cache to ensure counts are up to date site.pages['Repository Maintenance'].purge() + def delete_disabled_builds(apps, apkcache, repodirs): """Delete disabled build outputs. @@ -277,6 +285,7 @@ def delete_disabled_builds(apps, apkcache, repodirs): if apkfilename in apkcache: del apkcache[apkfilename] + def resize_icon(iconpath, density): if not os.path.isfile(iconpath): @@ -296,9 +305,10 @@ def resize_icon(iconpath, density): else: logging.info("%s is small enough: %s" % im.size) - except Exception,e: + except Exception, e: logging.error("Failed resizing {0} - {1}".format(iconpath, e)) + def resize_all_icons(repodirs): """Resize all icons that exceed the max size @@ -311,6 +321,7 @@ def resize_all_icons(repodirs): for iconpath in glob.glob(icon_glob): resize_icon(iconpath, density) + def scan_apks(apps, apkcache, repodir, knownapks): """Scan the apks in the given repo directory. @@ -476,7 +487,7 @@ def scan_apks(apps, apkcache, repodir, knownapks): iconfile = open(icondest, 'wb') iconfile.write(apk.read(iconsrc)) iconfile.close() - thisinfo['icons'][density] = iconfilename + thisinfo['icons'][density] = iconfilename except: logging.warn("Error retrieving icon file") @@ -503,7 +514,7 @@ def scan_apks(apps, apkcache, repodir, knownapks): os.path.join(get_icon_dir(repodir, density), iconfilename)) empty_densities.remove(density) break - except Exception,e: + except Exception, e: logging.warn("Failed reading {0} - {1}".format(iconpath, e)) if thisinfo['icons']: @@ -581,6 +592,7 @@ def scan_apks(apps, apkcache, repodir, knownapks): repo_pubkey_fingerprint = None + def make_index(apps, apks, repodir, archive, categories): """Make a repo index. @@ -598,6 +610,7 @@ def make_index(apps, apks, repodir, archive, categories): el = doc.createElement(name) el.appendChild(doc.createTextNode(value)) parent.appendChild(el) + def addElementCDATA(name, value, doc, parent): el = doc.createElement(name) el.appendChild(doc.createCDATASection(value)) @@ -684,6 +697,7 @@ def make_index(apps, apks, repodir, archive, categories): addElement('summary', app['Summary'], doc, apel) if app['icon']: addElement('icon', app['icon'], doc, apel) + def linkres(link): for app in apps: if app['id'] == link: @@ -813,7 +827,7 @@ def make_index(apps, apks, repodir, archive, categories): sys.exit(1) # Copy the repo icon into the repo directory... - icon_dir = os.path.join(repodir ,'icons') + icon_dir = os.path.join(repodir, 'icons') iconfilename = os.path.join(icon_dir, os.path.basename(config['repo_icon'])) shutil.copyfile(config['repo_icon'], iconfilename) @@ -826,7 +840,6 @@ def make_index(apps, apks, repodir, archive, categories): f.close() - def archive_old_apks(apps, apks, archapks, repodir, archivedir, defaultkeepversions): for app in apps: @@ -860,6 +873,7 @@ def archive_old_apks(apps, apks, archapks, repodir, archivedir, defaultkeepversi config = None options = None + def main(): global config, options @@ -879,7 +893,7 @@ def main(): parser.add_option("-I", "--icons", action="store_true", default=False, help="Resize all the icons exceeding the max pixel size and exit") parser.add_option("-e", "--editor", default="/etc/alternatives/editor", - help="Specify editor to use in interactive mode. Default "+ + help="Specify editor to use in interactive mode. Default " + "is /etc/alternatives/editor") parser.add_option("-w", "--wiki", default=False, action="store_true", help="Update the wiki") @@ -1055,4 +1069,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fdroidserver/verify.py b/fdroidserver/verify.py index 1ef05af5..3f7d2615 100644 --- a/fdroidserver/verify.py +++ b/fdroidserver/verify.py @@ -31,6 +31,7 @@ from common import FDroidPopen options = None config = None + def main(): global options, config @@ -116,5 +117,3 @@ def main(): if __name__ == "__main__": main() - -