Rev 2494: Fix a small bug when we have a symlink that does not need to be re-read. in http://bzr.arbash-meinel.com/branches/bzr/experimental/dirstate-nohc

John Arbash Meinel john at arbash-meinel.com
Fri Mar 2 01:28:01 GMT 2007


At http://bzr.arbash-meinel.com/branches/bzr/experimental/dirstate-nohc

------------------------------------------------------------
revno: 2494
revision-id: john at arbash-meinel.com-20070302012753-5jwb15csi4j2mi4w
parent: john at arbash-meinel.com-20070302002706-xz1pf69mu3tk9ud8
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: dirstate-nohc
timestamp: Thu 2007-03-01 19:27:53 -0600
message:
  Fix a small bug when we have a symlink that does not need to be re-read.
modified:
  bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
  bzrlib/tests/bzrdir_implementations/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
  bzrlib/tests/test_bundle.py    test.py-20050630184834-092aa401ab9f039c
  bzrlib/tests/test_dirstate.py  test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
-------------- next part --------------
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2007-03-02 00:07:29 +0000
+++ b/bzrlib/dirstate.py	2007-03-02 01:27:53 +0000
@@ -1059,7 +1059,7 @@
             and saved_file_size == stat_value.st_size):
             # The stat hasn't changed since we saved, so we can potentially
             # re-use the saved sha hash.
-            if minikind != 'f':
+            if minikind == 'd':
                 return None
 
             cutoff = self._sha_cutoff_time()

=== modified file 'bzrlib/tests/bzrdir_implementations/test_bzrdir.py'
--- a/bzrlib/tests/bzrdir_implementations/test_bzrdir.py	2007-02-25 22:50:34 +0000
+++ b/bzrlib/tests/bzrdir_implementations/test_bzrdir.py	2007-03-02 01:27:53 +0000
@@ -415,6 +415,7 @@
         self.assertNotEqual(dir.transport.base, target.transport.base)
         self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
                                     ['./.bzr/stat-cache',
+                                     './.bzr/checkout/dirstate',
                                      './.bzr/checkout/stat-cache',
                                      './.bzr/checkout/merge-hashes',
                                      './.bzr/merge-hashes',

=== modified file 'bzrlib/tests/test_bundle.py'
--- a/bzrlib/tests/test_bundle.py	2007-02-17 03:34:50 +0000
+++ b/bzrlib/tests/test_bundle.py	2007-03-02 01:27:53 +0000
@@ -488,7 +488,7 @@
             tree.update()
             delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
             self.assertFalse(delta.has_changed(),
-                             'Working tree has modifications')
+                             'Working tree has modifications: %s' % delta)
         return tree
 
     def valid_apply_bundle(self, base_rev_id, info, checkout_dir=None):

=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py	2007-03-02 00:07:29 +0000
+++ b/bzrlib/tests/test_dirstate.py	2007-03-02 01:27:53 +0000
@@ -1080,13 +1080,15 @@
                          state._dirblock_state)
 
         stat_value = os.lstat('a')
-        digest = state.update_entry(entry, abspath='a',
+        packed_stat = dirstate.pack_stat(stat_value)
+        link_or_sha1 = state.update_entry(entry, abspath='a',
                                           stat_value=stat_value)
-        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6', digest)
-        packed_stat = dirstate.pack_stat(stat_value)
+        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
+                         link_or_sha1)
 
         # The dirblock entry should be updated with the new info
-        self.assertEqual([('f', digest, 14, False, packed_stat)], entry[1])
+        self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
+                         entry[1])
         self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
                          state._dirblock_state)
         mode = stat_value.st_mode
@@ -1101,12 +1103,13 @@
         # guaranteed to look too new.
         state.adjust_time(-10)
 
-        digest = state.update_entry(entry, abspath='a',
+        link_or_sha1 = state.update_entry(entry, abspath='a',
                                           stat_value=stat_value)
         self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
                           ('sha1', 'a'), ('is_exec', mode, False),
                          ], state._log)
-        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6', digest)
+        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
+                         link_or_sha1)
         self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
                          state._dirblock_state)
         state.save()
@@ -1114,9 +1117,10 @@
         # However, if we move the clock forward so the file is considered
         # "stable", it should just returned the cached value.
         state.adjust_time(20)
-        digest = state.update_entry(entry, abspath='a',
+        link_or_sha1 = state.update_entry(entry, abspath='a',
                                           stat_value=stat_value)
-        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6', digest)
+        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
+                         link_or_sha1)
         self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
                           ('sha1', 'a'), ('is_exec', mode, False),
                          ], state._log)
@@ -1124,10 +1128,57 @@
     def test_update_entry_no_stat_value(self):
         """Passing the stat_value is optional."""
         state, entry = self.get_state_with_a()
+        state.adjust_time(-10) # Make sure the file looks new
         self.build_tree(['a'])
         # Add one where we don't provide the stat or sha already
