changeset 21:760782dd3c80

tconfig: add --depth to write depth-most subtree configuration tconfig --set --depth rewrites the subtree configuration so that subtrees are defined depth-most (i.e., within the nearest enclosing repository).
author jcoomes
date Sun, 02 Mar 2014 09:55:27 -0800
parents 678eb575c330
children 4ce70223c2b4
files tests/test-trees-local.t trees.py
diffstat 2 files changed, 211 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/tests/test-trees-local.t	Wed Feb 26 12:21:43 2014 -0800
+++ b/tests/test-trees-local.t	Sun Mar 02 09:55:27 2014 -0800
@@ -338,8 +338,8 @@
   s1
   s2
 
-  $ hg tconfig -R r4 -s
-  abort: use either --walk or subtrees (but not both)
+  $ hg tconfig -R r4 -s # should fail
+  abort: * (glob)
   [255]
   $ hg tconfig -R r4 -d --all
   $ hg tconfig -R r4
@@ -1216,3 +1216,140 @@
   summary:     Added tag xyz for changeset 3abbfd61fcf3
   
 
+Test tconfig --set --depth.
+
+  $ for r in \
+  > n1 n1/a n1/a/b/c n1/a/b/c2 n1/d n1/d/e/f/g n1/d/e/f/g/h n1/d/e/f/i \
+  > n1/d/e/f/j n1/p/q/r n1/p/q/s \
+  > n2 n2/a n2/a/b n2/a/b/c n2/b n2/c n2/d n2/d/e n2/d/e/f n2/d/e/f/g \
+  > n2/a/b/c/c2 \
+  > n3 n3/a/b/c n3/a/b/c/d n3/a/b/c/e n3/x/y n3/a/b/c/f n3/a/b/c/f/g/h \
+  >   n3/x/z n3/p/q/r
+  > do
+  >   mkdir -p $r
+  >   rmdir $r
+  > 	hg init $r
+  > done
+
+  $ hg -R n1 tconfig --set --walk
+  $ hg -R n1 tconfig
+  a
+  a/b/c
+  a/b/c2
+  d
+  d/e/f/g
+  d/e/f/g/h
+  d/e/f/i
+  d/e/f/j
+  p/q/r
+  p/q/s
+  $ hg -R n1 tlist --short
+  .
+  a
+  a/b/c
+  a/b/c2
+  d
+  d/e/f/g
+  d/e/f/g/h
+  d/e/f/i
+  d/e/f/j
+  p/q/r
+  p/q/s
+  $ hg -R n1 tconfig --set --depth
+  $ hg -R n1 tconfig
+  a
+  d
+  p/q/r
+  p/q/s
+  $ hg -R n1 tlist --short
+  .
+  a
+  a/b/c
+  a/b/c2
+  d
+  d/e/f/g
+  d/e/f/g/h
+  d/e/f/i
+  d/e/f/j
+  p/q/r
+  p/q/s
+  $ hg -R n1/a tconfig
+  b/c
+  b/c2
+  $ hg -R n1/d tconfig
+  e/f/g
+  e/f/i
+  e/f/j
+
+tconfig --set --depth with no args should be repeatable
+
+  $ hg -R n1 tconfig --set --depth
+  $ hg -R n1 tconfig
+  a
+  d
+  p/q/r
+  p/q/s
+  $ hg -R n1 tlist --short
+  .
+  a
+  a/b/c
+  a/b/c2
+  d
+  d/e/f/g
+  d/e/f/g/h
+  d/e/f/i
+  d/e/f/j
+  p/q/r
+  p/q/s
+
+  $ hg -R n2 tconfig --set --walk --depth
+  $ hg -R n2 tconfig
+  a
+  b
+  c
+  d
+  $ hg -R n2 tlist --short
+  .
+  a
+  a/b
+  a/b/c
+  a/b/c/c2
+  b
+  c
+  d
+  d/e
+  d/e/f
+  d/e/f/g
+  $ hg -R n2/d tconfig
+  e
+  $ hg -R n2/d/e tconfig
+  f
+  $ hg -R n2/d/e/f tconfig
+  g
+
+  $ hg -R n3 tconfig --set --depth a/b/c a/b/c/d a/b/c/e x/y a/b/c/f \
+  > a/b/c/f/g/h x/z p/q/r
+  $ hg -R n3 tconfig
+  a/b/c
+  x/y
+  x/z
+  p/q/r
+  $ hg -R n3 tlist --short
+  .
+  a/b/c
+  a/b/c/d
+  a/b/c/e
+  a/b/c/f
+  a/b/c/f/g/h
+  x/y
+  x/z
+  p/q/r
+  $ hg -R n3/a/b/c tlist --short
+  .
+  d
+  e
+  f
+  f/g/h
+  $ hg -R n3/a/b/c/f tlist --short
+  .
+  g/h
--- a/trees.py	Wed Feb 26 12:21:43 2014 -0800
+++ b/trees.py	Sun Mar 02 09:55:27 2014 -0800
@@ -457,13 +457,19 @@
 
     return _docmd1(condcommit, ui, repo, *pats, **opts)
 
