summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/completion/git-completion.bash78
-rwxr-xr-xcontrib/remote-helpers/git-remote-bzr9
-rwxr-xr-xcontrib/remote-helpers/git-remote-hg125
-rwxr-xr-xcontrib/remote-helpers/test-hg-bidi.sh11
-rwxr-xr-xcontrib/remote-helpers/test-hg-hg-git.sh8
-rwxr-xr-xcontrib/remote-helpers/test-hg.sh36
6 files changed, 189 insertions, 78 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 2ba1461422..6df62c2173 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -53,19 +53,6 @@ __gitdir ()
fi
}
-__gitcomp_1 ()
-{
- local c IFS=$' \t\n'
- for c in $1; do
- c="$c$2"
- case $c in
- --*=*|*.) ;;
- *) c="$c " ;;
- esac
- printf '%s\n' "$c"
- done
-}
-
# The following function is based on code from:
#
# bash_completion - programmable completion functions for bash 3.2+
@@ -195,8 +182,18 @@ _get_comp_words_by_ref ()
}
fi
-# Generates completion reply with compgen, appending a space to possible
-# completion words, if necessary.
+__gitcompadd ()
+{
+ local i=0
+ for x in $1; do
+ if [[ "$x" == "$3"* ]]; then
+ COMPREPLY[i++]="$2$x$4"
+ fi
+ done
+}
+
+# Generates completion reply, appending a space to possible completion words,
+# if necessary.
# It accepts 1 to 4 arguments:
# 1: List of possible completion words.
# 2: A prefix to be added to each possible completion word (optional).
@@ -208,19 +205,25 @@ __gitcomp ()
case "$cur_" in
--*=)
- COMPREPLY=()
;;
*)
- local IFS=$'\n'
- COMPREPLY=($(compgen -P "${2-}" \
- -W "$(__gitcomp_1 "${1-}" "${4-}")" \
- -- "$cur_"))
+ local c i=0 IFS=$' \t\n'
+ for c in $1; do
+ c="$c${4-}"
+ if [[ $c == "$cur_"* ]]; then
+ case $c in
+ --*=*|*.) ;;
+ *) c="$c " ;;
+ esac
+ COMPREPLY[i++]="${2-}$c"
+ fi
+ done
;;
esac
}
-# Generates completion reply with compgen from newline-separated possible
-# completion words by appending a space to all of them.
+# Generates completion reply from newline-separated possible completion words
+# by appending a space to all of them.
# It accepts 1 to 4 arguments:
# 1: List of possible completion words, separated by a single newline.
# 2: A prefix to be added to each possible completion word (optional).
@@ -231,7 +234,7 @@ __gitcomp ()
__gitcomp_nl ()
{
local IFS=$'\n'
- COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}"))
+ __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }"
}
# Generates completion reply with compgen from newline-separated possible
@@ -614,7 +617,6 @@ __git_complete_remote_or_refspec ()
case "$cmd" in
push) no_complete_refspec=1 ;;
fetch)
- COMPREPLY=()
return
;;
*) ;;
@@ -630,7 +632,6 @@ __git_complete_remote_or_refspec ()
return
fi
if [ $no_complete_refspec = 1 ]; then
- COMPREPLY=()
return
fi
[ "$remote" = "." ] && remote=
@@ -951,7 +952,6 @@ _git_am ()
"
return
esac
- COMPREPLY=()
}
_git_apply ()
@@ -971,7 +971,6 @@ _git_apply ()
"
return
esac
- COMPREPLY=()
}
_git_add ()
@@ -1031,7 +1030,6 @@ _git_bisect ()
__gitcomp_nl "$(__git_refs)"
;;
*)
- COMPREPLY=()
;;
esac
}
@@ -1124,9 +1122,14 @@ _git_cherry ()
_git_cherry_pick ()
{
+ local dir="$(__gitdir)"
+ if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
+ __gitcomp "--continue --quit --abort"
+ return
+ fi
case "$cur" in
--*)
- __gitcomp "--edit --no-commit"
+ __gitcomp "--edit --no-commit --signoff --strategy= --mainline"
;;
*)
__gitcomp_nl "$(__git_refs)"
@@ -1170,7 +1173,6 @@ _git_clone ()
return
;;
esac
- COMPREPLY=()
}
_git_commit ()
@@ -1354,7 +1356,6 @@ _git_fsck ()
return
;;
esac
- COMPREPLY=()
}
_git_gc ()
@@ -1365,7 +1366,6 @@ _git_gc ()
return
;;
esac
- COMPREPLY=()
}
_git_gitk ()
@@ -1442,7 +1442,6 @@ _git_init ()
return
;;
esac
- COMPREPLY=()
}
_git_ls_files ()
@@ -1578,7 +1577,6 @@ _git_mergetool ()
return
;;
esac
- COMPREPLY=()
}
_git_merge_base ()
@@ -1831,7 +1829,7 @@ _git_config ()
local remote="${prev#remote.}"
remote="${remote%.fetch}"
if [ -z "$cur" ]; then
- COMPREPLY=("refs/heads/")
+ __gitcompadd "refs/heads/" "" "" ""
return
fi
__gitcomp_nl "$(__git_refs_remotes "$remote")"
@@ -1891,7 +1889,6 @@ _git_config ()
return
;;
*.*)
- COMPREPLY=()
return
;;
esac
@@ -2272,7 +2269,6 @@ _git_remote ()
__gitcomp "$c"
;;
*)
- COMPREPLY=()
;;
esac
}
@@ -2388,8 +2384,6 @@ _git_stash ()
*)
if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then
__gitcomp "$subcommands"
- else
- COMPREPLY=()
fi
;;
esac
@@ -2402,14 +2396,12 @@ _git_stash ()
__gitcomp "--index --quiet"
;;
show,--*|drop,--*|branch,--*)
- COMPREPLY=()
;;
show,*|apply,*|drop,*|pop,*|branch,*)
__gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
| sed -n -e 's/:.*//p')"
;;
*)
- COMPREPLY=()
;;
esac
fi
@@ -2526,7 +2518,6 @@ _git_svn ()
__gitcomp "--revision= --parent"
;;
*)
- COMPREPLY=()
;;
esac
fi
@@ -2551,13 +2542,10 @@ _git_tag ()
case "$prev" in
-m|-F)
- COMPREPLY=()
;;
-*|tag)
if [ $f = 1 ]; then
__gitcomp_nl "$(__git_tags)"
- else
- COMPREPLY=()
fi
;;
*)
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
index bd25e08202..aa7bc97bee 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -249,7 +249,7 @@ def export_files(tree, files):
return final
def export_branch(branch, name):
- global prefix, dirname
+ global prefix
ref = '%s/heads/%s' % (prefix, name)
tip = marks.get_tip(name)
@@ -335,8 +335,10 @@ def export_branch(branch, name):
marks.set_tip(name, revid)
def export_tag(repo, name):
- global tags
- print "reset refs/tags/%s" % name
+ global tags, prefix
+
+ ref = '%s/tags/%s' % (prefix, name)
+ print "reset %s" % ref
print "from :%u" % rev_to_mark(tags[name])
print
@@ -649,6 +651,7 @@ def do_capabilities(parser):
print "import"
print "export"
print "refspec refs/heads/*:%s/heads/*" % prefix
+ print "refspec refs/tags/*:%s/tags/*" % prefix
path = os.path.join(dirname, 'marks-git')
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 328c2dc76d..548133121d 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -8,8 +8,11 @@
# Just copy to your ~/bin, or anywhere in your $PATH.
# Then you can clone with:
# git clone hg::/path/to/mercurial/repo/
+#
+# For remote repositories a local clone is stored in
+# "$GIT_DIR/hg/origin/clone/.hg/".
-from mercurial import hg, ui, bookmarks, context, util, encoding
+from mercurial import hg, ui, bookmarks, context, util, encoding, node, error
import re
import sys
@@ -18,11 +21,22 @@ import json
import shutil
import subprocess
import urllib
+import atexit
#
# If you want to switch to hg-git compatibility mode:
# git config --global remote-hg.hg-git-compat true
#
+# If you are not in hg-git-compat mode and want to disable the tracking of
+# named branches:
+# git config --global remote-hg.track-branches false
+#
+# If you don't want to force pushes (and thus risk creating new remote heads):
+# git config --global remote-hg.force-push false
+#
+# If you want the equivalent of hg's clone/pull--insecure option:
+# git config remote-hg.insecure true
+#
# git:
# Sensible defaults for git.
# hg bookmarks are exported as git branches, hg branches are prefixed
@@ -56,6 +70,9 @@ def hgmode(mode):
m = { '100755': 'x', '120000': 'l' }
return m.get(mode, '')
+def hghex(node):
+ return hg.node.hex(node)
+
def get_config(config):
cmd = ['git', 'config', '--get', config]
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
@@ -188,9 +205,15 @@ class Parser:
tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
return (user, int(date), -tz)
+def fix_file_path(path):
+ if not os.path.isabs(path):
+ return path
+ return os.path.relpath(path, '/')
+
def export_file(fc):
d = fc.data()
- print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+ path = fix_file_path(fc.path())
+ print "M %s inline %s" % (gitmode(fc.flags()), path)
print "data %d" % len(d)
print d
@@ -267,17 +290,30 @@ def get_repo(url, alias):
myui = ui.ui()
myui.setconfig('ui', 'interactive', 'off')
+ myui.fout = sys.stderr
+
+ try:
+ if get_config('remote-hg.insecure') == 'true\n':
+ myui.setconfig('web', 'cacerts', '')
+ except subprocess.CalledProcessError:
+ pass
if hg.islocal(url):
repo = hg.repository(myui, url)
else:
local_path = os.path.join(dirname, 'clone')
if not os.path.exists(local_path):
- peer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, pull=True)
+ try:
+ peer, dstpeer = hg.clone(myui, {}, url, local_path, update=True, pull=True)
+ except:
+ die('Repository error')
repo = dstpeer.local()
else:
repo = hg.repository(myui, local_path)
- peer = hg.peer(myui, {}, url)
+ try:
+ peer = hg.peer(myui, {}, url)
+ except:
+ die('Repository error')
repo.pull(peer, heads=None, force=True)
return repo
@@ -326,6 +362,8 @@ def export_ref(repo, name, kind, head):
else:
modified, removed = get_filechanges(repo, c, parents[0])
+ desc += '\n'
+
if mode == 'hg':
extra_msg = ''
@@ -349,7 +387,6 @@ def export_ref(repo, name, kind, head):
else:
extra_msg += "extra : %s : %s\n" % (key, urllib.quote(value))
- desc += '\n'
if extra_msg:
desc += '\n--HG--\n' + extra_msg
@@ -371,7 +408,7 @@ def export_ref(repo, name, kind, head):
for f in modified:
export_file(c.filectx(f))
for f in removed:
- print "D %s" % (f)
+ print "D %s" % (fix_file_path(f))
print
count += 1
@@ -531,7 +568,6 @@ def parse_blob(parser):
data = parser.get_data()
blob_marks[mark] = data
parser.next()
- return
def get_merge_files(repo, p1, p2, files):
for e in repo[p1].files():
@@ -542,7 +578,7 @@ def get_merge_files(repo, p1, p2, files):
files[e] = f
def parse_commit(parser):
- global marks, blob_marks, bmarks, parsed_refs
+ global marks, blob_marks, parsed_refs
global mode
from_mark = merge_mark = None
@@ -575,7 +611,7 @@ def parse_commit(parser):
mark = int(mark_ref[1:])
f = { 'mode' : hgmode(m), 'data' : blob_marks[mark] }
elif parser.check('D'):
- t, path = line.split(' ')
+ t, path = line.split(' ', 1)
f = { 'deleted' : True }
else:
die('Unknown file command: %s' % line)
@@ -618,11 +654,15 @@ def parse_commit(parser):
if merge_mark:
get_merge_files(repo, p1, p2, files)
+ # Check if the ref is supposed to be a named branch
+ if ref.startswith('refs/heads/branches/'):
+ extra['branch'] = ref[len('refs/heads/branches/'):]
+
if mode == 'hg':
i = data.find('\n--HG--\n')
if i >= 0:
tmp = data[i + len('\n--HG--\n'):].strip()
- for k, v in [e.split(' : ') for e in tmp.split('\n')]:
+ for k, v in [e.split(' : ', 1) for e in tmp.split('\n')]:
if k == 'rename':
old, new = v.split(' => ', 1)
files[new]['rename'] = old
@@ -647,10 +687,11 @@ def parse_commit(parser):
rev = repo[node].rev()
parsed_refs[ref] = node
-
marks.new_mark(rev, commit_mark)
def parse_reset(parser):
+ global parsed_refs
+
ref = parser[1]
parser.next()
# ugh
@@ -680,6 +721,8 @@ def parse_tag(parser):
def do_export(parser):
global parsed_refs, bmarks, peer
+ p_bmarks = []
+
parser.next()
for line in parser.each_block('done'):
@@ -698,28 +741,55 @@ def do_export(parser):
for ref, node in parsed_refs.iteritems():
if ref.startswith('refs/heads/branches'):
- pass
+ print "ok %s" % ref
elif ref.startswith('refs/heads/'):
bmark = ref[len('refs/heads/'):]
- if bmark in bmarks:
- old = bmarks[bmark].hex()
- else:
- old = ''
- if not bookmarks.pushbookmark(parser.repo, bmark, old, node):
- continue
+ p_bmarks.append((bmark, node))
+ continue
elif ref.startswith('refs/tags/'):
tag = ref[len('refs/tags/'):]
- parser.repo.tag([tag], node, None, True, None, {})
+ if mode == 'git':
+ msg = 'Added tag %s for changeset %s' % (tag, hghex(node[:6]));
+ parser.repo.tag([tag], node, msg, False, None, {})
+ else:
+ parser.repo.tag([tag], node, None, True, None, {})
+ print "ok %s" % ref
else:
# transport-helper/fast-export bugs
continue
+
+ if peer:
+ parser.repo.push(peer, force=force_push)
+
+ # handle bookmarks
+ for bmark, node in p_bmarks:
+ ref = 'refs/heads/' + bmark
+ new = hghex(node)
+
+ if bmark in bmarks:
+ old = bmarks[bmark].hex()
+ else:
+ old = ''
+
+ if bmark == 'master' and 'master' not in parser.repo._bookmarks:
+ # fake bookmark
+ pass
+ elif bookmarks.pushbookmark(parser.repo, bmark, old, new):
+ # updated locally
+ pass
+ else:
+ print "error %s" % ref
+ continue
+
+ if peer:
+ if not peer.pushkey('bookmarks', bmark, old, new):
+ print "error %s" % ref
+ continue
+
print "ok %s" % ref
print
- if peer:
- parser.repo.push(peer, force=False)
-
def fix_path(alias, repo, orig_url):
repo_url = util.url(repo.url())
url = util.url(orig_url)
@@ -732,7 +802,7 @@ def main(args):
global prefix, dirname, branches, bmarks
global marks, blob_marks, parsed_refs
global peer, mode, bad_mail, bad_name
- global track_branches
+ global track_branches, force_push, is_tmp
alias = args[1]
url = args[2]
@@ -740,12 +810,16 @@ def main(args):
hg_git_compat = False
track_branches = True
+ force_push = True
+
try:
if get_config('remote-hg.hg-git-compat') == 'true\n':
hg_git_compat = True
track_branches = False
if get_config('remote-hg.track-branches') == 'false\n':
track_branches = False
+ if get_config('remote-hg.force-push') == 'false\n':
+ force_push = False
except subprocess.CalledProcessError:
pass
@@ -770,6 +844,7 @@ def main(args):
bmarks = {}
blob_marks = {}
parsed_refs = {}
+ marks = None
repo = get_repo(url, alias)
prefix = 'refs/hg/%s' % alias
@@ -797,9 +872,13 @@ def main(args):
die('unhandled command: %s' % line)
sys.stdout.flush()
+def bye():
+ if not marks:
+ return
if not is_tmp:
marks.store()
else:
shutil.rmtree(dirname)
+atexit.register(bye)
sys.exit(main(sys.argv))
diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
index 1d61982436..f36895311e 100755
--- a/contrib/remote-helpers/test-hg-bidi.sh
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -22,7 +22,6 @@ fi
# clone to a git repo
git_clone () {
- hg -R $1 bookmark -f -r tip master &&
git clone -q "hg::$PWD/$1" $2
}
@@ -30,6 +29,7 @@ git_clone () {
hg_clone () {
(
hg init $2 &&
+ hg -R $2 bookmark -i master &&
cd $1 &&
git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
) &&
@@ -50,7 +50,8 @@ hg_push () {
}
hg_log () {
- hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+ hg -R $1 log --graph --debug >log &&
+ grep -v 'tag: *default/' log
}
setup () {
@@ -62,6 +63,8 @@ setup () {
echo "commit = -d \"0 0\""
echo "debugrawcommit = -d \"0 0\""
echo "tag = -d \"0 0\""
+ echo "[extensions]"
+ echo "graphlog ="
) >> "$HOME"/.hgrc &&
git config --global remote-hg.hg-git-compat true
@@ -200,8 +203,8 @@ test_expect_success 'hg branch' '
hg_push hgrepo gitrepo &&
hg_clone gitrepo hgrepo2 &&
- : TODO, avoid "master" bookmark &&
- (cd hgrepo2 && hg checkout gamma) &&
+ : Back to the common revision &&
+ (cd hgrepo && hg checkout default) &&
hg_log hgrepo > expected &&
hg_log hgrepo2 > actual &&
diff --git a/contrib/remote-helpers/test-hg-hg-git.sh b/contrib/remote-helpers/test-hg-hg-git.sh
index 3f253b7de7..253e65aaa8 100755
--- a/contrib/remote-helpers/test-hg-hg-git.sh
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -27,7 +27,6 @@ fi
# clone to a git repo with git
git_clone_git () {
- hg -R $1 bookmark -f -r tip master &&
git clone -q "hg::$PWD/$1" $2
}
@@ -35,6 +34,7 @@ git_clone_git () {
hg_clone_git () {
(
hg init $2 &&
+ hg -R $2 bookmark -i master &&
cd $1 &&
git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
) &&
@@ -47,7 +47,7 @@ git_clone_hg () {
(
git init -q $2 &&
cd $1 &&
- hg bookmark -f -r tip master &&
+ hg bookmark -i -f -r tip master &&
hg -q push -r master ../$2 || true
)
}
@@ -78,7 +78,8 @@ hg_push_hg () {
}
hg_log () {
- hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+ hg -R $1 log --graph --debug >log &&
+ grep -v 'tag: *default/' log
}
git_log () {
@@ -97,6 +98,7 @@ setup () {
echo "[extensions]"
echo "hgext.bookmarks ="
echo "hggit ="
+ echo "graphlog ="
) >> "$HOME"/.hgrc &&
git config --global receive.denycurrentbranch warn
git config --global remote-hg.hg-git-compat true
diff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh
index 7bb81f2f8e..d5b873051f 100755
--- a/contrib/remote-helpers/test-hg.sh
+++ b/contrib/remote-helpers/test-hg.sh
@@ -118,4 +118,40 @@ test_expect_success 'update bookmark' '
hg -R hgrepo bookmarks | egrep "devel[ ]+3:"
'
+author_test () {
+ echo $1 >> content &&
+ hg commit -u "$2" -m "add $1" &&
+ echo "$3" >> ../expected
+}
+
+test_expect_success 'authors' '
+ mkdir -p tmp && cd tmp &&
+ test_when_finished "cd .. && rm -rf tmp" &&
+
+ (
+ hg init hgrepo &&
+ cd hgrepo &&
+
+ touch content &&
+ hg add content &&
+
+ author_test alpha "" "H G Wells <wells@example.com>" &&
+ author_test beta "test" "test <unknown>" &&
+ author_test beta "test <test@example.com> (comment)" "test <unknown>" &&
+ author_test gamma "<test@example.com>" "Unknown <test@example.com>" &&
+ author_test delta "name<test@example.com>" "name <test@example.com>" &&
+ author_test epsilon "name <test@example.com" "name <unknown>" &&
+ author_test zeta " test " "test <unknown>" &&
+ author_test eta "test < test@example.com >" "test <test@example.com>" &&
+ author_test theta "test >test@example.com>" "test <unknown>" &&
+ author_test iota "test < test <at> example <dot> com>" "test <unknown>" &&
+ author_test kappa "test@example.com" "test@example.com <unknown>"
+ ) &&
+
+ git clone "hg::$PWD/hgrepo" gitrepo &&
+ git --git-dir=gitrepo/.git log --reverse --format="%an <%ae>" > actual &&
+
+ test_cmp expected actual
+'
+
test_done