changeset 4:579633139692

clone: allow clone to add subtrees to an existing repo The --skiproot option skips the clone of the root repo and only clones the specified subtrees.
author jcoomes
date Mon, 03 Jan 2011 21:14:19 -0800
parents 04c4cfd17ff4
children bd32d04e966f
files tests/test-trees-local.t trees.py
diffstat 2 files changed, 139 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/tests/test-trees-local.t	Wed Dec 29 16:30:24 2010 -0800
+++ b/tests/test-trees-local.t	Mon Jan 03 21:14:19 2011 -0800
@@ -19,7 +19,10 @@
 
   $ hg tclone -q r1 r2
   $ hg tclone -q r1 r3 s1 file:$TESTTMP/r2 s2
-  $ hg tclone    r1 r4 s1 file:$TESTTMP/r3 s2
+
+Clone r4 in two steps using skiproot.
+
+  $ hg tclone r1 r4 s1
   cloning r1
   updating (to branch default|working directory) (re)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -34,6 +37,9 @@
   updating (to branch default|working directory) (re)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   created $TESTTMP/r4/s1/s1.1 with spaces
+
+  $ hg tclone --skiproot r3 r4 s2
+  skipping root r3
   
   cloning $TESTTMP/r3/s2
   updating (to branch default|working directory) (re)
@@ -55,6 +61,70 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   created $TESTTMP/r4/s2/s2.2/s2.2.1
 
