diff --git a/docs/fdroid.texi b/docs/fdroid.texi index cbcea84c..fc9a7869 100644 --- a/docs/fdroid.texi +++ b/docs/fdroid.texi @@ -346,7 +346,7 @@ Along similar lines (and only in conjunction with @code{--test}, you can use @code{--force} to force a build of a Disabled application, where normally it would be completely ignored. Similarly a version that was found to contain ELFs or known non-free libraries can be forced to build. See also — -scanignore= in the Build Version section. +scanignore= and scandelete= in the Build Version section. If the build was unsuccessful, you can find out why by looking at the output in the logs/ directory. If that isn't illuminating, try building the app the @@ -476,6 +476,7 @@ The following sections describe the fields recognised within the file. * Requires Root:: * Archive Policy:: * Update Check Mode:: +* Vercode Operation:: * Update Check Data:: * Auto Update Mode:: * Current Version:: @@ -907,17 +908,17 @@ You can use $$SDK$$, $$NDK$$ and $$MVN3$$ to substitute the paths to the android SDK and NDK directories, and maven 3 executable respectively e.g. for when you need to run @code{android update project} explicitly. -@item initfun=yes -Enables a selection of mad hacks to make com.funambol.android build. -Probably not useful for any other application. - @item scanignore=path1;path2;... Enables one or more files/paths to be exlcuded from the scan process. This should only be used where there is a very good reason, and probably accompanied by a comment explaining why it is necessary. -When scanning, files whose relative paths start with any of the paths -given here are ignored. +When scanning the source tree for problems, matching files whose relative +paths start with any of the paths given here are ignored. + +@item scandelete=path1;path2;... +Similar to scanignore=, but instead of ignoring files under the given paths, +it tells f-droid to delete the matching files directly. @item build=xxxx As for 'prebuild', but runs during the actual build phase (but before the @@ -1136,6 +1137,20 @@ again, rather than retrieving a different one. Used in conjunction with @code{Update Check Mode} for certain modes. +@node Vercode Operation +@section Vercode Operation + +@cindex Vercode Operation + +Operation to be applied to the vercode obtained by the defined @code{Update +Check Mode}. @code{%c} will be replaced by the actual vercode, and the whole +string will be passed to python's @code{eval} function. + +Especially useful with apps that we want to compile for different ABIs, but +whose vercodes don't always have trailing zeros. With @code{Vercode Operation} +set at something like @code{%c*10 + 4}, we will be able to track updates and +build three different versions of every upstream version. + @node Archive Policy @section Archive Policy diff --git a/fdroidserver/checkupdates.py b/fdroidserver/checkupdates.py index 12de4e46..fff84b80 100644 --- a/fdroidserver/checkupdates.py +++ b/fdroidserver/checkupdates.py @@ -335,6 +335,7 @@ def main(): logmsg = None tag = None + msg = None mode = app['Update Check Mode'] if mode == 'Tags': (version, vercode, tag) = check_tags(app, config['sdk_path']) @@ -348,17 +349,21 @@ def main(): (version, vercode) = check_http(app) elif mode == 'Static': version = None - vercode = 'Checking disabled' + msg = 'Checking disabled' elif mode == 'None': version = None - vercode = 'Checking disabled' + msg = 'Checking disabled' else: version = None - vercode = 'Invalid update check method' + msg = 'Invalid update check method' + + if vercode and app['Vercode Operation']: + op = app['Vercode Operation'].replace("%c", str(int(vercode))) + vercode = str(eval(op)) updating = False if not version: - print "..." + vercode + print "...%s" % msg elif vercode == app['Current Version Code']: print "...up to date" else: diff --git a/fdroidserver/common.py b/fdroidserver/common.py index a41fa0a4..3923054a 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -211,7 +211,7 @@ class vcs_git(vcs): self.refreshed = True # Check out the appropriate revision... rev = str(rev if rev else 'origin/master') - if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0: + if subprocess.call(['git', 'checkout', '-f', rev], cwd=self.local) != 0: raise VCSException("Git checkout failed") # Get rid of any uncontrolled files left behind... if subprocess.call(['git', 'clean', '-dffx'], cwd=self.local) != 0: @@ -225,6 +225,14 @@ class vcs_git(vcs): if subprocess.call(['git', 'submodule', 'update'], cwd=self.local) != 0: raise VCSException("Git submodule update failed") + if subprocess.call(['git', 'submodule', 'foreach', + 'git', 'reset', '--hard'], + cwd=self.local) != 0: + raise VCSException("Git submodule reset failed") + if subprocess.call(['git', 'submodule', 'foreach', + 'git', 'clean', '-dffx'], + cwd=self.local) != 0: + raise VCSException("Git submodule clean failed") def gettags(self): self.checkrepo() @@ -572,6 +580,7 @@ def parse_metadata(metafile): thisinfo['AntiFeatures'] = None thisinfo['Archive Policy'] = None thisinfo['Update Check Mode'] = 'None' + thisinfo['Vercode Operation'] = None thisinfo['Auto Update Mode'] = 'None' thisinfo['Current Version'] = '' thisinfo['Current Version Code'] = '0' @@ -810,7 +819,7 @@ def write_metadata(dest, app): 'oldsdkloc', 'target', 'compilesdk', 'update', 'encoding', 'forceversion', 'forcevercode', 'rm', 'fixtrans', 'fixapos', 'extlibs', 'srclibs', - 'patch', 'prebuild', 'initfun', 'scanignore', 'build', + 'patch', 'prebuild', 'scanignore', 'scandelete', 'build', 'buildjni', 'gradle', 'maven', 'preassemble', 'bindir', 'antcommand', 'novcheck'] @@ -835,6 +844,8 @@ def write_metadata(dest, app): writefield('Archive Policy') writefield('Auto Update Mode') writefield('Update Check Mode') + if app['Vercode Operation']: + writefield('Vercode Operation') if 'Update Check Data' in app: writefield('Update Check Data') if len(app['Current Version']) > 0: @@ -1344,7 +1355,7 @@ def prepare_source(vcs, app, build, build_dir, srclib_dir, extlib_dir, sdk_path, raise BuildException('Missing subdir ' + root_dir) # Initialise submodules if requred... - if build.get('submodules', 'no') == 'yes': + if build.get('submodules', 'no') == 'yes': if verbose: print "Initialising submodules..." if build.get('submodules', 'no') == 'yes': if options.verbose: @@ -1645,14 +1656,50 @@ def scan_source(build_dir, root_dir, thisbuild): 'youtubeandroidplayerapi', 'bugsense'] - if 'scanignore' in thisbuild: - ignore = [p.strip() for p in thisbuild['scanignore'].split(';')] - else: - ignore = [] - + def getpaths(field): + paths = [] + if field not in thisbuild: + return paths + for p in thisbuild[field].split(';'): + p = p.strip() + if p == '.': + p = '/' + elif p.startswith('./'): + p = p[1:] + elif not p.startswith('/'): + p = '/' + p; + if p not in paths: + paths.append(p) + return paths + + scanignore = getpaths('scanignore') + scandelete = getpaths('scandelete') + ms = magic.open(magic.MIME_TYPE) ms.load() + def toignore(fd): + for i in scanignore: + if fd.startswith(i): + return True + return False + + def todelete(fd): + for i in scandelete: + if fd.startswith(i): + return True + return False + + def removeproblem(what, fd, fp): + print 'Removing %s at %s' % (what, fd) + os.remove(fp) + + def handleproblem(what, fd, fp): + if todelete(fd): + removeproblem(what, fd, fp) + else: + problems.append('Found %s at %s' % (what, fd)) + # Iterate through all files in the source code... for r,d,f in os.walk(build_dir): for curfile in f: @@ -1662,36 +1709,30 @@ def scan_source(build_dir, root_dir, thisbuild): # Path (relative) to the file... fp = os.path.join(r, curfile) - fd = fp[len(build_dir)+1:] + fd = fp[len(build_dir):] # Check if this file has been explicitly excluded from scanning... - ignorethis = False - for i in ignore: - if fd.startswith(i): - ignorethis = True - break - if ignorethis: + if toignore(fd): continue for suspect in usual_suspects: if suspect in curfile.lower(): - problems.append('Found usual supect in filename ' + fp) + handleproblem('usual supect', fd, fp) mime = ms.file(fp) if mime == 'application/x-sharedlib': - problems.append('Found shared library at %s' % fd) + handleproblem('shared library', fd, fp) elif mime == 'application/x-archive': - problems.append('Found static library at %s' % fd) + handleproblem('static library', fd, fp) elif mime == 'application/x-executable': - problems.append('Found binary executable at %s' % fd) + handleproblem('binary executable', fd, fp) elif mime == 'application/jar' and fp.endswith('.apk'): - print 'Removing apk file at %s' % fd - os.remove(fp) + removeproblem('APK file', fd, fp) elif curfile.endswith('.java'): for line in file(fp): if 'DexClassLoader' in line: - problems.append('Found DexClassLoader in ' + fp) + handleproblem('DexClassLoader', fd, fp) break ms.close()