Rev 5766: (jameinel) TreeTransform.create_file and new_file can be passed sha1, in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Apr 7 12:04:10 UTC 2011


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 5766 [merge]
revision-id: pqm at pqm.ubuntu.com-20110407120406-74kdkstr862qm9cv
parent: pqm at pqm.ubuntu.com-20110407111546-99kqi96vnk9u8qvc
parent: john at arbash-meinel.com-20110407103624-n76g6tjeqmznwdcd
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2011-04-07 12:04:06 +0000
message:
  (jameinel) TreeTransform.create_file and new_file can be passed sha1,
   which will trigger a call to Tree._observed_sha1,
   caching the sha and stat information. (John A Meinel)
modified:
  Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
  bzrlib/api.py                  api.py-20070626082640-35lspz7j0ys7a8ld-1
  bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
  bzrlib/bundle/apply_bundle.py  apply_changeset.py-20050620044656-dba4eb8021a36f95
  bzrlib/bundle/commands.py      __init__.py-20050617152058-1b6530d9ab85c11c
  bzrlib/chk_map.py              chk_map.py-20081001014447-ue6kkuhofvdecvxa-1
  bzrlib/cmd_version_info.py     __init__.py-20051228204928-697d01fdca29c99b
  bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
  bzrlib/directory_service.py    directory_service.py-20080305221044-vr2mkvlsk8jypa2y-1
  bzrlib/filters/__init__.py     __init__.py-20080416080515-mkxl29amuwrf6uir-2
  bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
  bzrlib/generate_ids.py         generate_ids.py-20061102205935-z3do15ipw6m7v26u-1
  bzrlib/hooks.py                hooks.py-20070325015548-ix4np2q0kd8452au-1
  bzrlib/ignores.py              ignores.py-20060712153832-2von9l0t7p43ixsv-1
  bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
  bzrlib/lockable_files.py       control_files.py-20051111201905-bb88546e799d669f
  bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
  bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
  bzrlib/merge_directive.py      merge_directive.py-20070228184838-ja62280spt1g7f4x-1
  bzrlib/plugins/launchpad/lp_propose.py lp_submit.py-20100120065117-penrmqruf596pui6-1
  bzrlib/plugins/netrc_credential_store/__init__.py __init__.py-20081006090402-hd75m8kcrrm0vlz1-1
  bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
  bzrlib/revision.py             revision.py-20050309040759-e77802c08f3999d5
  bzrlib/sign_my_commits.py      sign_my_commits.py-20060215152201-5a6363365180e671
  bzrlib/smart/medium.py         medium.py-20061103051856-rgu2huy59fkz902q-1
  bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
  bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
  bzrlib/trace.py                trace.py-20050309040759-c8ed824bdcd4748a
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
  bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
  bzrlib/transport/local.py      local_transport.py-20050711165921-9b1f142bfe480c24
  bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
  bzrlib/ui/__init__.py          ui.py-20050824083933-8cf663c763ba53a9
  bzrlib/ui/text.py              text.py-20051130153916-2e438cffc8afc478
  doc/en/release-notes/bzr-2.4.txt bzr2.4.txt-20110114053217-k7ym9jfz243fddjm-1
