cli: enable doctor on Windows

Summary:
Most of the fixes are pretty trivial as the code was using functions not
present on Windows, either work around them, or switch to ones that are
multi-platform.

Of note, it looks like `hg doctor` doesn't properly detect when Mercurial and
EdenFS are out of sync, disabling the  tests until we figure out why.

Reviewed By: genevievehelsel, fanzeyi

Differential Revision: D23409708

fbshipit-source-id: 3314c197d43364dda13891a6874caab4c29e76ca
This commit is contained in:
Xavier Deguillard 2020-08-28 19:47:44 -07:00 committed by Facebook GitHub Bot
parent 6b498dfa02
commit 4f9e1750c2
9 changed files with 60 additions and 57 deletions

View File

@ -8,6 +8,7 @@
import os
import shlex
import sys
from pathlib import Path
from textwrap import dedent
from typing import Dict, Optional
@ -117,7 +118,7 @@ class EdenDoctorChecker:
self.instance = instance
self.tracker = tracker
self.mount_table = mount_table if mount_table is not None else mtab.new()
self.fs_util = fs_util if fs_util is not None else filesystem.LinuxFsUtil()
self.fs_util = fs_util if fs_util is not None else filesystem.new()
self.proc_utils = proc_utils if proc_utils is not None else proc_utils_mod.new()
self.out = out if out is not None else ui.get_output()
@ -576,19 +577,24 @@ def check_edenfs_version(tracker: ProblemTracker, instance: EdenInstance) -> Non
if running_version == installed_version:
return
tracker.add_problem(
Problem(
dedent(
f"""\
The version of Eden that is installed on your machine is:
fb-eden-{installed_version}.x86_64
but the version of Eden that is currently running is:
fb-eden-{running_version}.x86_64
if sys.platform == "win32":
help_string = f"""\
The version of EdenFS that is installed on your machine is:
fb.eden {installed_version}
but the version of EdenFS that is currently running is:
fb.eden {running_version}
Consider running `eden restart --graceful` to migrate to the newer version,
Consider running `edenfsctl restart` to migrate to the newer version,
which may have important bug fixes or performance improvements.
"""
),
severity=ProblemSeverity.ADVICE,
)
)
else:
help_string = f"""\
The version of EdenFS that is installed on your machine is:
fb-eden-{installed_version}.x86_64
but the version of EdenFS that is currently running is:
fb-eden-{running_version}.x86_64
Consider running `edenfsctl restart --graceful` to migrate to the newer version,
which may have important bug fixes or performance improvements.
"""
tracker.add_problem(Problem(dedent(help_string), severity=ProblemSeverity.ADVICE))

View File

@ -151,14 +151,14 @@ def check_disk_usage(
for eden_mount_pt in eden_mount_pts_set:
if eden_mount_pt and os.path.exists(eden_mount_pt):
disk_status = fs_util.statvfs(eden_mount_pt)
disk_usage = fs_util.disk_usage(eden_mount_pt)
avail = disk_status.f_frsize * disk_status.f_bavail
size = disk_status.f_frsize * disk_status.f_blocks
size = disk_usage.total
if size == 0:
continue
used = size - avail
avail = disk_usage.free
used = disk_usage.used
used_percent = float(used) / size
message = (

View File

@ -9,6 +9,7 @@
import logging
import os
import shlex
import sys
from pathlib import Path
from typing import Dict, List, Optional
@ -26,7 +27,10 @@ def find_rogue_processes(
# so that below we can we only check each eden directory once even if there are
# multiple processes that appear to be running for it.
info_by_eden_dir: Dict[Path, List[EdenFSProcess]] = {}
user_id = os.getuid() if uid is None else uid
if sys.platform == "win32":
user_id = 0
else:
user_id = os.getuid() if uid is None else uid
for info in proc_utils.get_edenfs_processes():
# Ignore processes not owned by the current user
if info.uid != user_id:

View File

@ -24,9 +24,9 @@ class DiskUsageTest(DoctorTestBase):
def _mock_disk_usage(self, blocks, avail, frsize=1024) -> None:
"""Mock test for disk usage."""
self.fs_util.f_blocks = blocks
self.fs_util.f_bavail = avail
self.fs_util.f_frsize = frsize
self.fs_util.total = blocks * frsize
self.fs_util.free = avail * frsize
self.fs_util.used = self.fs_util.total - self.fs_util.free
mock_getmountpt_and_deviceid_patcher = patch(
"eden.fs.cli.doctor.check_filesystems.get_mountpt"

View File

@ -804,12 +804,12 @@ Repairing hg directory contents for {checkout.path}...<green>fixed<reset>
self.assertEqual(
"""\
<yellow>- Found problem:<reset>
The version of Eden that is installed on your machine is:
The version of EdenFS that is installed on your machine is:
fb-eden-20171120-246561.x86_64
but the version of Eden that is currently running is:
but the version of EdenFS that is currently running is:
fb-eden-20171213-165642.x86_64
Consider running `eden restart --graceful` to migrate to the newer version,
Consider running `edenfsctl restart --graceful` to migrate to the newer version,
which may have important bug fixes or performance improvements.
""",

View File

@ -5,7 +5,7 @@
# GNU General Public License version 2.
import os
from typing import Any, cast
import shutil
from eden.fs.cli.filesystem import FsUtil
@ -14,31 +14,11 @@ class FakeFsUtil(FsUtil):
def mkdir_p(self, path: str) -> str:
return path
f_bsize = 131072
f_frsize = 4096
f_blocks = 1000000
f_bfree = 500000
f_bavail = 500000
f_files = 0
f_ffree = 0
f_favail = 0
f_flag = 4098
f_namemax = 255
total = 1000000 * 4096
used = 500000 * 4096
free = 500000 * 4096
def statvfs(self, path: str) -> os.statvfs_result:
def disk_usage(self, path: str) -> shutil._ntuple_diskusage:
# A made up filesystem with 50% free, but with other fields
# defaulted from an EdenFS mount on Linux.
return cast(Any, os.statvfs_result)(
(
self.f_bsize,
self.f_frsize,
self.f_blocks,
self.f_bfree,
self.f_bavail,
self.f_files,
self.f_ffree,
self.f_favail,
self.f_flag,
self.f_namemax,
)
)
return shutil._ntuple_diskusage(self.total, self.used, self.free)

View File

@ -6,6 +6,7 @@
import abc
import os
import shutil
from . import util
@ -16,13 +17,17 @@ class FsUtil(abc.ABC):
"""Performs `mkdir -p <path>` and returns the path."""
@abc.abstractmethod
def statvfs(self, path: str) -> os.statvfs_result:
def disk_usage(self, path: str) -> shutil._ntuple_diskusage:
"""Calls os.statvfs on the mount"""
class LinuxFsUtil(FsUtil):
class RealFsUtil(FsUtil):
def mkdir_p(self, path: str) -> str:
return util.mkdir_p(path)
def statvfs(self, path: str) -> os.statvfs_result:
return os.statvfs(path)
def disk_usage(self, path: str) -> shutil._ntuple_diskusage:
return shutil.disk_usage(path)
def new() -> FsUtil:
return RealFsUtil()

View File

@ -5,6 +5,7 @@
# GNU General Public License version 2.
import subprocess
import sys
from pathlib import Path
from eden.integration.lib import hgrepo
@ -143,7 +144,10 @@ class DoctorTest(EdenHgTestCase):
cmd_result = self.run_doctor(dry_run=True)
doctor_out = cmd_result.stdout.decode("utf-8")
self.assertIn(f"Found inconsistent/missing data in {repo_path}/.hg", doctor_out)
self.assertIn(f"error parsing .hg/dirstate", doctor_out)
if sys.platform == "win32":
self.assertIn("error parsing .hg\\dirstate", doctor_out)
else:
self.assertIn("error parsing .hg/dirstate", doctor_out)
fixed_result = self.run_doctor(dry_run=False)
self.assertIn(b"Successfully fixed 1 problem", fixed_result.stdout)

View File

@ -106,7 +106,11 @@ if sys.platform == "win32":
"hg.debug_hg_dirstate_test.DebugHgDirstateTestTreeOnly": True,
"hg.debug_hg_get_dirstate_tuple_test.DebugHgGetDirstateTupleTestTreeOnly": True,
"hg.diff_test.DiffTestTreeOnly": True,
"hg.doctor_test.DoctorTestTreeOnly": True,
"hg.doctor_test.DoctorTestTreeOnly": [
# TODO: Figure out why `hg whereami` agrees with `hg log -r .`
"test_eden_doctor_fixes_invalid_mismatched_parents",
"test_eden_doctor_fixes_valid_mismatched_parents",
],
"hg.fold_test.FoldTestTreeOnly": True,
"hg.grep_test.GrepTestTreeOnly": [
"test_grep_directory_from_root",