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

Unified Diff: tools/auto_bisect/source_control.py

Issue 418113003: Extract SourceControl to module; extract common methods to bisect_utils. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | « tools/auto_bisect/bisect_utils.py ('k') | tools/bisect-perf-regression.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/auto_bisect/source_control.py
diff --git a/tools/auto_bisect/source_control.py b/tools/auto_bisect/source_control.py
new file mode 100644
index 0000000000000000000000000000000000000000..66b7e73b35c232fb81e0c79d93df754f317ad05f
--- /dev/null
+++ b/tools/auto_bisect/source_control.py
@@ -0,0 +1,287 @@
+# Copyright 2014 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.
+
+"""This module contains the SourceControl class and related functions."""
+
+import os
+
+from . import bisect_utils
+
+CROS_VERSION_PATTERN = 'new version number from %s'
+
+
+def DetermineAndCreateSourceControl(opts):
+ """Attempts to determine the underlying source control workflow and returns
+ a SourceControl object.
+
+ Returns:
+ An instance of a SourceControl object, or None if the current workflow
+ is unsupported.
+ """
+ (output, _) = bisect_utils.RunGit(['rev-parse', '--is-inside-work-tree'])
+
+ if output.strip() == 'true':
+ return GitSourceControl(opts)
+
+ return None
+
+
+class SourceControl(object):
shatch 2014/07/25 16:28:50 Not for this CL, but probably ok to kill the abstr
+ """SourceControl is an abstraction over the source control system."""
+
+ def __init__(self):
+ super(SourceControl, self).__init__()
+
+ def SyncToRevisionWithGClient(self, revision):
+ """Uses gclient to sync to the specified revision.
+
+ ie. gclient sync --revision <revision>
+
+ Args:
+ revision: The git SHA1 or svn CL (depending on workflow).
+
+ Returns:
+ The return code of the call.
+ """
+ return bisect_utils.RunGClient(['sync', '--verbose', '--reset', '--force',
+ '--delete_unversioned_trees', '--nohooks', '--revision', revision])
+
+ def SyncToRevisionWithRepo(self, timestamp):
+ """Uses repo to sync all the underlying git depots to the specified
+ time.
+
+ Args:
+ timestamp: The unix timestamp to sync to.
+
+ Returns:
+ The return code of the call.
+ """
+ return bisect_utils.RunRepoSyncAtTimestamp(timestamp)
+
+
+class GitSourceControl(SourceControl):
+ """GitSourceControl is used to query the underlying source control."""
+
+ def __init__(self, opts):
+ super(GitSourceControl, self).__init__()
+ self.opts = opts
+
+ def IsGit(self):
+ return True
+
+ def GetRevisionList(self, revision_range_end, revision_range_start, cwd=None):
+ """Retrieves a list of revisions between |revision_range_start| and
+ |revision_range_end|.
+
+ Args:
+ revision_range_end: The SHA1 for the end of the range.
+ revision_range_start: The SHA1 for the beginning of the range.
+
+ Returns:
+ A list of the revisions between |revision_range_start| and
+ |revision_range_end| (inclusive).
+ """
+ revision_range = '%s..%s' % (revision_range_start, revision_range_end)
+ cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range]
+ log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
+
+ revision_hash_list = log_output.split()
+ revision_hash_list.append(revision_range_start)
+
+ return revision_hash_list
+
+ def SyncToRevision(self, revision, sync_client=None):
+ """Syncs to the specified revision.
+
+ Args:
+ revision: The revision to sync to.
+ use_gclient: Specifies whether or not we should sync using gclient or
+ just use source control directly.
+
+ Returns:
+ True if successful.
+ """
+
+ if not sync_client:
+ results = bisect_utils.RunGit(['checkout', revision])[1]
+ elif sync_client == 'gclient':
+ results = self.SyncToRevisionWithGClient(revision)
+ elif sync_client == 'repo':
+ results = self.SyncToRevisionWithRepo(revision)
+
+ return not results
+
+ def ResolveToRevision(self, revision_to_check, depot, depot_deps_dict,
+ search, cwd=None):
+ """If an SVN revision is supplied, try to resolve it to a git SHA1.
+
+ Args:
+ revision_to_check: The user supplied revision string that may need to be
+ resolved to a git SHA1.
+ depot: The depot the revision_to_check is from.
+ depot_deps_dict: A dictionary with information about different depots.
+ search: The number of changelists to try if the first fails to resolve
+ to a git hash. If the value is negative, the function will search
+ backwards chronologically, otherwise it will search forward.
+
+ Returns:
+ A string containing a git SHA1 hash, otherwise None.
+ """
+ # Android-chrome is git only, so no need to resolve this to anything else.
+ if depot == 'android-chrome':
+ return revision_to_check
+
+ if depot != 'cros':
+ if not bisect_utils.IsStringInt(revision_to_check):
+ return revision_to_check
+
+ depot_svn = 'svn://svn.chromium.org/chrome/trunk/src'
+
+ if depot != 'chromium':
+ depot_svn = depot_deps_dict[depot]['svn']
+
+ svn_revision = int(revision_to_check)
+ git_revision = None
+
+ if search > 0:
+ search_range = xrange(svn_revision, svn_revision + search, 1)
+ else:
+ search_range = xrange(svn_revision, svn_revision + search, -1)
+
+ for i in search_range:
+ svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i)
+ cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern,
+ 'origin/master']
+
+ (log_output, return_code) = bisect_utils.RunGit(cmd, cwd=cwd)
+
+ assert not return_code, 'An error occurred while running'\
+ ' "git %s"' % ' '.join(cmd)
+
+ if not return_code:
+ log_output = log_output.strip()
+
+ if log_output:
+ git_revision = log_output
+
+ break
+
+ return git_revision
+ else:
+ if bisect_utils.IsStringInt(revision_to_check):
+ return int(revision_to_check)
+ else:
+ cwd = os.getcwd()
+ os.chdir(os.path.join(os.getcwd(), 'src', 'third_party',
+ 'chromiumos-overlay'))
+ pattern = CROS_VERSION_PATTERN % revision_to_check
+ cmd = ['log', '--format=%ct', '-1', '--grep', pattern]
+
+ git_revision = None
+
+ log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
+ if log_output:
+ git_revision = log_output
+ git_revision = int(log_output.strip())
+ os.chdir(cwd)
+
+ return git_revision
+
+ def IsInProperBranch(self):
+ """Confirms they're in the master branch for performing the bisection.
+ This is needed or gclient will fail to sync properly.
+
+ Returns:
+ True if the current branch on src is 'master'
+ """
+ cmd = ['rev-parse', '--abbrev-ref', 'HEAD']
+ log_output = bisect_utils.CheckRunGit(cmd)
+ log_output = log_output.strip()
+
+ return log_output == "master"
+
+ def SVNFindRev(self, revision, cwd=None):
+ """Maps directly to the 'git svn find-rev' command.
+
+ Args:
+ revision: The git SHA1 to use.
+
+ Returns:
+ An integer changelist #, otherwise None.
+ """
+
+ cmd = ['svn', 'find-rev', revision]
+
+ output = bisect_utils.CheckRunGit(cmd, cwd)
+ svn_revision = output.strip()
+
+ if bisect_utils.IsStringInt(svn_revision):
+ return int(svn_revision)
+
+ return None
+
+ def QueryRevisionInfo(self, revision, cwd=None):
+ """Gathers information on a particular revision, such as author's name,
+ email, subject, and date.
+
+ Args:
+ revision: Revision you want to gather information on.
+ Returns:
+ A dict in the following format:
+ {
+ 'author': %s,
+ 'email': %s,
+ 'date': %s,
+ 'subject': %s,
+ 'body': %s,
+ }
+ """
+ commit_info = {}
+
+ formats = ['%cN', '%cE', '%s', '%cD', '%b']
+ targets = ['author', 'email', 'subject', 'date', 'body']
+
+ for i in xrange(len(formats)):
+ cmd = ['log', '--format=%s' % formats[i], '-1', revision]
+ output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
+ commit_info[targets[i]] = output.rstrip()
+
+ return commit_info
+
+ def CheckoutFileAtRevision(self, file_name, revision, cwd=None):
+ """Performs a checkout on a file at the given revision.
+
+ Returns:
+ True if successful.
+ """
+ return not bisect_utils.RunGit(
+ ['checkout', revision, file_name], cwd=cwd)[1]
+
+ def RevertFileToHead(self, file_name):
+ """Unstages a file and returns it to HEAD.
+
+ Returns:
+ True if successful.
+ """
+ # Reset doesn't seem to return 0 on success.
+ bisect_utils.RunGit(['reset', 'HEAD', file_name])
+
+ return not bisect_utils.RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1]
+
+ def QueryFileRevisionHistory(self, filename, revision_start, revision_end):
+ """Returns a list of commits that modified this file.
+
+ Args:
+ filename: Name of file.
+ revision_start: Start of revision range.
+ revision_end: End of revision range.
+
+ Returns:
+ Returns a list of commits that touched this file.
+ """
+ cmd = ['log', '--format=%H', '%s~1..%s' % (revision_start, revision_end),
+ filename]
+ output = bisect_utils.CheckRunGit(cmd)
+
+ return [o for o in output.split('\n') if o]
« no previous file with comments | « tools/auto_bisect/bisect_utils.py ('k') | tools/bisect-perf-regression.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698