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