mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
9fd86a4fae
Summary: This applies the formatting changes from black v21.4b2 to all covered projects in fbsource. Most changes are to single line docstrings, as black will now remove leading and trailing whitespace to match PEP8. Any other formatting changes are likely due to files that landed without formatting, or files that previously triggered errors in black. Any changes to code should be AST identical. Any test failures are likely due to bad tests, or testing against the output of pyfmt. Reviewed By: thatch Differential Revision: D28204910 fbshipit-source-id: 804725bcd14f763e90c5ddff1d0418117c15809a
184 lines
6.3 KiB
Python
184 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2.
|
|
|
|
import errno
|
|
import os
|
|
import time
|
|
|
|
from .lib import testcase
|
|
|
|
|
|
@testcase.eden_repo_test
|
|
class RenameTest(testcase.EdenRepoTest):
|
|
def populate_repo(self) -> None:
|
|
self.repo.write_file("hello", "hola\n")
|
|
self.repo.write_file("adir/file", "foo!\n")
|
|
self.repo.symlink("slink", "hello")
|
|
self.repo.commit("Initial commit.")
|
|
|
|
def test_rename_errors(self) -> None:
|
|
"""Test some error cases"""
|
|
with self.assertRaises(OSError) as context:
|
|
os.rename(
|
|
os.path.join(self.mount, "not-exist"),
|
|
os.path.join(self.mount, "also-not-exist"),
|
|
)
|
|
self.assertEqual(
|
|
errno.ENOENT, context.exception.errno, msg="Renaming a bogus file -> ENOENT"
|
|
)
|
|
|
|
def test_rename_dir(self) -> None:
|
|
filename = os.path.join(self.mount, "adir")
|
|
targetname = os.path.join(self.mount, "a-new-target")
|
|
os.rename(filename, targetname)
|
|
|
|
with self.assertRaises(OSError) as context:
|
|
os.lstat(filename)
|
|
self.assertEqual(
|
|
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
|
|
)
|
|
|
|
os.lstat(targetname)
|
|
# Check that adir/file is now visible in the new location
|
|
targetfile = os.path.join(targetname, "file")
|
|
with open(targetfile, "r") as f:
|
|
self.assertEqual("foo!\n", f.read())
|
|
|
|
def test_rename_away_tree_entry(self) -> None:
|
|
"""Rename a tree entry away and back again"""
|
|
# We should be able to rename files that are in the Tree
|
|
hello = os.path.join(self.mount, "hello")
|
|
targetname = os.path.join(self.mount, "a-new-target")
|
|
os.rename(hello, targetname)
|
|
|
|
with self.assertRaises(OSError) as context:
|
|
os.lstat(hello)
|
|
self.assertEqual(
|
|
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
|
|
)
|
|
|
|
self.assert_checkout_root_entries({".eden", "a-new-target", "adir", "slink"})
|
|
|
|
with open(targetname, "r") as f:
|
|
self.assertEqual("hola\n", f.read(), msg="materialized correct data")
|
|
|
|
# Now, while we hold this file open, check that a rename
|
|
# leaves the handle connected to the file contents when
|
|
# we rename it back to its old name.
|
|
os.rename(targetname, hello)
|
|
|
|
self.assert_checkout_root_entries({".eden", "adir", "hello", "slink"})
|
|
|
|
with open(hello, "r+") as write_f:
|
|
write_f.seek(0, os.SEEK_END)
|
|
write_f.write("woot")
|
|
|
|
f.seek(0)
|
|
self.assertEqual("hola\nwoot", f.read())
|
|
|
|
def test_rename_overlay_only(self) -> None:
|
|
"""Create a local/overlay only file and rename it"""
|
|
# We should be able to rename files that are in the Tree
|
|
from_name = os.path.join(self.mount, "overlay-a")
|
|
to_name = os.path.join(self.mount, "overlay-b")
|
|
|
|
with open(from_name, "w") as f:
|
|
f.write("overlay-a\n")
|
|
|
|
os.rename(from_name, to_name)
|
|
|
|
with self.assertRaises(OSError) as context:
|
|
os.lstat(from_name)
|
|
self.assertEqual(
|
|
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
|
|
)
|
|
|
|
self.assert_checkout_root_entries(
|
|
{".eden", "adir", "hello", "overlay-b", "slink"}
|
|
)
|
|
|
|
with open(to_name, "r") as f:
|
|
self.assertEqual("overlay-a\n", f.read(), msg="holds correct data")
|
|
|
|
# Now, while we hold this file open, check that a rename
|
|
# leaves the handle connected to the file contents when
|
|
# we rename it back to its old name.
|
|
os.rename(to_name, from_name)
|
|
|
|
self.assert_checkout_root_entries(
|
|
{".eden", "adir", "hello", "overlay-a", "slink"}
|
|
)
|
|
|
|
with open(from_name, "r+") as write_f:
|
|
write_f.seek(0, os.SEEK_END)
|
|
write_f.write("woot")
|
|
|
|
f.seek(0)
|
|
self.assertEqual("overlay-a\nwoot", f.read())
|
|
|
|
def test_rename_overlay_over_tree(self) -> None:
|
|
"""Make an overlay file and overwrite a tree entry with it"""
|
|
|
|
from_name = os.path.join(self.mount, "overlay-a")
|
|
to_name = os.path.join(self.mount, "hello")
|
|
|
|
with open(from_name, "w") as f:
|
|
f.write("overlay-a\n")
|
|
|
|
os.rename(from_name, to_name)
|
|
|
|
with self.assertRaises(OSError) as context:
|
|
os.lstat(from_name)
|
|
self.assertEqual(
|
|
errno.ENOENT, context.exception.errno, msg="no longer visible as old name"
|
|
)
|
|
|
|
self.assert_checkout_root_entries({".eden", "adir", "hello", "slink"})
|
|
|
|
with open(to_name, "r") as f:
|
|
self.assertEqual("overlay-a\n", f.read(), msg="holds correct data")
|
|
|
|
def test_rename_between_different_dirs(self) -> None:
|
|
adir = os.path.join(self.mount, "adir")
|
|
bdir = os.path.join(self.mount, "bdir")
|
|
os.mkdir(bdir)
|
|
|
|
os.rename(os.path.join(adir, "file"), os.path.join(bdir, "FILE"))
|
|
|
|
self.assertEqual([], sorted(os.listdir(adir)))
|
|
self.assertEqual(["FILE"], sorted(os.listdir(bdir)))
|
|
|
|
# Restart to ensure that our serialized state is correct
|
|
self.eden.shutdown()
|
|
self.eden.start()
|
|
|
|
self.assertEqual([], sorted(os.listdir(adir)))
|
|
self.assertEqual(["FILE"], sorted(os.listdir(bdir)))
|
|
|
|
def test_rename_dir_over_empty_dir(self) -> None:
|
|
subdir = os.path.join(self.mount, "sub")
|
|
dir1 = os.path.join(subdir, "dir1")
|
|
dir2 = os.path.join(subdir, "dir2")
|
|
os.mkdir(subdir)
|
|
os.mkdir(dir1)
|
|
os.mkdir(dir2)
|
|
|
|
os.rename(dir1, dir2)
|
|
self.assertEqual(["dir2"], os.listdir(subdir))
|
|
|
|
def test_rename_updates_mtime(self) -> None:
|
|
adir_path = os.path.join(self.mount, "adir")
|
|
mtime_root = os.lstat(self.mount).st_mtime
|
|
mtime_adir = os.lstat(adir_path).st_mtime
|
|
|
|
while time.time() < max(mtime_root, mtime_adir):
|
|
time.sleep(0.01)
|
|
|
|
os.rename(os.path.join(self.mount, "hello"), os.path.join(adir_path, "hello"))
|
|
|
|
self.assertLess(mtime_root, os.lstat(self.mount).st_mtime)
|
|
self.assertLess(mtime_adir, os.lstat(adir_path).st_mtime)
|