Skip to content

Commit

Permalink
Support working on a Git repository with hg-git
Browse files Browse the repository at this point in the history
  • Loading branch information
paugier committed Mar 16, 2021
1 parent 3c18be6 commit 77f4d80
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 7 deletions.
119 changes: 112 additions & 7 deletions src/setuptools_scm/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@

class GitWorkdir(object):
"""experimental, may change at any time"""
COMMAND = "git"

def __init__(self, path):
require_command(self.COMMAND)
self.path = path

def do_ex(self, cmd):
Expand Down Expand Up @@ -78,6 +80,105 @@ def count_all_nodes(self):
revs, _, _ = self.do_ex("git rev-list HEAD")
return revs.count("\n") + 1

def default_describe(self):
return self.do_ex(DEFAULT_DESCRIBE)


class GitWorkdirHgClient(GitWorkdir):
COMMAND = "hg"

@classmethod
def from_potential_worktree(cls, wd):
root, _, 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):
rev_node, _, ret = self.do_ex("hg log -r . -T {node}")
if not ret:
return rev_node

def node(self):
hg_node = self.get_hg_node()
if hg_node is None:
return

with open(os.path.join(self.path, ".hg/git-mapfile"), "r") as file:
for line in file:
if hg_node in line:
git_node, hg_node = line.split()
break

return git_node[:7]

def count_all_nodes(self):
revs, _, _ = self.do_ex("hg log -r 'ancestors(.)' -T '.'")
return len(revs) + 1

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(.)) -T {tags}{if(tags, ' ', '')}"
)

if ret:
return None, None, None

git_tags = {}
with open(os.path.join(self.path, ".hg/git-tags"), "r") 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
# TODO: also check for match *[0-9]*
for tag in hg_tags:
if tag in git_tags:
break

out, _, ret = self.do_ex("hg log -r .:" + tag + " -T .")
if ret:
return None, None, None
distance = len(out) - 1

rev_node = self.node()
desc = f"{tag}-{distance}-g{rev_node}"

if self.is_dirty():
desc += "-dirty"

return desc, None, 0


def warn_on_shallow(wd):
"""experimental, may change at any time"""
Expand All @@ -96,31 +197,35 @@ def fail_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
raise ValueError(
"%r is shallow, please correct with " '"git fetch --unshallow"' % wd.path
"%r is shallow, please correct with "
'"git fetch --unshallow"' % wd.path
)


def parse(
root, describe_command=DEFAULT_DESCRIBE, pre_parse=warn_on_shallow, config=None
):
def parse(root, describe_command=None, pre_parse=warn_on_shallow, config=None):
"""
:param pre_parse: experimental pre_parse action, may change at any time
"""
if not config:
config = Configuration(root=root)

require_command("git")

wd = GitWorkdir.from_potential_worktree(config.absolute_root)
if wd is None:
wd = GitWorkdirHgClient.from_potential_worktree(config.absolute_root)
if wd is None:
return
if pre_parse:
pre_parse(wd)

if config.git_describe_command:
if config.git_describe_command is not None:
describe_command = config.git_describe_command

out, unused_err, ret = wd.do_ex(describe_command)
if describe_command is not None:
out, unused_err, ret = wd.do_ex(describe_command)
else:
out, unused_err, ret = wd.default_describe()

node_date = wd.get_head_date() or date.today()

if ret:
Expand Down
4 changes: 4 additions & 0 deletions src/setuptools_scm/hg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def _hg_tagdist_normalize_tagcommit(config, tag, dist, node, branch):


def parse(root, config=None):
if os.path.exists(os.path.join(root, ".hg/git")):
from .git import parse as git_parse
return git_parse(root, config=config)

if not config:
config = Configuration(root=root)

Expand Down

0 comments on commit 77f4d80

Please sign in to comment.