Skip to content

Instantly share code, notes, and snippets.

@mauritsvanrees
Forked from jimfulton/svn2git.py
Last active July 3, 2017 11:44
Show Gist options
  • Save mauritsvanrees/5765839 to your computer and use it in GitHub Desktop.
Save mauritsvanrees/5765839 to your computer and use it in GitHub Desktop.
local_authors.txt
authors.cfg
#! /bin/sh
echo "$1 <$1@example.org>"
m.van.rees = <m.van.rees@zestsoftware.nl>
# Wrapper around svn2git.py (which is normally in the same directory
# as this file) that calls it for each project in a list of
# repositories. Very hardcoded to my system, sorry.
import os
import time
REPOS = [
'https://svn.example.org/svn/repo',
]
PYTHON = 'python2.7'
SVN2GIT = '~/community/jim2git/svn2git.py'
AUTHORS = '~/community/jim2git/authors.txt'
AUTHORS_PROG = '/Users/mauritsvanrees/community/jim2git/author.py'
TARGET = '/Users/mauritsvanrees/tmp/gitmirror'
TARBALL_TARGET = '/Users/mauritsvanrees/tmp/targit'
def s(command):
print 'Running command:', command
if os.system(command):
raise SystemError
def r(command):
print 'Running command:', command
f = os.popen(command)
result = f.read()
f.close()
return result
def svn_ls(url):
return [line.strip('/') for line in r('svn ls %s' % url).strip().split()]
start_dir = os.getcwd()
if not os.path.isdir(TARGET):
os.mkdir(TARGET)
if not os.path.isdir(TARBALL_TARGET):
os.mkdir(TARBALL_TARGET)
for fullrepo in REPOS:
# Take last part of full repo url and create that directory locally.
reponame = fullrepo.strip('/').split('/')[-1]
print
print
print "############################################################\n" * 3
repo_dir = os.path.join(start_dir, reponame)
os.mkdir(repo_dir)
target_repo = os.path.join(TARGET, reponame)
os.mkdir(target_repo)
tarball_repo = os.path.join(TARBALL_TARGET, reponame)
os.mkdir(tarball_repo)
for project in svn_ls(fullrepo):
os.chdir(repo_dir)
print "########################################################\n" * 2
path = '%s/%s' % (fullrepo, project)
if 'trunk' not in svn_ls(path):
print "WARNING: ignoring because of no trunk: %s" % path
continue
print 'trunk found: %s' % path
bare_name = '%s.git' % project
bare = os.path.join(target_repo, bare_name)
print "Initializing bare repository: %s" % bare
os.mkdir(bare)
s('git init --bare %s' % bare)
output = r('%s %s --authors=%s --authors-prog=%s --target=%s %s' % (
PYTHON, SVN2GIT, AUTHORS, AUTHORS_PROG, target_repo, path))
# We could print the output, but it is not really useful. You
# see lots of lines anyway.
print "########################################################"
print "Done with project %s in repo %s." % (project, reponame)
print "Pausing a few seconds so you can see the result."
time.sleep(5)
os.chdir(target_repo)
print "Making tarball %s.tgz in %s" % (bare_name, tarball_repo)
r('tar czvf %s.tgz %s' % (os.path.join(tarball_repo, bare_name),
bare_name))
# One directory up.
os.chdir(os.pardir)
##############################################################################
#
# Copyright (c) 2012 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""%prog [options] subversion_url
svn to git conversion helper
Based loosely on the svn2git ruby tool.
You must have git and the svn git plugin installed.
A repository directory will be created with a name derived from the
subversion URL.
The subversion URL must point to a subversion project with a standard
layout, with trunk, branches, and tags.
"""
import optparse
parser = optparse.OptionParser(__doc__)
githelp="""
Create a github repository. The argument is a string of the form
DEST/token. where DEST is either 'users/USERNAME' or 'orgs/ORGNAME' and
token is a github OAuth token:
https://help.github.com/articles/creating-an-oauth-token-for-command-line-use
curl must be installed if you use this.
"""
targethelp = """
Base connection string to push the code to. For example:
git@git.example.org/organization
Then git@git.example.org/organization/reponame.git will be added as remote.
The branches and tags will be pushed there.
Note that the remote repository must already exist and be empty.
You probably want to do 'git init --bare .' in there.
"""
parser.add_option('--github', '-g', help=githelp)
parser.add_option('--target', '-t', help=targethelp)
parser.add_option('--restart', '-r', action='store_true',
help="Restart after fetch times out")
parser.add_option(
'--authors', '-a',
help = 'Path to authors.txt file (required). This must have lines '
'corresponding to the subversion authors, like this: '
'committer_id = <email@example.org>')
parser.add_option(
'--authors-prog', '-p',
help = 'Path to program to parse unknown authors. It must accepts a '
'subversion committer id and return a string like this: '
'Joe User <joe@example.org>')
import os
import sys
import xml.etree.ElementTree
def s(command):
print 'Running command:', command
if os.system(command):
raise SystemError
def r(command):
f = os.popen(command)
result = f.read()
f.close()
return result
def main(args=None):
if args is None:
args = sys.argv[1:]
options, args = parser.parse_args(args)
url, = args
if url.endswith('/'):
url = url[:-1]
name = url.rsplit('/', 1)[1]
if not options.restart:
os.mkdir(name)
os.chdir(name)
if not options.restart:
s('git svn init --no-metadata -s %s' % url)
assert options.authors
s('git config svn.authorsfile %s' %
os.path.abspath(os.path.expanduser(options.authors)))
fetch_cmd = 'git svn fetch'
if options.authors_prog:
fetch_cmd += ' --authors-prog=%s' % options.authors_prog
s(fetch_cmd)
tags = []
for tag in r('svn ls %s/tags' % url).strip().split():
if tag[-1] == '/':
tag = tag[:-1]
tags.append(tag)
for branch in r('svn ls %s/branches' % url).strip().split():
if branch[-1] == '/':
branch = branch[:-1]
s('git checkout %s' % branch)
if branch in tags:
# 1.1 -> 1.1.x
branch += '.x'
s('git checkout -b %s' % branch)
# Not sure if this is necessary, or sufficient. The Ruby
# version ran into trouble when git left files around between
# branche checkouts. I haven't had the problem, with this
# script, which unlike the Ruby version, doesn't process
# deleted branches.
s('git reset --hard HEAD')
for tag in tags:
f = os.popen('svn log --xml -l1 %s/tags/%s' % (url, tag))
date = xml.etree.ElementTree.ElementTree(
file=f).find('logentry').find('date').text
f.close()
s("GIT_COMMITTER_DATE=%r git tag %r 'tags/%s'" % (
date.replace('T', ' ').replace('Z', ' +0000'),
tag, tag,
))
s('git checkout trunk')
s('git branch -D master')
s('git checkout -f -b master')
s('git branch -d -r trunk')
s('git gc')
if options.github:
github_dest, github_token = options.github.rsplit('/', 1)
if github_dest.startswith('users/'):
github_user = github_dest[6:]
github_dest = 'user'
else:
assert github_dest.startswith('orgs/')
github_user = github_dest.split('/')[1]
s('curl -v -XPOST -H "Authorization: token %s"'
' https://api.github.com/%s/repos -d '
"""'{"name": "'"%s"'"}'"""
% (github_token, github_dest, name))
s('git remote add origin ssh://git@github.com/%s/%s.git'
% (github_user, name))
s("git push -u origin --all")
s("git push -u origin --tags")
if options.target:
s('git remote add origin %s/%s.git'
% (options.target, name))
s("git push -u origin --all")
s("git push -u origin --tags")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment