Optionally ignore some remote Mercurial revision names

... in particular when these would otherwise map to unsupported refnames.

Fixes mnauw/git-remote-hg#10
This commit is contained in:
Mark Nauwelaerts
2017-11-27 20:49:03 +01:00
parent 6c2f4d8ff4
commit 76be528c0d
4 changed files with 70 additions and 5 deletions

View File

@@ -243,6 +243,23 @@ also be enabled on an existing one by the following setting.
--------------------------------------
Note, however, that one should then perform a fetch from each relevant remote
to fully complete the conversion (prior to subsequent pushing).
Some Mercurial names (of branches, bookmarks, tags) may not be a valid git
refname. See e.g. `man git-check-ref-format` for a rather involved set of rules.
Moreover, while a slash `/` is allowed, it is not supported to have both a `parent`
and `parent/child` branch (though only the latter is allowed). So, pending some
"nice" bidirectional encoding (not even e.g. URL encoding is safe actually), it is more
likely that only a few instances (out of a whole Mercurial repo) are
problematic. This could be handled by a single-branch clone and/or configuring
a suitable refspec. However, it might be more convenient to simply filter out a
few unimportant pesky cases, which can be done by configuring a regural
expression in following setting:
--------------------------------------
% git config remote-hg.ignore-name nasty/nested/name
--------------------------------------
Recall also that a config setting can be provided at clone time
(command line using `--config` option).
--------------------------------------
% git config --global remote-hg.remove-username-quotes false
--------------------------------------

View File

@@ -94,6 +94,14 @@ for an existing repo:
Note that one should perform a fetch from each remote to properly complete the
conversion to shared marks files.
Mercurial name(s) (of a branch or bookmark) that are not a valid git refname,
can be ignored by configuring a suitable regular expression, e.g. avoiding
the invalid '~'
--------------------------------------
% git config --global remote-hg.ignore-name ~
--------------------------------------
NOTES
-----

View File

@@ -96,8 +96,8 @@ def check_version(*check):
return True
return hg_version >= check
def get_config(config):
cmd = ['git', 'config', '--get', config]
def get_config(config, getall=False):
cmd = ['git', 'config', '--get' if not getall else '--get-all', config]
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output, _ = process.communicate()
return output
@@ -707,6 +707,22 @@ def do_list(parser):
list_head(repo, cur)
ignore_ref = get_config('remote-hg.ignore-name', True)
ignore_re = []
for exp in ignore_ref.splitlines():
if exp:
try:
#warn("checking %s" % (
ignore_re.append(re.compile(exp.strip()))
except:
warn("Invalid regular expression '%s'" % (exp))
def ignore(kind, name):
for r in ignore_re:
if r.search(name):
warn("Ignoring matched %s %s" % (kind, name))
return True
return False
# for export command a ref's old_sha1 is taken from private namespace ref
# for push command a fake one is provided
# that avoids having the ref status reported as a new branch/tag
@@ -717,18 +733,20 @@ def do_list(parser):
if track_branches:
for branch in branches:
print "%s refs/heads/branches/%s" % (sha1, gitref(branch))
if not ignore('branch', branch):
print "%s refs/heads/branches/%s" % (sha1, gitref(branch))
for bmark in bmarks:
if bmarks[bmark].hex() == '0' * 40:
warn("Ignoring invalid bookmark '%s'", bmark)
else:
elif not ignore('bookmark', bmark):
print "%s refs/heads/%s" % (sha1, gitref(bmark))
for tag, node in repo.tagslist():
if tag == 'tip':
continue
print "%s refs/tags/%s" % (sha1, gitref(tag))
if not ignore('tag', tag):
print "%s refs/tags/%s" % (sha1, gitref(tag))
print

View File

@@ -1201,6 +1201,28 @@ test_expect_success 'clone replace directory with a file' '
check_files gitrepo "dir_or_file"
'
test_expect_success 'clone can ignore invalid refnames' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
touch test.txt &&
hg add test.txt &&
hg commit -m master &&
hg branch parent &&
echo test >test.txt &&
hg commit -m test &&
hg branch parent/child &&
echo test1 >test.txt &&
hg commit -m test1
) &&
git clone -c remote-hg.ignore-name=child "hg::hgrepo" gitrepo &&
check_files gitrepo "test.txt"
'
if test "$CAPABILITY_PUSH" != "t"
then
test_done