-def addconfig(ui, repo, subtrees, opts):
+def addconfig(ui, repo, subtrees, opts, ignoredups = False):
+    modified = False
     l = _subtreelist(ui, repo, opts)
     for subtree in subtrees:
         if subtree in l:
-            raise util.Abort(_('subtree %s already configured' % subtree))
-        l += [subtree]
-    return _writeconfig(repo, _ns(ui, opts), l)
+            if not ignoredups:
+                raise util.Abort(_('subtree %s already configured' % subtree))
+        else:
+            l += [subtree]
+            modified = True
+    if modified:
+        return _writeconfig(repo, _ns(ui, opts), l)
+    return 0
 
 def delconfig(ui, repo, subtrees, opts):
     all = opts.get('all')
@@ -497,13 +503,60 @@
             ui.write('\n')
     return rc
 
+def _depthmostsplit(subtreemap, subtree):
+    repo, sub = os.path.split(subtree)
+    while repo:
+        if repo in subtreemap:
+            return repo, sub
+        repo, sub2 = os.path.split(repo)
+        sub = subtree[len(repo) + 1:]
+    return '.', subtree
+
+def nestconfig(ui, repo, subtrees, opts):
+    newtrees = { }
+    subtreemap = dict.fromkeys(subtrees)
+    for sub in subtrees:
+        nestedrepo, nestedsub = _depthmostsplit(subtreemap, sub)
+        if nestedrepo in newtrees:
+            nl = newtrees[nestedrepo]
+            if nestedsub not in nl:
+                nl.append(nestedsub)
+        else:
+            newtrees[nestedrepo] = [nestedsub]
+    for sub in subtrees:
+        nr = hg_repo(ui, _subtreejoin(repo, sub), {})
+        _writeconfig(nr, _ns(ui, opts), newtrees.get(sub))
+    return _writeconfig(repo, _ns(ui, opts), newtrees.get('.'))
+
+# tconfig --set --depth example::
+#
+#   before         after
+#   ------------   --------------------
+#   $ hg tconfig   $ hg tconfig
+#   sub1           sub1
+#   sub1/sub1.1    sub2
+#   sub2           $ hg -R sub1 tconfig
+#   sub2/sub2.1    sub1.1
+#   sub2/sub2.2    $ hg -R sub2 tconfig
+#                  sub2.1
+#                  sub2.2
+
 def setconfig(ui, repo, subtrees, opts):
     walk = opts.get('walk')
-    if walk + bool(subtrees) != 1:
-        raise util.Abort(_('use either --walk or subtrees (but not both)'))
+    depth = opts.get('depth')
+    if walk and subtrees:
+        msg = _('subtrees cannot be specified when --walk is used')
+        raise util.Abort(msg)
+    elif not (subtrees or walk or depth):
+        msg = _('specify subtrees, or use --walk and/or --depth')
+        raise util.Abort(msg)
+
     if walk:
-        l = _shortpaths(repo.root, _walk(ui, repo, {}))[1:]
-        return _writeconfig(repo, _ns(ui, opts), l)
+        subtrees = _shortpaths(repo.root, _walk(ui, repo, {}))[1:]
+    elif not subtrees:
+        subtrees = _shortpaths(repo.root, _list(ui, repo, opts))[1:]
+    if depth:
+        return nestconfig(ui, repo, subtrees, opts)
     return _writeconfig(repo, _ns(ui, opts), subtrees)
 
 def config(ui, repo, *subtrees, **opts):
@@ -521,7 +574,10 @@
 
     --set:  set the subtree configuration to the specified subtrees.
       Use --set --walk to walk the filesystem rooted at REPO and set the
-      subtree configuration to the discovered repos.
+      subtree configuration to the discovered repos.  Use --depth
+      to write the subtree configuration depth-most, so that each
+      subtree is defined within the nearest enclosing repository.  Note
+      that --walk and --depth may be used together.
 
     --expand:  list the value of config items from the [trees] section.
       Items in the [trees] section can be defined in terms of other
@@ -529,9 +585,9 @@
       recursively expanded value.  It returns 0 if at least one config
       item was found; otherwise it returns 1.
 
-    Note that this command does not recurse into subtrees; it operates
-    only on the current repository.  (Use the tlist command to
-    recursively list subtrees.)
+    Note that with the slight exception of --set --depth, this command
+    does not recurse into subtrees; it operates only on the current
+    repository.  (To recursively list subtrees, use the tlist command.)
 
     """
 
@@ -542,8 +598,8 @@
     opset = opts.get('set')
     cnt = opadd + opdel + opexp + oplst + opset
     if cnt > 1:
-        raise util.Abort(_('at most one of --add, --del, --expand, --list ' +
-                           'or --set is allowed'))
+        raise util.Abort(_('at most one of --add, --del, --list, ' +
+                           '--set or --expand is allowed'))
     if not opexp and not repo:
         raise util.Abort(_('no repository found'))
     if repo:
@@ -833,6 +889,8 @@
                _('recursively expand config items in the [trees] section')),
               ('l', 'list', False,
                _('list the configured subtrees')),
+              ('', 'depth', False,
+               _('store subtree configuration depth-most')),
               ('s', 'set', False, _('set the subtree config to SUBTREEs'))
              ] + namespaceopt + walkopt