=== modified file 'Makefile'
--- a/Makefile	2011-04-05 13:36:20 +0000
+++ b/Makefile	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/api.py'
--- a/bzrlib/api.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/api.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2008, 2009, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/btree_index.py'
--- a/bzrlib/btree_index.py	2011-04-05 11:31:58 +0000
+++ b/bzrlib/btree_index.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2009, 2010 Canonical Ltd
+# Copyright (C) 2008-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/bundle/apply_bundle.py'
--- a/bzrlib/bundle/apply_bundle.py	2011-04-04 23:45:23 +0000
+++ b/bzrlib/bundle/apply_bundle.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2006, 2007, 2009, 2010 Canonical Ltd
+# Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/bundle/commands.py'
--- a/bzrlib/bundle/commands.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/bundle/commands.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/chk_map.py'
--- a/bzrlib/chk_map.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/chk_map.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2009, 2010 Canonical Ltd
+# Copyright (C) 2008-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/cmd_version_info.py'
--- a/bzrlib/cmd_version_info.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/cmd_version_info.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/diff.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd.
+# Copyright (C) 2005-2011 Canonical Ltd.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/directory_service.py'
--- a/bzrlib/directory_service.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/directory_service.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Canonical Ltd
+# Copyright (C) 2008, 2009, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/filters/__init__.py'
--- a/bzrlib/filters/__init__.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/filters/__init__.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Canonical Ltd
+# Copyright (C) 2008, 2009, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/foreign.py'
--- a/bzrlib/foreign.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/foreign.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2009, 2010 Canonical Ltd
+# Copyright (C) 2008-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/generate_ids.py'
--- a/bzrlib/generate_ids.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/generate_ids.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
+# Copyright (C) 2006, 2007, 2009, 2010, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/hooks.py'
--- a/bzrlib/hooks.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/hooks.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2010 Canonical Ltd
+# Copyright (C) 2007-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/ignores.py'
--- a/bzrlib/ignores.py	2011-03-31 15:20:57 +0000
+++ b/bzrlib/ignores.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2010 Canonical Ltd
+# Copyright (C) 2006-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/index.py'
--- a/bzrlib/index.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/index.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2010 Canonical Ltd
+# Copyright (C) 2007-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/lockable_files.py'
--- a/bzrlib/lockable_files.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/lockable_files.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py	2011-04-06 04:04:54 +0000
+++ b/bzrlib/log.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/merge.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/merge_directive.py'
--- a/bzrlib/merge_directive.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/merge_directive.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2010 Canonical Ltd
+# Copyright (C) 2007-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/plugins/launchpad/lp_propose.py'
--- a/bzrlib/plugins/launchpad/lp_propose.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/plugins/launchpad/lp_propose.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 Canonical Ltd
+# Copyright (C) 2010, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/plugins/netrc_credential_store/__init__.py'
--- a/bzrlib/plugins/netrc_credential_store/__init__.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/plugins/netrc_credential_store/__init__.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2009, 2010 Canonical Ltd
+# Copyright (C) 2008-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2010 Canonical Ltd
+# Copyright (C) 2007-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/revision.py'
--- a/bzrlib/revision.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/revision.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/sign_my_commits.py'
--- a/bzrlib/sign_my_commits.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/sign_my_commits.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
+# Copyright (C) 2006, 2007, 2009, 2010, 2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/smart/medium.py'
--- a/bzrlib/smart/medium.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/smart/medium.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2010 Canonical Ltd
+# Copyright (C) 2006-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2011-04-05 11:10:25 +0000
+++ b/bzrlib/tests/test_transform.py	2011-04-05 13:25:50 +0000
@@ -93,6 +93,16 @@
         self.addCleanup(transform.finalize)
         return transform, transform.root
 
+    def get_transform_for_sha1_test(self):
+        trans, root = self.get_transform()
+        self.wt.lock_tree_write()
+        self.addCleanup(self.wt.unlock)
+        contents = ['just some content\n']
+        sha1 = osutils.sha_strings(contents)
+        # Roll back the clock
+        trans._creation_mtime = time.time() - 20.0
+        return trans, root, contents, sha1
+
     def test_existing_limbo(self):
         transform, root = self.get_transform()
         limbo_name = transform._limbodir
@@ -161,6 +171,67 @@
         transform.finalize()
         transform.finalize()
 
+    def test_apply_informs_tree_of_observed_sha1(self):
+        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
+        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
+                                  sha1=sha1)
+        calls = []
+        orig = self.wt._observed_sha1
+        def _observed_sha1(*args):
+            calls.append(args)
+            orig(*args)
+        self.wt._observed_sha1 = _observed_sha1
+        trans.apply()
+        self.assertEqual([(None, 'file1', trans._observed_sha1s[trans_id])],
+                         calls)
+
+    def test_create_file_caches_sha1(self):
+        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
+        trans_id = trans.create_path('file1', root)
+        trans.create_file(contents, trans_id, sha1=sha1)
+        st_val = osutils.lstat(trans._limbo_name(trans_id))
+        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
+        self.assertEqual(o_sha1, sha1)
+        self.assertEqualStat(o_st_val, st_val)
+
+    def test__apply_insertions_updates_sha1(self):
+        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
+        trans_id = trans.create_path('file1', root)
+        trans.create_file(contents, trans_id, sha1=sha1)
+        st_val = osutils.lstat(trans._limbo_name(trans_id))
+        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
+        self.assertEqual(o_sha1, sha1)
+        self.assertEqualStat(o_st_val, st_val)
+        creation_mtime = trans._creation_mtime + 10.0
+        # We fake a time difference from when the file was created until now it
+        # is being renamed by using os.utime. Note that the change we actually
+        # want to see is the real ctime change from 'os.rename()', but as long
+        # as we observe a new stat value, we should be fine.
+        os.utime(trans._limbo_name(trans_id), (creation_mtime, creation_mtime))
+        trans.apply()
+        new_st_val = osutils.lstat(self.wt.abspath('file1'))
+        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
+        self.assertEqual(o_sha1, sha1)
+        self.assertEqualStat(o_st_val, new_st_val)
+        self.assertNotEqual(st_val.st_mtime, new_st_val.st_mtime)
+
+    def test_new_file_caches_sha1(self):
+        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
+        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
+                                  sha1=sha1)
+        st_val = osutils.lstat(trans._limbo_name(trans_id))
+        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
+        self.assertEqual(o_sha1, sha1)
+        self.assertEqualStat(o_st_val, st_val)
+
+    def test_cancel_creation_removes_observed_sha1(self):
+        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
+        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
+                                  sha1=sha1)
+        self.assertTrue(trans_id in trans._observed_sha1s)
+        trans.cancel_creation(trans_id)
+        self.assertFalse(trans_id in trans._observed_sha1s)
+
     def test_create_files_same_timestamp(self):
         transform, root = self.get_transform()
         self.wt.lock_tree_write()

