Skip to content

Instantly share code, notes, and snippets.

@josiahcarlson
Created November 22, 2010 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josiahcarlson/709643 to your computer and use it in GitHub Desktop.
Save josiahcarlson/709643 to your computer and use it in GitHub Desktop.
Convert PyPE's svn repository to git
'''
simple_svn2git.py
Written November 2010 by Josiah Carlson, released into the public domain.
This script was used to convert PyPE's svn repository on sourceforge to git.
Setup included checking out/cloning the two repos:
svn co https://pype.svn.sourceforge.net/svnroot/pype pype
git clone ssh://josiahcarlson@pype.git.sourceforge.net/gitroot/pype/pype pype.git
I then added the README file to the git repo, made a small modification, and
added it again... just in case I needed to do a "git rebase -i" to blow
everything away. The 'git reset' in case of exception worked to reset the
repo in case of error.
After the setup was completed, I ran this script in the parent of both of the
local paths, performed some verification, then did 'git push origin master' in
the git path.
This was written because both the standard 'git svn' and 'svn2git' options
would result in a git repo with no HEAD, no files, no history, etc. Since
PyPE didn't use tags, branches, etc., this script worked just fine. For other
repositories with only trunk, no tags, etc., a suitably modified version of
this script should "just work", though I make no promises and offer no
support.
'''
import os
import shutil
import stat
import subprocess
def get_output(args):
p = subprocess.Popen(args, shell=False, bufsize=4096,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
r = p.communicate()[0]
if 'cannot create' in r:
print r
raise Exception
if 'fatal:' in r:
print r
raise Exception
return r
def get_files_and_changelog(revision):
flist = [line.split(None, 1) for line in get_output(['svn', 'up', '-r', str(revision)]).split('\n')]
flist.pop()
flist.pop()
log = get_output(['svn', 'log', '-c', str(revision)]).strip('-\n ')
return flist, log
def isdir(path):
return stat.S_ISDIR(os.stat(path).st_mode)
def handle_file_changes(cwd, flist, message):
for ch, filename in flist:
dfn = filename if not filename.startswith('pype/') else filename[5:]
if ch in ('A', 'U'):
if isdir(os.path.join(cwd, 'pype', filename)):
continue
real_dest = os.path.join(cwd, 'pype.git', dfn)
try:
os.makedirs(os.path.split(real_dest)[0])
except OSError:
pass
mode = 'r'
if filename.split('.')[-1] in ('py', 'txt', 'cfg'):
# get rid of Windows line endings :P
inp = open(filename, 'rU')
out = open(real_dest, 'w')
shutil.copyfileobj(inp, out)
inp.close()
out.close()
else:
print get_output(['cp', filename, real_dest])
os.chdir(os.path.join(cwd, 'pype.git'))
for ch, filename in flist:
dfn = filename if not filename.startswith('pype/') else filename[5:]
if ch in ('A', 'U'):
if isdir(os.path.join(cwd, 'pype', filename)):
continue
print get_output(['git', 'add', dfn])
else:
try:
os.stat(dfn)
except OSError:
continue
print get_output(['git', 'rm', dfn])
print get_output(['git', 'commit', '-m', message])
def handle_one_revision(revision):
cwd = os.getcwd()
os.chdir(os.path.join(cwd, 'pype'))
files, log = get_files_and_changelog(revision)
handle_file_changes(cwd, files, log)
os.chdir(cwd)
cwd = os.getcwd()
try:
for i in xrange(2, 76):
handle_one_revision(i)
except:
os.chdir(os.path.join(cwd, 'pype'))
print get_output(['svn', 'up', '-r', '1'])
os.chdir(os.path.join(cwd, 'pype.git'))
print get_output(['git', 'reset', '--hard', '1dc57e0167a882af2821a0a13a2e142e0ac7fbc1'])
os.chdir(cwd)
raise
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment