Skip to content

Instantly share code, notes, and snippets.

@leper
Created March 6, 2012 23:19
Show Gist options
  • Save leper/1989705 to your computer and use it in GitHub Desktop.
Save leper/1989705 to your computer and use it in GitHub Desktop.
Generate SVN diffs from git. Checkout should be done via git svn. Dependencies: git subversion python3 (could work with 2 too)
#!/usr/bin/env python
import subprocess
import re
def getOutput(cmd):
command_stdout = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
return command_stdout.decode(encoding='utf-8')
# Find the most recent commit that came from SVN and return the SVN revision.
def getSVN():
revisions = getOutput(['git', 'rev-list', '--date-order', '--max-count=200', 'HEAD'])
#find the svn revision
for rev in revisions.split():
svnrev = getOutput(['git', 'svn', 'find-rev', rev]).strip()
if svnrev:
return [svnrev, rev]
# if we haven't returned yet we haven't found a svn revision
# TODO fail if we can't find one
print('Found no svn revision')
rev = getSVN()
svnrev = rev[0]
gitrev = rev[1]
#Generate a diff from the gitrev and transform it to a svn diff
# We use --no-pager as git diff will use a pager by default
diff = getOutput(['git', '--no-pager', 'diff', '--no-prefix', gitrev])
# For new added files only
newfiles = re.compile(r"""
^diff\s--git\s+([ab]/)?(?P<path>[^\s]*)\s.*\n # Match the first line of a changed file and get the path (exluding a leading a/ or b/)
new.*\n # Match optional 'new file mode' line
index.*\n # Match the index line for replacement with =
---\s/dev/null\n # Match a new file TODO add group with | for modified files
\+\+\+\s([ab]/)?(?P=path)\n # Match for new file
""", re.VERBOSE | re.MULTILINE) #TODO add check for content and not ^^diff
diff = newfiles.sub(r"""Index: \g<path>\n"""+67*'='+"""\n--- \g<path>\t(revision 0)\n+++ \g<path>\t(working copy)\n""", diff)
# For modified files
modifiedfiles = re.compile(r"""
^diff\s--git\s+([ab]/)?(?P<path>[^\s]*)\s.*\n # Match the first line
index.*\n # =
---\s([ab]/)?(?P=path)\n # old
\+\+\+\s([ab]/)?(?P=path)\n # new
""", re.VERBOSE | re.MULTILINE)
diff = modifiedfiles.sub(r"""Index: \g<path>\n"""+67*'='+"""\n--- \g<path>\t(revision """+svnrev+""")\n+++ \g<path>\t(working copy)\n""", diff)
# For binary files
# is the mime-type line needed?
binaryfiles = re.compile(r"""
^diff\s--git\s+([ab]/)?(?P<path>[^\s]*)\s.*\n # Match the first line
^index.*\n # =
^Binary\ files.*\n
""", re.VERBOSE | re.MULTILINE)
diff = binaryfiles.sub(r"""Index: \g<path>\n"""+67*'='+"""\nCannot display: file marked as binary type.\nsvn:mime-type = application/octet-stream\n""", diff)
# Remove stuff after the second @@
modifiedblock = re.compile(r"""
^@@\ (?P<modified>[-][0-9]+,[0-9]+\ [+][0-9]+(,[0-9]+)?)\ @@.* #match the @@ lines
""", re.VERBOSE | re.MULTILINE)
diff = modifiedblock.sub(r"""@@ \g<modified> @@""", diff)
print(diff)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment