1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-07-05 08:50:08 +02:00

Create archive repo (configurable option)

This commit is contained in:
Ciaran Gultnieks 2013-05-09 20:09:17 +01:00
parent 5ab225e1e1
commit 48296df5b0
4 changed files with 295 additions and 235 deletions

View File

@ -21,6 +21,20 @@ are binaries built from source by the admin of f-droid.org using the tools on
https://gitorious.org/f-droid. https://gitorious.org/f-droid.
""" """
# As above, but for the archive repo.
# archive_older sets the number of versions kept in the main repo, with all
# older ones going to the archive. Set it to 0, and there will be no archive
# repository, and no need to define the other archive_ values.
archive_older = 3
archive_url = "https://f-droid.org/archive"
archive_name = "F-Droid Archive"
archive_icon = "fdroid-icon.png"
archive_description = """
The archive repository of the F-Droid client. This contains older versions
of applications from the main repository.
"""
#The key (from the keystore defined below) to be used for signing the #The key (from the keystore defined below) to be used for signing the
#repository itself. Can be None for an unsigned repository. #repository itself. Can be None for an unsigned repository.
repo_keyalias = None repo_keyalias = None

View File

@ -22,10 +22,8 @@ import os
import shutil import shutil
import subprocess import subprocess
import re import re
import zipfile
import tarfile import tarfile
import traceback import traceback
from xml.dom.minidom import Document
from optparse import OptionParser from optparse import OptionParser
import common import common
@ -465,8 +463,8 @@ def build_local(app, thisbuild, vcs, build_dir, output_dir, extlib_dir, tmp_dir,
os.path.join(output_dir, tarfilename)) os.path.join(output_dir, tarfilename))
def trybuild(app, thisbuild, build_dir, output_dir, extlib_dir, tmp_dir, def trybuild(app, thisbuild, build_dir, output_dir, also_check_dir, extlib_dir,
repo_dir, vcs, test, server, install, force, verbose=False): tmp_dir, repo_dir, vcs, test, server, install, force, verbose=False):
""" """
Build a particular version of an application, if it needs building. Build a particular version of an application, if it needs building.
@ -481,6 +479,12 @@ def trybuild(app, thisbuild, build_dir, output_dir, extlib_dir, tmp_dir,
if os.path.exists(dest) or (not test and os.path.exists(dest_repo)): if os.path.exists(dest) or (not test and os.path.exists(dest_repo)):
return False return False
if also_check_dir:
dest_also = os.path.join(also_check_dir, app['id'] + '_' +
thisbuild['vercode'] + '.apk')
if os.path.exists(dest_also):
return False
if thisbuild['commit'].startswith('!'): if thisbuild['commit'].startswith('!'):
return False return False
@ -554,10 +558,13 @@ options = None
def main(): def main():
global options global options
# Read configuration... # Read configuration...
globals()['build_server_always'] = False globals()['build_server_always'] = False
globals()['mvn3'] = "mvn3" globals()['mvn3'] = "mvn3"
globals()['archive_older'] = 0
execfile('config.py', globals()) execfile('config.py', globals())
options, args = parse_commandline() options, args = parse_commandline()
if build_server_always: if build_server_always:
options.server = True options.server = True
@ -586,6 +593,11 @@ def main():
print "Creating output directory" print "Creating output directory"
os.makedirs(output_dir) os.makedirs(output_dir)
if archive_older != 0:
also_check_dir = 'archive'
else:
also_check_dir = None
repo_dir = 'repo' repo_dir = 'repo'
build_dir = 'build' build_dir = 'build'
@ -628,9 +640,10 @@ def main():
for thisbuild in app['builds']: for thisbuild in app['builds']:
wikilog = None wikilog = None
try: try:
if trybuild(app, thisbuild, build_dir, output_dir, extlib_dir, if trybuild(app, thisbuild, build_dir, output_dir, also_check_dir,
tmp_dir, repo_dir, vcs, options.test, options.server, extlib_dir, tmp_dir, repo_dir, vcs, options.test,
options.install, options.force, options.verbose): options.server, options.install, options.force,
options.verbose):
build_succeeded.append(app) build_succeeded.append(app)
wikilog = "Build succeeded" wikilog = "Build succeeded"
except BuildException as be: except BuildException as be:

View File

@ -25,6 +25,8 @@ from optparse import OptionParser
def main(): def main():
#Read configuration... #Read configuration...
global archive_older
archive_older = 0
execfile('config.py', globals()) execfile('config.py', globals())
# Parse command line... # Parse command line...
@ -41,12 +43,22 @@ def main():
print "The only command currently supported is 'update'" print "The only command currently supported is 'update'"
sys.exit(1) sys.exit(1)
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete', '--exclude', 'repo/index.xml', '--exclude', 'repo/index.jar', 'repo', serverwebroot]) != 0: repodirs = ['repo']
sys.exit(1) if archive_older != 0:
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete', 'repo/index.xml', serverwebroot + '/repo']) != 0: repodirs.append('archive')
sys.exit(1)
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete', 'repo/index.jar', serverwebroot + '/repo']) != 0: for repodir in repodirs:
sys.exit(1) index = os.path.join(repodir, 'index.xml')
indexjar = os.path.join(repodir, 'index.jar')
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete',
'--exclude', index, '--exclude', indexjar, repodir, serverwebroot]) != 0:
sys.exit(1)
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete',
index, serverwebroot + '/' + repodir]) != 0:
sys.exit(1)
if subprocess.call(['rsync', '-u', '-v', '-r', '--delete',
indexjar, serverwebroot + '/' + repodir]) != 0:
sys.exit(1)
sys.exit(0) sys.exit(0)

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# update.py - part of the FDroid server tools # update.py - part of the FDroid server tools
# Copyright (C) 2010-12, Ciaran Gultnieks, ciaran@ciarang.com # Copyright (C) 2010-2013, Ciaran Gultnieks, ciaran@ciarang.com
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU Affero General Public License as published by
@ -182,88 +182,52 @@ def update_wiki(apps, apks, verbose=False):
print "...FAILED to create page" print "...FAILED to create page"
def delete_disabled_builds(apps, apkcache, repodirs):
"""Delete disabled build outputs.
def main(): :param apps: list of all applications, as per common.read_metadata
:param apkcache: current apk cache information
# Read configuration... :param repodirs: the repo directories to process
global update_stats """
update_stats = False for app in apps:
execfile('config.py', globals()) for build in app['builds']:
if build['commit'].startswith('!'):
# Parse command line... apkfilename = app['id'] + '_' + str(build['vercode']) + '.apk'
parser = OptionParser() for repodir in repodirs:
parser.add_option("-c", "--createmeta", action="store_true", default=False, apkpath = os.path.join(repodir, apkfilename)
help="Create skeleton metadata files that are missing") srcpath = os.path.join(repodir, apkfilename[:-4] + "_src.tar.gz")
parser.add_option("-v", "--verbose", action="store_true", default=False, for name in [apkpath, srcpath]:
help="Spew out even more information than normal") if os.path.exists(name):
parser.add_option("-q", "--quiet", action="store_true", default=False, print "Deleting disabled build output " + apkfilename
help="No output, except for warnings and errors") os.remove(name)
parser.add_option("-b", "--buildreport", action="store_true", default=False, if apkfilename in apkcache:
help="Report on build data status") del apkcache[apkfilename]
parser.add_option("-i", "--interactive", default=False, action="store_true",
help="Interactively ask about things that need updating.")
parser.add_option("-e", "--editor", default="/etc/alternatives/editor",
help="Specify editor to use in interactive mode. Default "+
"is /etc/alternatives/editor")
parser.add_option("-w", "--wiki", default=False, action="store_true",
help="Update the wiki")
parser.add_option("", "--pretty", action="store_true", default=False,
help="Produce human-readable index.xml")
parser.add_option("--clean", action="store_true", default=False,
help="Clean update - don't uses caches, reprocess all apks")
(options, args) = parser.parse_args()
icon_dir=os.path.join('repo','icons') def scan_apks(apps, apkcache, repodir, knownapks):
"""Scan the apks in the given repo directory.
This also extracts the icons.
:param apps: list of all applications, as per common.read_metadata
:param apkcache: current apk cache information
:param repodir: repo directory to scan
:param knownapks: known apks info
:returns: (apks, cachechanged) where apks is a list of apk information,
and cachechanged is True if the apkcache got changed.
"""
cachechanged = False
icon_dir = os.path.join(repodir ,'icons')
# Delete and re-create the icon directory... # Delete and re-create the icon directory...
if options.clean and os.path.exists(icon_dir): if options.clean and os.path.exists(icon_dir):
shutil.rmtree(icon_dir) shutil.rmtree(icon_dir)
if not os.path.exists(icon_dir): if not os.path.exists(icon_dir):
os.makedirs(icon_dir) os.makedirs(icon_dir)
warnings = 0
# Get all apps...
apps = common.read_metadata(verbose=options.verbose)
# Generate a list of categories...
categories = []
for app in apps:
cats = app['Category'].split(';')
for cat in cats:
if cat not in categories:
categories.append(cat)
# Read known apks data (will be updated and written back when we've finished)
knownapks = common.KnownApks()
# Gather information about all the apk files in the repo directory, using
# cached data if possible.
apkcachefile = os.path.join('tmp', 'apkcache')
if not options.clean and os.path.exists(apkcachefile):
with open(apkcachefile, 'rb') as cf:
apkcache = pickle.load(cf)
else:
apkcache = {}
cachechanged = False
# Check repo directory for disabled builds and remove them...
for app in apps:
for build in app['builds']:
if build['commit'].startswith('!'):
apkfilename = app['id'] + '_' + str(build['vercode']) + '.apk'
apkpath = os.path.join('repo', apkfilename)
srcpath = apkfilename[:-4] + "_src.tar.gz"
for name in [apkpath, srcpath]:
if os.path.exists(name):
print "Deleting disabled build output " + apkfilename
os.remove(name)
if apkfilename in apkcache:
del apkcache[apkfilename]
apks = [] apks = []
for apkfile in glob.glob(os.path.join('repo','*.apk')): for apkfile in glob.glob(os.path.join(repodir, '*.apk')):
apkfilename = apkfile[5:] apkfilename = apkfile[5:]
if apkfilename.find(' ') != -1: if apkfilename.find(' ') != -1:
@ -282,7 +246,7 @@ def main():
print "Processing " + apkfilename print "Processing " + apkfilename
thisinfo = {} thisinfo = {}
thisinfo['apkname'] = apkfilename thisinfo['apkname'] = apkfilename
if os.path.exists(os.path.join('repo', srcfilename)): if os.path.exists(os.path.join(repodir, srcfilename)):
thisinfo['srcname'] = srcfilename thisinfo['srcname'] = srcfilename
thisinfo['size'] = os.path.getsize(apkfile) thisinfo['size'] = os.path.getsize(apkfile)
thisinfo['permissions'] = [] thisinfo['permissions'] = []
@ -377,7 +341,6 @@ def main():
iconfile.close() iconfile.close()
except: except:
print "WARNING: Error retrieving icon file" print "WARNING: Error retrieving icon file"
warnings += 1
apk.close() apk.close()
# Record in known apks, getting the added date at the same time.. # Record in known apks, getting the added date at the same time..
@ -390,79 +353,20 @@ def main():
apks.append(thisinfo) apks.append(thisinfo)
if cachechanged: return apks, cachechanged
with open(apkcachefile, 'wb') as cf:
pickle.dump(apkcache, cf)
# Some information from the apks needs to be applied up to the application
# level. When doing this, we use the info from the most recent version's apk.
# We deal with figuring out when the app was added and last updated at the
# same time.
for app in apps:
bestver = 0
added = None
lastupdated = None
for apk in apks:
if apk['id'] == app['id']:
if apk['versioncode'] > bestver:
bestver = apk['versioncode']
bestapk = apk
if 'added' in apk: def make_index(apps, apks, repodir, archive, categories):
if not added or apk['added'] < added: """Make a repo index.
added = apk['added']
if not lastupdated or apk['added'] > lastupdated:
lastupdated = apk['added']
if added: :param apps: fully populated apps list
app['added'] = added :param apks: full populated apks list
else: :param repodir: the repo directory
print "WARNING: Don't know when " + app['id'] + " was added" :param archive: True if this is the archive repo, False if it's the
if lastupdated: main one.
app['lastupdated'] = lastupdated :param categories: list of categories
else: """
print "WARNING: Don't know when " + app['id'] + " was last updated"
if bestver == 0:
if app['Name'] is None:
app['Name'] = app['id']
app['icon'] = ''
if app['Disabled'] is None:
print "WARNING: Application " + app['id'] + " has no packages"
else:
if app['Name'] is None:
app['Name'] = bestapk['name']
app['icon'] = bestapk['icon']
# Generate warnings for apk's with no metadata (or create skeleton
# metadata files, if requested on the command line)
for apk in apks:
found = False
for app in apps:
if app['id'] == apk['id']:
found = True
break
if not found:
if options.createmeta:
f = open(os.path.join('metadata', apk['id'] + '.txt'), 'w')
f.write("License:Unknown\n")
f.write("Web Site:\n")
f.write("Source Code:\n")
f.write("Issue Tracker:\n")
f.write("Summary:" + apk['name'] + "\n")
f.write("Description:\n")
f.write(apk['name'] + "\n")
f.write(".\n")
f.close()
print "Generated skeleton metadata for " + apk['id']
else:
print "WARNING: " + apk['apkname'] + " (" + apk['id'] + ") has no metadata"
print " " + apk['name'] + " - " + apk['version']
#Sort the app list by name, then the web site doesn't have to by default:
apps = sorted(apps, key=lambda app: app['Name'].upper())
# Create the index
doc = Document() doc = Document()
def addElement(name, value, doc, parent): def addElement(name, value, doc, parent):
@ -478,9 +382,16 @@ def main():
doc.appendChild(root) doc.appendChild(root)
repoel = doc.createElement("repo") repoel = doc.createElement("repo")
repoel.setAttribute("name", repo_name) if archive:
repoel.setAttribute("icon", os.path.basename(repo_icon)) repoel.setAttribute("name", archive_name)
repoel.setAttribute("url", repo_url) repoel.setAttribute("icon", os.path.basename(archive_icon))
repoel.setAttribute("url", archive_url)
addElement('description', archive_description, doc, repoel)
else:
repoel.setAttribute("name", repo_name)
repoel.setAttribute("icon", os.path.basename(repo_icon))
repoel.setAttribute("url", repo_url)
addElement('description', repo_description, doc, repoel)
if repo_keyalias != None: if repo_keyalias != None:
@ -509,30 +420,19 @@ def main():
repoel.setAttribute("pubkey", extract_pubkey()) repoel.setAttribute("pubkey", extract_pubkey())
addElement('description', repo_description, doc, repoel)
root.appendChild(repoel) root.appendChild(repoel)
apps_inrepo = 0
apps_disabled = 0
apps_nopkg = 0
for app in apps: for app in apps:
if app['Disabled'] is None: if app['Disabled'] is None:
# Get a list of the apks for this app... # Get a list of the apks for this app...
gotcurrentver = False
apklist = [] apklist = []
for apk in apks: for apk in apks:
if apk['id'] == app['id']: if apk['id'] == app['id']:
if str(apk['versioncode']) == app['Current Version Code']:
gotcurrentver = True
apklist.append(apk) apklist.append(apk)
if len(apklist) == 0: if len(apklist) != 0:
apps_nopkg += 1
else:
apps_inrepo += 1
apel = doc.createElement("application") apel = doc.createElement("application")
apel.setAttribute("id", app['id']) apel.setAttribute("id", app['id'])
root.appendChild(apel) root.appendChild(apel)
@ -627,62 +527,7 @@ def main():
if len(features) > 0: if len(features) > 0:
addElement('features', features, doc, apkel) addElement('features', features, doc, apkel)
if options.buildreport: of = open(os.path.join(repodir, 'index.xml'), 'wb')
if len(app['builds']) == 0:
print ("WARNING: No builds defined for " + app['id'] +
" Source: " + app['Source Code'])
warnings += 1
else:
if app['Current Version Code'] != '0':
gotbuild = False
for build in app['builds']:
if build['vercode'] == app['Current Version Code']:
gotbuild = True
if not gotbuild:
print ("WARNING: No build data for current version of "
+ app['id'] + " (" + app['Current Version']
+ ") " + app['Source Code'])
warnings += 1
# If we don't have the current version, check if there is a build
# with a commit ID starting with '!' - this means we can't build it
# for some reason, and don't want hassling about it...
if not gotcurrentver and app['Current Version Code'] != '0':
for build in app['builds']:
if build['vercode'] == app['Current Version Code']:
gotcurrentver = True
# Output a message of harassment if we don't have the current version:
if not gotcurrentver and app['Current Version Code'] != '0':
addr = app['Source Code']
print "WARNING: Don't have current version (" + app['Current Version'] + ") of " + app['Name']
print " (" + app['id'] + ") " + addr
warnings += 1
if options.verbose:
# A bit of extra debug info, basically for diagnosing
# app developer mistakes:
print " Current vercode:" + app['Current Version Code']
print " Got:"
for apk in apks:
if apk['id'] == app['id']:
print " " + str(apk['versioncode']) + " - " + apk['version']
if options.interactive:
print "Build data out of date for " + app['id']
while True:
answer = raw_input("[I]gnore, [E]dit or [Q]uit?").lower()
if answer == 'i':
break
elif answer == 'e':
subprocess.call([options.editor,
os.path.join('metadata',
app['id'] + '.txt')])
break
elif answer == 'q':
sys.exit(0)
else:
apps_disabled += 1
of = open(os.path.join('repo','index.xml'), 'wb')
if options.pretty: if options.pretty:
output = doc.toprettyxml() output = doc.toprettyxml()
else: else:
@ -698,7 +543,7 @@ def main():
#Create a jar of the index... #Create a jar of the index...
p = subprocess.Popen(['jar', 'cf', 'index.jar', 'index.xml'], p = subprocess.Popen(['jar', 'cf', 'index.jar', 'index.xml'],
cwd='repo', stdout=subprocess.PIPE) cwd=repodir, stdout=subprocess.PIPE)
output = p.communicate()[0] output = p.communicate()[0]
if options.verbose: if options.verbose:
print output print output
@ -710,7 +555,7 @@ def main():
p = subprocess.Popen(['jarsigner', '-keystore', keystore, p = subprocess.Popen(['jarsigner', '-keystore', keystore,
'-storepass', keystorepass, '-keypass', keypass, '-storepass', keystorepass, '-keypass', keypass,
'-digestalg', 'SHA1', '-sigalg', 'MD5withRSA', '-digestalg', 'SHA1', '-sigalg', 'MD5withRSA',
os.path.join('repo', 'index.jar') , repo_keyalias], stdout=subprocess.PIPE) os.path.join(repodir, 'index.jar') , repo_keyalias], stdout=subprocess.PIPE)
output = p.communicate()[0] output = p.communicate()[0]
if p.returncode != 0: if p.returncode != 0:
print "Failed to sign index" print "Failed to sign index"
@ -720,6 +565,7 @@ def main():
print output print output
# Copy the repo icon into the repo directory... # Copy the repo icon into the repo directory...
icon_dir=os.path.join(repodir ,'icons')
iconfilename = os.path.join(icon_dir, os.path.basename(repo_icon)) iconfilename = os.path.join(icon_dir, os.path.basename(repo_icon))
shutil.copyfile(repo_icon, iconfilename) shutil.copyfile(repo_icon, iconfilename)
@ -727,10 +573,185 @@ def main():
catdata = '' catdata = ''
for cat in categories: for cat in categories:
catdata += cat + '\n' catdata += cat + '\n'
f = open('repo/categories.txt', 'w') f = open(os.path.join(repodir, 'categories.txt'), 'w')
f.write(catdata) f.write(catdata)
f.close() f.close()
def archive_old_apks(apps, apks, repodir, archivedir, keepversions):
for app in apps:
# Get a list of the apks for this app...
apklist = []
for apk in apks:
if apk['id'] == app['id']:
apklist.append(apk)
# Sort the apk list into version order...
apklist = sorted(apklist, key=lambda apk: apk['versioncode'], reverse=True)
if len(apklist) > keepversions:
for apk in apklist[keepversions:]:
print "Moving " + apk['apkname'] + " to archive"
shutil.move(os.path.join(repodir, apk['apkname']),
os.path.join(archivedir, apk['apkname']))
if 'srcname' in apk:
shutil.move(os.path.join(repodir, apk['srcname']),
os.path.join(archivedir, apk['srcname']))
apks.remove(apk)
def main():
# Read configuration...
global update_stats, archive_older
update_stats = False
archive_older = 0
execfile('config.py', globals())
# Parse command line...
global options
parser = OptionParser()
parser.add_option("-c", "--createmeta", action="store_true", default=False,
help="Create skeleton metadata files that are missing")
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="Spew out even more information than normal")
parser.add_option("-q", "--quiet", action="store_true", default=False,
help="No output, except for warnings and errors")
parser.add_option("-b", "--buildreport", action="store_true", default=False,
help="Report on build data status")
parser.add_option("-i", "--interactive", default=False, action="store_true",
help="Interactively ask about things that need updating.")
parser.add_option("-e", "--editor", default="/etc/alternatives/editor",
help="Specify editor to use in interactive mode. Default "+
"is /etc/alternatives/editor")
parser.add_option("-w", "--wiki", default=False, action="store_true",
help="Update the wiki")
parser.add_option("", "--pretty", action="store_true", default=False,
help="Produce human-readable index.xml")
parser.add_option("--clean", action="store_true", default=False,
help="Clean update - don't uses caches, reprocess all apks")
(options, args) = parser.parse_args()
# Get all apps...
apps = common.read_metadata(verbose=options.verbose)
# Generate a list of categories...
categories = []
for app in apps:
cats = app['Category'].split(';')
for cat in cats:
if cat not in categories:
categories.append(cat)
# Read known apks data (will be updated and written back when we've finished)
knownapks = common.KnownApks()
# Gather information about all the apk files in the repo directory, using
# cached data if possible.
apkcachefile = os.path.join('tmp', 'apkcache')
if not options.clean and os.path.exists(apkcachefile):
with open(apkcachefile, 'rb') as cf:
apkcache = pickle.load(cf)
else:
apkcache = {}
cachechanged = False
repodirs = ['repo']
if archive_older != 0:
repodirs.append('archive')
if not os.path.exists('archive'):
os.mkdir('archive')
delete_disabled_builds(apps, apkcache, repodirs)
apks, cc = scan_apks(apps, apkcache, repodirs[0], knownapks)
if cc:
cachechanged = True
# Some information from the apks needs to be applied up to the application
# level. When doing this, we use the info from the most recent version's apk.
# We deal with figuring out when the app was added and last updated at the
# same time.
for app in apps:
bestver = 0
added = None
lastupdated = None
for apk in apks:
if apk['id'] == app['id']:
if apk['versioncode'] > bestver:
bestver = apk['versioncode']
bestapk = apk
if 'added' in apk:
if not added or apk['added'] < added:
added = apk['added']
if not lastupdated or apk['added'] > lastupdated:
lastupdated = apk['added']
if added:
app['added'] = added
else:
print "WARNING: Don't know when " + app['id'] + " was added"
if lastupdated:
app['lastupdated'] = lastupdated
else:
print "WARNING: Don't know when " + app['id'] + " was last updated"
if bestver == 0:
if app['Name'] is None:
app['Name'] = app['id']
app['icon'] = ''
if app['Disabled'] is None:
print "WARNING: Application " + app['id'] + " has no packages"
else:
if app['Name'] is None:
app['Name'] = bestapk['name']
app['icon'] = bestapk['icon']
# Sort the app list by name, then the web site doesn't have to by default.
# (we had to wait until we'd scanned the apks to do this, because mostly the
# name comes from there!)
apps = sorted(apps, key=lambda app: app['Name'].upper())
# Generate warnings for apk's with no metadata (or create skeleton
# metadata files, if requested on the command line)
for apk in apks:
found = False
for app in apps:
if app['id'] == apk['id']:
found = True
break
if not found:
if options.createmeta:
f = open(os.path.join('metadata', apk['id'] + '.txt'), 'w')
f.write("License:Unknown\n")
f.write("Web Site:\n")
f.write("Source Code:\n")
f.write("Issue Tracker:\n")
f.write("Summary:" + apk['name'] + "\n")
f.write("Description:\n")
f.write(apk['name'] + "\n")
f.write(".\n")
f.close()
print "Generated skeleton metadata for " + apk['id']
else:
print "WARNING: " + apk['apkname'] + " (" + apk['id'] + ") has no metadata"
print " " + apk['name'] + " - " + apk['version']
if len(repodirs) > 1:
archive_old_apks(apps, apks, repodirs[0], repodirs[1], archive_older)
make_index(apps, apks, repodirs[0], False, categories)
if len(repodirs) > 1:
apks, cc = scan_apks(apps, apkcache, repodirs[1], knownapks)
if cc:
cachechanged = True
make_index(apps, apks, repodirs[1], True, categories)
if update_stats: if update_stats:
# Update known apks info... # Update known apks info...
@ -748,19 +769,19 @@ def main():
data += app['icon'] + "\t" data += app['icon'] + "\t"
data += app['License'] + "\n" data += app['License'] + "\n"
break break
f = open('repo/latestapps.dat', 'w') f = open(os.path.join(repodirs[0], 'latestapps.dat'), 'w')
f.write(data) f.write(data)
f.close() f.close()
if cachechanged:
with open(apkcachefile, 'wb') as cf:
pickle.dump(apkcache, cf)
# Update the wiki... # Update the wiki...
if options.wiki: if options.wiki:
update_wiki(apps, apks, options.verbose) update_wiki(apps, apks, options.verbose)
print "Finished." print "Finished."
print str(apps_inrepo) + " apps in repo"
print str(apps_disabled) + " disabled"
print str(apps_nopkg) + " with no packages"
print str(warnings) + " warnings"
if __name__ == "__main__": if __name__ == "__main__":
main() main()