summaryrefslogtreecommitdiffstats
path: root/tupkg/update
diff options
context:
space:
mode:
Diffstat (limited to 'tupkg/update')
-rwxr-xr-xtupkg/update/tupkgupdate236
1 files changed, 236 insertions, 0 deletions
diff --git a/tupkg/update/tupkgupdate b/tupkg/update/tupkgupdate
new file mode 100755
index 0000000..4dbac35
--- /dev/null
+++ b/tupkg/update/tupkgupdate
@@ -0,0 +1,236 @@
+#!/usr/bin/python -O
+
+import re
+import os
+import sys
+
+# Define some classes we need
+class Version:
+ def __init__(self):
+ self.version = None
+ self.file = None
+
+class Package:
+ def __init__(self):
+ self.name = None
+ self.old = None
+ self.new = None
+
+# And a few convenience functions
+def filesForRegexp(topdir, regexp):
+ retval = []
+ def matchfile(regexp, dirpath, namelist):
+ for name in namelist:
+ if (regexp.match(name)):
+ retval.append(os.path.join(dirpath, name))
+ os.path.walk(topdir, matchfile, regexp)
+ return retval
+
+def packagesInTree(topdir):
+ return filesForRegexp(topdir, re.compile("^.*\.pkg\.tar\.gz$"))
+
+def pkgbuildsInTree(topdir):
+ return filesForRegexp(topdir, re.compile("^PKGBUILD$"))
+
+def parseAssignLine(line):
+ if (line == None):
+ return None
+ defline_re = re.compile("^\s*(?P<key>\w+)\s*=\s*(?P<value>.+)\s*$")
+ quote_re = re.compile("[\"']")
+ match = defline_re.match(line)
+ if (match != None):
+ key = match.group("key")
+ value = match.group("value")
+ value = quote_re.sub('', value)
+ return key, value
+ else:
+ return None
+
+def infoFromPkgbuild(filename):
+ fobj = file(filename)
+ lines = fobj.readlines()
+ fobj.close()
+
+ pkgname = None
+ pkgver = None
+ pkgrel = None
+
+ for line in lines:
+ result = parseAssignLine(line)
+ if (result != None):
+ key, value = result
+ if (key == "pkgname"):
+ pkgname = value
+ elif (key == "pkgver"):
+ pkgver = value
+ elif (key == "pkgrel"):
+ pkgrel = value
+ if (pkgname != None and pkgver != None and pkgrel != None):
+ return pkgname, pkgver + "-" + pkgrel
+ return None
+
+def infoFromPackageFile(filename):
+ regexp = re.compile("^(?P<pkgname>[^-]+)-(?P<version>[^-]+-[^\.]+)\.pkg\.tar\.gz$")
+ match = regexp.match(filename)
+ if (match != None):
+ return match.group("pkgname"), match.group("version")
+ return None
+
+def copyFileToRepo(filename, repodir):
+ destfile = os.path.join(repodir, os.path.basename(filename))
+ command = "cp '" + filename + "' '" + destfile + "'"
+ print(command + "\n")
+
+def deleteFile(filename):
+ command = "rm '" + filename + "'"
+ print(command + "\n")
+
+def runGensync(repo, pkgbuild):
+ target = os.path.join(repo, os.path.basename(repo) + ".db.tar.gz")
+ command = "gensync '" + pkgbuild_dir + "' '" + target + "'"
+ print(command + "\n")
+
+had_error = 0
+def error(string):
+ global had_error
+ print >>sys.stderr, string + "\n"
+ had_error = 1
+
+# ARGUMENTS
+#
+# tupkgupdate <repo_dir> <pkgbuild_dir> <build_dir>
+
+if (len(sys.argv) < 4):
+ print >>sys.stderr, "syntax: update-repository <repo_dir> <pkgbuild_tree> <build_tree>"
+ sys.exit(-1)
+
+repo_dir, pkgbuild_dir, build_dir = sys.argv[1:]
+
+# Set up the lists and tables
+packages = dict()
+copy = list()
+delete = list()
+
+# PASS 1: PARSING/LOCATING
+#
+# A) Go through the PKGBUILD tree
+# For each PKGBUILD, create a Package with new Version containing parsed version and and None for file
+
+a_files = pkgbuildsInTree(pkgbuild_dir)
+for a_file in a_files:
+ pkgname, ver = infoFromPkgbuild(a_file)
+
+ # Error (and skip) if we encounter any invalid PKGBUILD files
+ if (pkgname == None or ver == None):
+ error("Pkgbuild '" + a_file + "' is invalid!")
+ continue
+
+ # Error (and skip) if we encounter any duplicate package names
+ if (packages.get(pkgname)):
+ error("Pkgbuild '" + a_file + "' is a duplicate!")
+ continue
+
+ version = Version()
+ version.version = ver
+ version.file = None
+
+ package = Package()
+ package.name = pkgname
+ package.new = version
+
+ packages[pkgname] = package
+
+# B) Go through the old repo dir
+# For each package file we encounter, create a Package with old Version containing parsed version and filepath
+
+b_files = packagesInTree(repo_dir)
+for b_file in b_files:
+ pkgname, ver = infoFromPackageFile(b_file)
+
+ version = Version()
+ version.version = ver
+ version.file = b_file
+
+ package = packages.get(pkgname)
+ if (package == None):
+ package = Package()
+ package.name = pkgname
+ packages[pkgname] = package
+ package.old = version
+
+# C) Go through the build tree
+# For each package file we encounter:
+# 1 - look up the package name; if it fails, ignore the file (no error)
+# 2 - if package.new = None, ignore the package (no error)
+# 3 - if package.new.version doesn't match, then skip (no error)
+# 4 - if package.new.file = None, set the new version to point to that file
+# otherwise, log an error (and skip)
+
+c_files = packagesInTree(build_dir)
+for c_file in c_files:
+ pkgname, ver = infoFromPackageFile(c_file)
+
+ # 1
+ package = packages.get(pkgname)
+ if (package == None):
+ continue
+
+ # 2
+ if (package.new == None):
+ continue
+
+ # 3
+ if (package.new.version != ver):
+ continue
+
+ # 4
+ if (package.new.file == None):
+ package.new.file = c_file
+ continue
+ else:
+ error("Duplicate new file '" + c_file + "'")
+ continue
+
+# PASS 2: CHECKING
+#
+# Go through the package collection
+# 1 - if package has no new, place its file on the "delete" list
+# 2 - if package has a new but no new.file, error and skip
+# 3 - if package has no old, add new file to "copy" list into repo dir
+# 4 - if old > new, error and skip
+#
+# if new and old are the same version, do nothing
+# otherwise, add entry to "delete" list for old file and "copy" list for new file into repo dir with obvious name
+
+for package in packages.values():
+ if (package.new == None):
+ delete.append(package.old.file)
+ continue
+ if (package.new.file == None):
+ error("No new package supplied for " + package.name + " " + package.new.version + "!")
+ continue
+ if (package.old == None):
+ copy.append(package.new.file)
+ if (package.old.ver > package.new.ver):
+ error("Old package " + package.name + " " + package.old.version + " is newer than new version " + package.new.version + "!")
+ continue
+ if (package.old.ver < package.new.ver):
+ delete.append(package.old.file)
+ copy.append(package.new.file)
+ # do nothing if the packages are equal in version
+
+## IF WE HAVE HAD ANY ERRORS AT THIS POINT, ABORT! ##
+if (had_error == 1):
+ error("Aborting due to errors.")
+ sys.exit(-1)
+
+# PASS 3: EXECUTION
+#
+# Copy
+for file in copy:
+ copyFileToRepo(file, repo_dir)
+# Delete (second, for safety's sake)
+for file in delete:
+ deleteFile(file)
+# Run gensync to build the repo index
+runGensync(repo_dir, pkgbuild_dir)