From: Ralf Jung <post@ralfj.de>
Date: Wed, 6 Feb 2013 21:39:25 +0000 (+0100)
Subject: implement a version checker
X-Git-Url: https://git.ralfj.de/mass-build.git/commitdiff_plain/cd1b16983d17b2cf8675166758c48fe4bfd0bb0a

implement a version checker
---

diff --git a/build_system.py b/build_system.py
index 290eb6d..4658f4a 100644
--- a/build_system.py
+++ b/build_system.py
@@ -88,7 +88,7 @@ try:
 			# get version name
 			versionName = self.config['versionName'] if 'versionName' in self.config else self.vcs.version()
 			if versionName is None:
-				raise Exception("VCS did not provide us with a proper version number, please fix this")
+				raise Exception("VCS did not provide us with a proper version number, please provide one manually")
 			# create auto-debuild configuration
 			autoDebuildConfig = {
 				'sourceName': self.config['name'],
diff --git a/mass_build.py b/mass_build.py
index 3615dd6..0060da2 100755
--- a/mass_build.py
+++ b/mass_build.py
@@ -69,12 +69,12 @@ parser.add_argument("--no-update",
 parser.add_argument("--resume-from", metavar='PROJECT',
                     dest="resume_from",
                     help="From the projects specified, continue building with this one (i.e., remove all projects before this one from the list - this never adds new projects)")
+parser.add_argument("--check-versions",
+                    action="store_true", dest="version_check",
+                    help="Check the repositories for newer tags, if possible (does not perform any building steps)")
 parser.add_argument("projects",  metavar='PROJECT', nargs='*',
                     help="Manually specify projects or folders to be built (project names take precedence)")
 args = parser.parse_args()
-# sanitize
-if args.reset_source and not args.update:
-	raise Exception("When no update is performed, no reset to the given version can be done either")
 
 # load config
 config = imp.load_source('config', args.config).__dict__
@@ -139,11 +139,15 @@ if args.resume_from is not None:
 # and do it!
 for project in workProjects:
 	try:
-		if args.update:
-			print "Updating project",project.sourceFolder()
-			project.vcs.update(forceVersion=args.reset_source)
-		print "Building project",project.sourceFolder()
-		project.buildSystem.build(reconfigure=args.reconfigure, waitAfterConfig=args.wait_after_config)
+		if args.version_check:
+			print "Checking project",project.sourceFolder()
+			project.vcs.checkVersions()
+		else:
+			if args.update:
+				print "Updating project",project.sourceFolder()
+				project.vcs.update(mode = vcs.MODE_RESET if args.reset_source else vcs.MODE_REBASE)
+			print "Building project",project.sourceFolder()
+			project.buildSystem.build(reconfigure=args.reconfigure, waitAfterConfig=args.wait_after_config)
 		print
 	except (subprocess.CalledProcessError, KeyboardInterrupt) as e: # for some exceptions, a stackrace is usually pointless
 		print >> sys.stderr
diff --git a/vcs.py b/vcs.py
index 564b0c1..02a9192 100644
--- a/vcs.py
+++ b/vcs.py
@@ -15,12 +15,21 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
-import os, git, subprocess
+import os, git, subprocess, re
 
-'''A VCS must have an "update" method with an optional "forceVersion" parameter, and optionally a "version" method.'''
+'''A VCS must have an "update" method with an optional "mode" parameter taking one of the three values below,
+   a "version" method returning a version name (or None),
+   and a "newVersions" method which checks for new versions and prints the result to standard output.'''
+MODE_FETCH = 0
+MODE_REBASE = 1
+MODE_RESET = 2
+
+def natural_sort_key(val):
+	return [ (int(c) if c.isdigit() else c) for c in re.split('([0-9]+)', val) ]
 
 # Fetch updates from git
 class Git:
+	
 	def __init__(self, folder, url, commit):
 		self.folder = os.path.abspath(folder)
 		self.url = url
@@ -30,7 +39,7 @@ class Git:
 		def update(self, op_code, cur_count, max_count=None, message=''):
 			print self._cur_line+(" "*30)+"\r",
 
-	def update(self, forceVersion=False):
+	def update(self, mode = MODE_REBASE):
 		isBranch = (self.commit.startswith('origin/'))
 		if isBranch:
 			branchname = self.commit[len('origin/'):]
@@ -49,6 +58,8 @@ class Git:
 			origin = repo.create_remote('origin', self.url)
 		origin.fetch(progress=Git._ProgressPrinter()) # download new data
 		print " "*80+"\r", # clean the line we are in
+		if mode == MODE_FETCH:
+			return
 		# create/find correct branch
 		if branchname in repo.heads:
 			branch = repo.heads[branchname]
@@ -58,7 +69,7 @@ class Git:
 				branch.set_tracking_branch(origin.refs[branchname])
 		# update it to the latest remote commit
 		branch.checkout()
-		if forceVersion:
+		if mode == MODE_RESET:
 			repo.head.reset(self.commit, working_tree=True)
 		else:
 			repo.git.rebase(self.commit)
@@ -76,6 +87,23 @@ class Git:
 		if v.startswith('v'): v = v[1:]
 		return v
 
+	def checkVersions(self):
+		repo = git.Repo(self.folder)
+		# get tag for current commit, if any
+		commit = repo.commit(self.commit)
+		commitTag = filter(lambda t: t.commit == commit, repo.tags)
+		if not commitTag:
+			print "Version is not a tag"
+			return
+		currentVersion = str(commitTag[0])
+		# get sorted list of tag names
+		tags = map(str, repo.tags)
+		tags = filter(lambda t: natural_sort_key(t) > natural_sort_key(currentVersion), tags)
+		if not tags: return
+		tags.sort(key = natural_sort_key)
+		print "Versions newer than "+self.commit+" available:"
+		print tags
+
 # Fetch updates via SVN
 class SVN:
 	def __init__(self, folder, url):
@@ -90,3 +118,9 @@ class SVN:
 		else:
 			os.makedirs(self.folder) # if even the parent folder does not exist, svn fails
 			subprocess.check_call(['svn', 'co', self.url, self.folder]) # just download it
+	
+	def version(self):
+		return None
+	
+	def checkVersions(self):
+		print "Version checking not supporting with SVN"