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:
parent
ef09973730
commit
cf0287ac8a
71
common.py
71
common.py
@ -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
132
import.py
Executable 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user