convert_svn ("release early" edition)
Brendan Cully
brendan at kublai.com
Fri Jun 29 17:39:38 CDT 2007
On Sunday, 11 February 2007 at 23:47, Daniel Holth wrote:
> convert-repo patched to convert from Subversion.
>
> http://dingoskidneys.com/cgi-bin/hgwebdir.cgi/outgoing (patches applied)
> http://dingoskidneys.com/cgi-bin/hgwebdir.cgi/queue-convert-svn (just
> the patches)
Here's an update to 0.9.4. I can't really test it yet since my svn
1.4.3 bindings don't seem to return the right information from
get_dir2. But this patch does allow convert to churn for a while
before bailing out :)
-------------- next part --------------
# HG changeset patch
# User Brendan Cully <brendan at kublai.com>
# Date 1183156645 25200
# Node ID 0b6906b6035b2a5ff07fc9f18184bb58710bd34f
# Parent 1bcae4ff7dfacee7e4ae32290526dd00512dbdc4
Update convertsvn for 0.9.4
diff --git a/convert_svn b/convert_svn
--- a/convert_svn
+++ b/convert_svn
@@ -1,13 +1,78 @@ add convert_svn class
add convert_svn class
Patch to work with subversion binding 1.4 and python 2.3.
-diff -r e061269bc66b hgext/convert/__init__.py
---- a/hgext/convert/__init__.py Sun Jun 10 10:16:59 2007 -0400
-+++ b/hgext/convert/__init__.py Sun Jun 10 10:21:06 2007 -0400
-@@ -7,6 +7,18 @@
-
- import sys, os, zlib, sha, time, re, locale, socket
+diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
+--- a/hgext/convert/__init__.py
++++ b/hgext/convert/__init__.py
+@@ -9,17 +9,19 @@ from cvs import convert_cvs
+ from cvs import convert_cvs
+ from git import convert_git
+ from hg import convert_mercurial
++from convertsvn import convert_svn
+
+ import os
from mercurial import hg, ui, util, commands
+
+ commands.norepo += " convert"
+
+-converters = [convert_cvs, convert_git, convert_mercurial]
++converters = [convert_svn, convert_cvs, convert_git, convert_mercurial]
+
+ def converter(ui, path):
+- if not os.path.isdir(path):
+- raise util.Abort("%s: not a directory" % path)
++ # Subversion URLs are not directories
++ # if not os.path.isdir(path):
++ # raise util.Abort("%s: not a directory" % path)
+ for c in converters:
+ try:
+ return c(ui, path)
+@@ -179,6 +181,8 @@ class convert(object):
+ def copy(self, rev):
+ c = self.commitcache[rev]
+ files = self.source.getchanges(rev)
++
++ do_copies = (hasattr(c, 'copies') and hasattr(self.dest, 'copyfile'))
+
+ for f, v in files:
+ try:
+@@ -188,6 +192,11 @@ class convert(object):
+ else:
+ e = self.source.getmode(f, v)
+ self.dest.putfile(f, e, data)
++ if do_copies:
++ if f in c.copies:
++ # Merely marks that a copy happened.
++ self.dest.copyfile(c.copies[f], f)
++
+
+ r = [self.map[v] for v in c.parents]
+ f = [f for f, v in files]
+diff --git a/hgext/convert/common.py b/hgext/convert/common.py
+--- a/hgext/convert/common.py
++++ b/hgext/convert/common.py
+@@ -94,3 +94,12 @@ class converter_sink(object):
+ """Put tags into sink.
+ tags: {tagname: sink_rev_id, ...}"""
+ raise NotImplementedError()
++
++def recode(s):
++ try:
++ return s.decode("utf-8").encode("utf-8")
++ except:
++ try:
++ return s.decode("latin-1").encode("utf-8")
++ except:
++ return s.decode("utf-8", "replace").encode("utf-8")
+diff --git a/hgext/convert/convertsvn.py b/hgext/convert/convertsvn.py
+new file mode 100644
+--- /dev/null
++++ b/hgext/convert/convertsvn.py
+@@ -0,0 +1,401 @@
++# svn backend for convert extension
++
++from common import NoRepo, converter_source, commit, recode
++from mercurial import util
+
+import pprint
+# Subversion stuff. Works best with very recent Python SVN bindings
@@ -20,16 +85,54 @@ diff -r e061269bc66b hgext/convert/__ini
+import svn
+import transport
+from cStringIO import StringIO
-
- commands.norepo += " convert"
-
-@@ -108,6 +120,391 @@ class converter_sink(object):
- tags: {tagname: sink_rev_id, ...}"""
- raise NotImplementedError()
-
+
+# SVN conversion code stolen from bzr-svn and tailor
+class convert_svn(converter_source):
++ def __init__(self, ui, url):
++ try:
++ # Support file://path@rev syntax. Useful e.g. to convert
++ # deleted branches.
++ url, latest = url.rsplit("@", 1)
++ latest = int(latest)
++ except ValueError, e:
++ latest = None
++ self.url = url
++ self.encoding = 'UTF-8'
++ try:
++ self.transport = transport.SvnRaTransport(url = url)
++ self.ra = self.transport.ra
++ self.base = svn.ra.get_repos_root(self.ra)
++ self.module = self.url[len(self.base):]
++ self.modulemap = {} # revision, module
++ self.commits = {}
++ self.files = {}
++ self.uuid = svn.ra.get_uuid(self.ra).decode(self.encoding)
++ except SubversionException, e:
++ raise NoRepo("couldn't open SVN repo %s" % url)
++
++ try:
++ self.get_blacklist()
++ except IOError, e:
++ pass
++
++ try:
++ self.get_authors()
++ except IOError, e:
++ self.authors = None
++
++ if not latest:
++ latest = svn.ra.get_latest_revnum(self.ra)
++ dirent = svn.ra.stat(self.ra, self.module, latest)
++ self.last_changed = dirent.created_rev
++
++ self.head = (u"svn:%s%s@%s" % (self.uuid, self.module, self.last_changed)).decode(self.encoding)
++ # print "head is" + self.head
++
++ # Should lazily fetch revisions in batches of, say, 1,000...:
++ self._fetch_revisions(from_revnum=self.last_changed, to_revnum=0)
++ # self._parse()
++ # self._connect()
++
+ def get_blacklist(self):
+ """Avoid certain revision numbers.
+ It is not uncommon for two nearby revisions to cancel each other
@@ -65,51 +168,6 @@ diff -r e061269bc66b hgext/convert/__ini
+ authors[author] = email
+ self.authors = authors
+
-+ def __init__(self, url):
-+ try:
-+ # Support file://path@rev syntax. Useful e.g. to convert
-+ # deleted branches.
-+ url, latest = url.rsplit("@", 1)
-+ latest = int(latest)
-+ except ValueError, e:
-+ latest = None
-+ self.url = url
-+ self.encoding = 'UTF-8'
-+ try:
-+ self.transport = transport.SvnRaTransport(url = url)
-+ self.ra = self.transport.ra
-+ self.base = svn.ra.get_repos_root(self.ra)
-+ self.module = self.url[len(self.base):]
-+ self.modulemap = {} # revision, module
-+ self.commits = {}
-+ self.files = {}
-+ self.uuid = svn.ra.get_uuid(self.ra).decode(self.encoding)
-+ except SubversionException, e:
-+ raise NoRepo("couldn't open SVN repo %s" % url)
-+
-+ try:
-+ self.get_blacklist()
-+ except IOError, e:
-+ pass
-+
-+ try:
-+ self.get_authors()
-+ except IOError, e:
-+ self.authors = None
-+
-+ if not latest:
-+ latest = svn.ra.get_latest_revnum(self.ra)
-+ dirent = svn.ra.stat(self.ra, self.module, latest)
-+ self.last_changed = dirent.created_rev
-+
-+ self.head = (u"svn:%s%s@%s" % (self.uuid, self.module, self.last_changed)).decode(self.encoding)
-+ # print "head is" + self.head
-+
-+ # Should lazily fetch revisions in batches of, say, 1,000...:
-+ self._fetch_revisions(from_revnum=self.last_changed, to_revnum=0)
-+ # self._parse()
-+ # self._connect()
-+
+ def reparent(self, module):
+ svn_url = self.base + module
+ # print "reparent to %s" % svn_url.encode(self.encoding)
@@ -412,57 +470,41 @@ diff -r e061269bc66b hgext/convert/__ini
+
+ self.reparent(self.module)
+ return [path + "/" + c for c in children]
-
- # CVS conversion code inspired by hg-cvs-import and git-cvsimport
- class convert_cvs(converter_source):
-@@ -458,6 +855,13 @@ class convert_mercurial(converter_sink):
+diff --git a/hgext/convert/git.py b/hgext/convert/git.py
+--- a/hgext/convert/git.py
++++ b/hgext/convert/git.py
+@@ -2,16 +2,7 @@
+
+ import os
+
+-from common import NoRepo, commit, converter_source
+-
+-def recode(s):
+- try:
+- return s.decode("utf-8").encode("utf-8")
+- except:
+- try:
+- return s.decode("latin-1").encode("utf-8")
+- except:
+- return s.decode("utf-8", "replace").encode("utf-8")
++from common import NoRepo, commit, converter_source, recode
+
+ class convert_git(converter_source):
+ def __init__(self, ui, path):
+diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py
+--- a/hgext/convert/hg.py
++++ b/hgext/convert/hg.py
+@@ -28,6 +28,13 @@ class convert_mercurial(converter_sink):
+ self.repo.wwrite(f, data, e)
if self.repo.dirstate.state(f) == '?':
self.repo.dirstate.update([f], "a")
-
++
+ def copyfile(self, source, dest):
+ # Hold a copymap map[dest] = source, like Mercurial does?
+ # Might need to say self.repo.dirstate.copies()[dest] = source
+ # Just mark it, don't let it actually do anything:
+ assert hasattr(self.repo.dirstate, 'copymap')
+ self.repo.dirstate.copymap[dest] = source
-+
+
def delfile(self, f):
try:
- os.unlink(self.repo.wjoin(f))
-@@ -522,11 +926,12 @@ class convert_mercurial(converter_sink):
- date, self.repo.changelog.tip(), hg.nullid)
- return hg.hex(self.repo.changelog.tip())
-
--converters = [convert_cvs, convert_git, convert_mercurial]
-+converters = [convert_svn, convert_cvs, convert_git, convert_mercurial]
-
- def converter(ui, path):
-- if not os.path.isdir(path):
-- raise util.Abort("%s: not a directory" % path)
-+ # Subversion URLs are not directories
-+ # if not os.path.isdir(path):
-+ # raise util.Abort("%s: not a directory" % path)
- for c in converters:
- try:
- return c(ui, path)
-@@ -628,6 +1033,8 @@ class convert(object):
- def copy(self, rev):
- c = self.commitcache[rev]
- files = self.source.getchanges(rev)
-+
-+ do_copies = (hasattr(c, 'copies') and hasattr(self.dest, 'copyfile'))
-
- for f, v in files:
- try:
-@@ -637,6 +1044,11 @@ class convert(object):
- else:
- e = self.source.getmode(f, v)
- self.dest.putfile(f, e, data)
-+ if do_copies:
-+ if f in c.copies:
-+ # Merely marks that a copy happened.
-+ self.dest.copyfile(c.copies[f], f)
-+
-
- r = [self.map[v] for v in c.parents]
- f = [f for f, v in files]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 186 bytes
Desc: not available
Url : http://selenic.com/pipermail/mercurial-devel/attachments/20070629/d607823e/attachment.pgp
More information about the Mercurial-devel
mailing list