FreeCAD/src/Tools/SubWCRev.py

272 lines
8.7 KiB
Python

#! python
# -*- coding: utf-8 -*-
# (c) 2006 Werner Mayer LGPL
#
# FreeCAD RevInfo script to get the revision information from Subversion.
#
# Under Linux the Subversion tool SubWCRev shipped with TortoiseSVN isn't
# available which is provided by this script.
# 2011/02/05: The script was extended to support also Bazaar
import os,sys,string,re,time,getopt
import xml.sax
import xml.sax.handler
import xml.sax.xmlreader
import StringIO
# SAX handler to parse the subversion output
class SvnHandler(xml.sax.handler.ContentHandler):
def __init__(self):
self.inUrl = 0
self.inDate = 0
self.mapping = {}
def startElement(self, name, attributes):
if name == "entry":
self.buffer = ""
self.mapping["Rev"] = attributes["revision"]
elif name == "url":
self.inUrl = 1
elif name == "date":
self.inDate = 1
def characters(self, data):
if self.inUrl:
self.buffer += data
elif self.inDate:
self.buffer += data
def endElement(self, name):
if name == "url":
self.inUrl = 0
self.mapping["Url"] = self.buffer
self.buffer = ""
elif name == "date":
self.inDate = 0
self.mapping["Date"] = self.buffer
self.buffer = ""
class VersionControl:
def __init__(self):
self.rev = ""
self.date = ""
self.url = ""
def extractInfo(self, srcdir):
return False
def printInfo(self):
print ""
def writeVersion(self, lines):
content=[]
for line in lines:
line = string.replace(line,'$WCREV$',self.rev)
line = string.replace(line,'$WCDATE$',self.date)
line = string.replace(line,'$WCURL$',self.url)
content.append(line)
return content
class UnknownControl(VersionControl):
def extractInfo(self, srcdir):
# Do not overwrite existing file with almost useless information
if os.path.exists(srcdir+"/src/Build/Version.h"):
return False
self.rev = "Unknown"
self.date = "Unknown"
self.url = "Unknown"
return True
def printInfo(self):
print "Unknown version control"
class DebianChangelog(VersionControl):
def extractInfo(self, srcdir):
# Do not overwrite existing file with almost useless information
if os.path.exists(srcdir+"/src/Build/Version.h"):
return False
try:
f = open(srcdir+"/debian/changelog")
except:
return False
c = f.readline()
f.close()
r=re.search("bzr(\\d+)",c)
if r != None:
self.rev = r.groups()[0] + " (Launchpad)"
t = time.localtime()
self.date = ("%d/%02d/%02d %02d:%02d:%02d") % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
self.url = "https://code.launchpad.net/~vcs-imports/freecad/trunk"
return True
def printInfo(self):
print "debian/changelog"
class BazaarControl(VersionControl):
def extractInfo(self, srcdir):
info=os.popen("bzr log -l 1 %s" % (srcdir)).read()
if len(info) == 0:
return False
lines=info.split("\n")
for i in lines:
r = re.match("^revno: (\\d+)$", i)
if r != None:
self.rev = r.groups()[0]
continue
r=re.match("^timestamp: (\\w+ \\d+-\\d+-\\d+ \\d+:\\d+:\\d+)",i)
if r != None:
self.date = r.groups()[0]
continue
return True
def printInfo(self):
print "bazaar"
class GitControl(VersionControl):
#http://www.hermanradtke.com/blog/canonical-version-numbers-with-git/
#http://blog.marcingil.com/2011/11/creating-build-numbers-using-git-commits/
#http://gitref.org/remotes/#fetch
#http://cworth.org/hgbook-git/tour/
#http://git.or.cz/course/svn.html
#git help log
def extractInfo(self, srcdir):
# revision number
info=os.popen("git rev-list HEAD").read()
if len(info) == 0:
return False
self.rev='%04d (Git)' % (info.count('\n'))
# date/time
info=os.popen("git log -1 --date=iso").read()
info=info.split("\n")
for i in info:
r = re.match("^Date:\\W+(\\d+-\\d+-\\d+\\W+\\d+:\\d+:\\d+)", i)
if r != None:
self.date = r.groups()[0].replace('-','/')
break
self.url = "Unknown"
info=os.popen("git remote -v").read()
info=info.split("\n")
for i in info:
r = re.match("origin\\W+(\\S+)",i)
if r != None:
self.url = r.groups()[0]
break
self.hash=os.popen("git log -1 --pretty=format:%H").read()
for self.branch in os.popen("git branch").read().split('\n'):
if re.match( "\*", self.branch ) != None:
break
self.branch=self.branch[2:]
return True
def printInfo(self):
print "git"
def writeVersion(self, lines):
content = VersionControl.writeVersion(self, lines)
content.append('// Git relevant stuff\n')
content.append('#define FCRepositoryHash "%s"\n' % (self.hash))
content.append('#define FCRepositoryBranch "%s"\n' % (self.branch))
return content
class MercurialControl(VersionControl):
def extractInfo(self, srcdir):
return False
def printInfo(self):
print "mercurial"
class Subversion(VersionControl):
def extractInfo(self, srcdir):
parser=xml.sax.make_parser()
handler=SvnHandler()
parser.setContentHandler(handler)
#Create an XML stream with the required information and read in with a SAX parser
Ver=os.popen("svnversion %s -n" % (srcdir)).read()
Info=os.popen("svn info %s --xml" % (srcdir)).read()
try:
inpsrc = xml.sax.InputSource()
strio=StringIO.StringIO(Info)
inpsrc.setByteStream(strio)
parser.parse(inpsrc)
except:
return False
#Information of the Subversion stuff
self.url = handler.mapping["Url"]
self.rev = handler.mapping["Rev"]
self.date = handler.mapping["Date"]
self.date = self.date[:19]
#Same format as SubWCRev does
self.date = string.replace(self.date,'T',' ')
self.date = string.replace(self.date,'-','/')
#Date is given as GMT. Now we must convert to local date.
m=time.strptime(self.date,"%Y/%m/%d %H:%M:%S")
#Copy the tuple and set tm_isdst to 0 because it's GMT
l=(m.tm_year,m.tm_mon,m.tm_mday,m.tm_hour,m.tm_min,m.tm_sec,m.tm_wday,m.tm_yday,0)
#Take timezone into account
t=time.mktime(l)-time.timezone
self.date=time.strftime("%Y/%m/%d %H:%M:%S",time.localtime(t))
#Get the current local date
self.time = time.strftime("%Y/%m/%d %H:%M:%S")
self.mods = 'Src not modified'
self.mixed = 'Src not mixed'
self.range = self.rev
# if version string ends with an 'M'
r=re.search("M$",Ver)
if r != None:
self.mods = 'Src modified'
# if version string contains a range
r=re.match("^\\d+\\:\\d+",Ver)
if r != None:
self.mixed = 'Src mixed'
self.range = Ver[:r.end()]
return True
def printInfo(self):
print "subversion"
def main():
#if(len(sys.argv) != 2):
# sys.stderr.write("Usage: SubWCRev \"`svn info .. --xml`\"\n")
srcdir="."
bindir="."
try:
opts, args = getopt.getopt(sys.argv[1:], "sb:", ["srcdir=","bindir="])
except getopt.GetoptError:
pass
for o, a in opts:
if o in ("-s", "--srcdir"):
srcdir = a
if o in ("-b", "--bindir"):
bindir = a
vcs=[GitControl(), BazaarControl(), Subversion(), MercurialControl(), DebianChangelog(), UnknownControl()]
for i in vcs:
if i.extractInfo(srcdir):
# Open the template file and the version file
file = open("%s/src/Build/Version.h.in" % (srcdir))
lines = file.readlines()
file.close()
lines = i.writeVersion(lines)
out = open("%s/src/Build/Version.h" % (bindir),"w");
out.writelines(lines)
out.write('\n')
out.close()
i.printInfo()
sys.stdout.write("%s/src/Build/Version.h written\n" % (bindir))
break
if __name__ == "__main__":
main()