Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3709)

Unified Diff: build/util/lastchange.py

Issue 2101243005: Add a snapshot of flutter/engine/src/build to our sdk (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: add README.dart Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/util/LASTCHANGE ('k') | build/util/lib/common/__init__.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/util/lastchange.py
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
new file mode 100755
index 0000000000000000000000000000000000000000..3f3ee4af47117c5d00143713217a27964eb226c6
--- /dev/null
+++ b/build/util/lastchange.py
@@ -0,0 +1,309 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+lastchange.py -- Chromium revision fetching utility.
+"""
+
+import re
+import optparse
+import os
+import subprocess
+import sys
+
+_GIT_SVN_ID_REGEX = re.compile(r'.*git-svn-id:\s*([^@]*)@([0-9]+)', re.DOTALL)
+
+class VersionInfo(object):
+ def __init__(self, url, revision):
+ self.url = url
+ self.revision = revision
+
+
+def FetchSVNRevision(directory, svn_url_regex):
+ """
+ Fetch the Subversion branch and revision for a given directory.
+
+ Errors are swallowed.
+
+ Returns:
+ A VersionInfo object or None on error.
+ """
+ try:
+ proc = subprocess.Popen(['svn', 'info'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=directory,
+ shell=(sys.platform=='win32'))
+ except OSError:
+ # command is apparently either not installed or not executable.
+ return None
+ if not proc:
+ return None
+
+ attrs = {}
+ for line in proc.stdout:
+ line = line.strip()
+ if not line:
+ continue
+ key, val = line.split(': ', 1)
+ attrs[key] = val
+
+ try:
+ match = svn_url_regex.search(attrs['URL'])
+ if match:
+ url = match.group(2)
+ else:
+ url = ''
+ revision = attrs['Revision']
+ except KeyError:
+ return None
+
+ return VersionInfo(url, revision)
+
+
+def RunGitCommand(directory, command):
+ """
+ Launches git subcommand.
+
+ Errors are swallowed.
+
+ Returns:
+ A process object or None.
+ """
+ command = ['git'] + command
+ # Force shell usage under cygwin. This is a workaround for
+ # mysterious loss of cwd while invoking cygwin's git.
+ # We can't just pass shell=True to Popen, as under win32 this will
+ # cause CMD to be used, while we explicitly want a cygwin shell.
+ if sys.platform == 'cygwin':
+ command = ['sh', '-c', ' '.join(command)]
+ try:
+ proc = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=directory,
+ shell=(sys.platform=='win32'))
+ return proc
+ except OSError:
+ return None
+
+
+def FetchGitRevision(directory):
+ """
+ Fetch the Git hash for a given directory.
+
+ Errors are swallowed.
+
+ 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:
+ hsh = output
+ if not hsh:
+ return None
+ pos = ''
+ proc = RunGitCommand(directory, ['cat-file', 'commit', '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()
+ break
+ if not pos:
+ return VersionInfo('git', hsh)
+ return VersionInfo('git', '%s-%s' % (hsh, pos))
+
+
+def FetchGitSVNURLAndRevision(directory, svn_url_regex, go_deeper):
+ """
+ Fetch the Subversion URL and revision through Git.
+
+ Errors are swallowed.
+
+ Returns:
+ A tuple containing the Subversion URL and revision.
+ """
+ git_args = ['log', '-1', '--format=%b']
+ if go_deeper:
+ git_args.append('--grep=git-svn-id')
+ proc = RunGitCommand(directory, git_args)
+ if proc:
+ output = proc.communicate()[0].strip()
+ if proc.returncode == 0 and output:
+ # Extract the latest SVN revision and the SVN URL.
+ # The target line is the last "git-svn-id: ..." line like this:
+ # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
+ match = _GIT_SVN_ID_REGEX.search(output)
+ if match:
+ revision = match.group(2)
+ url_match = svn_url_regex.search(match.group(1))
+ if url_match:
+ url = url_match.group(2)
+ else:
+ url = ''
+ return url, revision
+ return None, None
+
+
+def FetchGitSVNRevision(directory, svn_url_regex, go_deeper):
+ """
+ Fetch the Git-SVN identifier for the local tree.
+
+ Errors are swallowed.
+ """
+ url, revision = FetchGitSVNURLAndRevision(directory, svn_url_regex, go_deeper)
+ if url and revision:
+ return VersionInfo(url, revision)
+ return None
+
+
+def FetchVersionInfo(default_lastchange, directory=None,
+ directory_regex_prior_to_src_url='chrome|blink|svn',
+ go_deeper=False):
+ """
+ Returns the last change (in the form of a branch, revision tuple),
+ from some appropriate revision control system.
+ """
+ svn_url_regex = re.compile(
+ r'.*/(' + directory_regex_prior_to_src_url + r')(/.*)')
+
+ version_info = (FetchSVNRevision(directory, svn_url_regex) or
+ FetchGitSVNRevision(directory, svn_url_regex, go_deeper) or
+ FetchGitRevision(directory))
+ if not version_info:
+ if default_lastchange and os.path.exists(default_lastchange):
+ revision = open(default_lastchange, 'r').read().strip()
+ version_info = VersionInfo(None, revision)
+ else:
+ 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):
+ """
+ Writes the specified contents to the specified file_name
+ iff the contents are different than the current contents.
+ """
+ try:
+ old_contents = open(file_name, 'r').read()
+ except EnvironmentError:
+ pass
+ else:
+ if contents == old_contents:
+ return
+ os.unlink(file_name)
+ open(file_name, 'w').write(contents)
+
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+
+ parser = optparse.OptionParser(usage="lastchange.py [options]")
+ parser.add_option("-d", "--default-lastchange", metavar="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. " +
+ "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. Overrides any " +
+ "file-output-related options.")
+ parser.add_option("-s", "--source-dir", metavar="DIR",
+ help="Use repository in the given directory.")
+ parser.add_option("--git-svn-go-deeper", action='store_true',
+ help="In a Git-SVN repo, dig down to the last committed " +
+ "SVN change (historic behaviour).")
+ 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:
+ out_file = args.pop(0)
+ if args:
+ sys.stderr.write('Unexpected arguments: %r\n\n' % args)
+ parser.print_help()
+ sys.exit(2)
+
+ if opts.source_dir:
+ src_dir = opts.source_dir
+ else:
+ src_dir = os.path.dirname(os.path.abspath(__file__))
+
+ version_info = FetchVersionInfo(opts.default_lastchange,
+ directory=src_dir,
+ go_deeper=opts.git_svn_go_deeper)
+
+ if version_info.revision == None:
+ version_info.revision = '0'
+
+ if opts.revision_only:
+ print version_info.revision
+ else:
+ contents = "LASTCHANGE=%s\n" % version_info.revision
+ 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
+
+
+if __name__ == '__main__':
+ sys.exit(main())
« no previous file with comments | « build/util/LASTCHANGE ('k') | build/util/lib/common/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698