[PATCH Updated] Add should automatically add unversioned parents

Michael Ellerman michael at ellerman.id.au
Fri Sep 9 16:15:00 BST 2005


Hi Martin,

Here's an updated (bzr revno 1189) version of my patch to make smart_add
automatically add unversioned parents. The logic is a bit cleaner than my 
previous patches, because I realised we don't care that os.path.dirname() is 
broken.

If you prefer, you can merge it from:
http://michael.ellerman.id.au/files/add-parents-automatically

revno: 1191  smart_add() adds unversioned parents
revno: 1190  Add (failing) tests for smart_add()

cheers

*** modified file 'bzrlib/selftest/versioning.py'
--- bzrlib/selftest/versioning.py 
+++ bzrlib/selftest/versioning.py 
@@ -17,7 +17,6 @@
 
 """Tests of simple versioning operations"""
 
-# TODO: test adding a file whose directory is not versioned
 # TODO: test trying to commit within a directory that is not yet added
 
 
@@ -55,11 +54,11 @@
         self.assertEquals(delta.added[0][0], 'foo')
         self.failIf(delta.modified)
 
-    def test_add_in_unversioned(self):
+    def test_branch_add_in_unversioned(self):
         """Try to add a file in an unversioned directory.
 
-        smart_add may eventually add the parent as necessary, but simple
-        branch add doesn't do that.
+        "bzr add" adds the parent as necessary, but simple branch add
+        doesn't do that.
         """
         from bzrlib.branch import Branch
         from bzrlib.errors import NotVersionedError
@@ -75,7 +74,53 @@
         
         self.check_and_upgrade()
 
-        
+
+    def test_add_in_unversioned(self):
+        """Try to add a file in an unversioned directory.
+
+        "bzr add" should add the parent(s) as necessary.
+        """
+        from bzrlib.branch import Branch
+        from bzrlib.commands import run_bzr
+        eq = self.assertEqual
+
+        b = Branch('.', init=True)
+
+        self.build_tree(['inertiatic/', 'inertiatic/esp'])
+        eq(list(b.unknowns()), ['inertiatic'])
+        run_bzr(['add', 'inertiatic/esp'])
+        eq(list(b.unknowns()), [])
+
+        # Multiple unversioned parents
+        self.build_tree(['veil/', 'veil/cerpin/', 'veil/cerpin/taxt'])
+        eq(list(b.unknowns()), ['veil'])
+        run_bzr(['add', 'veil/cerpin/taxt'])
+        eq(list(b.unknowns()), [])
+
+        # Check whacky paths work
+        self.build_tree(['cicatriz/', 'cicatriz/esp'])
+        eq(list(b.unknowns()), ['cicatriz'])
+        run_bzr(['add', 'inertiatic/../cicatriz/esp'])
+        eq(list(b.unknowns()), [])
+
+    def test_add_in_versioned(self):
+        """Try to add a file in a versioned directory.
+
+        "bzr add" should do this happily.
+        """
+        from bzrlib.branch import Branch
+        from bzrlib.commands import run_bzr
+        eq = self.assertEqual
+
+        b = Branch('.', init=True)
+
+        self.build_tree(['inertiatic/', 'inertiatic/esp'])
+        eq(list(b.unknowns()), ['inertiatic'])
+        run_bzr(['add', '--no-recurse', 'inertiatic'])
+        eq(list(b.unknowns()), ['inertiatic/esp'])
+        run_bzr(['add', 'inertiatic/esp'])
+        eq(list(b.unknowns()), [])
+
     def test_subdir_add(self):
         """Add in subdirectory should add only things from there down"""
         
@@ -130,7 +175,6 @@
         check(b)
         
 
-        
         
 class SubdirCommit(TestCaseInTempDir):
 

*** modified file 'bzrlib/add.py'
--- bzrlib/add.py 
+++ bzrlib/add.py 
@@ -18,6 +18,7 @@
 from bzrlib.errors import NotBranchError
 from bzrlib.branch import Branch
 from bzrlib.osutils import quotefn
+from os.path import dirname
 
 def glob_expand_for_win32(file_list):
     import glob
@@ -78,11 +79,8 @@
     Returns the number of files added.
     """
     import os
-    import sys
-    from bzrlib.osutils import quotefn
     from bzrlib.errors import BadFileKindError, ForbiddenFileError
     import bzrlib.branch
-    import bzrlib.osutils
 
     assert isinstance(recurse, bool)
 
@@ -129,10 +127,7 @@
         elif sub_tree:
             mutter("%r is a bzr tree" %f)
         else:
-            entry = inv.add_path(rf, kind=kind)
-            mutter("added %r kind %r file_id={%s}" % (rf, kind, 
entry.file_id))
-            count += 1 
-            reporter(rf, kind, entry)
+            count += __add_one(branch, inv, rf, kind, reporter)
 
         if kind == 'directory' and recurse and not sub_tree:
             for subf in os.listdir(af):
@@ -152,3 +147,21 @@
         branch._write_inventory(inv)
 
     return count
+
+def __add_one(branch, inv, path, kind, reporter):
+    """Add a file or directory, automatically add unversioned parents."""
+
+    # Nothing to do if path is already versioned.
+    # This is safe from infinite recursion because the branch root is
+    # always versioned.
+    if inv.path2id(path) != None:
+        return 0
+
+    # add parent
+    count = __add_one(branch, inv, dirname(path), 'directory', reporter)
+
+    entry = inv.add_path(path, kind=kind)
+    mutter("added %r kind %r file_id={%s}" % (path, kind, entry.file_id))
+    reporter(path, kind, entry)
+
+    return count + 1

*** modified file 'bzrlib/builtins.py'
--- bzrlib/builtins.py 
+++ bzrlib/builtins.py 
@@ -145,8 +145,10 @@
     Therefore simply saying 'bzr add' will version all files that
     are currently unknown.
 
-    TODO: Perhaps adding a file whose directly is not versioned should
-    recursively add that parent, rather than giving an error?
+    Adding a file whose parent directory is not versioned will
+    implicitly add the parent, and so on up to the root. This means
+    you should never need to explictly add a directory, they'll just
+    get added when you add a file in the directory.
     """
     takes_args = ['file*']
     takes_options = ['verbose', 'no-recurse']



-- 
Michael Ellerman
IBM OzLabs

email: michael:ellerman.id.au
inmsg: mpe:jabber.org
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20050910/9a57c2b0/attachment.pgp 


More information about the bazaar mailing list