[RFC] TreeTransform fooled by os.rename on case insensitive filesystems

Vincent Ladeuil v.ladeuil+lp at free.fr
Sun Aug 31 15:06:05 BST 2008


I'm working with Guillermo on making the test suite pass on OSX.

Currently
bzrlib.tests.test_transform.TestTreeTransform.test_case_insensitive_clash
is failing (among other, but this mail focus on this one).

        self.requireFeature(CaseInsensitiveFilesystemFeature)
        def tt_helper():
            wt = self.make_branch_and_tree('.')
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
            try:
                tt.new_file('foo', tt.root, 'bar')
                tt.new_file('Foo', tt.root, 'spam')
                # Lie to tt that we've already resolved all conflicts.
                tt.apply(no_conflicts=True)
            except:
                wt.unlock()
                raise
        err = self.assertRaises(errors.FileExists, tt_helper)
        self.assertContainsRe(str(err),
            "^File exists: .+/foo")


I narrowed it down to:

bzrlib.transform._FileMover.rename not raising errors.FileExists when:

'Foo' has already been renamed in its final location and we try
to do:

  os.rename('limbo/new-1', 'foo')

os.rename doc says:

,----
|  rename(  	src, dst)
| 
|     Rename the file or directory src to dst. If dst is a
|     directory, OSError will be raised. On Unix, if dst exists and
|     is a file, it will be removed silently if the user has
|     permission. The operation may fail on some Unix flavors if
|     src and dst are on different filesystems. If successful, the
|     renaming will be an atomic operation (this is a POSIX
|     requirement). On Windows, if dst already exists, OSError will
|     be raised even if it is a file; there may be no way to
|     implement an atomic rename when dst names an existing
|     file. Availability: Macintosh, Unix, Windows.
`----

OSX differs from windows here because OSError is not raised,
instead 'foo' just replaces 'Foo'.

There are several problems here:

- the test assumes a Windows behavior while requiring only a
  CaseInsensitiveFilesystemFeature,

- since the rename succeeds on OSX, there is no way for
  _FileMover.rollback() to restore a correct state ('Foo' content
  has vanished at this point).

I think this indicates a deeper problem than just a slight
mismatch between Windows and CaseInsensitiveFilesystemFeature.

Any idea about where and how that should be fixed ?

    Vincent



More information about the bazaar mailing list