Commit 28de290f authored by pkasting@chromium.org's avatar pkasting@chromium.org

Use --internal-diff on svn 1.7+ to slightly reduce disk thrashing.

This just saves the need to create and remove an empty directory on every call to GenerateDiff.

Review URL: https://chromiumcodereview.appspot.com/14064017

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@195328 0039d316-1c4b-4281-b951-d872f2087c98
parent aae3d86d
...@@ -781,83 +781,93 @@ class SVN(object): ...@@ -781,83 +781,93 @@ class SVN(object):
The diff will always use relative paths. The diff will always use relative paths.
""" """
assert isinstance(filenames, (list, tuple)) assert isinstance(filenames, (list, tuple))
# If the user specified a custom diff command in their svn config file,
# then it'll be used when we do svn diff, which we don't want to happen
# since we want the unified diff.
if SVN.AssertVersion("1.7")[0]:
# On svn >= 1.7, the "--internal-diff" flag will solve this.
return SVN._GenerateDiffInternal(filenames, cwd, full_move, revision,
["diff", "--internal-diff"])
else:
# On svn < 1.7, the "--internal-diff" flag doesn't exist. Using
# --diff-cmd=diff doesn't always work, since e.g. Windows cmd users may
# not have a "diff" executable in their path at all. So we use an empty
# temporary directory as the config directory, which bypasses any user
# settings for the diff-cmd.
bogus_dir = tempfile.mkdtemp()
try:
return SVN._GenerateDiffInternal(filenames, cwd, full_move, revision,
["diff", "--config_dir", bogus_dir])
finally:
gclient_utils.RemoveDirectory(bogus_dir)
@staticmethod
def _GenerateDiffInternal(filenames, cwd, full_move, revision, diff_command):
root = os.path.normcase(os.path.join(cwd, '')) root = os.path.normcase(os.path.join(cwd, ''))
def RelativePath(path, root): def RelativePath(path, root):
"""We must use relative paths.""" """We must use relative paths."""
if os.path.normcase(path).startswith(root): if os.path.normcase(path).startswith(root):
return path[len(root):] return path[len(root):]
return path return path
# If the user specified a custom diff command in their svn config file, # Cleanup filenames
# then it'll be used when we do svn diff, which we don't want to happen filenames = [RelativePath(f, root) for f in filenames]
# since we want the unified diff. Using --diff-cmd=diff doesn't always # Get information about the modified items (files and directories)
# work, since e.g. Windows cmd users may not have a "diff" executable in data = dict((f, SVN.CaptureLocalInfo([f], root)) for f in filenames)
# their path at all. So we use an empty temporary directory as the config diffs = []
# directory, which gets around these problems. if full_move:
bogus_dir = tempfile.mkdtemp() # Eliminate modified files inside moved/copied directory.
command = ['diff', '--config-dir', bogus_dir] for (filename, info) in data.iteritems():
try: if SVN.IsMovedInfo(info) and info.get("Node Kind") == "directory":
# Cleanup filenames # Remove files inside the directory.
filenames = [RelativePath(f, root) for f in filenames] filenames = [f for f in filenames
# Get information about the modified items (files and directories) if not f.startswith(filename + os.path.sep)]
data = dict((f, SVN.CaptureLocalInfo([f], root)) for f in filenames) for filename in data.keys():
diffs = [] if not filename in filenames:
if full_move: # Remove filtered out items.
# Eliminate modified files inside moved/copied directory. del data[filename]
for (filename, info) in data.iteritems(): else:
if SVN.IsMovedInfo(info) and info.get("Node Kind") == "directory": metaheaders = []
# Remove files inside the directory. for (filename, info) in data.iteritems():
filenames = [f for f in filenames if SVN.IsMovedInfo(info):
if not f.startswith(filename + os.path.sep)] # for now, the most common case is a head copy,
for filename in data.keys(): # so let's just encode that as a straight up cp.
if not filename in filenames: srcurl = info.get('Copied From URL')
# Remove filtered out items. file_root = info.get('Repository Root')
del data[filename] rev = int(info.get('Copied From Rev'))
else: assert srcurl.startswith(file_root)
metaheaders = [] src = srcurl[len(file_root)+1:]
for (filename, info) in data.iteritems(): try:
if SVN.IsMovedInfo(info): srcinfo = SVN.CaptureRemoteInfo(srcurl)
# for now, the most common case is a head copy, except subprocess2.CalledProcessError, e:
# so let's just encode that as a straight up cp. if not 'Not a valid URL' in e.stderr:
srcurl = info.get('Copied From URL') raise
file_root = info.get('Repository Root') # Assume the file was deleted. No idea how to figure out at which
rev = int(info.get('Copied From Rev')) # revision the file was deleted.
assert srcurl.startswith(file_root) srcinfo = {'Revision': rev}
src = srcurl[len(file_root)+1:] if (srcinfo.get('Revision') != rev and
try: SVN.Capture(diff_command + ['-r', '%d:head' % rev, srcurl], cwd)):
srcinfo = SVN.CaptureRemoteInfo(srcurl) metaheaders.append("#$ svn cp -r %d %s %s "
except subprocess2.CalledProcessError, e: "### WARNING: note non-trunk copy\n" %
if not 'Not a valid URL' in e.stderr: (rev, src, filename))
raise else:
# Assume the file was deleted. No idea how to figure out at which metaheaders.append("#$ cp %s %s\n" % (src,
# revision the file was deleted. filename))
srcinfo = {'Revision': rev} if metaheaders:
if (srcinfo.get('Revision') != rev and diffs.append("### BEGIN SVN COPY METADATA\n")
SVN.Capture(command + ['-r', '%d:head' % rev, srcurl], cwd)): diffs.extend(metaheaders)
metaheaders.append("#$ svn cp -r %d %s %s " diffs.append("### END SVN COPY METADATA\n")
"### WARNING: note non-trunk copy\n" % # Now ready to do the actual diff.
(rev, src, filename)) for filename in sorted(data):
else: diffs.append(SVN._DiffItemInternal(
metaheaders.append("#$ cp %s %s\n" % (src, filename, cwd, data[filename], diff_command, full_move, revision))
filename)) # Use StringIO since it can be messy when diffing a directory move with
# full_move=True.
if metaheaders: buf = cStringIO.StringIO()
diffs.append("### BEGIN SVN COPY METADATA\n") for d in filter(None, diffs):
diffs.extend(metaheaders) buf.write(d)
diffs.append("### END SVN COPY METADATA\n") result = buf.getvalue()
# Now ready to do the actual diff. buf.close()
for filename in sorted(data): return result
diffs.append(SVN._DiffItemInternal(
filename, cwd, data[filename], command, full_move, revision))
# Use StringIO since it can be messy when diffing a directory move with
# full_move=True.
buf = cStringIO.StringIO()
for d in filter(None, diffs):
buf.write(d)
result = buf.getvalue()
buf.close()
return result
finally:
gclient_utils.RemoveDirectory(bogus_dir)
@staticmethod @staticmethod
def _DiffItemInternal(filename, cwd, info, diff_command, full_move, revision): def _DiffItemInternal(filename, cwd, info, diff_command, full_move, revision):
......
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