hgext/convert/subversion.py
changeset 5100 39b6eaee6fd7
parent 5077 487659a90497
child 5105 78eb03cbe535
equal deleted inserted replaced
5099:117dab48ca99 5100:39b6eaee6fd7
    22 # e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing
    22 # e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing
    23 # these bindings.
    23 # these bindings.
    24 
    24 
    25 from cStringIO import StringIO
    25 from cStringIO import StringIO
    26 
    26 
    27 from common import NoRepo, commit, converter_source
    27 from common import NoRepo, commit, converter_source, encodeargs
    28 
    28 
    29 try:
    29 try:
    30     from svn.core import SubversionException, Pool
    30     from svn.core import SubversionException, Pool
    31     import svn
    31     import svn
    32     import svn.client
    32     import svn.client
    55 class changedpath(object):
    55 class changedpath(object):
    56     def __init__(self, p):
    56     def __init__(self, p):
    57         self.copyfrom_path = p.copyfrom_path
    57         self.copyfrom_path = p.copyfrom_path
    58         self.copyfrom_rev = p.copyfrom_rev
    58         self.copyfrom_rev = p.copyfrom_rev
    59         self.action = p.action
    59         self.action = p.action
       
    60 
       
    61 def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
       
    62                     strict_node_history=False):
       
    63     protocol = -1
       
    64     def receiver(orig_paths, revnum, author, date, message, pool):
       
    65         if orig_paths is not None:
       
    66             for k, v in orig_paths.iteritems():
       
    67                 orig_paths[k] = changedpath(v)
       
    68         pickle.dump((orig_paths, revnum, author, date, message),
       
    69                                 fp, protocol)
       
    70         
       
    71     try:
       
    72         # Use an ra of our own so that our parent can consume
       
    73         # our results without confusing the server.
       
    74         t = transport.SvnRaTransport(url=url)
       
    75         svn.ra.get_log(t.ra, paths, start, end, limit,
       
    76                        discover_changed_paths,
       
    77                        strict_node_history,
       
    78                        receiver)
       
    79     except SubversionException, (_, num):
       
    80         pickle.dump(num, fp, protocol)
       
    81     else:
       
    82         pickle.dump(None, fp, protocol)
       
    83     fp.close()
    60 
    84 
    61 # SVN conversion code stolen from bzr-svn and tailor
    85 # SVN conversion code stolen from bzr-svn and tailor
    62 class convert_svn(converter_source):
    86 class convert_svn(converter_source):
    63     def __init__(self, ui, url, rev=None):
    87     def __init__(self, ui, url, rev=None):
    64         super(convert_svn, self).__init__(ui, url, rev=rev)
    88         super(convert_svn, self).__init__(ui, url, rev=rev)
   194         del self.commits[rev]
   218         del self.commits[rev]
   195         return commit
   219         return commit
   196 
   220 
   197     def get_log(self, paths, start, end, limit=0, discover_changed_paths=True,
   221     def get_log(self, paths, start, end, limit=0, discover_changed_paths=True,
   198                 strict_node_history=False):
   222                 strict_node_history=False):
   199         '''wrapper for svn.ra.get_log.
       
   200         on a large repository, svn.ra.get_log pins huge amounts of
       
   201         memory that cannot be recovered.  work around it by forking
       
   202         and writing results over a pipe.'''
       
   203 
       
   204         def child(fp):
       
   205             protocol = -1
       
   206             def receiver(orig_paths, revnum, author, date, message, pool):
       
   207                 if orig_paths is not None:
       
   208                     for k, v in orig_paths.iteritems():
       
   209                         orig_paths[k] = changedpath(v)
       
   210                 pickle.dump((orig_paths, revnum, author, date, message),
       
   211                             fp, protocol)
       
   212 
       
   213             try:
       
   214                 # Use an ra of our own so that our parent can consume
       
   215                 # our results without confusing the server.
       
   216                 t = transport.SvnRaTransport(url=self.url)
       
   217                 svn.ra.get_log(t.ra, paths, start, end, limit,
       
   218                                discover_changed_paths,
       
   219                                strict_node_history,
       
   220                                receiver)
       
   221             except SubversionException, (_, num):
       
   222                 self.ui.print_exc()
       
   223                 pickle.dump(num, fp, protocol)
       
   224             else:
       
   225                 pickle.dump(None, fp, protocol)
       
   226             fp.close()
       
   227 
   223 
   228         def parent(fp):
   224         def parent(fp):
   229             while True:
   225             while True:
   230                 entry = pickle.load(fp)
   226                 entry = pickle.load(fp)
   231                 try:
   227                 try:
   233                 except:
   229                 except:
   234                     if entry is None:
   230                     if entry is None:
   235                         break
   231                         break
   236                     raise SubversionException("child raised exception", entry)
   232                     raise SubversionException("child raised exception", entry)
   237                 yield entry
   233                 yield entry
   238 
   234             
   239         rfd, wfd = os.pipe()
   235         args = [self.url, paths, start, end, limit, discover_changed_paths,
   240         pid = os.fork()
   236                 strict_node_history]
   241         if pid:
   237         arg = encodeargs(args)
   242             os.close(wfd)
   238         hgexe = util.hgexecutable()
   243             for p in parent(os.fdopen(rfd, 'rb')):
   239         cmd = '"%s "debug-svn-log""' % util.shellquote(hgexe)
   244                 yield p
   240         stdin, stdout = os.popen2(cmd, 'b')
   245             ret = os.waitpid(pid, 0)[1]
   241         
   246             if ret:
   242         stdin.write(arg)
   247                 raise util.Abort(_('get_log %s') % util.explain_exit(ret))
   243         stdin.close()
   248         else:
   244 
   249             os.close(rfd)
   245         for p in parent(stdout):
   250             child(os.fdopen(wfd, 'wb'))
   246             yield p
   251             os._exit(0)
       
   252 
   247 
   253     def gettags(self):
   248     def gettags(self):
   254         tags = {}
   249         tags = {}
   255         start = self.revnum(self.head)
   250         start = self.revnum(self.head)
   256         try:
   251         try: