mirror of
https://github.com/kristoferssolo/School.git
synced 2025-10-21 20:10:38 +00:00
134 lines
3.4 KiB
Python
134 lines
3.4 KiB
Python
import os
|
|
from datetime import datetime
|
|
|
|
from .git import GitWorkdir
|
|
from .hg import HgWorkdir
|
|
from .utils import do_ex
|
|
from .utils import require_command
|
|
from .utils import trace
|
|
|
|
|
|
class GitWorkdirHgClient(GitWorkdir, HgWorkdir):
|
|
COMMAND = "hg"
|
|
|
|
@classmethod
|
|
def from_potential_worktree(cls, wd):
|
|
require_command(cls.COMMAND)
|
|
root, err, ret = do_ex("hg root", wd)
|
|
if ret:
|
|
return
|
|
return cls(root)
|
|
|
|
def is_dirty(self):
|
|
out, _, _ = self.do_ex("hg id -T '{dirty}'")
|
|
return bool(out)
|
|
|
|
def get_branch(self):
|
|
branch, err, ret = self.do_ex("hg id -T {bookmarks}")
|
|
if ret:
|
|
trace("branch err", branch, err, ret)
|
|
return
|
|
return branch
|
|
|
|
def get_head_date(self):
|
|
date_part, err, ret = self.do_ex("hg log -r . -T {shortdate(date)}")
|
|
if ret:
|
|
trace("head date err", date_part, err, ret)
|
|
return
|
|
return datetime.strptime(date_part, r"%Y-%m-%d").date()
|
|
|
|
def is_shallow(self):
|
|
return False
|
|
|
|
def fetch_shallow(self):
|
|
pass
|
|
|
|
def get_hg_node(self):
|
|
node, _, ret = self.do_ex("hg log -r . -T {node}")
|
|
if not ret:
|
|
return node
|
|
|
|
def _hg2git(self, hg_node):
|
|
git_node = None
|
|
with open(os.path.join(self.path, ".hg/git-mapfile")) as file:
|
|
for line in file:
|
|
if hg_node in line:
|
|
git_node, hg_node = line.split()
|
|
break
|
|
return git_node
|
|
|
|
def node(self):
|
|
hg_node = self.get_hg_node()
|
|
if hg_node is None:
|
|
return
|
|
|
|
git_node = self._hg2git(hg_node)
|
|
|
|
if git_node is None:
|
|
# trying again after hg -> git
|
|
self.do_ex("hg gexport")
|
|
git_node = self._hg2git(hg_node)
|
|
|
|
if git_node is None:
|
|
trace("Cannot get git node so we use hg node", hg_node)
|
|
|
|
if hg_node == "0" * len(hg_node):
|
|
# mimick Git behavior
|
|
return None
|
|
|
|
return hg_node
|
|
|
|
return git_node[:7]
|
|
|
|
def count_all_nodes(self):
|
|
revs, _, _ = self.do_ex("hg log -r 'ancestors(.)' -T '.'")
|
|
return len(revs)
|
|
|
|
def default_describe(self):
|
|
"""
|
|
Tentative to reproduce the output of
|
|
|
|
`git describe --dirty --tags --long --match *[0-9]*`
|
|
|
|
"""
|
|
hg_tags, _, ret = self.do_ex(
|
|
[
|
|
"hg",
|
|
"log",
|
|
"-r",
|
|
"(reverse(ancestors(.)) and tag(r're:[0-9]'))",
|
|
"-T",
|
|
"{tags}{if(tags, ' ', '')}",
|
|
]
|
|
)
|
|
if ret:
|
|
return None, None, None
|
|
hg_tags = hg_tags.split()
|
|
|
|
if not hg_tags:
|
|
return None, None, None
|
|
|
|
git_tags = {}
|
|
with open(os.path.join(self.path, ".hg/git-tags")) as file:
|
|
for line in file:
|
|
node, tag = line.split()
|
|
git_tags[tag] = node
|
|
|
|
# find the first hg tag which is also a git tag
|
|
for tag in hg_tags:
|
|
if tag in git_tags:
|
|
break
|
|
|
|
out, _, ret = self.do_ex(["hg", "log", "-r", f"'{tag}'::.", "-T", "."])
|
|
if ret:
|
|
return None, None, None
|
|
distance = len(out) - 1
|
|
|
|
node = self.node()
|
|
desc = f"{tag}-{distance}-g{node}"
|
|
|
|
if self.is_dirty():
|
|
desc += "-dirty"
|
|
|
|
return desc, None, 0
|