+Clone using skiproot without explicitly listing subtrees.
+
+  $ hg tclone r1/s1 rx
+  cloning r1/s1
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx
+  
+  cloning $TESTTMP/r1/s1/s1.1 with spaces
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s1.1 with spaces
+
+  $ hg tclone --skiproot rflat rx
+  skipping root rflat
+  
+  cloning $TESTTMP/rflat/s1
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s1
+  
+  cloning $TESTTMP/rflat/s2
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s2
+  
+  cloning $TESTTMP/rflat/s3
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s3
+  
+  cloning $TESTTMP/rflat/s4
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s4
+  
+  cloning $TESTTMP/rflat/s5
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s5
+  
+  cloning $TESTTMP/rflat/s6
+  updating (to branch default|working directory) (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/s6
+
+Clone with skiproot where the source is not a repository.
+
+  $ mkdir not-a-repo
+  $ hg init not-a-repo/x1
+  $ hg init not-a-repo/x2
+  $ hg tclone --skiproot not-a-repo rx x1 x2
+  skipping root not-a-repo
+  
+  cloning not-a-repo/x1
+  updating (to branch default|working directory) (re)
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/x1
+  
+  cloning not-a-repo/x2
+  updating (to branch default|working directory) (re)
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created $TESTTMP/rx/x2
+
 List the configuration.
 
   $ hg tconfig -R rflat
@@ -69,6 +139,17 @@
   s1
   s2
 
+  $ hg tconfig -R rx
+  s1.1 with spaces
+  s1
+  s2
+  s3
+  s4
+  s5
+  s6
+  x1
+  x2
+
   $ for r in r1 r2 r3 r4
   > do
   >     echo
--- a/trees.py	Wed Dec 29 16:30:24 2010 -0800
+++ b/trees.py	Mon Jan 03 21:14:19 2011 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -160,8 +160,8 @@
             l += [dirpath]
     return sorted(l)
 
-def _writeconfig(repo, subtrees):
-    f = open(repo.join('trees'), 'w')
+def _writeconfig(repo, subtrees, append = False):
+    f = open(repo.join('trees'), append and 'a' or 'w')
     try:
         if subtrees:
             f.write('\n'.join(subtrees) + '\n')
@@ -171,32 +171,62 @@
 
 # ---------------- commands and associated recursion helpers -------------------
 
+def _clonerepo(ui, source, dest, opts):
+    _makeparentdir(dest)
+    # Copied from mercurial/hg.py; need the returned dest repo.
+    return hg.clone(hg.remoteui(ui, opts), source, dest,
+                    pull=opts.get('pull'),
+                    stream=opts.get('uncompressed'),
+                    rev=opts.get('rev'),
+                    update=opts.get('updaterev') or not opts.get('noupdate'),
+                    branch=opts.get('branch'))
+
+def _skiprepo(ui, source, dest):
+    src = None
+    try:
+        src = hg.repository(ui, source)
+    except:
+        class fakerepo(object):
+            def __init__(self, ui, path):
+                self.ui = ui
+                self._path = path
+            def capable(self, s):
+                return False
+            def local(self):
+                return True
+            def wjoin(self, path):
+                return os.path.join(self._path, path)
+        src = fakerepo(ui, source)
+    return (src, hg.repository(ui, dest))
+
+def _clonesubtrees(ui, src, dst, opts):
+    subtrees = []
+    for src, subtree in _subtreegen(src.ui, src, opts):
+        ui.status('\n')
+        _clone(ui, _subtreejoin(src, subtree), dst.wjoin(subtree), opts)
+        subtrees.append(subtree)
+    return subtrees
+
+def _clone(ui, source, dest, opts):
+    ui.status('cloning %s\n' % source)
+    src, dst = _clonerepo(ui, source, dest, opts)
+    ui.status(_('created %s\n') % dst.root)
+    subtrees = _clonesubtrees(ui, src, dst, opts)
+    _writeconfig(dst, subtrees)
+
 def clone(ui, source, dest=None, *subtreeargs, **opts):
     '''copy one or more existing repositories to create a tree'''
     if subtreeargs:
         s = __builtin__.list(subtreeargs)
         s.extend(opts.get('subtrees')) # Note:  extend does not return a value
         opts['subtrees'] = s
-
-    ui.status('cloning %s\n' % source)
-    _makeparentdir(dest)
-    # Copied from mercurial/hg.py; need the returned dest repo.
-    r = hg.clone(hg.remoteui(ui, opts), source, dest,
-                 pull=opts.get('pull'),
-                 stream=opts.get('uncompressed'),
-                 rev=opts.get('rev'),
-                 update=opts.get('updaterev') or not opts.get('noupdate'),
-                 branch=opts.get('branch'))
-    src = r[0]
-    dst = r[1]
-    ui.status(_('created %s\n') % dst.root)
-
-    subtrees = []
-    for src, subtree in _subtreegen(src.ui, src, opts):
-        ui.status('\n')
-        clone(ui, _subtreejoin(src, subtree), dst.wjoin(subtree), **opts)
-        subtrees.append(subtree)
-    _writeconfig(dst, subtrees)
+    if not opts.get('skiproot'):
+        _clone(ui, source, dest, opts)
+    else:
+        ui.status('skipping root %s\n' % source)
+        src, dst = _skiprepo(ui, source, dest)
+        subtrees = _clonesubtrees(ui, src, dst, opts)
+        _writeconfig(dst, subtrees, True)
     return 0
 
 def _command(ui, repo, argv, stop, opts):
@@ -468,6 +498,9 @@
 walkopt = [('w', 'walk', False,
             _('walk the filesystem to discover subtrees'))]
 
+cloneopts = [('', 'skiproot', False,
+              _('do not clone the root repo in the tree'))
+            ] + subtreesopt
 commandopts = [('', 'stop', False,
                 _('stop if command returns non-zero'))
               ] + subtreesopt
@@ -511,7 +544,7 @@
 
     global cmdtable
     cmdtable = {
-        '^tclone': _newcte('clone', clone, subtreesopt,
+        '^tclone': _newcte('clone', clone, cloneopts,
                            _('[OPTION]... SOURCE [DEST [SUBTREE]...]')),
         'tcommand': (command, commandopts, _('command [arg] ...')),
         'tconfig': (config, configopts, _('[OPTION]... [SUBTREE]...')),