[PATCH] convert: svn_sink: workaround of command line size limitation on win32

Shun-ichi Goto shunichi.goto at gmail.com
Wed Jan 2 15:28:38 CST 2008


# HG changeset patch
# User Shun-ichi GOTO <shunichi.goto at gmail.com>
# Date 1199309130 -32400
# Node ID f99b3e808ac01f613b568fe5a9f2c146cac94313
# Parent  f3881154bc4d990e79235b1f33ffa690f0a4c990
convert: svn_sink: workaround of command line size limitation on win32.

On win32, the command line arguments seems to be limited about 2400
bytes.  So 'add', 'delete', 'propget' and 'propdel' operations are
called several times within this limitation.  And also 'commit'
operation is changed to be called without passing target files not to
exceeds this limitation because it cannot be a separated like other
operations above.

diff -r f3881154bc4d -r f99b3e808ac0 hgext/convert/subversion.py
--- a/hgext/convert/subversion.py	Thu Jan 03 06:25:30 2008 +0900
+++ b/hgext/convert/subversion.py	Thu Jan 03 06:25:30 2008 +0900
@@ -707,6 +707,27 @@ class svn_sink(converter_sink, commandli
 class svn_sink(converter_sink, commandline):
     commit_re = re.compile(r'Committed revision (\d+).', re.M)
 
+    # iterates sublist of given list for concatenated length is within limit
+    def limit_arglist(self, files):
+        if os.name != 'nt':
+            yield files
+            return
+        # When I tested on WinXP, limit = 2500 is NG, 2400 is OK
+        limit = 2000
+        bytes = 0
+        fl = []
+        for fn in files:
+            b = len(fn) + 1
+            if bytes + b < limit:
+                fl.append(fn)
+                bytes += b
+            else:
+                yield fl
+                fl = []
+                bytes = 0
+        if fl:
+            yield fl
+
     def prerun(self):
         if self.wc:
             os.chdir(self.wc)
@@ -845,12 +866,14 @@ class svn_sink(converter_sink, commandli
                     if not os.path.exists(self.wjoin(d, '.svn', 'entries'))]
         if add_dirs:
             add_dirs.sort()
-            self.run('add', non_recursive=True, quiet=True, *add_dirs)
+            for fl in self.limit_arglist(add_dirs):
+                self.run('add', non_recursive=True, quiet=True, *fl)
         return add_dirs
 
     def add_files(self, files):
         if files:
-            self.run('add', quiet=True, *files)
+            for fl in self.limit_arglist(files):
+                self.run('add', quiet=True, *fl)
         return files
 
     def tidy_dirs(self, names):
@@ -884,15 +907,18 @@ class svn_sink(converter_sink, commandli
                 self._copyfile(s, d)
             self.copies = []
         if self.delete:
-            self.run0('delete', *self.delete)
+            for fl in self.limit_arglist(self.delete):
+                self.run0('delete', *fl)
             self.delete = []
         entries.update(self.add_files(files.difference(entries)))
         entries.update(self.tidy_dirs(entries))
         if self.delexec:
-            self.run0('propdel', 'svn:executable', *self.delexec)
+            for fl in self.limit_arglist(self.delexec):
+                self.run0('propdel', 'svn:executable', *fl)
             self.delexec = []
         if self.setexec:
-            self.run0('propset', 'svn:executable', '*', *self.setexec)
+            for fl in self.limit_arglist(self.setexec):
+                self.run0('propset', 'svn:executable', '*', *fl)
             self.setexec = []
 
         fd, messagefile = tempfile.mkstemp(prefix='hg-convert-')
@@ -903,8 +929,7 @@ class svn_sink(converter_sink, commandli
             output = self.run0('commit',
                                username=util.shortuser(commit.author),
                                file=messagefile,
-                               encoding='utf-8',
-                               *list(entries))
+                               encoding='utf-8')
             try:
                 rev = self.commit_re.search(output).group(1)
             except AttributeError:


More information about the Mercurial mailing list