Index: trychange.py |
diff --git a/trychange.py b/trychange.py |
index 691c67de285546ed79077886cc6d2670cd1d76fb..2389bb0939e76edefc071d54251922de33a213f9 100755 |
--- a/trychange.py |
+++ b/trychange.py |
@@ -25,9 +25,8 @@ import gcl |
import gclient_utils |
import scm |
import presubmit_support |
-import upload |
-__version__ = '1.1.2' |
+__version__ = '1.2' |
# Constants |
@@ -66,23 +65,6 @@ class NoTryServerAccess(Exception): |
return self.args[0] + '\n' + HELP_STRING |
-def PathDifference(root, subpath): |
- """Returns the difference subpath minus root.""" |
- if subpath.find(root) != 0: |
- return None |
- # If the root does not have a trailing \ or /, we add it so the returned path |
- # starts immediately after the seperator regardless of whether it is provided. |
- if not root.endswith(os.sep): |
- root += os.sep |
- return subpath[len(root):] |
- |
- |
-def GetSourceRoot(): |
- """Returns the absolute directory one level up from the repository root.""" |
- # TODO(maruel): This is odd to assume that '..' is the source root. |
- return os.path.abspath(os.path.join(gcl.GetRepositoryRoot(), '..')) |
- |
- |
def GetTryServerSettings(): |
"""Grab try server settings local to the repository.""" |
def _SafeResolve(host): |
@@ -124,62 +106,62 @@ class SCM(object): |
def __init__(self, options): |
self.options = options |
- def ProcessOptions(self): |
- raise NotImplementedError |
+ def GetFileNames(self): |
+ """Return the list of files in the diff.""" |
+ return self.options.files |
class SVN(SCM): |
"""Gathers the options and diff for a subversion checkout.""" |
- def GenerateDiff(self, files, root): |
+ def __init__(self, *args, **kwargs): |
+ SCM.__init__(self, *args, **kwargs) |
+ self.checkout_root = scm.SVN.GetCheckoutRoot(os.getcwd()) |
+ self.options.files |
+ if not self.options.diff: |
+ # Generate the diff from the scm. |
+ self.options.diff = self._GenerateDiff() |
+ if not self.options.email: |
+ # Assumes the svn credential is an email address. |
+ self.options.email = scm.SVN.GetEmail(self.checkout_root) |
+ |
+ def _GenerateDiff(self): |
"""Returns a string containing the diff for the given file list. |
The files in the list should either be absolute paths or relative to the |
- given root. If no root directory is provided, the repository root will be |
- used. |
+ given root. |
""" |
previous_cwd = os.getcwd() |
- os.chdir(root or scm.SVN.GetCheckoutRoot(previous_cwd)) |
- |
+ os.chdir(self.checkout_root) |
+ if not self.options.files: |
+ self.options.files = [f[1] for f in scm.SVN.CaptureStatus(None)] |
# Directories will return None so filter them out. |
- diff = filter(None, [scm.SVN.DiffItem(f) for f in files]) |
+ diff = filter(None, [scm.SVN.DiffItem(f) for f in self.options.files]) |
os.chdir(previous_cwd) |
return "".join(diff) |
- def GetFileNames(self): |
- """Return the list of files in the diff.""" |
- return self.change_info.GetFileNames() |
- |
def GetLocalRoot(self): |
"""Return the path of the repository root.""" |
- return self.change_info.GetLocalRoot() |
- |
- def ProcessOptions(self): |
- checkout_root = None |
- if not self.options.diff: |
- # Generate the diff with svn and write it to the submit queue path. The |
- # files are relative to the repository root, but we need patches relative |
- # to one level up from there (i.e., 'src'), so adjust both the file |
- # paths and the root of the diff. |
- # TODO(maruel): Remove this hack. |
- source_root = GetSourceRoot() |
- checkout_root = scm.SVN.GetCheckoutRoot(os.getcwd()) |
- prefix = PathDifference(source_root, checkout_root) |
- adjusted_paths = [os.path.join(prefix, x) for x in self.options.files] |
- self.options.diff = self.GenerateDiff(adjusted_paths, root=source_root) |
- self.change_info = gcl.LoadChangelistInfoForMultiple(self.options.name, |
- gcl.GetRepositoryRoot(), True, True) |
- if not self.options.email: |
- checkout_root = checkout_root or scm.SVN.GetCheckoutRoot(os.getcwd()) |
- self.options.email = scm.SVN.GetEmail(checkout_root) |
+ return self.checkout_root |
class GIT(SCM): |
"""Gathers the options and diff for a git checkout.""" |
- def GenerateDiff(self): |
+ def __init__(self, *args, **kwargs): |
+ SCM.__init__(self, *args, **kwargs) |
+ self.checkout_root = os.path.abspath( |
+ gclient_utils.CheckCall(['git', 'rev-parse', '--show-cdup']).strip()) |
+ if not self.options.diff: |
+ self.options.diff = self._GenerateDiff() |
+ if not self.options.name: |
+ self.options.name = self._GetPatchName() |
+ if not self.options.email: |
+ self.options.email = scm.GIT.GetEmail('.') |
+ |
+ def _GenerateDiff(self): |
"""Get the diff we'll send to the try server. We ignore the files list.""" |
- branch = upload.RunShell(['git', 'cl', 'upstream']).strip() |
- diff = upload.RunShell(['git', 'diff-tree', '-p', '--no-prefix', |
- branch, 'HEAD']).splitlines(True) |
+ branch = gclient_utils.CheckCall(['git', 'cl', 'upstream']).strip() |
+ diff = gclient_utils.CheckCall(['git', 'diff-tree', '-p', '--no-prefix', |
+ branch, 'HEAD']).splitlines(True) |
for i in range(len(diff)): |
# In the case of added files, replace /dev/null with the path to the |
# file being added. |
@@ -187,34 +169,20 @@ class GIT(SCM): |
diff[i] = '--- %s' % diff[i+1][4:] |
return ''.join(diff) |
- def GetFileNames(self): |
- """Return the list of files in the diff.""" |
- return self.options.files |
- |
- def GetLocalRoot(self): |
- """Return the path of the repository root.""" |
- # TODO: check for errors here? |
- root = upload.RunShell(['git', 'rev-parse', '--show-cdup']).strip() |
- return os.path.abspath(root) |
- |
- def GetPatchName(self): |
+ def _GetPatchName(self): |
"""Construct a name for this patch.""" |
# TODO: perhaps include the hash of the current commit, to distinguish |
# patches? |
- branch = upload.RunShell(['git', 'symbolic-ref', 'HEAD']).strip() |
+ branch = gclient_utils.CheckCall(['git', 'symbolic-ref', 'HEAD']).strip() |
if not branch.startswith('refs/heads/'): |
# TODO(maruel): Find a better type. |
raise NoTryServerAccess("Couldn't figure out branch name") |
branch = branch[len('refs/heads/'):] |
return branch |
- def ProcessOptions(self): |
- if not self.options.diff: |
- self.options.diff = self.GenerateDiff() |
- if not self.options.name: |
- self.options.name = self.GetPatchName() |
- if not self.options.email: |
- self.options.email = scm.GIT.GetEmail('.') |
+ def GetLocalRoot(self): |
+ """Return the path of the repository root.""" |
+ return self.checkout_root |
def _ParseSendChangeOptions(options): |
@@ -365,17 +333,12 @@ def GuessVCS(options): |
# Git has a command to test if you're in a git tree. |
# Try running it, but don't die if we don't have git installed. |
try: |
- out, returncode = subprocess.Popen( |
- ["git", "rev-parse", "--is-inside-work-tree"], |
- shell=sys.platform.startswith('win'), |
- stdout=subprocess.PIPE).communicate()[0] |
- if returncode == 0: |
- logging.info("Guessed VCS = Git") |
- return GIT(options) |
- except OSError, (errno, message): |
- if errno != 2: # ENOENT -- they don't have git installed. |
+ gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"]) |
+ logging.info("Guessed VCS = Git") |
+ return GIT(options) |
+ except gclient_utils.CheckCallError, e: |
+ if e.retcode != 2: # ENOENT -- they don't have git installed. |
raise |
- |
raise NoTryServerAccess("Could not guess version control system. " |
"Are you in a working copy directory?") |
@@ -520,7 +483,6 @@ def TryChange(argv, |
# Process the VCS in any case at least to retrieve the email address. |
try: |
options.scm = GuessVCS(options) |
- options.scm.ProcessOptions() |
except NoTryServerAccess, e: |
# If we got the diff, we don't care. |
if not options.diff: |