Returns:
A VersionInfo object or None on error.
"""
+ hsh = ''
proc = RunGitCommand(directory, ['rev-parse', 'HEAD'])
if proc:
output = proc.communicate()[0].strip()
if proc.returncode == 0 and output:
- return VersionInfo('git', output[:7])
- return None
+ hsh = output
+ if not hsh:
+ return None
+ pos = ''
+ proc = RunGitCommand(directory, ['show', '-s', '--format=%B', 'HEAD'])
+ if proc:
+ output = proc.communicate()[0]
+ if proc.returncode == 0 and output:
+ for line in reversed(output.splitlines()):
+ if line.startswith('Cr-Commit-Position:'):
+ pos = line.rsplit()[-1].strip()
+ if not pos:
+ return VersionInfo('git', hsh)
+ return VersionInfo('git', '%s-%s' % (hsh, pos))
def FetchGitSVNURLAndRevision(directory, svn_url_regex):
Returns:
A tuple containing the Subversion URL and revision.
"""
- proc = RunGitCommand(directory, ['log', '-1',
- '--grep=git-svn-id', '--format=%b'])
+ proc = RunGitCommand(directory, ['log', '-1', '--format=%b'])
if proc:
output = proc.communicate()[0].strip()
if proc.returncode == 0 and output:
version_info = VersionInfo(None, None)
return version_info
+def GetHeaderGuard(path):
+ """
+ Returns the header #define guard for the given file path.
+ This treats everything after the last instance of "src/" as being a
+ relevant part of the guard. If there is no "src/", then the entire path
+ is used.
+ """
+ src_index = path.rfind('src/')
+ if src_index != -1:
+ guard = path[src_index + 4:]
+ else:
+ guard = path
+ guard = guard.upper()
+ return guard.replace('/', '_').replace('.', '_').replace('\\', '_') + '_'
+
+def GetHeaderContents(path, define, version):
+ """
+ Returns what the contents of the header file should be that indicate the given
+ revision. Note that the #define is specified as a string, even though it's
+ currently always a SVN revision number, in case we need to move to git hashes.
+ """
+ header_guard = GetHeaderGuard(path)
+
+ header_contents = """/* Generated by lastchange.py, do not edit.*/
+
+#ifndef %(header_guard)s
+#define %(header_guard)s
+
+#define %(define)s "%(version)s"
+
+#endif // %(header_guard)s
+"""
+ header_contents = header_contents % { 'header_guard': header_guard,
+ 'define': define,
+ 'version': version }
+ return header_contents
def WriteIfChanged(file_name, contents):
"""
parser = optparse.OptionParser(usage="lastchange.py [options]")
parser.add_option("-d", "--default-lastchange", metavar="FILE",
- help="default last change input FILE")
+ help="Default last change input FILE.")
+ parser.add_option("-m", "--version-macro",
+ help="Name of C #define when using --header. Defaults to " +
+ "LAST_CHANGE.",
+ default="LAST_CHANGE")
parser.add_option("-o", "--output", metavar="FILE",
- help="write last change to FILE")
+ help="Write last change to FILE. " +
+ "Can be combined with --header to write both files.")
+ parser.add_option("", "--header", metavar="FILE",
+ help="Write last change to FILE as a C/C++ header. " +
+ "Can be combined with --output to write both files.")
parser.add_option("--revision-only", action='store_true',
- help="just print the SVN revision number")
+ help="Just print the SVN revision number. Overrides any " +
+ "file-output-related options.")
parser.add_option("-s", "--source-dir", metavar="DIR",
- help="use repository in the given directory")
+ help="Use repository in the given directory.")
opts, args = parser.parse_args(argv[1:])
out_file = opts.output
+ header = opts.header
while len(args) and out_file is None:
if out_file is None:
print version_info.revision
else:
contents = "LASTCHANGE=%s\n" % version_info.revision
- if out_file:
- WriteIfChanged(out_file, contents)
- else:
+ if not out_file and not opts.header:
sys.stdout.write(contents)
+ else:
+ if out_file:
+ WriteIfChanged(out_file, contents)
+ if header:
+ WriteIfChanged(header,
+ GetHeaderContents(header, opts.version_macro,
+ version_info.revision))
return 0