Rev 4935: Basic implementation for windows and bug #488724. in http://bazaar.launchpad.net/~jameinel/bzr/2.1.0rc1-set-mtime

John Arbash Meinel john at arbash-meinel.com
Tue Jan 5 18:35:44 GMT 2010


At http://bazaar.launchpad.net/~jameinel/bzr/2.1.0rc1-set-mtime

------------------------------------------------------------
revno: 4935
revision-id: john at arbash-meinel.com-20100105183525-6hbg9m5o76j1cb16
parent: pqm at pqm.ubuntu.com-20100105165512-ip2jyuy8f999raxm
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1.0rc1-set-mtime
timestamp: Tue 2010-01-05 12:35:25 -0600
message:
  Basic implementation for windows and bug #488724.
  
  
  The request is that whenever we create a new batch of files,
  they should all get the same timestamp.
  This is so that if you version both a source file and its generated
  result, then when you update to a new version, the system doesn't
  think that the generated file needs to be rebuilt.
  
  This is done on Windows using the SetFileInformationByHandle api.
  We'll probably implement it on POSIX using futimes.
  Though ideally we'd support futimens if it was available.
-------------- next part --------------
=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2009-12-04 06:13:25 +0000
+++ b/bzrlib/tests/test_transform.py	2010-01-05 18:35:25 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008 Canonical Ltd
+# Copyright (C) 2006, 2007, 2008, 2009 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
@@ -17,6 +17,7 @@
 import os
 from StringIO import StringIO
 import sys
+import time
 
 from bzrlib import (
     bencode,
@@ -136,6 +137,26 @@
         transform.finalize()
         transform.finalize()
 
+    def test_create_files_same_timestamp(self):
+        transform, root = self.get_transform()
+        self.wt.lock_tree_write()
+        self.addCleanup(self.wt.unlock)
+        # Roll back the clock, so that we know everything is being set to the
+        # exact time
+        transform._creation_mtime = time.time() - 10.0
+        transform.create_file('content-one',
+                              transform.create_path('one', root))
+        time.sleep(1) # *ugly*
+        transform.create_file('content-two',
+                              transform.create_path('two', root))
+        transform.apply()
+        fo, st1 = self.wt.get_file_with_stat(None, path='one', filtered=False)
+        fo.close()
+        fo, st2 = self.wt.get_file_with_stat(None, path='two', filtered=False)
+        fo.close()
+        self.assertEqual(st1.st_mtime, st2.st_mtime)
+        self.assertEqual(transform._creation_mtime, st1.st_mtime)
+
     def test_hardlink(self):
         self.requireFeature(HardlinkFeature)
         transform, root = self.get_transform()

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2009-12-03 05:57:41 +0000
+++ b/bzrlib/transform.py	2010-01-05 18:35:25 +0000
@@ -17,6 +17,7 @@
 import os
 import errno
 from stat import S_ISREG, S_IEXEC
+import time
 
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
@@ -1131,6 +1132,7 @@
                 raise
 
             f.writelines(contents)
+            self._set_mtime(f)
         finally:
             f.close()
         self._set_mode(trans_id, mode_id, S_ISREG)
@@ -1298,6 +1300,7 @@
         DiskTreeTransform.__init__(self, tree, limbodir, pb,
                                    tree.case_sensitive)
         self._deletiondir = deletiondir
+        self._creation_mtime = None
 
     def canonical_path(self, path):
         """Get the canonical tree-relative path"""
@@ -1360,6 +1363,34 @@
         if typefunc(mode):
             os.chmod(self._limbo_name(trans_id), mode)
 
+    def _set_mtime(self, f):
+        """All files that are created get the same mtime.
+
+        This time is set by the first object to be created.
+        """
+        if self._creation_mtime is None:
+            self._creation_mtime = time.time()
+        import ctypes, msvcrt
+        class BASIC_INFO(ctypes.Structure):
+             _fields_ = [('CreationTime', ctypes.c_int64),
+                         ('LastAccessTime', ctypes.c_int64),
+                         ('LastWriteTime', ctypes.c_int64),
+                         ('ChangeTime', ctypes.c_int64),
+                         ('FileAttributes', ctypes.c_uint32),
+                        ]
+        bi = BASIC_INFO()
+        gfi = ctypes.windll.kernel32.GetFileInformationByHandleEx
+        handle = msvcrt.get_osfhandle(f.fileno())
+        ret = gfi(handle, 0, ctypes.byref(bi), ctypes.sizeof(bi))
+        assert ret, "failed to get file information: %d" % (
+            ctypes.GetLastError(),)
+        sfi = ctypes.windll.kernel32.SetFileInformationByHandle
+        bi.LastWriteTime = int((self._creation_mtime + 11644473600.0) * 1.0e7)
+        ret = sfi(handle, 0, ctypes.byref(bi), ctypes.sizeof(bi))
+        assert ret, "Failed to set file information: %d" % (
+            ctypes.GetLastError(),)
+
+
     def iter_tree_children(self, parent_id):
         """Iterate through the entry's tree children, if any"""
         try:



More information about the bazaar-commits mailing list