From: Ciaran Gultnieks Date: Sun, 5 Feb 2012 11:02:01 +0000 (+0000) Subject: Simple metadata generator X-Git-Tag: 0.1~987 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=cf0287ac8a6842609868d96093ecf436b0ccf5fd;p=fdroidserver.git Simple metadata generator --- diff --git a/common.py b/common.py index e88bf551..8d12767d 100644 --- a/common.py +++ b/common.py @@ -65,6 +65,8 @@ class vcs: # be dirty, or even non-existent. If the repository does already exist # locally, it will be updated from the origin, but only once in the # lifetime of the vcs object. + # None is acceptable for 'rev' if you know you are cloning a clean copy of + # the repo - otherwise it must specify a valid revision. def gotorevision(self, rev): raise VCSException("This VCS type doesn't define gotorevision") @@ -115,8 +117,9 @@ class vcs_git(vcs): raise VCSException("Git fetch failed") self.refreshed = True # Check out the appropriate revision... - if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0: - raise VCSException("Git checkout failed") + if rev: + if subprocess.call(['git', 'checkout', 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: raise VCSException("Git clean failed") @@ -165,15 +168,16 @@ class vcs_gitsvn(vcs): cwd=self.local) != 0: raise VCSException("Git svn rebase failed") self.refreshed = True - # Figure out the git commit id corresponding to the svn revision... - p = subprocess.Popen(['git', 'svn', 'find-rev', 'r' + rev], - cwd=self.local, stdout=subprocess.PIPE) - rev = p.communicate()[0].rstrip() - if p.returncode != 0: - raise VCSException("Failed to get git treeish from svn rev") - # Check out the appropriate revision... - if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0: - raise VCSException("Git checkout failed") + if rev: + # Figure out the git commit id corresponding to the svn revision... + p = subprocess.Popen(['git', 'svn', 'find-rev', 'r' + rev], + cwd=self.local, stdout=subprocess.PIPE) + rev = p.communicate()[0].rstrip() + if p.returncode != 0: + raise VCSException("Failed to get git treeish from svn rev") + # Check out the appropriate revision... + if subprocess.call(['git', 'checkout', 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: raise VCSException("Git clean failed") @@ -204,10 +208,11 @@ class vcs_svn(vcs): self.userargs(), cwd=self.local) != 0: raise VCSException("Svn update failed") self.refreshed = True - revargs = ['-r', rev] - if subprocess.call(['svn', 'update', '--force'] + revargs + - self.userargs(), cwd=self.local) != 0: - raise VCSException("Svn update failed") + if ref: + revargs = ['-r', rev] + if subprocess.call(['svn', 'update', '--force'] + revargs + + self.userargs(), cwd=self.local) != 0: + raise VCSException("Svn update failed") class vcs_hg(vcs): @@ -225,10 +230,11 @@ class vcs_hg(vcs): cwd=self.local) != 0: raise VCSException("Hg pull failed") self.refreshed = True - revargs = [rev] - if subprocess.call(['hg', 'checkout', '-C'] + revargs, - cwd=self.local) != 0: - raise VCSException("Hg checkout failed") + if rev: + revargs = [rev] + if subprocess.call(['hg', 'checkout', '-C'] + revargs, + cwd=self.local) != 0: + raise VCSException("Hg checkout failed") class vcs_bzr(vcs): @@ -246,10 +252,11 @@ class vcs_bzr(vcs): cwd=self.local) != 0: raise VCSException("Bzr update failed") self.refreshed = True - revargs = ['-r', rev] - if subprocess.call(['bzr', 'revert'] + revargs, - cwd=self.local) != 0: - raise VCSException("Bzr revert failed") + if rev: + revargs = ['-r', rev] + if subprocess.call(['bzr', 'revert'] + revargs, + cwd=self.local) != 0: + raise VCSException("Bzr revert failed") class vcs_srclib(vcs): @@ -290,7 +297,7 @@ def metafieldtype(name): # Parse metadata for a single application. # # 'metafile' - the filename to read. The package id for the application comes -# from this filename. +# from this filename. Pass None to get a blank entry. # # Returns a dictionary containing all the details of the application. There are # two major kinds of information in the dictionary. Keys beginning with capital @@ -335,12 +342,15 @@ def parse_metadata(metafile, **kw): thisinfo['comments'].append((key, comment)) del curcomments[:] - if not isinstance(metafile, file): - metafile = open(metafile, "r") thisinfo = {} - thisinfo['id'] = metafile.name[9:-4] - if kw.get("verbose", False): - print "Reading metadata for " + thisinfo['id'] + if metafile: + if not isinstance(metafile, file): + metafile = open(metafile, "r") + thisinfo['id'] = metafile.name[9:-4] + if kw.get("verbose", False): + print "Reading metadata for " + thisinfo['id'] + else: + thisinfo['id'] = None # Defaults for fields that come from metadata... thisinfo['Name'] = None @@ -365,6 +375,9 @@ def parse_metadata(metafile, **kw): thisinfo['builds'] = [] thisinfo['comments'] = [] + if metafile is None: + return thisinfo + mode = 0 buildlines = [] curcomments = [] diff --git a/import.py b/import.py new file mode 100755 index 00000000..eb4fe04c --- /dev/null +++ b/import.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# import.py - part of the FDroid server tools +# Copyright (C) 2010-12, 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 . + +import sys +import os +import shutil +import subprocess +import re +from optparse import OptionParser + +#Read configuration... +repo_name = None +repo_description = None +repo_icon = None +repo_url = None +execfile('config.py') + +import common + +# Parse command line... +parser = OptionParser() +parser.add_option("-u", "--url", default=None, + help="Project URL to import from.") +parser.add_option("-s", "--subdir", default=None, + help="Path to main android project subdirectory, if not in root.") +(options, args) = parser.parse_args() + +if not options.url: + print "Specify project url." + sys.exit(1) +url = options.url + +tmp_dir = 'tmp' +if not os.path.isdir(tmp_dir): + print "Creating temporary directory" + os.makedirs(tmp_dir) + +# Get all apps... +apps = common.read_metadata() + +# Figure out what kind of project it is... +projecttype = None +if url.startswith('https://github.com'): + projecttype = 'github' + repo = url + '.git' + repotype = 'git' + sourcecode = url + +if not projecttype: + print "Unable to determine the project type." + sys.exit(1) + +# Get a copy of the source so we can extract some info... +src_dir = os.path.join(tmp_dir, 'importer') +if os.path.exists(tmp_dir): + shutil.rmtree(tmp_dir) +vcs = common.getvcs(repotype, repo, src_dir) +vcs.gotorevision(None) +if options.subdir: + root_dir = os.path.join(src_dir, options.subdir) +else: + root_dir = src_dir + +# Check AndroidManiifest.xml exists... +manifest = os.path.join(root_dir, 'AndroidManifest.xml') +if not os.path.exists(manifest): + print "AndroidManifest.xml did not exist in the expected location. Specify --subdir?" + sys.exit(1) + +# Extract some information... +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) +if not package: + print "Couldn't find package ID" + sys.exit(1) +if not version: + print "Couldn't find latest version name" + sys.exit(1) +if not vercode: + print "Couldn't find latest version code" + sys.exit(1) + +# Make sure it's actually new... +for app in apps: + if app['id'] == package: + print "Package ' + package + ' already exists" + sys.exit(1) + +# Construct the metadata... +app = common.parse_metadata(None) +app['id'] = package +app['Web Site'] = url +app['Source Code'] = sourcecode +app['Repo Type'] = repotype +app['Repo'] = repo +metafile = os.path.join('metadata', package + '.txt') +common.write_metadata(metafile, app) +print "Wrote " + metafile +