From 871c8b7197884d08962e1d328be13b3e88b177f7 Mon Sep 17 00:00:00 2001 From: Ciaran Gultnieks Date: Thu, 11 Nov 2010 22:34:39 +0000 Subject: [PATCH] Now building multiple versions of apks from specified commits --- build.py | 161 +++++++++-------------- metadata.py | 106 +++++++++++++++ metadata/com.eleybourn.bookcatalogue.txt | 2 + metadata/org.fdroid.fdroid.txt | 3 + update.py | 67 +--------- 5 files changed, 177 insertions(+), 162 deletions(-) create mode 100644 metadata.py diff --git a/build.py b/build.py index 40a8fc7a..d89ed1f6 100644 --- a/build.py +++ b/build.py @@ -30,6 +30,8 @@ from optparse import OptionParser #Read configuration... execfile('config.py') +execfile('metadata.py') + # Parse command line... parser = OptionParser() parser.add_option("-v", "--verbose", action="store_true", default=False, @@ -37,79 +39,7 @@ parser.add_option("-v", "--verbose", action="store_true", default=False, (options, args) = parser.parse_args() # Get all apps... -apps = [] - -for metafile in glob.glob(os.path.join('metadata','*.txt')): - - thisinfo = {} - - # Get metadata... - thisinfo['id'] = metafile[9:-4] - print "Reading metadata for " + thisinfo['id'] - thisinfo['description'] = '' - thisinfo['summary'] = '' - thisinfo['license'] = 'Unknown' - thisinfo['web'] = '' - thisinfo['source'] = '' - thisinfo['tracker'] = '' - thisinfo['disabled'] = None - thisinfo['marketversion'] = '' - thisinfo['marketvercode'] = '0' - thisinfo['repotype'] = '' - thisinfo['repo'] = '' - f = open(metafile, 'r') - mode = 0 - for line in f.readlines(): - line = line.rstrip('\r\n') - if len(line) == 0: - pass - elif mode == 0: - index = line.find(':') - if index == -1: - print "Invalid metadata in " + metafile + " at:" + line - sys.exit(1) - field = line[:index] - value = line[index+1:] - if field == 'Description': - mode = 1 - elif field == 'Summary': - thisinfo['summary'] = value - elif field == 'Source Code': - thisinfo['source'] = value - elif field == 'License': - thisinfo['license'] = value - elif field == 'Web Site': - thisinfo['web'] = value - elif field == 'Issue Tracker': - thisinfo['tracker'] = value - elif field == 'Disabled': - thisinfo['disabled'] = value - elif field == 'Market Version': - thisinfo['marketversion'] = value - elif field == 'Market Version Code': - thisinfo['marketvercode'] = value - elif field == 'Repo Type': - thisinfo['repotype'] = value - elif field == 'Repo': - thisinfo['repo'] = value - else: - print "Unrecognised field " + field - sys.exit(1) - elif mode == 1: - if line == '.': - mode = 0 - else: - if len(line) == 0: - thisinfo['description'] += '\n\n' - else: - if (not thisinfo['description'].endswith('\n') and - len(thisinfo['description']) > 0): - thisinfo['description'] += ' ' - thisinfo['description'] += line - if len(thisinfo['description']) == 0: - thisinfo['description'] = 'No description available' - - apps.append(thisinfo) +apps = read_metadata() unsigned_dir = 'unsigned' if os.path.exists(unsigned_dir): @@ -137,35 +67,70 @@ for app in apps: print "Invalid repo type " + app['repotype'] + " in " + app['id'] sys.exit(1) - # Generate (or update) the ant build file, build.xml... - if subprocess.call(['android','update','project','-p','.'], - cwd=build_dir) != 0: - print "Failed to update project" - sys.exit(1) + for thisbuild in app['builds']: - # If the app has ant set up to sign the release, we need to switch - # that off, because we want the unsigned apk... - if os.path.exists(os.path.join(build_dir, 'build.properties')): - if subprocess.call(['sed','-i','s/^key.store/#/', - 'build.properties'], cwd=build_dir) !=0: - print "Failed to amend build.properties" + print "Building version " + thisbuild['version'] + + if app['repotype'] == 'git': + if subprocess.call(['git','checkout',thisbuild['commit']], + cwd=build_dir) != 0: + print "Git checkout failed" + sys.exit(1) + else: + print "Invalid repo type " + app['repotype'] sys.exit(1) - # Build the release... - p = subprocess.Popen(['ant','release'], cwd=build_dir, - stdout=subprocess.PIPE) - output = p.communicate()[0] - print output - if p.returncode != 0: - print "Build failed" - sys.exit(1) + # Generate (or update) the ant build file, build.xml... + if subprocess.call(['android','update','project','-p','.'], + cwd=build_dir) != 0: + print "Failed to update project" + sys.exit(1) - # Find the apk name in the output... - src = re.match(r".*^.*Creating (\S+) for release.*$.*", output, - re.S|re.M).group(1) - dest = os.path.join(unsigned_dir, app['id'] + '.apk') - shutil.copyfile(os.path.join( os.path.join(build_dir, 'bin'), - src), dest) + # If the app has ant set up to sign the release, we need to switch + # that off, because we want the unsigned apk... + if os.path.exists(os.path.join(build_dir, 'build.properties')): + if subprocess.call(['sed','-i','s/^key.store/#/', + 'build.properties'], cwd=build_dir) !=0: + print "Failed to amend build.properties" + sys.exit(1) + + # Build the release... + p = subprocess.Popen(['ant','release'], cwd=build_dir, + stdout=subprocess.PIPE) + output = p.communicate()[0] + print output + if p.returncode != 0: + print "Build failed" + sys.exit(1) + + # Find the apk name in the output... + src = re.match(r".*^.*Creating (\S+) for release.*$.*", output, + re.S|re.M).group(1) + src = os.path.join(os.path.join(build_dir, 'bin'), src) + + # By way of a sanity check, make sure the version and version + # code in our new apk match what we expect... + p = subprocess.Popen([aapt_path,'dump','badging', + src], stdout=subprocess.PIPE) + output = p.communicate()[0] + vercode = None + version = None + for line in output.splitlines(): + if line.startswith("package:"): + pat = re.compile(".*versionCode='([0-9]*)'.*") + vercode = re.match(pat, line).group(1) + pat = re.compile(".*versionName='([^']*)'.*") + version = re.match(pat, line).group(1) + if (version != thisbuild['version'] or + vercode != thisbuild['vercode']): + print "Unexpected version/version code in output" + sys.exit(1) + + # Copy the unsigned apk to our 'unsigned' directory to be + # dealt with later... + dest = os.path.join(unsigned_dir, app['id'] + '_' + + thisbuild['vercode'] + '.apk') + shutil.copyfile(src, dest) print "Finished." diff --git a/metadata.py b/metadata.py new file mode 100644 index 00000000..e7ebf41f --- /dev/null +++ b/metadata.py @@ -0,0 +1,106 @@ +# -*- coding: UTF-8 -*- +# +# metadata.py - part of the FDroid server tools +# Copyright (C) 2010, Ciaran Gultnieks, ciaran@ciarang.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +def read_metadata(): + + apps = [] + + for metafile in glob.glob(os.path.join('metadata','*.txt')): + + thisinfo = {} + + # Get metadata... + thisinfo['id'] = metafile[9:-4] + print "Reading metadata for " + thisinfo['id'] + thisinfo['description'] = '' + thisinfo['summary'] = '' + thisinfo['license'] = 'Unknown' + thisinfo['web'] = '' + thisinfo['source'] = '' + thisinfo['tracker'] = '' + thisinfo['disabled'] = None + thisinfo['marketversion'] = '' + thisinfo['marketvercode'] = '0' + thisinfo['repotype'] = '' + thisinfo['repo'] = '' + thisinfo['builds'] = [] + f = open(metafile, 'r') + mode = 0 + for line in f.readlines(): + line = line.rstrip('\r\n') + if len(line) == 0: + pass + elif mode == 0: + index = line.find(':') + if index == -1: + print "Invalid metadata in " + metafile + " at:" + line + sys.exit(1) + field = line[:index] + value = line[index+1:] + if field == 'Description': + mode = 1 + elif field == 'Summary': + thisinfo['summary'] = value + elif field == 'Source Code': + thisinfo['source'] = value + elif field == 'License': + thisinfo['license'] = value + elif field == 'Web Site': + thisinfo['web'] = value + elif field == 'Issue Tracker': + thisinfo['tracker'] = value + elif field == 'Disabled': + thisinfo['disabled'] = value + elif field == 'Market Version': + thisinfo['marketversion'] = value + elif field == 'Market Version Code': + thisinfo['marketvercode'] = value + elif field == 'Repo Type': + thisinfo['repotype'] = value + elif field == 'Repo': + thisinfo['repo'] = value + elif field == 'Build Version': + parts = value.split(",") + if len(parts) != 3: + print "Invalid build format: " + value + sys.exit(1) + thisbuild = {} + thisbuild['version'] = parts[0] + thisbuild['vercode'] = parts[1] + thisbuild['commit'] = parts[2] + thisinfo['builds'].append(thisbuild) + else: + print "Unrecognised field " + field + sys.exit(1) + elif mode == 1: + if line == '.': + mode = 0 + else: + if len(line) == 0: + thisinfo['description'] += '\n\n' + else: + if (not thisinfo['description'].endswith('\n') and + len(thisinfo['description']) > 0): + thisinfo['description'] += ' ' + thisinfo['description'] += line + if len(thisinfo['description']) == 0: + thisinfo['description'] = 'No description available' + + apps.append(thisinfo) + + return apps diff --git a/metadata/com.eleybourn.bookcatalogue.txt b/metadata/com.eleybourn.bookcatalogue.txt index da1595a7..af503a08 100644 --- a/metadata/com.eleybourn.bookcatalogue.txt +++ b/metadata/com.eleybourn.bookcatalogue.txt @@ -11,3 +11,5 @@ Market Version:3.0.1 Market Version Code:37 Repo Type:git Repo:git://github.com/eleybourn/Book-Catalogue.git +Build Version:3.0.1,36,b876c6df82c7e195ec5d +Build Version:3.0,35,448858bad8b397974db7 diff --git a/metadata/org.fdroid.fdroid.txt b/metadata/org.fdroid.fdroid.txt index c3798041..90727154 100644 --- a/metadata/org.fdroid.fdroid.txt +++ b/metadata/org.fdroid.fdroid.txt @@ -9,3 +9,6 @@ it is? . Repo Type:git Repo:git://gitorious.org/f-droid/fdroidclient.git +Build Version:0.12,3,651696a49be2cd7db5ce6a2fa8185e31f9a20035 +Build Version:0.13,4,4f677285cc2cf0b7e7feb5c9acf61791bec15fbc + diff --git a/update.py b/update.py index af43b9cc..851c102c 100644 --- a/update.py +++ b/update.py @@ -30,6 +30,8 @@ from optparse import OptionParser #Read configuration... execfile('config.py') +execfile('metadata.py') + # Parse command line... parser = OptionParser() parser.add_option("-c", "--createmeta", action="store_true", default=False, @@ -126,70 +128,7 @@ for apkfile in glob.glob(os.path.join('repo','*.apk')): apks.append(thisinfo) # Get all apps... -apps = [] - -for metafile in glob.glob(os.path.join('metadata','*.txt')): - - thisinfo = {} - - # Get metadata... - thisinfo['id'] = metafile[9:-4] - print "Reading metadata for " + thisinfo['id'] - thisinfo['description'] = '' - thisinfo['summary'] = '' - thisinfo['license'] = 'Unknown' - thisinfo['web'] = '' - thisinfo['source'] = '' - thisinfo['tracker'] = '' - thisinfo['disabled'] = None - thisinfo['marketversion'] = '' - thisinfo['marketvercode'] = '0' - f = open(metafile, 'r') - mode = 0 - for line in f.readlines(): - line = line.rstrip('\r\n') - if len(line) == 0: - pass - elif mode == 0: - index = line.find(':') - if index == -1: - print "Invalid metadata in " + metafile + " at:" + line - sys.exit(1) - field = line[:index] - value = line[index+1:] - if field == 'Description': - mode = 1 - elif field == 'Summary': - thisinfo['summary'] = value - elif field == 'Source Code': - thisinfo['source'] = value - elif field == 'License': - thisinfo['license'] = value - elif field == 'Web Site': - thisinfo['web'] = value - elif field == 'Issue Tracker': - thisinfo['tracker'] = value - elif field == 'Disabled': - thisinfo['disabled'] = value - elif field == 'Market Version': - thisinfo['marketversion'] = value - elif field == 'Market Version Code': - thisinfo['marketvercode'] = value - elif mode == 1: - if line == '.': - mode = 0 - else: - if len(line) == 0: - thisinfo['description'] += '\n\n' - else: - if (not thisinfo['description'].endswith('\n') and - len(thisinfo['description']) > 0): - thisinfo['description'] += ' ' - thisinfo['description'] += line - if len(thisinfo['description']) == 0: - thisinfo['description'] = 'No description available' - - apps.append(thisinfo) +apps = read_metadata() # Some information from the apks needs to be applied up to the application # level. When doing this, we use the info from the most recent version's apk.