# -*- coding: utf-8 -*-
#
# common.py - part of the FDroid server tools
# Copyright (C) 2010-13, 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
'
self.state = self.stPARA
elif self.state == self.stPARA:
self.text_html += ' '
self.text_plain += ' '
self.addtext(line)
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):
ps = DescriptionFormatter(linkres)
for line in lines:
ps.parseline(line)
ps.end()
return ps.text_plain
# Parse multiple lines of description as written in a metadata file, returning
# a single string in wiki format.
def description_wiki(lines):
ps = DescriptionFormatter(None)
for line in lines:
ps.parseline(line)
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):
ps = DescriptionFormatter(linkres)
for line in lines:
ps.parseline(line)
ps.end()
return ps.text_html
# Extract some information from the AndroidManifest.xml at the given path.
# Returns (version, vercode, package), any or all of which might be None.
# All values returned are strings.
def parse_androidmanifest(manifest):
vcsearch = re.compile(r'.*android:versionCode="([^"]+)".*').search
vnsearch = re.compile(r'.*android:versionName="([^"]+)".*').search
psearch = re.compile(r'.*package="([^"]+)".*').search
version = None
vercode = None
package = None
for line in file(manifest):
if not package:
matches = psearch(line)
if matches:
package = matches.group(1)
if not version:
matches = vnsearch(line)
if matches:
version = matches.group(1)
if not vercode:
matches = vcsearch(line)
if matches:
vercode = matches.group(1)
return (version, vercode, package)
class BuildException(Exception):
def __init__(self, value, stdout = None, stderr = None):
self.value = value
self.stdout = stdout
self.stderr = stderr
def __str__(self):
ret = repr(self.value)
if self.stdout:
ret = ret + "\n==== stdout begin ====\n" + str(self.stdout) + "\n==== stdout end ===="
if self.stderr:
ret = ret + "\n==== stderr begin ====\n" + str(self.stderr) + "\n==== stderr end ===="
return ret
class VCSException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class MetaDataException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
# Get the specified source library.
# Returns the path to it. Normally this is the path to be used when referencing
# it, which may be a subdirectory of the actual project. If you want the base
# directory of the project, pass 'basepath=True'.
# TODO: These are currently just hard-coded in this method. It will be a
# metadata-driven system eventually, but not yet.
def getsrclib(spec, extlib_dir, sdk_path, basepath=False):
name, ref = spec.split('@')
if name == 'GreenDroid':
sdir = os.path.join(extlib_dir, 'GreenDroid')
vcs = getvcs('git',
'https://github.com/cyrilmottier/GreenDroid.git', sdir, sdk_path)
vcs.gotorevision(ref)
return os.path.join(sdir, 'GreenDroid')
if name == 'Dropbear':
sdir = os.path.join(extlib_dir, 'Dropbear')
vcs = getvcs('git',
'https://github.com/CyanogenMod/android_external_dropbear.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'ActionBarSherlock':
sdir = os.path.join(extlib_dir, 'ActionBarSherlock')
vcs = getvcs('git',
'https://github.com/JakeWharton/ActionBarSherlock.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
# For latest ABS releases
if not os.path.exists(libdir):
libdir = os.path.join(sdir, 'actionbarsherlock')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating ActionBarSherlock project')
if basepath:
return sdir
return libdir
if name == 'Google-Gson':
sdir = os.path.join(extlib_dir, 'Google-Gson')
vcs = getvcs('git-svn',
'http://google-gson.googlecode.com/svn/trunk', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'gson')
return libdir
if name == 'libsuperuser':
sdir = os.path.join(extlib_dir, 'libsuperuser')
vcs = getvcs('git',
'https://github.com/Chainfire/libsuperuser', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'libsuperuser')
if basepath:
return sdir
return libdir
if name == 'AndroidUtils':
sdir = os.path.join(extlib_dir, 'AndroidUtils')
vcs = getvcs('git',
'https://github.com/yuriykulikov/AndroidUtils', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'Amazing-ListView':
sdir = os.path.join(extlib_dir, 'Amazing-ListView')
vcs = getvcs('git-svn',
'http://android-amazing-listview.googlecode.com/svn/trunk', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'AmazingListView')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating Amazing-ListView project')
if basepath:
return sdir
return libdir
if name == 'ViewPagerIndicator':
sdir = os.path.join(extlib_dir, 'ViewPagerIndicator')
vcs = getvcs('git',
'https://github.com/JakeWharton/Android-ViewPagerIndicator.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating Android-ViewPagerIndicator project')
if basepath:
return sdir
return libdir
if name == 'UITableView':
sdir = os.path.join(extlib_dir, 'UITableView')
vcs = getvcs('git',
'https://github.com/thiagolocatelli/android-uitableview.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'android-uitableview')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating UITableView project')
if basepath:
return sdir
return libdir
if name == 'ViewPagerTabs':
sdir = os.path.join(extlib_dir, 'ViewPagerTabs')
vcs = getvcs('git',
'https://github.com/astuetz/android-viewpagertabs.git', sdir, sdk_path)
vcs.gotorevision(ref)
pp = open(os.path.join(sdir, 'project.properties'), 'w')
pp.write('android.library=true\n')
pp.write('target=android-15\n')
pp.close()
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating ViewPagerTabs project')
return sdir
if name == 'ActionBar':
sdir = os.path.join(extlib_dir, 'ActionBar')
vcs = getvcs('git',
'https://github.com/johannilsson/android-actionbar.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'actionbar')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating ActionBar project')
if basepath:
return sdir
return libdir
if name == 'ActionBarNW':
sdir = os.path.join(extlib_dir, 'ActionBarNW')
vcs = getvcs('git',
'https://github.com/NightWhistler/android-actionbar.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'actionbar')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating ActionBarNW project')
if basepath:
return sdir
return libdir
if name == 'FacebookSDK':
sdir = os.path.join(extlib_dir, 'FacebookSDK')
vcs = getvcs('git',
'git://github.com/facebook/facebook-android-sdk.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'facebook')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating FacebookSDK project')
if basepath:
return sdir
return libdir
if name == 'OI':
sdir = os.path.join(extlib_dir, 'OI')
vcs = getvcs('git-svn',
'http://openintents.googlecode.com/svn/trunk/', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'JOpenDocument':
sdir = os.path.join(extlib_dir, 'JOpenDocument')
vcs = getvcs('git',
'https://github.com/andiwand/JOpenDocument.git', sdir, sdk_path)
vcs.gotorevision(ref)
shutil.rmtree(os.path.join(sdir, 'bin'))
return sdir
if name == 'BitcoinJWallet':
sdir = os.path.join(extlib_dir, 'BitcoinJWallet')
vcs = getvcs('git',
'https://code.google.com/r/andreasschildbach-bitcoinj/', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'Color-Picker':
sdir = os.path.join(extlib_dir, 'Color-Picker')
vcs = getvcs('git',
'https://github.com/brk3/android-color-picker.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating Color-Picker project')
return sdir
if name == 'Processing-Multitouch':
sdir = os.path.join(extlib_dir, 'Processing-Multitouch')
vcs = getvcs('git',
'https://github.com/rjmarsan/AndroidProcessingMultitouch.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating Multitouch project')
return sdir
if name == 'NewQuickAction3D':
sdir = os.path.join(extlib_dir, 'NewQuickAction3D')
vcs = getvcs('git',
'https://github.com/alt236/NewQuickAction3D.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating NewQuickAction3D project')
return sdir
if name == 'AnySoftKeyboard-API':
sdir = os.path.join(extlib_dir, 'AnySoftKeyboard-API')
vcs = getvcs('git',
'https://github.com/AnySoftKeyboard/AnySoftKeyboard-API.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating AnySoftKeyboard-API project')
return sdir
if name == 'File-Picker':
sdir = os.path.join(extlib_dir, 'File-Picker')
vcs = getvcs('hg',
'https://code.google.com/p/android-file-picker/', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating File-Picker project')
return sdir
if name == 'EmulatorView':
sdir = os.path.join(extlib_dir, 'EmulatorView')
vcs = getvcs('git',
'https://github.com/jackpal/Android-Terminal-Emulator.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'libraries', 'emulatorview')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating EmulatorView project')
if basepath:
return sdir
return libdir
#Leave the native code as a blob; submodules required for that
if name == 'Libpd':
sdir = os.path.join(extlib_dir, 'Libpd')
vcs = getvcs('git',
'https://github.com/libpd/pd-for-android.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'PdCore')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('LibPd project')
if basepath:
return sdir
return libdir
if name == 'Tree-View-List':
sdir = os.path.join(extlib_dir, 'Tree-View-List')
vcs = getvcs('hg',
'https://code.google.com/p/tree-view-list-android/', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating Tree-List-View project')
return sdir
if name == 'PrayTimes':
sdir = os.path.join(extlib_dir, 'PrayTimes')
vcs = getvcs('git',
'https://github.com/ebraminio/PrayTimes.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'HoloEverywhere':
sdir = os.path.join(extlib_dir, 'HoloEverywhere')
vcs = getvcs('git',
'https://github.com/ChristopheVersieux/HoloEverywhere.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating HoloEverywhere project')
if basepath:
return sdir
return libdir
if name == 'PullToRefresh':
sdir = os.path.join(extlib_dir, 'PullToRefresh')
vcs = getvcs('git',
'https://github.com/chrisbanes/Android-PullToRefresh.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'TessTwo':
sdir = os.path.join(extlib_dir, 'TessTwo')
vcs = getvcs('git',
'https://github.com/rmtheis/tess-two.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'tess-two')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating TessTwo project')
if basepath:
return sdir
return libdir
if name == 'TwidereExtension':
sdir = os.path.join(extlib_dir, 'TwidereExtension')
vcs = getvcs('git',
'https://github.com/mariotaku/twidere-extension-library.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'EncfsJava':
sdir = os.path.join(extlib_dir, 'EncfsJava')
vcs = getvcs('git',
'https://github.com/mrpdaemon/encfs-java.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'FinfAgent':
sdir = os.path.join(extlib_dir, 'FinfAgent')
vcs = getvcs('git',
'https://github.com/uniqdom/FinfAgent.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating FinfAgent project')
return sdir
if name == 'MobAdMob':
sdir = os.path.join(extlib_dir, 'MobAdMob')
vcs = getvcs('git',
'https://github.com/mar-v-in/MobAdMob.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'MobAdMob')
pp = open(os.path.join(libdir, 'project.properties'), 'w')
pp.write('android.library=true\n')
pp.write('target=android-16\n')
pp.close()
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating MobAdMob project')
if basepath:
return sdir
return libdir
if name == 'WebSMSAPI':
sdir = os.path.join(extlib_dir, 'WebSMSAPI')
vcs = getvcs('git',
'https://github.com/felixb/websms-api.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating WebSMSAPI project')
shutil.rmtree(os.path.join(sdir, 'test'))
return sdir
if name == 'ub0rlib':
sdir = os.path.join(extlib_dir, 'ub0rlib')
vcs = getvcs('git',
'https://github.com/felixb/ub0rlib.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating ub0rlib project')
return sdir
if name == 'JustPlayerPluginsAdView':
sdir = os.path.join(extlib_dir, 'JustPlayerPluginsAdView')
vcs = getvcs('git',
'https://bitbucket.org/yokmama/just-player-plugins.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'AdView')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating JustPlayerPluginsAdview project')
if basepath:
return sdir
return libdir
if name == 'NoAnalytics':
sdir = os.path.join(extlib_dir, 'NoAnalytics')
vcs = getvcs('git',
'https://github.com/mar-v-in/NoAnalytics.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'NoAnalytics')
pp = open(os.path.join(libdir, 'project.properties'), 'w')
pp.write('android.library=true\n')
pp.write('target=android-16\n')
pp.close()
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating NoAnalytics project')
if basepath:
return sdir
return libdir
if name == 'TintAddon':
sdir = os.path.join(extlib_dir, 'TintAddon')
vcs = getvcs('git',
'https://github.com/Anasthase/TintBrowserAddonFrameworkLibrary.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating TintAddon project')
return sdir
if name == 'EyesFree':
sdir = os.path.join(extlib_dir, 'EyesFree')
vcs = getvcs('git-svn',
'http://eyes-free.googlecode.com/svn/trunk', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'SL4A':
sdir = os.path.join(extlib_dir, 'SL4A')
vcs = getvcs('hg',
'https://code.google.com/p/android-scripting', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'GNUPG':
sdir = os.path.join(extlib_dir, 'GNUPG')
vcs = getvcs('git',
'https://github.com/guardianproject/gnupg-for-android.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'IOCipher':
sdir = os.path.join(extlib_dir, 'IOCipher')
vcs = getvcs('git',
'https://github.com/guardianproject/IOCipher.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'FFMPEG-Java':
sdir = os.path.join(extlib_dir, 'FFMPEG-Java')
vcs = getvcs('git',
'https://github.com/guardianproject/android-ffmpeg-java.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'Slider':
sdir = os.path.join(extlib_dir, 'Slider')
vcs = getvcs('git',
'https://github.com/Xlythe/Slider', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating Slider project')
return sdir
if name == 'NumberPicker':
sdir = os.path.join(extlib_dir, 'NumberPicker')
vcs = getvcs('git',
'https://github.com/thibault/NumberPickerWidget.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'RootCommands':
sdir = os.path.join(extlib_dir, 'RootCommands')
vcs = getvcs('git',
'https://github.com/dschuermann/root-commands.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'RootCommands-Library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating RootCommands project')
if basepath:
return sdir
return libdir
if name == 'LibPageKite':
sdir = os.path.join(extlib_dir, 'LibPageKite')
vcs = getvcs('git',
'https://github.com/pagekite/libpagekite.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'OpenSSL-GP':
sdir = os.path.join(extlib_dir, 'OpenSSL-GP')
vcs = getvcs('git',
'https://github.com/guardianproject/openssl-android.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'NumberPicker-SimonVT':
sdir = os.path.join(extlib_dir, 'NumberPicker-SimonVT')
vcs = getvcs('git',
'https://github.com/SimonVT/android-numberpicker.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating NumberPicker-SimonVT project')
if basepath:
return sdir
return libdir
if name == 'ComicViewer':
sdir = os.path.join(extlib_dir, 'ComicViewer')
vcs = getvcs('git',
'https://github.com/tcoxon/ComicViewer.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating ComicViewer project')
return sdir
if name == 'GitHubAPI':
sdir = os.path.join(extlib_dir, 'GitHubAPI')
vcs = getvcs('git',
'git://git.eclipse.org/gitroot/egit/egit-github.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'Busybox':
sdir = os.path.join(extlib_dir, 'Busybox')
vcs = getvcs('git',
'git://busybox.net/busybox.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'BusyboxConfigs':
sdir = os.path.join(extlib_dir, 'BusyboxConfigs')
vcs = getvcs('git',
'https://github.com/tias/android-busybox-ndk.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'AppMsg':
sdir = os.path.join(extlib_dir, 'AppMsg')
vcs = getvcs('git',
'https://github.com/johnkil/Android-AppMsg.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating AppMsg project')
if basepath:
return sdir
return libdir
if name == 'BillingLibrary':
sdir = os.path.join(extlib_dir, 'BillingLibrary')
vcs = getvcs('git',
'https://github.com/robotmedia/AndroidBillingLibrary.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'AndroidBillingLibrary')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating BillingLibrary project')
if basepath:
return sdir
return libdir
if name == 'FilePicker':
sdir = os.path.join(extlib_dir, 'FilePicker')
vcs = getvcs('git',
'https://github.com/Filepicker/filepicker-android.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating AppMsg project')
return sdir
if name == 'aFileChooser':
sdir = os.path.join(extlib_dir, 'aFileChooser')
vcs = getvcs('git',
'https://github.com/TomTasche/aFileChooser', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'aFileChooser')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating aFileChooser project')
if basepath:
return sdir
return libdir
if name == 'SlidingMenu':
sdir = os.path.join(extlib_dir, 'SlidingMenu')
vcs = getvcs('git',
'https://github.com/jfeinstein10/SlidingMenu', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating SlidingMenu project')
if basepath:
return sdir
return libdir
if name == 'K9Mail-XOAUTH':
sdir = os.path.join(extlib_dir, 'K9Mail-XOAUTH')
vcs = getvcs('git',
'https://github.com/jberkel/k9mail.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating KMail-XOAUTH project')
return sdir
if name == 'RootTools':
sdir = os.path.join(extlib_dir, 'RootTools')
vcs = getvcs('svn',
'http://roottools.googlecode.com/svn/trunk/Stable/RootTools-sdk3-generic', sdir, sdk_path)
vcs.gotorevision(ref)
pp = open(os.path.join(sdir, 'project.properties'), 'w')
pp.write('android.library=true\n')
pp.write('target=android-16\n')
pp.close()
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating RootTools project')
os.remove(os.path.join(sdir, 'android.jar'))
return sdir
if name == 'OsmAnd-tools':
sdir = os.path.join(extlib_dir, 'OsmAnd-tools')
vcs = getvcs('git',
'https://github.com/osmandapp/OsmAnd-tools', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'OsmAnd-core':
sdir = os.path.join(extlib_dir, 'OsmAnd-core')
vcs = getvcs('git',
'https://github.com/osmandapp/OsmAnd-core', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'AndrozicLib':
sdir = os.path.join(extlib_dir, 'AndrozicLib')
vcs = getvcs('git',
'https://github.com/andreynovikov/androzic-library', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating AndrozicLib project')
return sdir
if name == 'Otr4j':
sdir = os.path.join(extlib_dir, 'Otr4j')
vcs = getvcs('git',
'https://github.com/redsolution/otr4j.git', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'AnySoftKeyboardTools':
sdir = os.path.join(extlib_dir, 'AnySoftKeyboardTools')
vcs = getvcs('git',
'https://github.com/AnySoftKeyboard/AnySoftKeyboardTools', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'DashClock':
sdir = os.path.join(extlib_dir, 'DashClock')
vcs = getvcs('git',
'https://code.google.com/p/dashclock', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'KoushWidgets':
sdir = os.path.join(extlib_dir, 'KoushWidgets')
vcs = getvcs('git',
'https://github.com/koush/Widgets', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'Widgets')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating KoushWidgets project')
if basepath:
return sdir
return libdir
if name == 'HoloColorPicker':
sdir = os.path.join(extlib_dir, 'HoloColorPicker')
vcs = getvcs('git',
'https://github.com/frigus02/HoloColorPicker', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating HoloColorPicker project')
return sdir
if name == 'ColorPickerPreference':
sdir = os.path.join(extlib_dir, 'ColorPickerPreference')
vcs = getvcs('git',
'https://github.com/attenzione/android-ColorPickerPreference', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating ColorPickerPreference project')
return sdir
if name == 'ChartLib':
sdir = os.path.join(extlib_dir, 'ChartLib')
vcs = getvcs('git',
'https://bitbucket.org/frigus02/chartlib', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating ChartLib project')
return sdir
if name == 'MeterLib':
sdir = os.path.join(extlib_dir, 'MeterLib')
vcs = getvcs('git',
'https://github.com/zaren678/HdhomerunSignalMeterLib', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating MeterLib project')
return sdir
if name == 'SunriseSunset':
sdir = os.path.join(extlib_dir, 'SunriseSunset')
vcs = getvcs('git',
'https://github.com/mikereedell/sunrisesunsetlib-java', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'LocaleAPI':
sdir = os.path.join(extlib_dir, 'LocaleAPI')
vcs = getvcs('git',
'https://git.gitorious.org/locale-api/mirror.git', sdir, sdk_path)
vcs.gotorevision(ref)
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
sdir]) != 0:
raise BuildException('Error updating LocaleAPI project')
return sdir
if name == 'iptables':
sdir = os.path.join(extlib_dir, 'iptables')
vcs = getvcs('git',
'https://android.googlesource.com/platform/external/iptables', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'LockPattern':
sdir = os.path.join(extlib_dir, 'LockPattern')
vcs = getvcs('hg',
'https://code.google.com/p/android-lockpattern', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'code')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating LockPattern project')
if basepath:
return sdir
return libdir
if name == 'XChange':
sdir = os.path.join(extlib_dir, 'XChange')
vcs = getvcs('git',
'https://github.com/timmolter/XChange', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'MusicBrainz-API':
sdir = os.path.join(extlib_dir, 'MusicBrainz-API')
vcs = getvcs('git',
'https://github.com/jdamcd/musicbrainz-android', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'api')
if basepath:
return sdir
return libdir
if name == 'XChart':
sdir = os.path.join(extlib_dir, 'XChart')
vcs = getvcs('git',
'https://github.com/timmolter/XChart', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'xchart')
return libdir
if name == 'Libxmp':
sdir = os.path.join(extlib_dir, 'Libxmp')
vcs = getvcs('git',
'git://git.code.sf.net/p/xmp/libxmp', sdir, sdk_path)
vcs.gotorevision(ref)
return sdir
if name == 'MenuDrawer':
sdir = os.path.join(extlib_dir, 'MenuDrawer')
vcs = getvcs('git',
'https://github.com/SimonVT/android-menudrawer', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating MenuDrawer project')
if name == 'ImageLoader':
sdir = os.path.join(extlib_dir, 'ImageLoader')
vcs = getvcs('git',
'https://github.com/nostra13/Android-Universal-Image-Loader.git', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating ImageLoader project')
if basepath:
return sdir
shutil.rmtree(os.path.join(sdir, 'downloads'))
return libdir
if name == 'DragSort':
sdir = os.path.join(extlib_dir, 'DragSort')
vcs = getvcs('git',
'https://github.com/bauerca/drag-sort-listview', sdir, sdk_path)
vcs.gotorevision(ref)
libdir = os.path.join(sdir, 'library')
if subprocess.call([os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p',
libdir]) != 0:
raise BuildException('Error updating DragSort project')
if basepath:
return sdir
return libdir
raise BuildException('Unknown srclib ' + name)
# Prepare the source code for a particular build
# 'vcs' - the appropriate vcs object for the application
# 'app' - the application details from the metadata
# 'build' - the build details from the metadata
# 'build_dir' - the path to the build directory, usually
# 'build/app.id'
# 'extlib_dir' - the path to the external libraries directory, usually
# 'build/extlib'
# 'sdk_path' - the path to the Android SDK
# 'ndk_path' - the path to the Android NDK
# 'javacc_path' - the path to javacc
# 'mvn3' - the path to the maven 3 executable
# 'verbose' - optional: verbose or not (default=False)
# Returns the (root, srclibpaths) where:
# 'root' is the root directory, which may be the same as 'build_dir' or may
# be a subdirectory of it.
# 'srclibpaths' is information on the srclibs being used
def prepare_source(vcs, app, build, build_dir, extlib_dir, sdk_path, ndk_path, javacc_path, mvn3, verbose=False):
# Optionally, the actual app source can be in a subdirectory...
if 'subdir' in build:
root_dir = os.path.join(build_dir, build['subdir'])
else:
root_dir = build_dir
# Get a working copy of the right revision...
print "Getting source for revision " + build['commit']
vcs.gotorevision(build['commit'])
# Check that a subdir (if we're using one) exists. This has to happen
# after the checkout, since it might not exist elsewhere...
if not os.path.exists(root_dir):
raise BuildException('Missing subdir ' + root_dir)
# Initialise submodules if requred...
if build.get('submodules', 'no') == 'yes':
if verbose: print "Initialising submodules..."
vcs.initsubmodules()
# Run an init command if one is required...
if 'init' in build:
init = build['init']
init = init.replace('$$SDK$$', sdk_path)
init = init.replace('$$NDK$$', ndk_path)
init = init.replace('$$MVN$$', mvn3)
if verbose: print "Doing init: exec '%s' in '%s'"%(init,root_dir)
if subprocess.call(init, cwd=root_dir, shell=True) != 0:
raise BuildException("Error running init command")
# Generate (or update) the ant build file, build.xml...
updatemode = build.get('update', '.')
if (updatemode != 'no' and
'maven' not in build):
parms = [os.path.join(sdk_path, 'tools', 'android'),
'update', 'project', '-p', '.']
parms.append('--subprojects')
if 'target' in build:
parms.append('-t')
parms.append(build['target'])
update_dirs = updatemode.split(';')
# Force build.xml update if necessary...
if updatemode == 'force' or 'target' in build:
if updatemode == 'force':
update_dirs = ['.']
buildxml = os.path.join(root_dir, 'build.xml')
if os.path.exists(buildxml):
print 'Force-removing old build.xml'
os.remove(buildxml)
for d in update_dirs:
cwd = root_dir + '/' + d
if verbose:
print "Update of '%s': exec '%s' in '%s'"%\
(d," ".join(parms),cwd)
p = subprocess.Popen(parms, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()
if p.returncode != 0:
raise BuildException("Failed to update project with stdout '%s' and stderr '%s'"%(out,err))
# check to see whether an error was returned without a proper exit code (this is the case for the 'no target set or target invalid' error)
if err != "" and err.startswith("Error: "):
raise BuildException("Failed to update project with stdout '%s' and stderr '%s'"%(out,err))
# If the app has ant set up to sign the release, we need to switch
# that off, because we want the unsigned apk...
for propfile in ('build.properties', 'default.properties', 'ant.properties'):
if os.path.exists(os.path.join(root_dir, propfile)):
if subprocess.call(['sed','-i','s/^key.store/#/',
propfile], cwd=root_dir) !=0:
raise BuildException("Failed to amend %s" % propfile)
# Update the local.properties file...
locprops = os.path.join(root_dir, 'local.properties')
if os.path.exists(locprops):
f = open(locprops, 'r')
props = f.read()
f.close()
# Fix old-fashioned 'sdk-location' by copying
# from sdk.dir, if necessary...
if build.get('oldsdkloc', 'no') == "yes":
sdkloc = re.match(r".*^sdk.dir=(\S+)$.*", props,
re.S|re.M).group(1)
props += "\nsdk-location=" + sdkloc + "\n"
# Add ndk location...
props+= "\nndk.dir=" + ndk_path + "\n"
# Add java.encoding if necessary...
if 'encoding' in build:
props += "\njava.encoding=" + build['encoding'] + "\n"
f = open(locprops, 'w')
f.write(props)
f.close()
# Insert version code and number into the manifest if necessary...
if 'forceversion' in build:
if subprocess.call(['sed','-r','-i',
's/android:versionName="[^"]+"/android:versionName="' + build['version'] + '"/g',
'AndroidManifest.xml'], cwd=root_dir) !=0:
raise BuildException("Failed to amend manifest")
if 'forcevercode' in build:
if subprocess.call(['sed','-r','-i',
's/android:versionCode="[^"]+"/android:versionCode="' + build['vercode'] + '"/g',
'AndroidManifest.xml'], cwd=root_dir) !=0:
raise BuildException("Failed to amend manifest")
# Delete unwanted file...
if 'rm' in build:
for part in build['rm'].split(';'):
dest = os.path.join(build_dir, part)
if os.path.exists(dest):
os.remove(dest)
# Fix apostrophes translation files if necessary...
if build.get('fixapos', 'no') == 'yes':
for root, dirs, files in os.walk(os.path.join(root_dir, 'res')):
for filename in files:
if filename.endswith('.xml'):
if subprocess.call(['sed','-i','s@' +
r"\([^\\]\)'@\1\\'" +
'@g',
os.path.join(root, filename)]) != 0:
raise BuildException("Failed to amend " + filename)
# Fix translation files if necessary...
if build.get('fixtrans', 'no') == 'yes':
for root, dirs, files in os.walk(os.path.join(root_dir, 'res')):
for filename in files:
if filename.endswith('.xml'):
f = open(os.path.join(root, filename))
changed = False
outlines = []
for line in f:
num = 1
index = 0
oldline = line
while True:
index = line.find("%", index)
if index == -1:
break
next = line[index+1:index+2]
if next == "s" or next == "d":
line = (line[:index+1] +
str(num) + "$" +
line[index+1:])
num += 1
index += 3
else:
index += 1
# We only want to insert the positional arguments
# when there is more than one argument...
if oldline != line:
if num > 2:
changed = True
else:
line = oldline
outlines.append(line)
f.close()
if changed:
f = open(os.path.join(root, filename), 'w')
f.writelines(outlines)
f.close()
# Add required external libraries...
if 'extlibs' in build:
libsdir = os.path.join(root_dir, 'libs')
if not os.path.exists(libsdir):
os.mkdir(libsdir)
for lib in build['extlibs'].split(';'):
libf = os.path.basename(lib)
shutil.copyfile(os.path.join(extlib_dir, lib),
os.path.join(libsdir, libf))
# Get required source libraries...
srclibpaths = []
if 'srclibs' in build:
for lib in build['srclibs'].split(';'):
name, _ = lib.split('@')
srclibpaths.append((name, getsrclib(lib, extlib_dir, sdk_path)))
basesrclib = vcs.getsrclib()
# If one was used for the main source, add that too.
if basesrclib:
srclibpaths.append(basesrclib)
# There should never be gen or bin directories in the source, so just get
# rid of them...
for baddir in ['gen', 'bin', 'obj', 'libs/armeabi', 'libs/mips', 'libs/x86']:
badpath = os.path.join(root_dir, baddir)
if os.path.exists(badpath):
shutil.rmtree(badpath)
# Apply patches if any
if 'patch' in build:
for patch in build['patch'].split(';'):
print "Applying " + patch
patch_path = os.path.join('metadata', app['id'], patch)
if subprocess.call(['patch', '-p1',
'-i', os.path.abspath(patch_path)], cwd=build_dir) != 0:
raise BuildException("Failed to apply patch %s" % patch_path)
# Run a pre-build command if one is required...
if 'prebuild' in build:
prebuild = build['prebuild']
# Substitute source library paths into prebuild commands...
for name, libpath in srclibpaths:
libpath = os.path.relpath(libpath, root_dir)
prebuild = prebuild.replace('$$' + name + '$$', libpath)
prebuild = prebuild.replace('$$SDK$$', sdk_path)
prebuild = prebuild.replace('$$NDK$$', ndk_path)
prebuild = prebuild.replace('$$MVN3$$', mvn3)
p = subprocess.Popen(prebuild, cwd=root_dir, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if p.returncode != 0:
raise BuildException("Error running pre-build command", out, err)
if build.get('anal-tics', 'no') == 'yes':
fp = os.path.join(root_dir, 'src', 'com', 'google', 'android', 'apps', 'analytics')
os.makedirs(fp)
with open(os.path.join(fp, 'GoogleAnalyticsTracker.java'), 'w') as f:
f.write("""
package com.google.android.apps.analytics;
public class GoogleAnalyticsTracker {
private static GoogleAnalyticsTracker instance;
private GoogleAnalyticsTracker() {
}
public static GoogleAnalyticsTracker getInstance() {
if(instance == null)
instance = new GoogleAnalyticsTracker();
return instance;
}
public void start(String i,int think ,Object not) {
}
public void dispatch() {
}
public void stop() {
}
public void setProductVersion(String uh, String hu) {
}
public void trackEvent(String that,String just,String aint,int happening) {
}
public void trackPageView(String nope) {
}
public void setCustomVar(int mind,String your,String own,int business) {
}
}
""")
# Special case init functions for funambol...
if build.get('initfun', 'no') == "yes":
if subprocess.call(['sed','-i','s@' +
'