mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 09:17:30 +03:00
fbdb46f5cb
Reviewed By: chadaustin Differential Revision: D17872966 fbshipit-source-id: cd60a364a2146f0dadbeca693b1d4a5d7c97ff63
134 lines
4.9 KiB
Python
134 lines
4.9 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 os
|
|
import stat
|
|
import time
|
|
|
|
from facebook.eden.ttypes import TimeSpec
|
|
|
|
from .lib import edenclient, testcase
|
|
|
|
|
|
@testcase.eden_repo_test
|
|
class DebugGetPathTest(testcase.EdenRepoTest):
|
|
def populate_repo(self) -> None:
|
|
self.repo.write_file("hello", "hola\n")
|
|
self.repo.commit("Initial commit.")
|
|
|
|
def test_getpath_root_inode(self) -> None:
|
|
"""
|
|
Test that calling `eden debug getpath 1` returns the path to the eden
|
|
mount, and indicates that the inode is loaded.
|
|
"""
|
|
output = self.eden.run_cmd("debug", "getpath", "1", cwd=self.mount)
|
|
|
|
self.assertEqual("loaded " + self.mount + "\n", output)
|
|
|
|
def test_getpath_dot_eden_inode(self) -> None:
|
|
"""
|
|
Test that calling `eden debug getpath ${ino}` returns the path to the
|
|
.eden directory, and indicates that the inode is loaded.
|
|
"""
|
|
st = os.lstat(os.path.join(self.mount, ".eden"))
|
|
self.assertTrue(stat.S_ISDIR(st.st_mode))
|
|
ino = st.st_ino
|
|
|
|
output = self.eden.run_cmd("debug", "getpath", str(ino), cwd=self.mount)
|
|
|
|
self.assertEqual("loaded " + os.path.join(self.mount, ".eden") + "\n", output)
|
|
|
|
def test_getpath_invalid_inode(self) -> None:
|
|
"""
|
|
Test that calling `eden debug getpath 1234` raises an error since
|
|
1234 is not a valid inode number
|
|
"""
|
|
with self.assertRaises(edenclient.EdenCommandError) as context:
|
|
self.eden.run_cmd("debug", "getpath", "1234", cwd=self.mount)
|
|
self.assertIn(
|
|
"unknown inode number 1234", context.exception.stderr.decode()
|
|
)
|
|
|
|
def test_getpath_unloaded_inode(self) -> None:
|
|
"""
|
|
Test that calling `eden debug getpath` on an unloaded inode returns the
|
|
correct path and indicates that it is unloaded
|
|
"""
|
|
dirpath = os.path.join(self.mount, "dir")
|
|
filepath = os.path.join(dirpath, "file")
|
|
|
|
# Create the file
|
|
self.write_file(os.path.join("dir", "file"), "blah")
|
|
# Get the inodeNumber
|
|
stat = os.stat(filepath)
|
|
self.unload_one_inode_under("dir")
|
|
|
|
# Get the path for dir/file from its inodeNumber
|
|
output = self.eden.run_cmd("debug", "getpath", str(stat.st_ino), cwd=self.mount)
|
|
|
|
self.assertEqual(f"unloaded {filepath}\n", output)
|
|
|
|
def test_getpath_unloaded_inode_rename_parent(self) -> None:
|
|
"""
|
|
Test that when an unloaded inode has one of its parents renamed,
|
|
`eden debug getpath` returns the new path
|
|
"""
|
|
# Create the file
|
|
self.write_file(os.path.join("foo", "bar", "test.txt"), "blah")
|
|
dirpath = os.path.join(self.mount, "foo", "bar")
|
|
# Get the inodeNumber
|
|
stat = os.stat(os.path.join(dirpath, "test.txt"))
|
|
|
|
self.unload_one_inode_under(os.path.join("foo", "bar"))
|
|
|
|
# Rename the foo directory
|
|
os.rename(os.path.join(self.mount, "foo"), os.path.join(self.mount, "newname"))
|
|
# Get the new path for the file from its inodeNumber
|
|
output = self.eden.run_cmd("debug", "getpath", str(stat.st_ino), cwd=self.mount)
|
|
|
|
self.assertEqual(
|
|
"unloaded " + os.path.join(self.mount, "newname", "bar", "test.txt") + "\n",
|
|
output,
|
|
)
|
|
|
|
def unload_one_inode_under(self, path: str) -> None:
|
|
# TODO: To support unloading more than one inode, sum the return value
|
|
# until count is reached our the attempt limit has been reached.
|
|
remaining_attempts = 5
|
|
while True:
|
|
age = TimeSpec() # zero
|
|
with self.eden.get_thrift_client() as client:
|
|
count = client.unloadInodeForPath(
|
|
os.fsencode(self.mount), os.fsencode(path), age
|
|
)
|
|
if remaining_attempts == 1:
|
|
self.assertEqual(1, count)
|
|
elif count == 1:
|
|
break
|
|
else:
|
|
remaining_attempts -= 1
|
|
time.sleep(1)
|
|
continue
|
|
|
|
def test_getpath_unlinked_inode(self) -> None:
|
|
"""
|
|
Test that when an inode is unlinked, `eden debug getpath` indicates
|
|
that it is unlinked
|
|
"""
|
|
# Create the file
|
|
self.write_file(os.path.join("foo", "bar", "test.txt"), "blah")
|
|
# Keep an open file handle so that the inode doesn't become invalid
|
|
f = open(os.path.join(self.mount, "foo", "bar", "test.txt"))
|
|
# Get the inodeNumber
|
|
stat = os.stat(os.path.join(self.mount, "foo", "bar", "test.txt"))
|
|
# Unlink the file
|
|
os.unlink(os.path.join(self.mount, "foo", "bar", "test.txt"))
|
|
output = self.eden.run_cmd("debug", "getpath", str(stat.st_ino), cwd=self.mount)
|
|
# Close the file handle
|
|
f.close()
|
|
|
|
self.assertEqual("loaded [unlinked]\n", output)
|