[Pkg-ocaml-maint-commits] r5603 - /trunk/tools/svn2git/glondu_svn2git.py
glondu-guest at users.alioth.debian.org
glondu-guest at users.alioth.debian.org
Fri May 9 20:06:30 UTC 2008
Author: glondu-guest
Date: Fri May 9 20:06:30 2008
New Revision: 5603
URL: http://svn.debian.org/wsvn/?sc=1&rev=5603
Log:
svn2git script customized for alioth which handles upstream sources
I ended up rewriting everything from scratch. This script is still a
draft. It succeeded in converting ocsigen packaging (the result shoud
be available soon on git.debian.org among my own repos). I put it here
so that I don't loose it and everyone can have a look, but it is not
directly reusable as it is.
Added:
trunk/tools/svn2git/glondu_svn2git.py
Added: trunk/tools/svn2git/glondu_svn2git.py
URL: http://svn.debian.org/wsvn/trunk/tools/svn2git/glondu_svn2git.py?rev=5603&op=file
==============================================================================
--- trunk/tools/svn2git/glondu_svn2git.py (added)
+++ trunk/tools/svn2git/glondu_svn2git.py Fri May 9 20:06:30 2008
@@ -1,0 +1,211 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2008 Stéphane Glondu <steph at glondu.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+import sys, os, re
+from datetime import datetime, tzinfo, timedelta
+from debian_bundle.debian_support import version_compare
+from tempfile import NamedTemporaryFile
+from commands import getoutput, getstatusoutput
+from xml.dom.minidom import parseString
+
+
+svntag_re = re.compile(r"^\[svn-buildpackage\][^(]+\(([^)]+)\)$")
+
+
+# Mapping from alioth login to name and email
+users_dict = {
+ "glondu-guest": ("Stephane Glondu", "steph at glondu.net"),
+ "smimram": ("Samuel Mimram", "smimram at debian.org"),
+ "zack": ("Stefano Zacchiroli", "zack at debian.org"),
+}
+
+
+def run_command(name, cmd):
+ s, o = getstatusoutput(cmd)
+ if s:
+ raise IOError("'%s' returned with code %d" % (cmd, s))
+ return o
+
+
+ZERO = timedelta(0)
+class UTC(tzinfo):
+ """UTC"""
+ def utcoffset(self, dt):
+ return ZERO
+ def tzname(self, dt):
+ return "UTC"
+ def dst(self, dt):
+ return ZERO
+utc = UTC()
+
+
+def parse_datetime(str):
+ if len(str) >= 21 and str[4] == '-' and str[7] == '-' \
+ and str[10] == 'T' and str[13] == ':' and str[16] == ':' \
+ and str[19] == '.' and str[-1] == 'Z':
+ year, month, day = int(str[0:4]), int(str[5:7]), int(str[8:10])
+ hour, minute, second = int(str[11:13]), int(str[14:16]), int(str[17:19])
+ microsecond = int(float(str[19:-1]) * 1000000.)
+ return datetime(year, month, day, hour, minute, second, microsecond, utc)
+ else:
+ raise ValueError("Unable to parse date '%s'" % str)
+
+
+def git_init():
+ os.mkdir("git")
+ run_command("git", "cd git && git init")
+
+
+class GitCommit:
+
+ def __init__(self, logentry, svn2git):
+ self.svn2git = svn2git
+ self.rev = int(logentry.getAttribute("revision"))
+ self.msg = logentry.getElementsByTagName("msg")[0].firstChild.nodeValue
+ user_elt = logentry.getElementsByTagName("author")[0]
+ self.name, self.email = users_dict[user_elt.firstChild.nodeValue]
+ date_elt = logentry.getElementsByTagName("date")[0]
+ date = parse_datetime(date_elt.firstChild.nodeValue)
+ self.date = date.strftime("%Y-%m-%d %H:%M:%S %z")
+
+ def setup_env(self):
+ os.putenv("GIT_AUTHOR_NAME", self.name)
+ os.putenv("GIT_AUTHOR_EMAIL", self.email)
+ os.putenv("GIT_AUTHOR_DATE", self.date)
+ os.putenv("GIT_COMMITTER_NAME", self.name)
+ os.putenv("GIT_COMMITTER_EMAIL", self.email)
+ os.putenv("GIT_COMMITTER_DATE", self.date)
+
+ def checkout(self):
+ if os.path.exists("svn"):
+ os.chdir("svn")
+ # Actually an update
+ print "Retreiving revision %d from svn..." % self.rev,
+ run_command("svn", "svn update -r%d" % self.rev)
+ print "OK!"
+ os.chdir("..")
+ else:
+ # Really a checkout
+ print "Checking out revision %d from svn..." % self.rev,
+ run_command("svn", "svn checkout %s@%d svn" % (self.svn2git.repos, self.rev))
+ print "OK!"
+
+ def commit(self):
+ tarball_path = "../svn/" + self.svn2git.tarball_path
+ os.chdir("git")
+
+ # Call git-import-orig if needed
+ if os.path.exists(tarball_path):
+ n = []
+ for x in os.listdir(tarball_path):
+ if not self.svn2git.seen.has_key(x):
+ n.append(x)
+ if len(n) == 1:
+ tgz = n[0]
+ print "New upstream tarball:", tgz
+ run_command("git-import-orig", "git-import-orig --pristine-tar --no-dch %s/%s" % (tarball_path, tgz))
+ self.svn2git.seen[n[0]] = True
+ elif len(n) > 1:
+ print "Too many new tarballs:", ", ".join(n)
+ sys.exit(1)
+ else:
+ print "No upstream directory!"
+
+ print "Committing revision %d to git..." % self.rev,
+ self.setup_env()
+
+ s, o = getstatusoutput("rsync -rt --exclude=.svn ../svn/trunk/debian/ debian")
+ if s:
+ print "nothing to sync! (rsync returned with code %d)" % s
+ os.chdir("..")
+ return None
+ s, o = getstatusoutput("git add .")
+ if s:
+ print "nothing to add! (git returned with code %d)" % s
+ os.chdir("..")
+ return None
+ f = NamedTemporaryFile()
+ f.file.write(self.msg.encode("UTF-8"))
+ f.file.close()
+ s, o = getstatusoutput("git commit -F%s" % f.name)
+ f.close()
+ if s:
+ print "nothing to commit! (git returned with code %d)" % s
+ os.chdir("..")
+ return None
+ print "OK!"
+ os.chdir("..")
+
+ def check_clean(self):
+ s, o = getstatusoutput("find svn|grep -vE '^svn($|/(.svn|upstream)($|/)|/trunk($|/(debian|\.svn)))'")
+ if not s:
+ print "Unexpected content in svn repos:"
+ print o
+
+
+class GitTag(GitCommit):
+
+ def commit(self):
+ m = svntag_re.match(self.msg)
+ if m:
+ tagname = "debian/" + m.group(1)
+ else:
+ print "Ignoring tag from revision %d:" % self.rev, self.msg
+ return None
+ # '~' is not valid in tag names
+ tagname = tagname.replace('~', '.')
+ os.chdir("git")
+ print "Tagging revision %d as %s..." % (self.rev, tagname),
+ self.setup_env()
+ f = NamedTemporaryFile()
+ f.file.write(self.msg.encode("UTF-8"))
+ f.file.close()
+ run_command("git", "git tag -a -F%s %s" % (f.name, tagname))
+ f.close()
+ print "OK!"
+ os.chdir("..")
+
+
+class Svn2Git:
+
+ def __init__(self, package, tarball_path):
+ self.tarball_path = tarball_path
+ self.repos = "svn://svn.debian.org/svn/pkg-ocaml-maint/trunk/packages/%s" % package
+ self.tagrepos = "svn://svn.debian.org/svn/pkg-ocaml-maint/tags/packages/%s" % package
+ # Retrieve history
+ r = run_command("svn", "svn log --xml %s" % self.repos)
+ r = parseString(r).getElementsByTagName("logentry")
+ revs = [GitCommit(x, self) for x in r]
+ r = run_command("svn", "svn log --xml %s" % self.tagrepos)
+ r = parseString(r).getElementsByTagName("logentry")
+ tags = [GitTag(x, self) for x in r]
+ self.logentries = revs+tags
+ self.logentries.sort(key=lambda x: x.rev)
+ # Initialize the list of already-seen tarballs
+ self.seen = {".svn": True}
+ s, o = getstatusoutput("cd git && git log -b pristine-tar 2>/dev/null|sed -nr 's/^ pristine-tar data for //p'")
+ for x in o.split("\n"):
+ if x:
+ print "Seen:", x
+ self.seen[x] = True
+
+ def do(self, from_revision):
+ for x in self.logentries:
+ if x.rev >= from_revision:
+ x.checkout()
+ x.check_clean()
+ x.commit()
+
+
+if __name__ == "__main__":
+ #run_command("clean", "rm -Rf git svn")
+ #git_init()
+ a = Svn2Git("ocsigen", "upstream")
+ a.do(0)
More information about the Pkg-ocaml-maint-commits
mailing list