mirror of
https://github.com/facebook/sapling.git
synced 2025-01-07 22:21:40 +03:00
fbdb46f5cb
Reviewed By: chadaustin Differential Revision: D17872966 fbshipit-source-id: cd60a364a2146f0dadbeca693b1d4a5d7c97ff63
118 lines
3.8 KiB
Python
118 lines
3.8 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.
|
|
|
|
# pyre-strict
|
|
|
|
import binascii
|
|
import typing
|
|
from pathlib import Path
|
|
from typing import BinaryIO, Dict, Tuple
|
|
|
|
import eden.dirstate
|
|
|
|
from .config import EdenCheckout
|
|
|
|
|
|
_DEFAULT_EXTRA_HGRC_CONTENTS: str = """\
|
|
[extensions]
|
|
eden =
|
|
share =
|
|
|
|
[ui]
|
|
portablefilenames = ignore
|
|
"""
|
|
|
|
|
|
def setup_hg_dir(checkout: EdenCheckout, commit_id: str) -> None:
|
|
checkout_hg_dir = checkout.path / ".hg"
|
|
try:
|
|
checkout_hg_dir.mkdir()
|
|
except FileExistsError:
|
|
raise Exception(f"{checkout_hg_dir} directory already exists")
|
|
|
|
# hgrc
|
|
hgrc_data = get_hgrc_data(checkout)
|
|
(checkout_hg_dir / "hgrc").write_text(hgrc_data)
|
|
|
|
# requires
|
|
requires_data = get_requires_data(checkout)
|
|
(checkout_hg_dir / "requires").write_text(requires_data)
|
|
|
|
# Create the shared and sharedpath files, which tell mercurial where it should
|
|
# really look for most of the mercurial state, and that bookmarks should also be
|
|
# shared.
|
|
#
|
|
# Note that the sharedpath file intentionally does not include a trailing newline.
|
|
# This matches how it is generated by mercurial.
|
|
backing_hg_dir = get_backing_hg_dir(checkout)
|
|
(checkout_hg_dir / "sharedpath").write_bytes(bytes(backing_hg_dir))
|
|
(checkout_hg_dir / "shared").write_text("bookmarks\n")
|
|
|
|
# Create an empty bookmarks file
|
|
(checkout_hg_dir / "bookmarks").touch()
|
|
|
|
# Create a branch file with the contents "default\n". Even though we do not
|
|
# use branches, we have seen some users with a function in their .bashrc
|
|
# that categorically reads the .hg/branch file to include in their prompt.
|
|
(checkout_hg_dir / "branch").write_text("default\n")
|
|
|
|
# Write the parents to the dirstate file.
|
|
with typing.cast(BinaryIO, (checkout_hg_dir / "dirstate").open("wb")) as f:
|
|
parents = (binascii.unhexlify(commit_id), b"\x00" * 20)
|
|
tuples_dict: Dict[bytes, Tuple[str, int, int]] = {}
|
|
copymap: Dict[bytes, bytes] = {}
|
|
eden.dirstate.write(f, parents, tuples_dict, copymap)
|
|
|
|
|
|
def get_backing_hg_dir(checkout: EdenCheckout) -> Path:
|
|
"""Given an EdenCheckout object, return the path to the actual .hg/ directory that
|
|
contains the mercurial data store.
|
|
|
|
This is the path that .hg/sharedpath should point to.
|
|
"""
|
|
return checkout.get_config().backing_repo / ".hg"
|
|
|
|
|
|
def get_hgrc_data(checkout: EdenCheckout) -> str:
|
|
backing_hg_dir = get_backing_hg_dir(checkout)
|
|
extra_hgrc = checkout.instance.get_config_value(
|
|
"hg.extra_hgrc", default=_DEFAULT_EXTRA_HGRC_CONTENTS
|
|
)
|
|
|
|
if extra_hgrc and extra_hgrc[-1] != "\n":
|
|
extra_hgrc += "\n"
|
|
|
|
try:
|
|
orig_hgrc = (backing_hg_dir / "hgrc").read_text()
|
|
except FileNotFoundError:
|
|
# Repositories aren't required to have an .hgrc file
|
|
# Make sure the .hg directory itself exists though, to confirm
|
|
# we weren't called with incorrect arguments.
|
|
if not backing_hg_dir.is_dir():
|
|
raise Exception(f"backing repository does not exist: {backing_hg_dir}")
|
|
orig_hgrc = ""
|
|
|
|
return orig_hgrc + "\n" + extra_hgrc
|
|
|
|
|
|
def get_requires_data(checkout: EdenCheckout) -> str:
|
|
backing_hg_dir = get_backing_hg_dir(checkout)
|
|
try:
|
|
orig_requires_data = (backing_hg_dir / "requires").read_text()
|
|
requires = set(orig_requires_data.splitlines())
|
|
except FileNotFoundError:
|
|
requires = set()
|
|
|
|
# Add eden as a requirement
|
|
requires.add("eden")
|
|
|
|
# Drop other dirstate-related requirements that are specific to
|
|
# the backing repository's dirstate.
|
|
requires.discard("sqldirstate")
|
|
requires.discard("treedirstate")
|
|
|
|
return "\n".join(sorted(requires)) + "\n"
|