diff --git a/scm.py b/scm.py index eabaad119..af11d541d 100644 --- a/scm.py +++ b/scm.py @@ -550,7 +550,7 @@ class SVN(object): return output @staticmethod - def DiffItem(filename, full_move=False): + def DiffItem(filename, full_move=False, revision=None): """Diffs a single file. Be sure to be in the appropriate directory before calling to have the @@ -570,7 +570,10 @@ class SVN(object): bogus_dir = tempfile.mkdtemp() try: # Grabs the diff data. - data = SVN.Capture(["diff", "--config-dir", bogus_dir, filename], None) + command = ["diff", "--config-dir", bogus_dir, filename] + if revision is not None: + command.extend(['--revision', revision]) + data = SVN.Capture(command, None) if data: pass elif SVN.IsMoved(filename): @@ -600,7 +603,7 @@ class SVN(object): return data @staticmethod - def GenerateDiff(filenames, root=None, full_move=False): + def GenerateDiff(filenames, root=None, full_move=False, revision=None): """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 @@ -618,7 +621,7 @@ class SVN(object): try: os.chdir(root) diff = "".join(filter(None, - [SVN.DiffItem(RelativePath(f, root), + [SVN.DiffItem(RelativePath(f, root, revision), full_move=full_move) for f in filenames])) finally: diff --git a/tests/trychange_unittest.py b/tests/trychange_unittest.py index 5d1493eac..dbaa763b2 100644 --- a/tests/trychange_unittest.py +++ b/tests/trychange_unittest.py @@ -63,8 +63,10 @@ class SVNUnittest(TryChangeTestsBase): def testBasic(self): trychange.scm.SVN.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root) - trychange.scm.SVN.GenerateDiff(['foo.txt', 'bar.txt'], self.fake_root, - full_move=True).AndReturn('A diff') + trychange.scm.SVN.GenerateDiff(['foo.txt', 'bar.txt'], + self.fake_root, + full_move=True, + revision=None).AndReturn('A diff') trychange.scm.SVN.GetEmail(self.fake_root).AndReturn('georges@example.com') self.mox.ReplayAll() svn = trychange.SVN(self.options, self.fake_root) @@ -87,7 +89,8 @@ class GITUnittest(TryChangeTestsBase): def testBasic(self): trychange.scm.GIT.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root) trychange.scm.GIT.GenerateDiff(self.fake_root, - full_move=True).AndReturn('A diff') + full_move=True, + branch=None).AndReturn('A diff') trychange.scm.GIT.GetPatchName(self.fake_root).AndReturn('bleh-1233') trychange.scm.GIT.GetEmail(self.fake_root).AndReturn('georges@example.com') self.mox.ReplayAll() diff --git a/trychange.py b/trychange.py index cf3d45929..d8d019f88 100755 --- a/trychange.py +++ b/trychange.py @@ -74,8 +74,12 @@ def EscapeDot(name): class SCM(object): """Simplistic base class to implement one function: ProcessOptions.""" - def __init__(self, options, cwd): - self.checkout_root = cwd + def __init__(self, options, path): + items = path.split('@') + assert len(items) <= 2 + self.checkout_root = items[0] + items.append(None) + self.diff_against = items[1] self.options = options self.files = self.options.files self.options.files = None @@ -176,7 +180,8 @@ class SVN(SCM): if f[0][0] not in excluded ] os.chdir(previous_cwd) - return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True) + return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True, + revision=self.diff_against) class GIT(SCM): @@ -202,7 +207,8 @@ class GIT(SCM): def GenerateDiff(self): # For now, ignores self.files - return scm.GIT.GenerateDiff(self.checkout_root, full_move=True) + return scm.GIT.GenerateDiff(self.checkout_root, full_move=True, + branch=self.diff_against) def _ParseSendChangeOptions(options): @@ -365,16 +371,17 @@ def GuessVCS(options, path): A SCM instance. Exits if the SCM can't be guessed. """ __pychecker__ = 'no-returnvalues' + real_path = path.split('@')[0] logging.info("GuessVCS(%s)" % path) # Subversion has a .svn in all working directories. - if os.path.isdir(os.path.join(path, '.svn')): + if os.path.isdir(os.path.join(real_path, '.svn')): return SVN(options, path) # 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: gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"], - path) + real_path) return GIT(options, path) except gclient_utils.CheckCallError, e: if e.retcode != errno.ENOENT and e.retcode != 128: @@ -464,7 +471,9 @@ def TryChange(argv, help="Used as -pN parameter to patch") group.add_option("-s", "--sub_rep", action="append", default=[], help="Subcheckout to use in addition. This is mainly " - "useful for gclient-style checkouts.") + "useful for gclient-style checkouts. Use @rev or " + "@branch or @branch1..branch2 to specify the " + "revision/branch to diff against.") group.add_option("--no_gclient", action="store_true", help="Disable automatic search for gclient checkout.") parser.add_option_group(group)