def test_file_copier(self): copier = FileCopier() copier.add('foo/bar', GeneratedFile('foobar')) copier.add('foo/qux', GeneratedFile('fooqux')) copier.add('foo/deep/nested/directory/file', GeneratedFile('fooz')) copier.add('bar', GeneratedFile('bar')) copier.add('qux/foo', GeneratedFile('quxfoo')) copier.add('qux/bar', GeneratedFile('')) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['foo/deep/nested/directory', 'qux'])) self.assertEqual(result.updated_files, set(self.tmppath(p) for p in self.all_files(self.tmpdir))) self.assertEqual(result.existing_files, set()) self.assertEqual(result.removed_files, set()) self.assertEqual(result.removed_directories, set()) copier.remove('foo') copier.add('test', GeneratedFile('test')) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['qux'])) self.assertEqual(result.removed_files, set(self.tmppath(p) for p in ('foo/bar', 'foo/qux', 'foo/deep/nested/directory/file')))
def test_file_copier(self): copier = FileCopier() copier.add('foo/bar', GeneratedFile('foobar')) copier.add('foo/qux', GeneratedFile('fooqux')) copier.add('foo/deep/nested/directory/file', GeneratedFile('fooz')) copier.add('bar', GeneratedFile('bar')) copier.add('qux/foo', GeneratedFile('quxfoo')) copier.add('qux/bar', GeneratedFile('')) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['foo/deep/nested/directory', 'qux'])) self.assertEqual( result.updated_files, set(self.tmppath(p) for p in self.all_files(self.tmpdir))) self.assertEqual(result.existing_files, set()) self.assertEqual(result.removed_files, set()) self.assertEqual(result.removed_directories, set()) copier.remove('foo') copier.add('test', GeneratedFile('test')) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['qux'])) self.assertEqual( result.removed_files, set( self.tmppath(p) for p in ('foo/bar', 'foo/qux', 'foo/deep/nested/directory/file')))
def test_file_copier(self): copier = FileCopier() copier.add("foo/bar", GeneratedFile(b"foobar")) copier.add("foo/qux", GeneratedFile(b"fooqux")) copier.add("foo/deep/nested/directory/file", GeneratedFile(b"fooz")) copier.add("bar", GeneratedFile(b"bar")) copier.add("qux/foo", GeneratedFile(b"quxfoo")) copier.add("qux/bar", GeneratedFile(b"")) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(["foo/deep/nested/directory", "qux"])) self.assertEqual( result.updated_files, set(self.tmppath(p) for p in self.all_files(self.tmpdir)), ) self.assertEqual(result.existing_files, set()) self.assertEqual(result.removed_files, set()) self.assertEqual(result.removed_directories, set()) copier.remove("foo") copier.add("test", GeneratedFile(b"test")) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(["qux"])) self.assertEqual( result.removed_files, set( self.tmppath(p) for p in ("foo/bar", "foo/qux", "foo/deep/nested/directory/file")), )
def test_file_copier(self): copier = FileCopier() copier.add("foo/bar", GeneratedFile("foobar")) copier.add("foo/qux", GeneratedFile("fooqux")) copier.add("foo/deep/nested/directory/file", GeneratedFile("fooz")) copier.add("bar", GeneratedFile("bar")) copier.add("qux/foo", GeneratedFile("quxfoo")) copier.add("qux/bar", GeneratedFile("")) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(["foo/deep/nested/directory", "qux"])) self.assertEqual(result.updated_files, set(self.tmppath(p) for p in self.all_files(self.tmpdir))) self.assertEqual(result.existing_files, set()) self.assertEqual(result.removed_files, set()) self.assertEqual(result.removed_directories, set()) copier.remove("foo") copier.add("test", GeneratedFile("test")) result = copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(["qux"])) self.assertEqual( result.removed_files, set(self.tmppath(p) for p in ("foo/bar", "foo/qux", "foo/deep/nested/directory/file")) )
def test_add_entries_from(self): source = self.tmppath("source") os.mkdir(source) os.mkdir("%s/base" % source) os.mkdir("%s/base/foo" % source) with open("%s/base/foo/file1" % source, "a"): pass with open("%s/base/foo/file2" % source, "a"): pass m = InstallManifest() m.add_pattern_link("%s/base" % source, "**", "dest") p = InstallManifest() p.add_entries_from(m) self.assertEqual(len(p), 1) c = FileCopier() p.populate_registry(c) self.assertEqual(c.paths(), ["dest/foo/file1", "dest/foo/file2"]) q = InstallManifest() q.add_entries_from(m, base="target") self.assertEqual(len(q), 1) d = FileCopier() q.populate_registry(d) self.assertEqual(d.paths(), ["target/dest/foo/file1", "target/dest/foo/file2"]) # Some of the values in an InstallManifest include destination # information that is present in the keys. Verify that we can # round-trip serialization. r = InstallManifest() r.add_entries_from(m) r.add_entries_from(m, base="target") self.assertEqual(len(r), 2) temp_path = self.tmppath("temp_path") r.write(path=temp_path) s = InstallManifest(path=temp_path) e = FileCopier() s.populate_registry(e) self.assertEqual( e.paths(), [ "dest/foo/file1", "dest/foo/file2", "target/dest/foo/file1", "target/dest/foo/file2", ], )
def test_add_entries_from(self): source = self.tmppath('source') os.mkdir(source) os.mkdir('%s/base' % source) os.mkdir('%s/base/foo' % source) with open('%s/base/foo/file1' % source, 'a'): pass with open('%s/base/foo/file2' % source, 'a'): pass m = InstallManifest() m.add_pattern_link('%s/base' % source, '**', 'dest') p = InstallManifest() p.add_entries_from(m) self.assertEqual(len(p), 1) c = FileCopier() p.populate_registry(c) self.assertEqual(c.paths(), ['dest/foo/file1', 'dest/foo/file2']) q = InstallManifest() q.add_entries_from(m, base='target') self.assertEqual(len(q), 1) d = FileCopier() q.populate_registry(d) self.assertEqual(d.paths(), ['target/dest/foo/file1', 'target/dest/foo/file2']) # Some of the values in an InstallManifest include destination # information that is present in the keys. Verify that we can # round-trip serialization. r = InstallManifest() r.add_entries_from(m) r.add_entries_from(m, base='target') self.assertEqual(len(r), 2) temp_path = self.tmppath('temp_path') r.write(path=temp_path) s = InstallManifest(path=temp_path) e = FileCopier() s.populate_registry(e) self.assertEqual(e.paths(), [ 'dest/foo/file1', 'dest/foo/file2', 'target/dest/foo/file1', 'target/dest/foo/file2' ])
def test_add_entries_from(self): source = self.tmppath('source') os.mkdir(source) os.mkdir('%s/base' % source) os.mkdir('%s/base/foo' % source) with open('%s/base/foo/file1' % source, 'a'): pass with open('%s/base/foo/file2' % source, 'a'): pass m = InstallManifest() m.add_pattern_link('%s/base' % source, '**', 'dest') p = InstallManifest() p.add_entries_from(m) self.assertEqual(len(p), 1) c = FileCopier() p.populate_registry(c) self.assertEqual(c.paths(), ['dest/foo/file1', 'dest/foo/file2']) q = InstallManifest() q.add_entries_from(m, base='target') self.assertEqual(len(q), 1) d = FileCopier() q.populate_registry(d) self.assertEqual(d.paths(), ['target/dest/foo/file1', 'target/dest/foo/file2']) # Some of the values in an InstallManifest include destination # information that is present in the keys. Verify that we can # round-trip serialization. r = InstallManifest() r.add_entries_from(m) r.add_entries_from(m, base='target') self.assertEqual(len(r), 2) temp_path = self.tmppath('temp_path') r.write(path=temp_path) s = InstallManifest(path=temp_path) e = FileCopier() s.populate_registry(e) self.assertEqual(e.paths(), ['dest/foo/file1', 'dest/foo/file2', 'target/dest/foo/file1', 'target/dest/foo/file2'])
def test_remove_unaccounted_file_registry(self): """Test FileCopier.copy(remove_unaccounted=FileRegistry())""" dest = self.tmppath("dest") copier = FileCopier() copier.add("foo/bar/baz", GeneratedFile(b"foobarbaz")) copier.add("foo/bar/qux", GeneratedFile(b"foobarqux")) copier.add("foo/hoge/fuga", GeneratedFile(b"foohogefuga")) copier.add("foo/toto/tata", GeneratedFile(b"footototata")) os.makedirs(os.path.join(dest, "bar")) with open(os.path.join(dest, "bar", "bar"), "w") as fh: fh.write("barbar") os.makedirs(os.path.join(dest, "foo", "toto")) with open(os.path.join(dest, "foo", "toto", "toto"), "w") as fh: fh.write("foototototo") result = copier.copy(dest, remove_unaccounted=False) self.assertEqual(self.all_files(dest), set(copier.paths()) | {"foo/toto/toto", "bar/bar"}) self.assertEqual(self.all_dirs(dest), {"foo/bar", "foo/hoge", "foo/toto", "bar"}) copier2 = FileCopier() copier2.add("foo/hoge/fuga", GeneratedFile(b"foohogefuga")) # We expect only files copied from the first copier to be removed, # not the extra file that was there beforehand. result = copier2.copy(dest, remove_unaccounted=copier) self.assertEqual(self.all_files(dest), set(copier2.paths()) | {"foo/toto/toto", "bar/bar"}) self.assertEqual(self.all_dirs(dest), {"foo/hoge", "foo/toto", "bar"}) self.assertEqual(result.updated_files, {self.tmppath("dest/foo/hoge/fuga")}) self.assertEqual(result.existing_files, set()) self.assertEqual( result.removed_files, { self.tmppath(p) for p in ("dest/foo/bar/baz", "dest/foo/bar/qux", "dest/foo/toto/tata") }, ) self.assertEqual(result.removed_directories, {self.tmppath("dest/foo/bar")})
def test_symlink_directory_replaced(self): """Directory symlinks in destination are replaced if they need to be real directories.""" if not self.symlink_supported: return dest = self.tmppath("dest") copier = FileCopier() copier.add("foo/bar/baz", GeneratedFile(b"foobarbaz")) os.makedirs(self.tmppath("dest/foo")) dummy = self.tmppath("dummy") os.mkdir(dummy) link = self.tmppath("dest/foo/bar") os.symlink(dummy, link) result = copier.copy(dest) st = os.lstat(link) self.assertFalse(stat.S_ISLNK(st.st_mode)) self.assertTrue(stat.S_ISDIR(st.st_mode)) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(result.removed_directories, set()) self.assertEqual(len(result.updated_files), 1)
def test_symlink_directory_replaced(self): """Directory symlinks in destination are replaced if they need to be real directories.""" if not self.symlink_supported: return dest = self.tmppath('dest') copier = FileCopier() copier.add('foo/bar/baz', GeneratedFile('foobarbaz')) os.makedirs(self.tmppath('dest/foo')) dummy = self.tmppath('dummy') os.mkdir(dummy) link = self.tmppath('dest/foo/bar') os.symlink(dummy, link) result = copier.copy(dest) st = os.lstat(link) self.assertFalse(stat.S_ISLNK(st.st_mode)) self.assertTrue(stat.S_ISDIR(st.st_mode)) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(result.removed_directories, set()) self.assertEqual(len(result.updated_files), 1)
def test_symlink_directory(self): """Directory symlinks in destination are deleted.""" if not self.symlink_supported: return dest = self.tmppath('dest') copier = FileCopier() copier.add('foo/bar/baz', GeneratedFile('foobarbaz')) os.makedirs(self.tmppath('dest/foo')) dummy = self.tmppath('dummy') os.mkdir(dummy) link = self.tmppath('dest/foo/bar') os.symlink(dummy, link) result = copier.copy(dest) st = os.lstat(link) self.assertFalse(stat.S_ISLNK(st.st_mode)) self.assertTrue(stat.S_ISDIR(st.st_mode)) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(result.removed_directories, set()) self.assertEqual(len(result.updated_files), 1)
def test_remove_unaccounted_file_registry(self): """Test FileCopier.copy(remove_unaccounted=FileRegistry())""" dest = self.tmppath('dest') copier = FileCopier() copier.add('foo/bar/baz', GeneratedFile('foobarbaz')) copier.add('foo/bar/qux', GeneratedFile('foobarqux')) copier.add('foo/hoge/fuga', GeneratedFile('foohogefuga')) copier.add('foo/toto/tata', GeneratedFile('footototata')) os.makedirs(os.path.join(dest, 'bar')) with open(os.path.join(dest, 'bar', 'bar'), 'w') as fh: fh.write('barbar') os.makedirs(os.path.join(dest, 'foo', 'toto')) with open(os.path.join(dest, 'foo', 'toto', 'toto'), 'w') as fh: fh.write('foototototo') result = copier.copy(dest, remove_unaccounted=False) self.assertEqual(self.all_files(dest), set(copier.paths()) | {'foo/toto/toto', 'bar/bar'}) self.assertEqual(self.all_dirs(dest), {'foo/bar', 'foo/hoge', 'foo/toto', 'bar'}) copier2 = FileCopier() copier2.add('foo/hoge/fuga', GeneratedFile('foohogefuga')) # We expect only files copied from the first copier to be removed, # not the extra file that was there beforehand. result = copier2.copy(dest, remove_unaccounted=copier) self.assertEqual(self.all_files(dest), set(copier2.paths()) | {'foo/toto/toto', 'bar/bar'}) self.assertEqual(self.all_dirs(dest), {'foo/hoge', 'foo/toto', 'bar'}) self.assertEqual(result.updated_files, {self.tmppath('dest/foo/hoge/fuga')}) self.assertEqual(result.existing_files, set()) self.assertEqual( result.removed_files, { self.tmppath(p) for p in ('dest/foo/bar/baz', 'dest/foo/bar/qux', 'dest/foo/toto/tata') }) self.assertEqual(result.removed_directories, {self.tmppath('dest/foo/bar')})
def test_file_copier(self): copier = FileCopier() copier.add('foo/bar', GeneratedFile('foobar')) copier.add('foo/qux', GeneratedFile('fooqux')) copier.add('foo/deep/nested/directory/file', GeneratedFile('fooz')) copier.add('bar', GeneratedFile('bar')) copier.add('qux/foo', GeneratedFile('quxfoo')) copier.add('qux/bar', GeneratedFile('')) copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['foo/deep/nested/directory', 'qux'])) copier.remove('foo') copier.add('test', GeneratedFile('test')) copier.copy(self.tmpdir) self.assertEqual(self.all_files(self.tmpdir), set(copier.paths())) self.assertEqual(self.all_dirs(self.tmpdir), set(['qux']))
def test_remove_unaccounted_file_registry(self): """Test FileCopier.copy(remove_unaccounted=FileRegistry())""" dest = self.tmppath('dest') copier = FileCopier() copier.add('foo/bar/baz', GeneratedFile('foobarbaz')) copier.add('foo/bar/qux', GeneratedFile('foobarqux')) copier.add('foo/hoge/fuga', GeneratedFile('foohogefuga')) copier.add('foo/toto/tata', GeneratedFile('footototata')) os.makedirs(os.path.join(dest, 'bar')) with open(os.path.join(dest, 'bar', 'bar'), 'w') as fh: fh.write('barbar'); os.makedirs(os.path.join(dest, 'foo', 'toto')) with open(os.path.join(dest, 'foo', 'toto', 'toto'), 'w') as fh: fh.write('foototototo'); result = copier.copy(dest, remove_unaccounted=False) self.assertEqual(self.all_files(dest), set(copier.paths()) | { 'foo/toto/toto', 'bar/bar'}) self.assertEqual(self.all_dirs(dest), {'foo/bar', 'foo/hoge', 'foo/toto', 'bar'}) copier2 = FileCopier() copier2.add('foo/hoge/fuga', GeneratedFile('foohogefuga')) # We expect only files copied from the first copier to be removed, # not the extra file that was there beforehand. result = copier2.copy(dest, remove_unaccounted=copier) self.assertEqual(self.all_files(dest), set(copier2.paths()) | { 'foo/toto/toto', 'bar/bar'}) self.assertEqual(self.all_dirs(dest), {'foo/hoge', 'foo/toto', 'bar'}) self.assertEqual(result.updated_files, {self.tmppath('dest/foo/hoge/fuga')}) self.assertEqual(result.existing_files, set()) self.assertEqual(result.removed_files, {self.tmppath(p) for p in ('dest/foo/bar/baz', 'dest/foo/bar/qux', 'dest/foo/toto/tata')}) self.assertEqual(result.removed_directories, {self.tmppath('dest/foo/bar')})
def test_remove_unaccounted_file_registry(self): """Test FileCopier.copy(remove_unaccounted=FileRegistry())""" dest = self.tmppath("dest") copier = FileCopier() copier.add("foo/bar/baz", GeneratedFile("foobarbaz")) copier.add("foo/bar/qux", GeneratedFile("foobarqux")) copier.add("foo/hoge/fuga", GeneratedFile("foohogefuga")) copier.add("foo/toto/tata", GeneratedFile("footototata")) os.makedirs(os.path.join(dest, "bar")) with open(os.path.join(dest, "bar", "bar"), "w") as fh: fh.write("barbar") os.makedirs(os.path.join(dest, "foo", "toto")) with open(os.path.join(dest, "foo", "toto", "toto"), "w") as fh: fh.write("foototototo") result = copier.copy(dest, remove_unaccounted=False) self.assertEqual(self.all_files(dest), set(copier.paths()) | {"foo/toto/toto", "bar/bar"}) self.assertEqual(self.all_dirs(dest), {"foo/bar", "foo/hoge", "foo/toto", "bar"}) copier2 = FileCopier() copier2.add("foo/hoge/fuga", GeneratedFile("foohogefuga")) # We expect only files copied from the first copier to be removed, # not the extra file that was there beforehand. result = copier2.copy(dest, remove_unaccounted=copier) self.assertEqual(self.all_files(dest), set(copier2.paths()) | {"foo/toto/toto", "bar/bar"}) self.assertEqual(self.all_dirs(dest), {"foo/hoge", "foo/toto", "bar"}) self.assertEqual(result.updated_files, {self.tmppath("dest/foo/hoge/fuga")}) self.assertEqual(result.existing_files, set()) self.assertEqual( result.removed_files, {self.tmppath(p) for p in ("dest/foo/bar/baz", "dest/foo/bar/qux", "dest/foo/toto/tata")}, ) self.assertEqual(result.removed_directories, {self.tmppath("dest/foo/bar")})
def test_pattern_expansion(self): source = self.tmppath('source') os.mkdir(source) os.mkdir('%s/base' % source) os.mkdir('%s/base/foo' % source) with open('%s/base/foo/file1' % source, 'a'): pass with open('%s/base/foo/file2' % source, 'a'): pass m = InstallManifest() m.add_pattern_symlink('%s/base' % source, '**', 'dest') c = FileCopier() m.populate_registry(c) self.assertEqual(c.paths(), ['dest/foo/file1', 'dest/foo/file2'])
def test_pattern_expansion(self): source = self.tmppath("source") os.mkdir(source) os.mkdir("%s/base" % source) os.mkdir("%s/base/foo" % source) with open("%s/base/foo/file1" % source, "a"): pass with open("%s/base/foo/file2" % source, "a"): pass m = InstallManifest() m.add_pattern_symlink("%s/base" % source, "**", "dest") c = FileCopier() m.populate_registry(c) self.assertEqual(c.paths(), ["dest/foo/file1", "dest/foo/file2"])
def test_pattern_expansion(self): source = self.tmppath("source") os.mkdir(source) os.mkdir("%s/base" % source) os.mkdir("%s/base/foo" % source) with open("%s/base/foo/file1" % source, "a"): pass with open("%s/base/foo/file2" % source, "a"): pass m = InstallManifest() m.add_pattern_link("%s/base" % source, "**", "dest") c = FileCopier() m.populate_registry(c) self.assertEqual(c.paths(), ["dest/foo/file1", "dest/foo/file2"])
def test_remove_unaccounted_directory_symlinks(self): """Directory symlinks in destination that are not in the way are deleted according to remove_unaccounted and remove_all_directory_symlinks. """ if not self.symlink_supported: return dest = self.tmppath("dest") copier = FileCopier() copier.add("foo/bar/baz", GeneratedFile(b"foobarbaz")) os.makedirs(self.tmppath("dest/foo")) dummy = self.tmppath("dummy") os.mkdir(dummy) os.mkdir(self.tmppath("dest/zot")) link = self.tmppath("dest/zot/zap") os.symlink(dummy, link) # If not remove_unaccounted but remove_empty_directories, then # the symlinked directory remains (as does its containing # directory). result = copier.copy( dest, remove_unaccounted=False, remove_empty_directories=True, remove_all_directory_symlinks=False, ) st = os.lstat(link) self.assertTrue(stat.S_ISLNK(st.st_mode)) self.assertFalse(stat.S_ISDIR(st.st_mode)) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(["foo/bar"])) self.assertEqual(result.removed_directories, set()) self.assertEqual(len(result.updated_files), 1) # If remove_unaccounted but not remove_empty_directories, then # only the symlinked directory is removed. result = copier.copy( dest, remove_unaccounted=True, remove_empty_directories=False, remove_all_directory_symlinks=False, ) st = os.lstat(self.tmppath("dest/zot")) self.assertFalse(stat.S_ISLNK(st.st_mode)) self.assertTrue(stat.S_ISDIR(st.st_mode)) self.assertEqual(result.removed_files, set([link])) self.assertEqual(result.removed_directories, set()) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(["foo/bar", "zot"])) # If remove_unaccounted and remove_empty_directories, then # both the symlink and its containing directory are removed. link = self.tmppath("dest/zot/zap") os.symlink(dummy, link) result = copier.copy( dest, remove_unaccounted=True, remove_empty_directories=True, remove_all_directory_symlinks=False, ) self.assertEqual(result.removed_files, set([link])) self.assertEqual(result.removed_directories, set([self.tmppath("dest/zot")])) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(["foo/bar"]))
def test_remove_unaccounted_directory_symlinks(self): """Directory symlinks in destination that are not in the way are deleted according to remove_unaccounted and remove_all_directory_symlinks. """ if not self.symlink_supported: return dest = self.tmppath('dest') copier = FileCopier() copier.add('foo/bar/baz', GeneratedFile('foobarbaz')) os.makedirs(self.tmppath('dest/foo')) dummy = self.tmppath('dummy') os.mkdir(dummy) os.mkdir(self.tmppath('dest/zot')) link = self.tmppath('dest/zot/zap') os.symlink(dummy, link) # If not remove_unaccounted but remove_empty_directories, then # the symlinked directory remains (as does its containing # directory). result = copier.copy(dest, remove_unaccounted=False, remove_empty_directories=True, remove_all_directory_symlinks=False) st = os.lstat(link) self.assertTrue(stat.S_ISLNK(st.st_mode)) self.assertFalse(stat.S_ISDIR(st.st_mode)) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(['foo/bar'])) self.assertEqual(result.removed_directories, set()) self.assertEqual(len(result.updated_files), 1) # If remove_unaccounted but not remove_empty_directories, then # only the symlinked directory is removed. result = copier.copy(dest, remove_unaccounted=True, remove_empty_directories=False, remove_all_directory_symlinks=False) st = os.lstat(self.tmppath('dest/zot')) self.assertFalse(stat.S_ISLNK(st.st_mode)) self.assertTrue(stat.S_ISDIR(st.st_mode)) self.assertEqual(result.removed_files, set([link])) self.assertEqual(result.removed_directories, set()) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(['foo/bar', 'zot'])) # If remove_unaccounted and remove_empty_directories, then # both the symlink and its containing directory are removed. link = self.tmppath('dest/zot/zap') os.symlink(dummy, link) result = copier.copy(dest, remove_unaccounted=True, remove_empty_directories=True, remove_all_directory_symlinks=False) self.assertEqual(result.removed_files, set([link])) self.assertEqual(result.removed_directories, set([self.tmppath('dest/zot')])) self.assertEqual(self.all_files(dest), set(copier.paths())) self.assertEqual(self.all_dirs(dest), set(['foo/bar']))