=== modified file 'bzrlib/tests/test_workingtree_4.py'
--- a/bzrlib/tests/test_workingtree_4.py	2011-04-05 14:00:26 +0000
+++ b/bzrlib/tests/test_workingtree_4.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2010 Canonical Ltd
+# Copyright (C) 2007-2011 Canonical Ltd
 # Authors:  Robert Collins <robert.collins at canonical.com>
 #
 # This program is free software; you can redistribute it and/or modify

=== modified file 'bzrlib/trace.py'
--- a/bzrlib/trace.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/trace.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2011-04-05 14:47:26 +0000
+++ b/bzrlib/transform.py	2011-04-07 10:36:24 +0000
@@ -102,6 +102,8 @@
         self._new_parent = {}
         # mapping of trans_id with new contents -> new file_kind
         self._new_contents = {}
+        # mapping of trans_id => (sha1 of content, stat_value)
+        self._observed_sha1s = {}
         # Set of trans_ids whose contents will be removed
         self._removed_contents = set()
         # Mapping of trans_id -> new execute-bit value
@@ -751,7 +753,7 @@
         return trans_id
 
     def new_file(self, name, parent_id, contents, file_id=None,
-                 executable=None):
+                 executable=None, sha1=None):
         """Convenience method to create files.
 
         name is the name of the file to create.
@@ -764,7 +766,7 @@
         trans_id = self._new_entry(name, parent_id, file_id)
         # TODO: rather than scheduling a set_executable call,
         # have create_file create the file with the right mode.
-        self.create_file(contents, trans_id)
+        self.create_file(contents, trans_id, sha1=sha1)
         if executable is not None:
             self.set_executability(executable, trans_id)
         return trans_id
@@ -1246,16 +1248,19 @@
             descendants.update(self._limbo_descendants(descendant))
         return descendants
 
-    def create_file(self, contents, trans_id, mode_id=None):
+    def create_file(self, contents, trans_id, mode_id=None, sha1=None):
         """Schedule creation of a new file.
 
