Commit 1c7db8e6 authored by maruel@chromium.org's avatar maruel@chromium.org

Add "diff against" support when sending try patches.

This is mostly useful with git when diffing against arbitrary branches.

Review URL: http://codereview.chromium.org/524046

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@35684 0039d316-1c4b-4281-b951-d872f2087c98
parent 01d8c1d1
...@@ -550,7 +550,7 @@ class SVN(object): ...@@ -550,7 +550,7 @@ class SVN(object):
return output return output
@staticmethod @staticmethod
def DiffItem(filename, full_move=False): def DiffItem(filename, full_move=False, revision=None):
"""Diffs a single file. """Diffs a single file.
Be sure to be in the appropriate directory before calling to have the Be sure to be in the appropriate directory before calling to have the
...@@ -570,7 +570,10 @@ class SVN(object): ...@@ -570,7 +570,10 @@ class SVN(object):
bogus_dir = tempfile.mkdtemp() bogus_dir = tempfile.mkdtemp()
try: try:
# Grabs the diff data. # 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: if data:
pass pass
elif SVN.IsMoved(filename): elif SVN.IsMoved(filename):
...@@ -600,7 +603,7 @@ class SVN(object): ...@@ -600,7 +603,7 @@ class SVN(object):
return data return data
@staticmethod @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. """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 The files in the list should either be absolute paths or relative to the
...@@ -618,7 +621,7 @@ class SVN(object): ...@@ -618,7 +621,7 @@ class SVN(object):
try: try:
os.chdir(root) os.chdir(root)
diff = "".join(filter(None, diff = "".join(filter(None,
[SVN.DiffItem(RelativePath(f, root), [SVN.DiffItem(RelativePath(f, root, revision),
full_move=full_move) full_move=full_move)
for f in filenames])) for f in filenames]))
finally: finally:
......
...@@ -63,8 +63,10 @@ class SVNUnittest(TryChangeTestsBase): ...@@ -63,8 +63,10 @@ class SVNUnittest(TryChangeTestsBase):
def testBasic(self): def testBasic(self):
trychange.scm.SVN.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root) trychange.scm.SVN.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root)
trychange.scm.SVN.GenerateDiff(['foo.txt', 'bar.txt'], self.fake_root, trychange.scm.SVN.GenerateDiff(['foo.txt', 'bar.txt'],
full_move=True).AndReturn('A diff') self.fake_root,
full_move=True,
revision=None).AndReturn('A diff')
trychange.scm.SVN.GetEmail(self.fake_root).AndReturn('georges@example.com') trychange.scm.SVN.GetEmail(self.fake_root).AndReturn('georges@example.com')
self.mox.ReplayAll() self.mox.ReplayAll()
svn = trychange.SVN(self.options, self.fake_root) svn = trychange.SVN(self.options, self.fake_root)
...@@ -87,7 +89,8 @@ class GITUnittest(TryChangeTestsBase): ...@@ -87,7 +89,8 @@ class GITUnittest(TryChangeTestsBase):
def testBasic(self): def testBasic(self):
trychange.scm.GIT.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root) trychange.scm.GIT.GetCheckoutRoot(self.fake_root).AndReturn(self.fake_root)
trychange.scm.GIT.GenerateDiff(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.GetPatchName(self.fake_root).AndReturn('bleh-1233')
trychange.scm.GIT.GetEmail(self.fake_root).AndReturn('georges@example.com') trychange.scm.GIT.GetEmail(self.fake_root).AndReturn('georges@example.com')
self.mox.ReplayAll() self.mox.ReplayAll()
......
...@@ -74,8 +74,12 @@ def EscapeDot(name): ...@@ -74,8 +74,12 @@ def EscapeDot(name):
class SCM(object): class SCM(object):
"""Simplistic base class to implement one function: ProcessOptions.""" """Simplistic base class to implement one function: ProcessOptions."""
def __init__(self, options, cwd): def __init__(self, options, path):
self.checkout_root = cwd items = path.split('@')
assert len(items) <= 2
self.checkout_root = items[0]
items.append(None)
self.diff_against = items[1]
self.options = options self.options = options
self.files = self.options.files self.files = self.options.files
self.options.files = None self.options.files = None
...@@ -176,7 +180,8 @@ class SVN(SCM): ...@@ -176,7 +180,8 @@ class SVN(SCM):
if f[0][0] not in excluded if f[0][0] not in excluded
] ]
os.chdir(previous_cwd) 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): class GIT(SCM):
...@@ -202,7 +207,8 @@ class GIT(SCM): ...@@ -202,7 +207,8 @@ class GIT(SCM):
def GenerateDiff(self): def GenerateDiff(self):
# For now, ignores self.files # 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): def _ParseSendChangeOptions(options):
...@@ -365,16 +371,17 @@ def GuessVCS(options, path): ...@@ -365,16 +371,17 @@ def GuessVCS(options, path):
A SCM instance. Exits if the SCM can't be guessed. A SCM instance. Exits if the SCM can't be guessed.
""" """
__pychecker__ = 'no-returnvalues' __pychecker__ = 'no-returnvalues'
real_path = path.split('@')[0]
logging.info("GuessVCS(%s)" % path) logging.info("GuessVCS(%s)" % path)
# Subversion has a .svn in all working directories. # 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) return SVN(options, path)
# Git has a command to test if you're in a git tree. # 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 running it, but don't die if we don't have git installed.
try: try:
gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"], gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"],
path) real_path)
return GIT(options, path) return GIT(options, path)
except gclient_utils.CheckCallError, e: except gclient_utils.CheckCallError, e:
if e.retcode != errno.ENOENT and e.retcode != 128: if e.retcode != errno.ENOENT and e.retcode != 128:
...@@ -464,7 +471,9 @@ def TryChange(argv, ...@@ -464,7 +471,9 @@ def TryChange(argv,
help="Used as -pN parameter to patch") help="Used as -pN parameter to patch")
group.add_option("-s", "--sub_rep", action="append", default=[], group.add_option("-s", "--sub_rep", action="append", default=[],
help="Subcheckout to use in addition. This is mainly " 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", group.add_option("--no_gclient", action="store_true",
help="Disable automatic search for gclient checkout.") help="Disable automatic search for gclient checkout.")
parser.add_option_group(group) parser.add_option_group(group)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment