1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-11-09 00:40:11 +01:00

Simple metadata generator

This commit is contained in:
Ciaran Gultnieks 2012-02-05 11:02:01 +00:00
parent ef09973730
commit cf0287ac8a
2 changed files with 174 additions and 29 deletions

View File

@ -65,6 +65,8 @@ class vcs:
# be dirty, or even non-existent. If the repository does already exist # 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 # locally, it will be updated from the origin, but only once in the
# lifetime of the vcs object. # 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): def gotorevision(self, rev):
raise VCSException("This VCS type doesn't define gotorevision") raise VCSException("This VCS type doesn't define gotorevision")
@ -115,8 +117,9 @@ class vcs_git(vcs):
raise VCSException("Git fetch failed") raise VCSException("Git fetch failed")
self.refreshed = True self.refreshed = True
# Check out the appropriate revision... # Check out the appropriate revision...
if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0: if rev:
raise VCSException("Git checkout failed") if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0:
raise VCSException("Git checkout failed")
# Get rid of any uncontrolled files left behind... # Get rid of any uncontrolled files left behind...
if subprocess.call(['git', 'clean', '-dffx'], cwd=self.local) != 0: if subprocess.call(['git', 'clean', '-dffx'], cwd=self.local) != 0:
raise VCSException("Git clean failed") raise VCSException("Git clean failed")
@ -165,15 +168,16 @@ class vcs_gitsvn(vcs):
cwd=self.local) != 0: cwd=self.local) != 0:
raise VCSException("Git svn rebase failed") raise VCSException("Git svn rebase failed")
self.refreshed = True self.refreshed = True
# Figure out the git commit id corresponding to the svn revision... if rev:
p = subprocess.Popen(['git', 'svn', 'find-rev', 'r' + rev], # Figure out the git commit id corresponding to the svn revision...
cwd=self.local, stdout=subprocess.PIPE) p = subprocess.Popen(['git', 'svn', 'find-rev', 'r' + rev],
rev = p.communicate()[0].rstrip() cwd=self.local, stdout=subprocess.PIPE)
if p.returncode != 0: rev = p.communicate()[0].rstrip()
raise VCSException("Failed to get git treeish from svn rev") if p.returncode != 0:
# Check out the appropriate revision... raise VCSException("Failed to get git treeish from svn rev")
if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0: # Check out the appropriate revision...
raise VCSException("Git checkout failed") if subprocess.call(['git', 'checkout', rev], cwd=self.local) != 0:
raise VCSException("Git checkout failed")
# Get rid of any uncontrolled files left behind... # Get rid of any uncontrolled files left behind...
if subprocess.call(['git', 'clean', '-dffx'], cwd=self.local) != 0: if subprocess.call(['git', 'clean', '-dffx'], cwd=self.local) != 0:
raise VCSException("Git clean failed") raise VCSException("Git clean failed")
@ -204,10 +208,11 @@ class vcs_svn(vcs):
self.userargs(), cwd=self.local) != 0: self.userargs(), cwd=self.local) != 0:
raise VCSException("Svn update failed") raise VCSException("Svn update failed")
self.refreshed = True self.refreshed = True
revargs = ['-r', rev] if ref:
if subprocess.call(['svn', 'update', '--force'] + revargs + revargs = ['-r', rev]
self.userargs(), cwd=self.local) != 0: if subprocess.call(['svn', 'update', '--force'] + revargs +
raise VCSException("Svn update failed") self.userargs(), cwd=self.local) != 0:
raise VCSException("Svn update failed")
class vcs_hg(vcs): class vcs_hg(vcs):
@ -225,10 +230,11 @@ class vcs_hg(vcs):
cwd=self.local) != 0: cwd=self.local) != 0:
raise VCSException("Hg pull failed") raise VCSException("Hg pull failed")
self.refreshed = True self.refreshed = True
revargs = [rev] if rev:
if subprocess.call(['hg', 'checkout', '-C'] + revargs, revargs = [rev]
cwd=self.local) != 0: if subprocess.call(['hg', 'checkout', '-C'] + revargs,
raise VCSException("Hg checkout failed") cwd=self.local) != 0:
raise VCSException("Hg checkout failed")
class vcs_bzr(vcs): class vcs_bzr(vcs):
@ -246,10 +252,11 @@ class vcs_bzr(vcs):
cwd=self.local) != 0: cwd=self.local) != 0:
raise VCSException("Bzr update failed") raise VCSException("Bzr update failed")
self.refreshed = True self.refreshed = True
revargs = ['-r', rev] if rev:
if subprocess.call(['bzr', 'revert'] + revargs, revargs = ['-r', rev]
cwd=self.local) != 0: if subprocess.call(['bzr', 'revert'] + revargs,
raise VCSException("Bzr revert failed") cwd=self.local) != 0:
raise VCSException("Bzr revert failed")
class vcs_srclib(vcs): class vcs_srclib(vcs):
@ -290,7 +297,7 @@ def metafieldtype(name):
# Parse metadata for a single application. # Parse metadata for a single application.
# #
# 'metafile' - the filename to read. The package id for the application comes # '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 # Returns a dictionary containing all the details of the application. There are
# two major kinds of information in the dictionary. Keys beginning with capital # 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)) thisinfo['comments'].append((key, comment))
del curcomments[:] del curcomments[:]
if not isinstance(metafile, file):
metafile = open(metafile, "r")
thisinfo = {} thisinfo = {}
thisinfo['id'] = metafile.name[9:-4] if metafile:
if kw.get("verbose", False): if not isinstance(metafile, file):
print "Reading metadata for " + thisinfo['id'] 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... # Defaults for fields that come from metadata...
thisinfo['Name'] = None thisinfo['Name'] = None
@ -365,6 +375,9 @@ def parse_metadata(metafile, **kw):
thisinfo['builds'] = [] thisinfo['builds'] = []
thisinfo['comments'] = [] thisinfo['comments'] = []
if metafile is None:
return thisinfo
mode = 0 mode = 0
buildlines = [] buildlines = []
curcomments = [] curcomments = []

132
import.py Executable file
View File

@ -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 <http://www.gnu.org/licenses/>.
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