comparison mercurial/subrepo.py @ 13027:7f2ecb64140d

subrepo: archive git subrepos
author Eric Eisner <ede@mit.edu>
date Thu, 18 Nov 2010 19:20:21 -0500
parents 96956105e92d
children f930032aa6d5
comparison
equal deleted inserted replaced
13026:53391819f195 13027:7f2ecb64140d
4 # 4 #
5 # This software may be used and distributed according to the terms of the 5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version. 6 # GNU General Public License version 2 or any later version.
7 7
8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath 8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
9 import stat, subprocess 9 import stat, subprocess, tarfile
10 from i18n import _ 10 from i18n import _
11 import config, util, node, error, cmdutil 11 import config, util, node, error, cmdutil
12 hg = None 12 hg = None
13 13
14 nullstate = ('', '', 'empty') 14 nullstate = ('', '', 'empty')
611 self._ctx = ctx 611 self._ctx = ctx
612 self._relpath = path 612 self._relpath = path
613 self._path = ctx._repo.wjoin(path) 613 self._path = ctx._repo.wjoin(path)
614 self._ui = ctx._repo.ui 614 self._ui = ctx._repo.ui
615 615
616 def _gitcommand(self, commands): 616 def _gitcommand(self, commands, stream=False):
617 return self._gitdir(commands)[0] 617 return self._gitdir(commands, stream=stream)[0]
618 618
619 def _gitdir(self, commands): 619 def _gitdir(self, commands, stream=False):
620 commands = ['--no-pager', '--git-dir=%s/.git' % self._path, 620 commands = ['--no-pager', '--git-dir=%s/.git' % self._path,
621 '--work-tree=%s' % self._path] + commands 621 '--work-tree=%s' % self._path] + commands
622 return self._gitnodir(commands) 622 return self._gitnodir(commands, stream=stream)
623 623
624 def _gitnodir(self, commands): 624 def _gitnodir(self, commands, stream=False):
625 """Calls the git command 625 """Calls the git command
626 626
627 The methods tries to call the git command. versions previor to 1.6.0 627 The methods tries to call the git command. versions previor to 1.6.0
628 are not supported and very probably fail. 628 are not supported and very probably fail.
629 """ 629 """
631 cmd = [util.shellquote(arg) for arg in cmd] 631 cmd = [util.shellquote(arg) for arg in cmd]
632 cmd = util.quotecommand(' '.join(cmd)) 632 cmd = util.quotecommand(' '.join(cmd))
633 633
634 # print git's stderr, which is mostly progress and useful info 634 # print git's stderr, which is mostly progress and useful info
635 p = subprocess.Popen(cmd, shell=True, bufsize=-1, 635 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
636 close_fds=(os.name == 'posix'), 636 close_fds=util.closefds,
637 stdout=subprocess.PIPE) 637 stdout=subprocess.PIPE)
638 if stream:
639 return p.stdout, None
640
638 retdata = p.stdout.read() 641 retdata = p.stdout.read()
639 # wait for the child to exit to avoid race condition. 642 # wait for the child to exit to avoid race condition.
640 p.wait() 643 p.wait()
641 644
642 if p.returncode != 0: 645 if p.returncode != 0:
793 if os.path.isdir(path) and not os.path.islink(path): 796 if os.path.isdir(path) and not os.path.islink(path):
794 shutil.rmtree(path) 797 shutil.rmtree(path)
795 else: 798 else:
796 os.remove(path) 799 os.remove(path)
797 800
801 def archive(self, archiver, prefix):
802 source, revision = self._state
803 self._fetch(source, revision)
804
805 # Parse git's native archive command.
806 # This should be much faster than manually traversing the trees
807 # and objects with many subprocess calls.
808 tarstream = self._gitcommand(['archive', revision], stream=True)
809 tar = tarfile.open(fileobj=tarstream, mode='r|')
810 for info in tar:
811 archiver.addfile(os.path.join(prefix, self._relpath, info.name),
812 info.mode, info.issym(),
813 tar.extractfile(info).read())
814
798 types = { 815 types = {
799 'hg': hgsubrepo, 816 'hg': hgsubrepo,
800 'svn': svnsubrepo, 817 'svn': svnsubrepo,
801 'git': gitsubrepo, 818 'git': gitsubrepo,
802 } 819 }