-        digest = state.update_entry(entry, abspath='a')
-        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6', digest)
+        link_or_sha1 = state.update_entry(entry, abspath='a')
+        self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
+                         link_or_sha1)
+        stat_value = os.lstat('a')
+        self.assertEqual([('lstat', 'a'), ('sha1', 'a'),
+                          ('is_exec', stat_value.st_mode, False),
+                         ], state._log)
+
+    def test_update_entry_symlink(self):
+        """Update entry should read symlinks."""
+        if not osutils.has_symlinks():
+            return # PlatformDeficiency / TestSkipped
+        state, entry = self.get_state_with_a()
+        state.save()
+        self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
+                         state._dirblock_state)
+        os.symlink('target', 'a')
+
+        state.adjust_time(-10) # Make the symlink look new
+        stat_value = os.lstat('a')
+        packed_stat = dirstate.pack_stat(stat_value)
+        link_or_sha1 = state.update_entry(entry, abspath='a',
+                                          stat_value=stat_value)
+        self.assertEqual('target', link_or_sha1)
+        self.assertEqual([('read_link', 'a', '')], state._log)
+        # Dirblock is updated
+        self.assertEqual([('l', link_or_sha1, 6, False, packed_stat)],
+                         entry[1])
+        self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
+                         state._dirblock_state)
+
+        # Because the stat_value looks new, we should re-read the target
+        link_or_sha1 = state.update_entry(entry, abspath='a',
+                                          stat_value=stat_value)
+        self.assertEqual('target', link_or_sha1)
+        self.assertEqual([('read_link', 'a', ''),
+                          ('read_link', 'a', 'target'),
+                         ], state._log)
+        state.adjust_time(+20) # Skip into the future, all files look old
+        link_or_sha1 = state.update_entry(entry, abspath='a',
+                                          stat_value=stat_value)
+        self.assertEqual('target', link_or_sha1)
+        # There should not be a new read_link call.
+        # (this is a weak assertion, because read_link is fairly inexpensive,
+        # versus the number of symlinks that we would have)
+        self.assertEqual([('read_link', 'a', ''),
+                          ('read_link', 'a', 'target'),
+                         ], state._log)
 
     def test_update_entry_dir(self):
         state, entry = self.get_state_with_a()

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-03-02 00:27:06 +0000
+++ b/bzrlib/workingtree_4.py	2007-03-02 01:27:53 +0000
@@ -1604,7 +1604,7 @@
                 source_details = entry[1][source_index]
             target_details = entry[1][target_index]
             target_minikind = target_details[0]
-            if path_info is not None and target_minikind not in 'ar':
+            if path_info is not None and target_minikind in 'fdl':
                 assert target_index == 0
                 link_or_sha1 = state.update_entry(entry, abspath=path_info[4],
                                                   stat_value=path_info[3])
@@ -1664,6 +1664,7 @@
                             # We could check the size, but we already have the
                             # sha1 hash.
                             content_change = (link_or_sha1 != source_details[1])
+                        # Target details is updated at update_entry time
                         target_exec = target_details[3]
                     elif target_kind == 'symlink':
                         if source_minikind != 'l':
@@ -1706,7 +1707,6 @@
                         last_target_parent[2] = target_parent_entry
 
                 source_exec = source_details[3]
-                #path_unicode = utf8_decode(path)[0]
                 return ((entry[0][2], path, content_change,
                         (True, True),
                         (source_parent_id, target_parent_id),
@@ -1719,20 +1719,17 @@
                     path = pathjoin(entry[0][0], entry[0][1])
                     # parent id is the entry for the path in the target tree
                     # TODO: these are the same for an entire directory: cache em.
-                    parent_id = state._get_entry(target_index, path_utf8=entry[0][0])[0][2]
+                    parent_id = state._get_entry(target_index,
+                                                 path_utf8=entry[0][0])[0][2]
                     if parent_id == entry[0][2]:
                         parent_id = None
-                    # basename
-                    new_executable = bool(
-                        stat.S_ISREG(path_info[3].st_mode)
-                        and stat.S_IEXEC & path_info[3].st_mode)
-                    #path_unicode = utf8_decode(path)[0]
+                    target_exec = target_details[3]
                     return ((entry[0][2], path, True,
                             (False, True),
                             (None, parent_id),
                             (None, entry[0][1]),
                             (None, path_info[2]),
-                            (None, new_executable)),)
+                            (None, target_exec)),)
                 else:
                     # but its not on disk: we deliberately treat this as just
                     # never-present. (Why ?! - RBC 20070224)
@@ -1747,7 +1744,6 @@
                 parent_id = state._get_entry(source_index, path_utf8=entry[0][0])[0][2]
                 if parent_id == entry[0][2]:
                     parent_id = None
-                #old_path_unicode = utf8_decode(old_path)[0]
                 return ((entry[0][2], old_path, True,
                         (True, False),
                         (parent_id, None),



More information about the bazaar-commits mailing list