[PATCH] subrepo: archive git subrepos
Eric Eisner
ede at MIT.EDU
Thu Nov 18 18:46:59 CST 2010
# HG changeset patch
# User Eric Eisner <ede at mit.edu>
# Date 1290126021 18000
# Node ID bf15f3eed02ea6af83c1be1d18404eb12d02b51e
# Parent 9efc316a67160831684bea85101616d971ed06b4
subrepo: archive git subrepos
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -6,7 +6,7 @@
# GNU General Public License version 2 or any later version.
import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
-import stat, subprocess
+import stat, subprocess, tarfile
from i18n import _
import config, util, node, error, cmdutil
hg = None
@@ -605,15 +605,15 @@ class gitsubrepo(object):
self._path = ctx._repo.wjoin(path)
self._ui = ctx._repo.ui
- def _gitcommand(self, commands):
- return self._gitdir(commands)[0]
+ def _gitcommand(self, commands, stream=False):
+ return self._gitdir(commands, stream=stream)[0]
- def _gitdir(self, commands):
+ def _gitdir(self, commands, stream=False):
commands = ['--no-pager', '--git-dir=%s/.git' % self._path,
'--work-tree=%s' % self._path] + commands
- return self._gitnodir(commands)
+ return self._gitnodir(commands, stream=stream)
- def _gitnodir(self, commands):
+ def _gitnodir(self, commands, stream=False):
"""Calls the git command
The methods tries to call the git command. versions previor to 1.6.0
@@ -625,8 +625,11 @@ class gitsubrepo(object):
# print git's stderr, which is mostly progress and useful info
p = subprocess.Popen(cmd, shell=True, bufsize=-1,
- close_fds=(os.name == 'posix'),
+ close_fds=util.closefds,
stdout=subprocess.PIPE)
+ if stream:
+ return p.stdout, None
+
retdata = p.stdout.read()
# wait for the child to exit to avoid race condition.
p.wait()
@@ -787,6 +790,20 @@ class gitsubrepo(object):
else:
os.remove(path)
+ def archive(self, archiver, prefix):
+ source, revision = self._state
+ self._fetch(source, revision)
+
+ # Parse git's native archive command.
+ # This should be much faster than manually traversing the trees
+ # and objects with many subprocess calls.
+ tarstream = self._gitcommand(['archive', revision], stream=True)
+ tar = tarfile.open(fileobj=tarstream, mode='r|')
+ for info in tar:
+ archiver.addfile(os.path.join(prefix, self._relpath, info.name),
+ info.mode, info.issym(),
+ tar.extractfile(info).read())
+
types = {
'hg': hgsubrepo,
'svn': svnsubrepo,
diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t
--- a/tests/test-subrepo-git.t
+++ b/tests/test-subrepo-git.t
@@ -193,3 +193,17 @@ update to a revision without the subrepo
..
.git
g
+
+archive subrepos
+
+ $ cd ../t
+ $ hg archive --subrepos -r tip ../archive
+ pulling subrepo s
+ $ cd ../archive
+ $ cat s/f
+ f
+ $ cat s/g
+ g
+ gg
+ ggg
+
More information about the Mercurial-devel
mailing list