-        See also new_file.
-
-        Contents is an iterator of strings, all of which will be written
-        to the target destination.
-
-        New file takes the permissions of any existing file with that id,
-        unless mode_id is specified.
+        :seealso: new_file.
+
+        :param contents: an iterator of strings, all of which will be written
+            to the target destination.
+        :param trans_id: TreeTransform handle
+        :param mode_id: If not None, force the mode of the target file to match
+            the mode of the object referenced by mode_id.
+            Otherwise, we will try to preserve mode bits of an existing file.
+        :param sha1: If the sha1 of this content is already known, pass it in.
+            We can use it to prevent future sha1 computations.
         """
         name = self._limbo_name(trans_id)
         f = open(name, 'wb')
@@ -1268,12 +1273,16 @@
                 f.close()
                 os.unlink(name)
                 raise
-
             f.writelines(contents)
         finally:
             f.close()
         self._set_mtime(name)
         self._set_mode(trans_id, mode_id, S_ISREG)
+        # It is unfortunate we have to use lstat instead of fstat, but we just
+        # used utime and chmod on the file, so we need the accurate final
+        # details.
+        if sha1 is not None:
+            self._observed_sha1s[trans_id] = (sha1, osutils.lstat(name))
 
     def _read_file_chunks(self, trans_id):
         cur_file = open(self._limbo_name(trans_id), 'rb')
@@ -1338,6 +1347,8 @@
     def cancel_creation(self, trans_id):
         """Cancel the creation of new file contents."""
         del self._new_contents[trans_id]
+        if trans_id in self._observed_sha1s:
+            del self._observed_sha1s[trans_id]
         children = self._limbo_children.get(trans_id)
         # if this is a limbo directory with children, move them before removing
         # the directory
@@ -1699,6 +1710,7 @@
         finally:
             child_pb.finished()
         self._tree.apply_inventory_delta(inventory_delta)
+        self._apply_observed_sha1s()
         self._done = True
         self.finalize()
         return _TransformResults(modified_paths, self.rename_count)
@@ -1824,17 +1836,47 @@
                             raise
                     else:
                         self.rename_count += 1
+                    # TODO: if trans_id in self._observed_sha1s, we should
+                    #       re-stat the final target, since ctime will be
+                    #       updated by the change.
                 if (trans_id in self._new_contents or
                     self.path_changed(trans_id)):
                     if trans_id in self._new_contents:
                         modified_paths.append(full_path)
                 if trans_id in self._new_executability:
                     self._set_executability(path, trans_id)
+                if trans_id in self._observed_sha1s:
+                    o_sha1, o_st_val = self._observed_sha1s[trans_id]
+                    st = osutils.lstat(full_path)
+                    self._observed_sha1s[trans_id] = (o_sha1, st)
         finally:
             child_pb.finished()
         self._new_contents.clear()
         return modified_paths
 
+    def _apply_observed_sha1s(self):
+        """After we have finished renaming everything, update observed sha1s
+
+        This has to be done after self._tree.apply_inventory_delta, otherwise
+        it doesn't know anything about the files we are updating. Also, we want
+        to do this as late as possible, so that most entries end up cached.
+        """
+        # TODO: this doesn't update the stat information for directories. So
+        #       the first 'bzr status' will still need to rewrite
+        #       .bzr/checkout/dirstate. However, we at least don't need to
+        #       re-read all of the files.
+        # TODO: If the operation took a while, we could do a time.sleep(3) here
+        #       to allow the clock to tick over and ensure we won't have any
+        #       problems. (we could observe start time, and finish time, and if
+        #       it is less than eg 10% overhead, add a sleep call.)
+        paths = FinalPaths(self)
+        for trans_id, observed in self._observed_sha1s.iteritems():
+            path = paths.get_path(trans_id)
+            # We could get the file_id, but dirstate prefers to use the path
+            # anyway, and it is 'cheaper' to determine.
+            # file_id = self._new_id[trans_id]
+            self._tree._observed_sha1(None, path, observed)
+
 
 class TransformPreview(DiskTreeTransform):
     """A TreeTransform for generating preview trees.

=== modified file 'bzrlib/transport/__init__.py'
--- a/bzrlib/transport/__init__.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/transport/__init__.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/transport/local.py'
--- a/bzrlib/transport/local.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/transport/local.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/tree.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/ui/__init__.py'
--- a/bzrlib/ui/__init__.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/ui/__init__.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'bzrlib/ui/text.py'
--- a/bzrlib/ui/text.py	2011-04-05 01:12:15 +0000
+++ b/bzrlib/ui/text.py	2011-04-07 10:36:24 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2011 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- a/doc/en/release-notes/bzr-2.4.txt	2011-04-06 04:04:54 +0000
+++ b/doc/en/release-notes/bzr-2.4.txt	2011-04-07 10:36:24 +0000
@@ -42,18 +42,24 @@
 .. Fixes for situations where bzr would previously crash or give incorrect
    or undesirable results.
 
- * ``bzrlib.log._DEFAULT_REQUEST_PARAMS`` is no longer accidentally
-   mutated by ``bzrlib.log._apply_log_request_defaults``.  In practice
-   these default values aren't relied on very often so this probably
-   wasn't causing any trouble.  (Andrew Bennetts)
+* ``bzrlib.log._DEFAULT_REQUEST_PARAMS`` is no longer accidentally
+  mutated by ``bzrlib.log._apply_log_request_defaults``.  In practice
+  these default values aren't relied on very often so this probably
+  wasn't causing any trouble.  (Andrew Bennetts)
 
- * Lazy hooks are now reset between test runs. (Jelmer Vernooij, #745566)
+* Lazy hooks are now reset between test runs. (Jelmer Vernooij, #745566)
 
 * Standalone bzr.exe installation on Windows: user can put additional python 
   libraries into ``site-packages`` subdirectory of the installation directory,
   this might be required for "installing" extra dependencies for some plugins.
   (Alexander Belchenko, #743256)
 
+* ``TreeTransform.create_file/new_file`` can now take an optional ``sha1``
+  parameter. If supplied, when the transform is applied, it will then call
+  ``self._tree._observed_sha1`` for those files. This lets us update the
+  hash-cache for content that we create, preventing us from re-reading the
+  content in the next ``bzr status``.  (John Arbash Meinel, #740932)
+
 Documentation
 *************
 




More information about the bazaar-commits mailing list