summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rwxr-xr-xcontrib/completion/git-completion.bash515
-rw-r--r--contrib/emacs/git-blame.el2
-rw-r--r--contrib/emacs/git.el8
-rwxr-xr-xcontrib/examples/git-commit.sh6
-rwxr-xr-xcontrib/examples/git-merge.sh554
-rwxr-xr-xcontrib/examples/git-remote.perl7
-rwxr-xr-xcontrib/examples/git-svnimport.perl2
-rwxr-xr-xcontrib/examples/git-tag.sh2
-rwxr-xr-xcontrib/fast-import/git-p4103
-rw-r--r--contrib/fast-import/git-p4.txt133
-rwxr-xr-xcontrib/fast-import/import-zips.py72
-rwxr-xr-xcontrib/hg-to-git/hg-to-git.py27
-rw-r--r--contrib/hooks/setgitperms.perl4
-rwxr-xr-xcontrib/stats/packinfo.pl14
-rw-r--r--contrib/thunderbird-patch-inline/README20
-rwxr-xr-xcontrib/thunderbird-patch-inline/appp.sh55
16 files changed, 1273 insertions, 251 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 72f02f208f..554a03ff4f 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -73,26 +73,26 @@ __git_ps1 ()
if [ -n "$g" ]; then
local r
local b
- if [ -d "$g/../.dotest" ]
+ if [ -d "$g/rebase-apply" ]
then
- if test -f "$g/../.dotest/rebasing"
+ if test -f "$g/rebase-apply/rebasing"
then
r="|REBASE"
- elif test -f "$g/../.dotest/applying"
+ elif test -f "$g/rebase-apply/applying"
then
r="|AM"
else
r="|AM/REBASE"
fi
b="$(git symbolic-ref HEAD 2>/dev/null)"
- elif [ -f "$g/.dotest-merge/interactive" ]
+ elif [ -f "$g/rebase-merge/interactive" ]
then
r="|REBASE-i"
- b="$(cat "$g/.dotest-merge/head-name")"
- elif [ -d "$g/.dotest-merge" ]
+ b="$(cat "$g/rebase-merge/head-name")"
+ elif [ -d "$g/rebase-merge" ]
then
r="|REBASE-m"
- b="$(cat "$g/.dotest-merge/head-name")"
+ b="$(cat "$g/rebase-merge/head-name")"
elif [ -f "$g/MERGE_HEAD" ]
then
r="|MERGING"
@@ -271,15 +271,17 @@ __git_merge_strategies ()
echo "$__git_merge_strategylist"
return
fi
- sed -n "/^all_strategies='/{
- s/^all_strategies='//
- s/'//
+ git merge -s help 2>&1 |
+ sed -n -e '/[Aa]vailable strategies are: /,/^$/{
+ s/\.$//
+ s/.*://
+ s/^[ ]*//
+ s/[ ]*$//
p
- q
- }" "$(git --exec-path)/git-merge"
+ }'
}
__git_merge_strategylist=
-__git_merge_strategylist="$(__git_merge_strategies 2>/dev/null)"
+__git_merge_strategylist=$(__git_merge_strategies 2>/dev/null)
__git_complete_file ()
{
@@ -349,10 +351,10 @@ __git_complete_revlist ()
esac
}
-__git_commands ()
+__git_all_commands ()
{
- if [ -n "$__git_commandlist" ]; then
- echo "$__git_commandlist"
+ if [ -n "$__git_all_commandlist" ]; then
+ echo "$__git_all_commandlist"
return
fi
local i IFS=" "$'\n'
@@ -360,13 +362,33 @@ __git_commands ()
do
case $i in
*--*) : helper pattern;;
+ *) echo $i;;
+ esac
+ done
+}
+__git_all_commandlist=
+__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
+
+__git_porcelain_commands ()
+{
+ if [ -n "$__git_porcelain_commandlist" ]; then
+ echo "$__git_porcelain_commandlist"
+ return
+ fi
+ local i IFS=" "$'\n'
+ for i in "help" $(__git_all_commands)
+ do
+ case $i in
+ *--*) : helper pattern;;
applymbox) : ask gittus;;
applypatch) : ask gittus;;
archimport) : import;;
cat-file) : plumbing;;
check-attr) : plumbing;;
check-ref-format) : plumbing;;
+ checkout-index) : plumbing;;
commit-tree) : plumbing;;
+ count-objects) : infrequent;;
cvsexportcommit) : export;;
cvsimport) : import;;
cvsserver) : daemon;;
@@ -375,6 +397,7 @@ __git_commands ()
diff-index) : plumbing;;
diff-tree) : plumbing;;
fast-import) : import;;
+ fast-export) : export;;
fsck-objects) : plumbing;;
fetch-pack) : plumbing;;
fmt-merge-msg) : plumbing;;
@@ -384,6 +407,10 @@ __git_commands ()
index-pack) : plumbing;;
init-db) : deprecated;;
local-fetch) : plumbing;;
+ lost-found) : infrequent;;
+ ls-files) : plumbing;;
+ ls-remote) : plumbing;;
+ ls-tree) : plumbing;;
mailinfo) : plumbing;;
mailsplit) : plumbing;;
merge-*) : plumbing;;
@@ -408,6 +435,7 @@ __git_commands ()
runstatus) : plumbing;;
sh-setup) : internal;;
shell) : daemon;;
+ show-ref) : plumbing;;
send-pack) : plumbing;;
show-index) : plumbing;;
ssh-*) : transport;;
@@ -422,13 +450,15 @@ __git_commands ()
upload-archive) : plumbing;;
upload-pack) : plumbing;;
write-tree) : plumbing;;
+ var) : infrequent;;
+ verify-pack) : infrequent;;
verify-tag) : plumbing;;
*) echo $i;;
esac
done
}
-__git_commandlist=
-__git_commandlist="$(__git_commands 2>/dev/null)"
+__git_porcelain_commandlist=
+__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)"
__git_aliases ()
{
@@ -483,13 +513,13 @@ __git_has_doubledash ()
return 1
}
-__git_whitespacelist="nowarn warn error error-all strip"
+__git_whitespacelist="nowarn warn error error-all fix"
_git_am ()
{
- local cur="${COMP_WORDS[COMP_CWORD]}"
- if [ -d .dotest ]; then
- __gitcomp "--skip --resolved"
+ local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+ if [ -d "$dir"/rebase-apply ]; then
+ __gitcomp "--skip --resolved --abort"
return
fi
case "$cur" in
@@ -543,11 +573,34 @@ _git_add ()
COMPREPLY=()
}
+_git_archive ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --format=*)
+ __gitcomp "$(git archive --list)" "" "${cur##--format=}"
+ return
+ ;;
+ --remote=*)
+ __gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
+ return
+ ;;
+ --*)
+ __gitcomp "
+ --format= --list --verbose
+ --prefix= --remote= --exec=
+ "
+ return
+ ;;
+ esac
+ __git_complete_file
+}
+
_git_bisect ()
{
__git_has_doubledash && return
- local subcommands="start bad good reset visualize replay log"
+ local subcommands="start bad good skip reset visualize replay log run"
local subcommand="$(__git_find_subcommand "$subcommands")"
if [ -z "$subcommand" ]; then
__gitcomp "$subcommands"
@@ -555,7 +608,7 @@ _git_bisect ()
fi
case "$subcommand" in
- bad|good|reset)
+ bad|good|reset|skip)
__gitcomp "$(__git_refs)"
;;
*)
@@ -582,7 +635,7 @@ _git_branch ()
--*)
__gitcomp "
--color --no-color --verbose --abbrev= --no-abbrev
- --track --no-track
+ --track --no-track --contains --merged --no-merged
"
;;
*)
@@ -597,21 +650,12 @@ _git_branch ()
_git_bundle ()
{
- local mycword="$COMP_CWORD"
- case "${COMP_WORDS[0]}" in
- git)
- local cmd="${COMP_WORDS[2]}"
- mycword="$((mycword-1))"
- ;;
- git-bundle*)
- local cmd="${COMP_WORDS[1]}"
- ;;
- esac
- case "$mycword" in
- 1)
+ local cmd="${COMP_WORDS[2]}"
+ case "$COMP_CWORD" in
+ 2)
__gitcomp "create list-heads verify unbundle"
;;
- 2)
+ 3)
# looking for a file
;;
*)
@@ -626,6 +670,8 @@ _git_bundle ()
_git_checkout ()
{
+ __git_has_doubledash && return
+
__gitcomp "$(__git_refs)"
}
@@ -647,6 +693,45 @@ _git_cherry_pick ()
esac
}
+_git_clean ()
+{
+ __git_has_doubledash && return
+
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--dry-run --quiet"
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_clone ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --local
+ --no-hardlinks
+ --shared
+ --reference
+ --quiet
+ --no-checkout
+ --bare
+ --mirror
+ --origin
+ --upload-pack
+ --template=
+ --depth
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_commit ()
{
__git_has_doubledash && return
@@ -656,7 +741,7 @@ _git_commit ()
--*)
__gitcomp "
--all --author= --signoff --verify --no-verify
- --edit --amend --include --only
+ --edit --amend --include --only --interactive
"
return
esac
@@ -665,6 +750,15 @@ _git_commit ()
_git_describe ()
{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --all --tags --contains --abbrev= --candidates=
+ --exact-match --debug --long --match --always
+ "
+ return
+ esac
__gitcomp "$(__git_refs)"
}
@@ -678,7 +772,7 @@ _git_diff ()
__gitcomp "--cached --stat --numstat --shortstat --summary
--patch-with-stat --name-only --name-status --color
--no-color --color-words --no-renames --check
- --full-index --binary --abbrev --diff-filter
+ --full-index --binary --abbrev --diff-filter=
--find-copies-harder --pickaxe-all --pickaxe-regex
--text --ignore-space-at-eol --ignore-space-change
--ignore-all-space --exit-code --quiet --ext-diff
@@ -692,23 +786,13 @@ _git_diff ()
__git_complete_file
}
-_git_diff_tree ()
-{
- __gitcomp "$(__git_refs)"
-}
-
_git_fetch ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-fetch*,1)
- __gitcomp "$(__git_remotes)"
- ;;
- git,2)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- *)
+ else
case "$cur" in
*:*)
local pfx=""
@@ -719,16 +803,10 @@ _git_fetch ()
__gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
;;
*)
- local remote
- case "${COMP_WORDS[0]}" in
- git-fetch) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
- __gitcomp "$(__git_refs2 "$remote")"
+ __gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
;;
esac
- ;;
- esac
+ fi
}
_git_format_patch ()
@@ -767,6 +845,83 @@ _git_gc ()
COMPREPLY=()
}
+_git_grep ()
+{
+ __git_has_doubledash && return
+
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --cached
+ --text --ignore-case --word-regexp --invert-match
+ --full-name
+ --extended-regexp --basic-regexp --fixed-strings
+ --files-with-matches --name-only
+ --files-without-match
+ --count
+ --and --or --not --all-match
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_help ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--all --info --man --web"
+ return
+ ;;
+ esac
+ __gitcomp "$(__git_all_commands)
+ attributes cli core-tutorial cvs-migration
+ diffcore gitk glossary hooks ignore modules
+ repository-layout tutorial tutorial-2
+ "
+}
+
+_git_init ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --shared=*)
+ __gitcomp "
+ false true umask group all world everybody
+ " "" "${cur##--shared=}"
+ return
+ ;;
+ --*)
+ __gitcomp "--quiet --bare --template= --shared --shared="
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_ls_files ()
+{
+ __git_has_doubledash && return
+
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--cached --deleted --modified --others --ignored
+ --stage --directory --no-empty-directory --unmerged
+ --killed --exclude= --exclude-from=
+ --exclude-per-directory= --exclude-standard
+ --error-unmatch --with-tree= --full-name
+ --abbrev --ignored --exclude-per-directory
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_ls_remote ()
{
__gitcomp "$(__git_remotes)"
@@ -809,6 +964,11 @@ _git_log ()
--not --all
--left-right --cherry-pick
--graph
+ --stat --numstat --shortstat
+ --decorate --diff-filter=
+ --color-words --walk-reflogs
+ --parents --children --full-history
+ --merge
"
return
;;
@@ -838,11 +998,42 @@ _git_merge ()
__gitcomp "$(__git_refs)"
}
+_git_mergetool ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --tool=*)
+ __gitcomp "
+ kdiff3 tkdiff meld xxdiff emerge
+ vimdiff gvimdiff ecmerge opendiff
+ " "" "${cur##--tool=}"
+ return
+ ;;
+ --*)
+ __gitcomp "--tool="
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_merge_base ()
{
__gitcomp "$(__git_refs)"
}
+_git_mv ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--dry-run"
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_name_rev ()
{
__gitcomp "--tags --all --stdin"
@@ -852,51 +1043,29 @@ _git_pull ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-pull*,1)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- git,2)
- __gitcomp "$(__git_remotes)"
- ;;
- *)
- local remote
- case "${COMP_WORDS[0]}" in
- git-pull) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
- __gitcomp "$(__git_refs "$remote")"
- ;;
- esac
+ else
+ __gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
+ fi
}
_git_push ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-push*,1)
- __gitcomp "$(__git_remotes)"
- ;;
- git,2)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- *)
+ else
case "$cur" in
*:*)
- local remote
- case "${COMP_WORDS[0]}" in
- git-push) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
-
local pfx=""
case "$COMP_WORDBREAKS" in
*:*) : great ;;
*) pfx="${cur%%:*}:" ;;
esac
- __gitcomp "$(__git_refs "$remote")" "$pfx" "${cur#*:}"
+ __gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
;;
+*)
__gitcomp "$(__git_refs)" + "${cur#+}"
@@ -905,14 +1074,13 @@ _git_push ()
__gitcomp "$(__git_refs)"
;;
esac
- ;;
- esac
+ fi
}
_git_rebase ()
{
local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
- if [ -d .dotest ] || [ -d "$dir"/.dotest-merge ]; then
+ if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
__gitcomp "--continue --skip --abort"
return
fi
@@ -933,6 +1101,24 @@ _git_rebase ()
__gitcomp "$(__git_refs)"
}
+_git_send_email ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
+ --dry-run --envelope-sender --from --identity
+ --in-reply-to --no-chain-reply-to --no-signed-off-by-cc
+ --no-suppress-from --no-thread --quiet
+ --signed-off-by-cc --smtp-pass --smtp-server
+ --smtp-server-port --smtp-ssl --smtp-user --subject
+ --suppress-cc --suppress-from --thread --to"
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_config ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1092,7 +1278,6 @@ _git_config ()
pull.octopus
pull.twohead
repack.useDeltaBaseOffset
- show.difftree
showbranch.default
tar.umask
transfer.unpackLimit
@@ -1101,7 +1286,6 @@ _git_config ()
user.name
user.email
user.signingkey
- whatchanged.difftree
branch. remote.
"
}
@@ -1151,6 +1335,32 @@ _git_reset ()
__gitcomp "$(__git_refs)"
}
+_git_revert ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+ return
+ ;;
+ esac
+ __gitcomp "$(__git_refs)"
+}
+
+_git_rm ()
+{
+ __git_has_doubledash && return
+
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_shortlog ()
{
__git_has_doubledash && return
@@ -1175,6 +1385,8 @@ _git_shortlog ()
_git_show ()
{
+ __git_has_doubledash && return
+
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--pretty=*)
@@ -1191,11 +1403,48 @@ _git_show ()
__git_complete_file
}
+_git_show_branch ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --all --remotes --topo-order --current --more=
+ --list --independent --merge-base --no-name
+ --sha1-name --topics --reflog
+ "
+ return
+ ;;
+ esac
+ __git_complete_revlist
+}
+
_git_stash ()
{
- local subcommands='save list show apply clear drop pop create'
- if [ -z "$(__git_find_subcommand "$subcommands")" ]; then
+ local subcommands='save list show apply clear drop pop create branch'
+ local subcommand="$(__git_find_subcommand "$subcommands")"
+ if [ -z "$subcommand" ]; then
__gitcomp "$subcommands"
+ else
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$subcommand,$cur" in
+ save,--*)
+ __gitcomp "--keep-index"
+ ;;
+ apply,--*)
+ __gitcomp "--index"
+ ;;
+ show,--*|drop,--*|pop,--*|branch,--*)
+ COMPREPLY=()
+ ;;
+ show,*|apply,*|drop,*|pop,*|branch,*)
+ __gitcomp "$(git --git-dir="$(__gitdir)" stash list \
+ | sed -n -e 's/:.*//p')"
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
fi
}
@@ -1317,7 +1566,7 @@ _git_tag ()
-m|-F)
COMPREPLY=()
;;
- -*|tag|git-tag)
+ -*|tag)
if [ $f = 1 ]; then
__gitcomp "$(__git_tags)"
else
@@ -1339,7 +1588,8 @@ _git ()
case "$i" in
--git-dir=*) __git_dir="${i#--git-dir=}" ;;
--bare) __git_dir="." ;;
- --version|--help|-p|--paginate) ;;
+ --version|-p|--paginate) ;;
+ --help) command="help"; break ;;
*) command="$i"; break ;;
esac
c=$((++c))
@@ -1359,7 +1609,7 @@ _git ()
--help
"
;;
- *) __gitcomp "$(__git_commands) $(__git_aliases)" ;;
+ *) __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;;
esac
return
fi
@@ -1371,12 +1621,15 @@ _git ()
am) _git_am ;;
add) _git_add ;;
apply) _git_apply ;;
+ archive) _git_archive ;;
bisect) _git_bisect ;;
bundle) _git_bundle ;;
branch) _git_branch ;;
checkout) _git_checkout ;;
cherry) _git_cherry ;;
cherry-pick) _git_cherry_pick ;;
+ clean) _git_clean ;;
+ clone) _git_clone ;;
commit) _git_commit ;;
config) _git_config ;;
describe) _git_describe ;;
@@ -1384,20 +1637,29 @@ _git ()
fetch) _git_fetch ;;
format-patch) _git_format_patch ;;
gc) _git_gc ;;
+ grep) _git_grep ;;
+ help) _git_help ;;
+ init) _git_init ;;
log) _git_log ;;
+ ls-files) _git_ls_files ;;
ls-remote) _git_ls_remote ;;
ls-tree) _git_ls_tree ;;
merge) _git_merge;;
+ mergetool) _git_mergetool;;
merge-base) _git_merge_base ;;
+ mv) _git_mv ;;
name-rev) _git_name_rev ;;
pull) _git_pull ;;
push) _git_push ;;
rebase) _git_rebase ;;
remote) _git_remote ;;
reset) _git_reset ;;
+ revert) _git_revert ;;
+ rm) _git_rm ;;
+ send-email) _git_send_email ;;
shortlog) _git_shortlog ;;
show) _git_show ;;
- show-branch) _git_log ;;
+ show-branch) _git_show_branch ;;
stash) _git_stash ;;
submodule) _git_submodule ;;
svn) _git_svn ;;
@@ -1428,64 +1690,11 @@ _gitk ()
complete -o default -o nospace -F _git git
complete -o default -o nospace -F _gitk gitk
-complete -o default -o nospace -F _git_am git-am
-complete -o default -o nospace -F _git_apply git-apply
-complete -o default -o nospace -F _git_bisect git-bisect
-complete -o default -o nospace -F _git_branch git-branch
-complete -o default -o nospace -F _git_bundle git-bundle
-complete -o default -o nospace -F _git_checkout git-checkout
-complete -o default -o nospace -F _git_cherry git-cherry
-complete -o default -o nospace -F _git_cherry_pick git-cherry-pick
-complete -o default -o nospace -F _git_commit git-commit
-complete -o default -o nospace -F _git_describe git-describe
-complete -o default -o nospace -F _git_diff git-diff
-complete -o default -o nospace -F _git_fetch git-fetch
-complete -o default -o nospace -F _git_format_patch git-format-patch
-complete -o default -o nospace -F _git_gc git-gc
-complete -o default -o nospace -F _git_log git-log
-complete -o default -o nospace -F _git_ls_remote git-ls-remote
-complete -o default -o nospace -F _git_ls_tree git-ls-tree
-complete -o default -o nospace -F _git_merge git-merge
-complete -o default -o nospace -F _git_merge_base git-merge-base
-complete -o default -o nospace -F _git_name_rev git-name-rev
-complete -o default -o nospace -F _git_pull git-pull
-complete -o default -o nospace -F _git_push git-push
-complete -o default -o nospace -F _git_rebase git-rebase
-complete -o default -o nospace -F _git_config git-config
-complete -o default -o nospace -F _git_remote git-remote
-complete -o default -o nospace -F _git_reset git-reset
-complete -o default -o nospace -F _git_shortlog git-shortlog
-complete -o default -o nospace -F _git_show git-show
-complete -o default -o nospace -F _git_stash git-stash
-complete -o default -o nospace -F _git_submodule git-submodule
-complete -o default -o nospace -F _git_svn git-svn
-complete -o default -o nospace -F _git_log git-show-branch
-complete -o default -o nospace -F _git_tag git-tag
-complete -o default -o nospace -F _git_log git-whatchanged
# The following are necessary only for Cygwin, and only are needed
# when the user has tab-completed the executable name and consequently
# included the '.exe' suffix.
#
if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-complete -o default -o nospace -F _git_add git-add.exe
-complete -o default -o nospace -F _git_apply git-apply.exe
complete -o default -o nospace -F _git git.exe
-complete -o default -o nospace -F _git_branch git-branch.exe
-complete -o default -o nospace -F _git_bundle git-bundle.exe
-complete -o default -o nospace -F _git_cherry git-cherry.exe
-complete -o default -o nospace -F _git_describe git-describe.exe
-complete -o default -o nospace -F _git_diff git-diff.exe
-complete -o default -o nospace -F _git_format_patch git-format-patch.exe
-complete -o default -o nospace -F _git_log git-log.exe
-complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
-complete -o default -o nospace -F _git_merge_base git-merge-base.exe
-complete -o default -o nospace -F _git_name_rev git-name-rev.exe
-complete -o default -o nospace -F _git_push git-push.exe
-complete -o default -o nospace -F _git_config git-config
-complete -o default -o nospace -F _git_shortlog git-shortlog.exe
-complete -o default -o nospace -F _git_show git-show.exe
-complete -o default -o nospace -F _git_log git-show-branch.exe
-complete -o default -o nospace -F _git_tag git-tag.exe
-complete -o default -o nospace -F _git_log git-whatchanged.exe
fi
diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index 9f92cd250b..4fa70c5ad4 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -381,7 +381,7 @@ See also function `git-blame-mode'."
"log" "-1"
(concat "--pretty=" git-blame-log-oneline-format)
hash)
- (buffer-substring (point-min) (1- (point-max)))))
+ (buffer-substring (point-min) (point-max))))
(defvar git-blame-last-identification nil)
(make-variable-buffer-local 'git-blame-last-identification)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 4fa853fae7..c1cf1cbcc0 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1252,8 +1252,8 @@ Return the list of files that haven't been handled."
"\n")
(when subject (insert subject "\n\n"))
(cond (msg (insert msg "\n"))
- ((file-readable-p ".dotest/msg")
- (insert-file-contents ".dotest/msg"))
+ ((file-readable-p ".git/rebase-apply/msg")
+ (insert-file-contents ".git/rebase-apply/msg"))
((file-readable-p ".git/MERGE_MSG")
(insert-file-contents ".git/MERGE_MSG")))
; delete empty lines at end
@@ -1272,9 +1272,9 @@ Return the list of files that haven't been handled."
(coding-system (git-get-commits-coding-system))
author-name author-email subject date)
(when (eq 0 (buffer-size buffer))
- (when (file-readable-p ".dotest/info")
+ (when (file-readable-p ".git/rebase-apply/info")
(with-temp-buffer
- (insert-file-contents ".dotest/info")
+ (insert-file-contents ".git/rebase-apply/info")
(goto-char (point-min))
(when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t)
(setq author-name (match-string 1))
diff --git a/contrib/examples/git-commit.sh b/contrib/examples/git-commit.sh
index 2c4a4062a5..5c72f655c7 100755
--- a/contrib/examples/git-commit.sh
+++ b/contrib/examples/git-commit.sh
@@ -443,7 +443,7 @@ fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
case "$signoff" in
t)
- sign=$(git-var GIT_COMMITTER_IDENT | sed -e '
+ sign=$(git var GIT_COMMITTER_IDENT | sed -e '
s/>.*/>/
s/^/Signed-off-by: /
')
@@ -535,8 +535,8 @@ esac
case "$no_edit" in
'')
- git-var GIT_AUTHOR_IDENT > /dev/null || die
- git-var GIT_COMMITTER_IDENT > /dev/null || die
+ git var GIT_AUTHOR_IDENT > /dev/null || die
+ git var GIT_COMMITTER_IDENT > /dev/null || die
git_editor "$GIT_DIR/COMMIT_EDITMSG"
;;
esac
diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh
new file mode 100755
index 0000000000..e9588eec33
--- /dev/null
+++ b/contrib/examples/git-merge.sh
@@ -0,0 +1,554 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git merge [options] <remote>...
+git merge [options] <msg> HEAD <remote>
+--
+stat show a diffstat at the end of the merge
+n don't show a diffstat at the end of the merge
+summary (synonym to --stat)
+log add list of one-line log to merge commit message
+squash create a single commit instead of doing a merge
+commit perform a commit if the merge succeeds (default)
+ff allow fast forward (default)
+s,strategy= merge strategy to use
+m,message= message to be used for the merge commit (if any)
+"
+
+SUBDIRECTORY_OK=Yes
+. git-sh-setup
+require_work_tree
+cd_to_toplevel
+
+test -z "$(git ls-files -u)" ||
+ die "You are in the middle of a conflicted merge."
+
+LF='
+'
+
+all_strategies='recur recursive octopus resolve stupid ours subtree'
+default_twohead_strategies='recursive'
+default_octopus_strategies='octopus'
+no_fast_forward_strategies='subtree ours'
+no_trivial_strategies='recursive recur subtree ours'
+use_strategies=
+
+allow_fast_forward=t
+allow_trivial_merge=t
+squash= no_commit= log_arg=
+
+dropsave() {
+ rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
+ "$GIT_DIR/MERGE_STASH" || exit 1
+}
+
+savestate() {
+ # Stash away any local modifications.
+ git stash create >"$GIT_DIR/MERGE_STASH"
+}
+
+restorestate() {
+ if test -f "$GIT_DIR/MERGE_STASH"
+ then
+ git reset --hard $head >/dev/null
+ git stash apply $(cat "$GIT_DIR/MERGE_STASH")
+ git update-index --refresh >/dev/null
+ fi
+}
+
+finish_up_to_date () {
+ case "$squash" in
+ t)
+ echo "$1 (nothing to squash)" ;;
+ '')
+ echo "$1" ;;
+ esac
+ dropsave
+}
+
+squash_message () {
+ echo Squashed commit of the following:
+ echo
+ git log --no-merges --pretty=medium ^"$head" $remoteheads
+}
+
+finish () {
+ if test '' = "$2"
+ then
+ rlogm="$GIT_REFLOG_ACTION"
+ else
+ echo "$2"
+ rlogm="$GIT_REFLOG_ACTION: $2"
+ fi
+ case "$squash" in
+ t)
+ echo "Squash commit -- not updating HEAD"
+ squash_message >"$GIT_DIR/SQUASH_MSG"
+ ;;
+ '')
+ case "$merge_msg" in
+ '')
+ echo "No merge message -- not updating HEAD"
+ ;;
+ *)
+ git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
+ git gc --auto
+ ;;
+ esac
+ ;;
+ esac
+ case "$1" in
+ '')
+ ;;
+ ?*)
+ if test "$show_diffstat" = t
+ then
+ # We want color (if set), but no pager
+ GIT_PAGER='' git diff --stat --summary -M "$head" "$1"
+ fi
+ ;;
+ esac
+
+ # Run a post-merge hook
+ if test -x "$GIT_DIR"/hooks/post-merge
+ then
+ case "$squash" in
+ t)
+ "$GIT_DIR"/hooks/post-merge 1
+ ;;
+ '')
+ "$GIT_DIR"/hooks/post-merge 0
+ ;;
+ esac
+ fi
+}
+
+merge_name () {
+ remote="$1"
+ rh=$(git rev-parse --verify "$remote^0" 2>/dev/null) || return
+ bh=$(git show-ref -s --verify "refs/heads/$remote" 2>/dev/null)
+ if test "$rh" = "$bh"
+ then
+ echo "$rh branch '$remote' of ."
+ elif truname=$(expr "$remote" : '\(.*\)~[1-9][0-9]*$') &&
+ git show-ref -q --verify "refs/heads/$truname" 2>/dev/null
+ then
+ echo "$rh branch '$truname' (early part) of ."
+ elif test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD"
+ then
+ sed -e 's/ not-for-merge / /' -e 1q \
+ "$GIT_DIR/FETCH_HEAD"
+ else
+ echo "$rh commit '$remote'"
+ fi
+}
+
+parse_config () {
+ while test $# != 0; do
+ case "$1" in
+ -n|--no-stat|--no-summary)
+ show_diffstat=false ;;
+ --stat|--summary)
+ show_diffstat=t ;;
+ --log|--no-log)
+ log_arg=$1 ;;
+ --squash)
+ test "$allow_fast_forward" = t ||
+ die "You cannot combine --squash with --no-ff."
+ squash=t no_commit=t ;;
+ --no-squash)
+ squash= no_commit= ;;
+ --commit)
+ no_commit= ;;
+ --no-commit)
+ no_commit=t ;;
+ --ff)
+ allow_fast_forward=t ;;
+ --no-ff)
+ test "$squash" != t ||
+ die "You cannot combine --squash with --no-ff."
+ allow_fast_forward=f ;;
+ -s|--strategy)
+ shift
+ case " $all_strategies " in
+ *" $1 "*)
+ use_strategies="$use_strategies$1 " ;;
+ *)
+ die "available strategies are: $all_strategies" ;;
+ esac
+ ;;
+ -m|--message)
+ shift
+ merge_msg="$1"
+ have_message=t
+ ;;
+ --)
+ shift
+ break ;;
+ *) usage ;;
+ esac
+ shift
+ done
+ args_left=$#
+}
+
+test $# != 0 || usage
+
+have_message=
+
+if branch=$(git-symbolic-ref -q HEAD)
+then
+ mergeopts=$(git config "branch.${branch#refs/heads/}.mergeoptions")
+ if test -n "$mergeopts"
+ then
+ parse_config $mergeopts --
+ fi
+fi
+
+parse_config "$@"
+while test $args_left -lt $#; do shift; done
+
+if test -z "$show_diffstat"; then
+ test "$(git config --bool merge.diffstat)" = false && show_diffstat=false
+ test "$(git config --bool merge.stat)" = false && show_diffstat=false
+ test -z "$show_diffstat" && show_diffstat=t
+fi
+
+# This could be traditional "merge <msg> HEAD <commit>..." and the
+# way we can tell it is to see if the second token is HEAD, but some
+# people might have misused the interface and used a committish that
+# is the same as HEAD there instead. Traditional format never would
+# have "-m" so it is an additional safety measure to check for it.
+
+if test -z "$have_message" &&
+ second_token=$(git rev-parse --verify "$2^0" 2>/dev/null) &&
+ head_commit=$(git rev-parse --verify "HEAD" 2>/dev/null) &&
+ test "$second_token" = "$head_commit"
+then
+ merge_msg="$1"
+ shift
+ head_arg="$1"
+ shift
+elif ! git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ # If the merged head is a valid one there is no reason to
+ # forbid "git merge" into a branch yet to be born. We do
+ # the same for "git pull".
+ if test 1 -ne $#
+ then
+ echo >&2 "Can merge only exactly one commit into empty head"
+ exit 1
+ fi
+
+ rh=$(git rev-parse --verify "$1^0") ||
+ die "$1 - not something we can merge"
+
+ git update-ref -m "initial pull" HEAD "$rh" "" &&
+ git read-tree --reset -u HEAD
+ exit
+
+else
+ # We are invoked directly as the first-class UI.
+ head_arg=HEAD
+
+ # All the rest are the commits being merged; prepare
+ # the standard merge summary message to be appended to
+ # the given message. If remote is invalid we will die
+ # later in the common codepath so we discard the error
+ # in this loop.
+ merge_name=$(for remote
+ do
+ merge_name "$remote"
+ done | git fmt-merge-msg $log_arg
+ )
+ merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
+fi
+head=$(git rev-parse --verify "$head_arg"^0) || usage
+
+# All the rest are remote heads
+test "$#" = 0 && usage ;# we need at least one remote head.
+set_reflog_action "merge $*"
+
+remoteheads=
+for remote
+do
+ remotehead=$(git rev-parse --verify "$remote"^0 2>/dev/null) ||
+ die "$remote - not something we can merge"
+ remoteheads="${remoteheads}$remotehead "
+ eval GITHEAD_$remotehead='"$remote"'
+ export GITHEAD_$remotehead
+done
+set x $remoteheads ; shift
+
+case "$use_strategies" in
+'')
+ case "$#" in
+ 1)
+ var="`git config --get pull.twohead`"
+ if test -n "$var"
+ then
+ use_strategies="$var"
+ else
+ use_strategies="$default_twohead_strategies"
+ fi ;;
+ *)
+ var="`git config --get pull.octopus`"
+ if test -n "$var"
+ then
+ use_strategies="$var"
+ else
+ use_strategies="$default_octopus_strategies"
+ fi ;;
+ esac
+ ;;
+esac
+
+for s in $use_strategies
+do
+ for ss in $no_fast_forward_strategies
+ do
+ case " $s " in
+ *" $ss "*)
+ allow_fast_forward=f
+ break
+ ;;
+ esac
+ done
+ for ss in $no_trivial_strategies
+ do
+ case " $s " in
+ *" $ss "*)
+ allow_trivial_merge=f
+ break
+ ;;
+ esac
+ done
+done
+
+case "$#" in
+1)
+ common=$(git merge-base --all $head "$@")
+ ;;
+*)
+ common=$(git show-branch --merge-base $head "$@")
+ ;;
+esac
+echo "$head" >"$GIT_DIR/ORIG_HEAD"
+
+case "$allow_fast_forward,$#,$common,$no_commit" in
+?,*,'',*)
+ # No common ancestors found. We need a real merge.
+ ;;
+?,1,"$1",*)
+ # If head can reach all the merge then we are up to date.
+ # but first the most common case of merging one remote.
+ finish_up_to_date "Already up-to-date."
+ exit 0
+ ;;
+t,1,"$head",*)
+ # Again the most common case of merging one remote.
+ echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $1)"
+ git update-index --refresh 2>/dev/null
+ msg="Fast forward"
+ if test -n "$have_message"
+ then
+ msg="$msg (no commit created; -m option ignored)"
+ fi
+ new_head=$(git rev-parse --verify "$1^0") &&
+ git read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
+ finish "$new_head" "$msg" || exit
+ dropsave
+ exit 0
+ ;;
+?,1,?*"$LF"?*,*)
+ # We are not doing octopus and not fast forward. Need a
+ # real merge.
+ ;;
+?,1,*,)
+ # We are not doing octopus, not fast forward, and have only
+ # one common.
+ git update-index --refresh 2>/dev/null
+ case "$allow_trivial_merge" in
+ t)
+ # See if it is really trivial.
+ git var GIT_COMMITTER_IDENT >/dev/null || exit
+ echo "Trying really trivial in-index merge..."
+ if git read-tree --trivial -m -u -v $common $head "$1" &&
+ result_tree=$(git write-tree)
+ then
+ echo "Wonderful."
+ result_commit=$(
+ printf '%s\n' "$merge_msg" |
+ git commit-tree $result_tree -p HEAD -p "$1"
+ ) || exit
+ finish "$result_commit" "In-index merge"
+ dropsave
+ exit 0
+ fi
+ echo "Nope."
+ esac
+ ;;
+*)
+ # An octopus. If we can reach all the remote we are up to date.
+ up_to_date=t
+ for remote
+ do
+ common_one=$(git merge-base --all $head $remote)
+ if test "$common_one" != "$remote"
+ then
+ up_to_date=f
+ break
+ fi
+ done
+ if test "$up_to_date" = t
+ then
+ finish_up_to_date "Already up-to-date. Yeeah!"
+ exit 0
+ fi
+ ;;
+esac
+
+# We are going to make a new commit.
+git var GIT_COMMITTER_IDENT >/dev/null || exit
+
+# At this point, we need a real merge. No matter what strategy
+# we use, it would operate on the index, possibly affecting the
+# working tree, and when resolved cleanly, have the desired tree
+# in the index -- this means that the index must be in sync with
+# the $head commit. The strategies are responsible to ensure this.
+
+case "$use_strategies" in
+?*' '?*)
+ # Stash away the local changes so that we can try more than one.
+ savestate
+ single_strategy=no
+ ;;
+*)
+ rm -f "$GIT_DIR/MERGE_STASH"
+ single_strategy=yes
+ ;;
+esac
+
+result_tree= best_cnt=-1 best_strategy= wt_strategy=
+merge_was_ok=
+for strategy in $use_strategies
+do
+ test "$wt_strategy" = '' || {
+ echo "Rewinding the tree to pristine..."
+ restorestate
+ }
+ case "$single_strategy" in
+ no)
+ echo "Trying merge strategy $strategy..."
+ ;;
+ esac
+
+ # Remember which strategy left the state in the working tree
+ wt_strategy=$strategy
+
+ git-merge-$strategy $common -- "$head_arg" "$@"
+ exit=$?
+ if test "$no_commit" = t && test "$exit" = 0
+ then
+ merge_was_ok=t
+ exit=1 ;# pretend it left conflicts.
+ fi
+
+ test "$exit" = 0 || {
+
+ # The backend exits with 1 when conflicts are left to be resolved,
+ # with 2 when it does not handle the given merge at all.
+
+ if test "$exit" -eq 1
+ then
+ cnt=`{
+ git diff-files --name-only
+ git ls-files --unmerged
+ } | wc -l`
+ if test $best_cnt -le 0 -o $cnt -le $best_cnt
+ then
+ best_strategy=$strategy
+ best_cnt=$cnt
+ fi
+ fi
+ continue
+ }
+
+ # Automerge succeeded.
+ result_tree=$(git write-tree) && break
+done
+
+# If we have a resulting tree, that means the strategy module
+# auto resolved the merge cleanly.
+if test '' != "$result_tree"
+then
+ if test "$allow_fast_forward" = "t"
+ then
+ parents=$(git show-branch --independent "$head" "$@")
+ else
+ parents=$(git rev-parse "$head" "$@")
+ fi
+ parents=$(echo "$parents" | sed -e 's/^/-p /')
+ result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
+ finish "$result_commit" "Merge made by $wt_strategy."
+ dropsave
+ exit 0
+fi
+
+# Pick the result from the best strategy and have the user fix it up.
+case "$best_strategy" in
+'')
+ restorestate
+ case "$use_strategies" in
+ ?*' '?*)
+ echo >&2 "No merge strategy handled the merge."
+ ;;
+ *)
+ echo >&2 "Merge with strategy $use_strategies failed."
+ ;;
+ esac
+ exit 2
+ ;;
+"$wt_strategy")
+ # We already have its result in the working tree.
+ ;;
+*)
+ echo "Rewinding the tree to pristine..."
+ restorestate
+ echo "Using the $best_strategy to prepare resolving by hand."
+ git-merge-$best_strategy $common -- "$head_arg" "$@"
+ ;;
+esac
+
+if test "$squash" = t
+then
+ finish
+else
+ for remote
+ do
+ echo $remote
+ done >"$GIT_DIR/MERGE_HEAD"
+ printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG"
+fi
+
+if test "$merge_was_ok" = t
+then
+ echo >&2 \
+ "Automatic merge went well; stopped before committing as requested"
+ exit 0
+else
+ {
+ echo '
+Conflicts:
+'
+ git ls-files --unmerged |
+ sed -e 's/^[^ ]* / /' |
+ uniq
+ } >>"$GIT_DIR/MERGE_MSG"
+ git rerere
+ die "Automatic merge failed; fix conflicts and then commit the result."
+fi
diff --git a/contrib/examples/git-remote.perl b/contrib/examples/git-remote.perl
index b30ed734e7..b17952a785 100755
--- a/contrib/examples/git-remote.perl
+++ b/contrib/examples/git-remote.perl
@@ -129,10 +129,7 @@ sub update_ls_remote {
return if (($harder == 0) ||
(($harder == 1) && exists $info->{'LS_REMOTE'}));
- my @ref = map {
- s|^[0-9a-f]{40}\s+refs/heads/||;
- $_;
- } $git->command(qw(ls-remote --heads), $info->{'URL'});
+ my @ref = map { s|refs/heads/||; $_; } keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
$info->{'LS_REMOTE'} = \@ref;
}
@@ -312,7 +309,7 @@ sub update_remote {
}
}
} else {
- print STDERR "Remote group $name does not exists.\n";
+ print STDERR "Remote group $name does not exist.\n";
exit(1);
}
for (@remotes) {
diff --git a/contrib/examples/git-svnimport.perl b/contrib/examples/git-svnimport.perl
index ea8c1b2f60..a13bb6afec 100755
--- a/contrib/examples/git-svnimport.perl
+++ b/contrib/examples/git-svnimport.perl
@@ -933,7 +933,7 @@ while ($to_rev < $opt_l) {
$to_rev = $from_rev + $repack_after;
$to_rev = $opt_l if $opt_l < $to_rev;
print "Fetching from $from_rev to $to_rev ...\n" if $opt_v;
- $svn->{'svn'}->get_log("/",$from_rev,$to_rev,0,1,1,\&commit_all);
+ $svn->{'svn'}->get_log("",$from_rev,$to_rev,0,1,1,\&commit_all);
my $pid = fork();
die "Fork: $!\n" unless defined $pid;
unless($pid) {
diff --git a/contrib/examples/git-tag.sh b/contrib/examples/git-tag.sh
index e9f3a228af..2c15bc955b 100755
--- a/contrib/examples/git-tag.sh
+++ b/contrib/examples/git-tag.sh
@@ -164,7 +164,7 @@ git check-ref-format "tags/$name" ||
object=$(git rev-parse --verify --default HEAD "$@") || exit 1
type=$(git cat-file -t $object) || exit 1
-tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1
+tagger=$(git var GIT_COMMITTER_IDENT) || exit 1
test -n "$username" ||
username=$(git config user.signingkey) ||
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index d8de9f6c25..2b122d3f51 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -16,6 +16,46 @@ from sets import Set;
verbose = False
+
+def p4_build_cmd(cmd):
+ """Build a suitable p4 command line.
+
+ This consolidates building and returning a p4 command line into one
+ location. It means that hooking into the environment, or other configuration
+ can be done more easily.
+ """
+ real_cmd = "%s " % "p4"
+
+ user = gitConfig("git-p4.user")
+ if len(user) > 0:
+ real_cmd += "-u %s " % user
+
+ password = gitConfig("git-p4.password")
+ if len(password) > 0:
+ real_cmd += "-P %s " % password
+
+ port = gitConfig("git-p4.port")
+ if len(port) > 0:
+ real_cmd += "-p %s " % port
+
+ host = gitConfig("git-p4.host")
+ if len(host) > 0:
+ real_cmd += "-h %s " % host
+
+ client = gitConfig("git-p4.client")
+ if len(client) > 0:
+ real_cmd += "-c %s " % client
+
+ real_cmd += "%s" % (cmd)
+ if verbose:
+ print real_cmd
+ return real_cmd
+
+def chdir(dir):
+ if os.name == 'nt':
+ os.environ['PWD']=dir
+ os.chdir(dir)
+
def die(msg):
if verbose:
raise Exception(msg)
@@ -34,6 +74,10 @@ def write_pipe(c, str):
return val
+def p4_write_pipe(c, str):
+ real_cmd = p4_build_cmd(c)
+ return write_pipe(real_cmd, str)
+
def read_pipe(c, ignore_error=False):
if verbose:
sys.stderr.write('Reading pipe: %s\n' % c)
@@ -45,6 +89,9 @@ def read_pipe(c, ignore_error=False):
return val
+def p4_read_pipe(c, ignore_error=False):
+ real_cmd = p4_build_cmd(c)
+ return read_pipe(real_cmd, ignore_error)
def read_pipe_lines(c):
if verbose:
@@ -57,12 +104,22 @@ def read_pipe_lines(c):
return val
+def p4_read_pipe_lines(c):
+ """Specifically invoke p4 on the command supplied. """
+ real_cmd = p4_build_cmd(c)
+ return read_pipe_lines(real_cmd)
+
def system(cmd):
if verbose:
sys.stderr.write("executing %s\n" % cmd)
if os.system(cmd) != 0:
die("command failed: %s" % cmd)
+def p4_system(cmd):
+ """Specifically invoke p4 as the system command. """
+ real_cmd = p4_build_cmd(cmd)
+ return system(real_cmd)
+
def isP4Exec(kind):
"""Determine if a Perforce 'kind' should have execute permission
@@ -84,12 +141,12 @@ def setP4ExecBit(file, mode):
if p4Type[-1] == "+":
p4Type = p4Type[0:-1]
- system("p4 reopen -t %s %s" % (p4Type, file))
+ p4_system("reopen -t %s %s" % (p4Type, file))
def getP4OpenedType(file):
# Returns the perforce file type for the given file.
- result = read_pipe("p4 opened %s" % file)
+ result = p4_read_pipe("opened %s" % file)
match = re.match(".*\((.+)\)\r?$", result)
if match:
return match.group(1)
@@ -145,7 +202,7 @@ def isModeExecChanged(src_mode, dst_mode):
return isModeExec(src_mode) != isModeExec(dst_mode)
def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
- cmd = "p4 -G %s" % cmd
+ cmd = p4_build_cmd("-G %s" % (cmd))
if verbose:
sys.stderr.write("Opening pipe: %s\n" % cmd)
@@ -364,7 +421,7 @@ def originP4BranchesExist():
def p4ChangesForPaths(depotPaths, changeRange):
assert depotPaths
- output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, changeRange)
+ output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange)
for p in depotPaths]))
changes = []
@@ -512,7 +569,7 @@ class P4Submit(Command):
# remove lines in the Files section that show changes to files outside the depot path we're committing into
template = ""
inFilesSection = False
- for line in read_pipe_lines("p4 change -o"):
+ for line in p4_read_pipe_lines("change -o"):
if line.endswith("\r\n"):
line = line[:-2] + "\n"
if inFilesSection:
@@ -547,7 +604,7 @@ class P4Submit(Command):
modifier = diff['status']
path = diff['src']
if modifier == "M":
- system("p4 edit \"%s\"" % path)
+ p4_system("edit \"%s\"" % path)
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
filesToChangeExecBit[path] = diff['dst_mode']
editedFiles.add(path)
@@ -562,8 +619,8 @@ class P4Submit(Command):
filesToAdd.remove(path)
elif modifier == "R":
src, dest = diff['src'], diff['dst']
- system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
- system("p4 edit \"%s\"" % (dest))
+ p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest))
+ p4_system("edit \"%s\"" % (dest))
if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
filesToChangeExecBit[dest] = diff['dst_mode']
os.unlink(dest)
@@ -587,7 +644,7 @@ class P4Submit(Command):
if response == "s":
print "Skipping! Good luck with the next patches..."
for f in editedFiles:
- system("p4 revert \"%s\"" % f);
+ p4_system("revert \"%s\"" % f);
for f in filesToAdd:
system("rm %s" %f)
return
@@ -610,10 +667,10 @@ class P4Submit(Command):
system(applyPatchCmd)
for f in filesToAdd:
- system("p4 add \"%s\"" % f)
+ p4_system("add \"%s\"" % f)
for f in filesToDelete:
- system("p4 revert \"%s\"" % f)
- system("p4 delete \"%s\"" % f)
+ p4_system("revert \"%s\"" % f)
+ p4_system("delete \"%s\"" % f)
# Set/clear executable bits
for f in filesToChangeExecBit.keys():
@@ -629,7 +686,7 @@ class P4Submit(Command):
submitTemplate = self.prepareLogMessage(template, logMessage)
if os.environ.has_key("P4DIFF"):
del(os.environ["P4DIFF"])
- diff = read_pipe("p4 diff -du ...")
+ diff = p4_read_pipe("diff -du ...")
newdiff = ""
for newFile in filesToAdd:
@@ -667,7 +724,7 @@ class P4Submit(Command):
if self.isWindows:
submitTemplate = submitTemplate.replace("\r\n", "\n")
- write_pipe("p4 submit -i", submitTemplate)
+ p4_write_pipe("submit -i", submitTemplate)
else:
fileName = "submit.txt"
file = open(fileName, "w+")
@@ -687,6 +744,10 @@ class P4Submit(Command):
else:
return False
+ allowSubmit = gitConfig("git-p4.allowSubmit")
+ if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
+ die("%s is not in git-p4.allowSubmit" % self.master)
+
[upstream, settings] = findUpstreamBranchPoint()
self.depotPath = settings['depot-paths'][0]
if len(self.origin) == 0:
@@ -708,9 +769,9 @@ class P4Submit(Command):
print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath)
self.oldWorkingDirectory = os.getcwd()
- os.chdir(self.clientPath)
+ chdir(self.clientPath)
print "Syncronizing p4 checkout..."
- system("p4 sync ...")
+ p4_system("sync ...")
self.check()
@@ -728,7 +789,7 @@ class P4Submit(Command):
if len(commits) == 0:
print "All changes applied!"
- os.chdir(self.oldWorkingDirectory)
+ chdir(self.oldWorkingDirectory)
sync = P4Sync()
sync.run([])
@@ -902,7 +963,7 @@ class P4Sync(Command):
if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'):
text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text)
elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'):
- text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text)
+ text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text)
contents[stat['depotFile']] = text
@@ -1395,7 +1456,7 @@ class P4Sync(Command):
if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch):
system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch))
- if self.useClientSpec or gitConfig("p4.useclientspec") == "true":
+ if self.useClientSpec or gitConfig("git-p4.useclientspec") == "true":
self.getClientSpec()
# TODO: should always look at previous commits,
@@ -1666,7 +1727,7 @@ class P4Clone(P4Sync):
print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)
if not os.path.exists(self.cloneDestination):
os.makedirs(self.cloneDestination)
- os.chdir(self.cloneDestination)
+ chdir(self.cloneDestination)
system("git init")
self.gitdir = os.getcwd() + "/.git"
if not P4Sync.run(self, depotPaths):
@@ -1778,7 +1839,7 @@ def main():
if os.path.exists(cmd.gitdir):
cdup = read_pipe("git rev-parse --show-cdup").strip()
if len(cdup) > 0:
- os.chdir(cdup);
+ chdir(cdup);
if not isValidGitDir(cmd.gitdir):
if isValidGitDir(cmd.gitdir + "/.git"):
diff --git a/contrib/fast-import/git-p4.txt b/contrib/fast-import/git-p4.txt
index b16a8384bc..49b335921a 100644
--- a/contrib/fast-import/git-p4.txt
+++ b/contrib/fast-import/git-p4.txt
@@ -3,14 +3,16 @@ git-p4 - Perforce <-> Git converter using git-fast-import
Usage
=====
-git-p4 supports two main modes: Importing from Perforce to a Git repository is
-done using "git-p4 sync" or "git-p4 rebase". Submitting changes from Git back
-to Perforce is done using "git-p4 submit".
+git-p4 can be used in two different ways:
+
+1) To import changes from Perforce to a Git repository, using "git-p4 sync".
+
+2) To submit changes from Git back to Perforce, using "git-p4 submit".
Importing
=========
-You can simply start with
+Simply start with
git-p4 clone //depot/path/project
@@ -18,11 +20,18 @@ or
git-p4 clone //depot/path/project myproject
-This will create an empty git repository in a subdirectory called "project" (or
-"myproject" with the second command), import the head revision from the
-specified perforce path into a git "p4" branch (remotes/p4 actually), create a
-master branch off it and check it out. If you want the entire history (not just
-the head revision) then you can simply append a "@all" to the depot path:
+This will:
+
+1) Create an empty git repository in a subdirectory called "project" (or
+"myproject" with the second command)
+
+2) Import the head revision from the given Perforce path into a git branch
+called "p4" (remotes/p4 actually)
+
+3) Create a master branch based on it and check it out.
+
+If you want the entire history (not just the head revision) then you can simply
+append a "@all" to the depot path:
git-p4 clone //depot/project/main@all myproject
@@ -37,43 +46,40 @@ If you want more control you can also use the git-p4 sync command directly:
This will import the current head revision of the specified depot path into a
"remotes/p4/master" branch of your git repository. You can use the
---branch=mybranch option to use a different branch.
+--branch=mybranch option to import into a different branch.
-If you want to import the entire history of a given depot path just use
+If you want to import the entire history of a given depot path simply use:
git-p4 sync //path/in/depot@all
+
+Note:
+
To achieve optimal compression you may want to run 'git repack -a -d -f' after
a big import. This may take a while.
-Support for Perforce integrations is still work in progress. Don't bother
-trying it unless you want to hack on it :)
-
Incremental Imports
===================
-After an initial import you can easily synchronize your git repository with
-newer changes from the Perforce depot by just calling
+After an initial import you can continue to synchronize your git repository
+with newer changes from the Perforce depot by just calling
git-p4 sync
in your git repository. By default the "remotes/p4/master" branch is updated.
-It is recommended to run 'git repack -a -d -f' from time to time when using
-incremental imports to optimally combine the individual git packs that each
-incremental import creates through the use of git-fast-import.
-
+Advanced Setup
+==============
-A useful setup may be that you have a periodically updated git repository
-somewhere that contains a complete import of a Perforce project. That git
-repository can be used to clone the working repository from and one would
-import from Perforce directly after cloning using git-p4. If the connection to
-the Perforce server is slow and the working repository hasn't been synced for a
-while it may be desirable to fetch changes from the origin git repository using
-the efficient git protocol. git-p4 supports this setup by calling "git fetch origin"
-by default if there is an origin branch. You can disable this using
+Suppose you have a periodically updated git repository somewhere, containing a
+complete import of a Perforce project. This repository can be cloned and used
+with git-p4. When updating the cloned repository with the "sync" command,
+git-p4 will try to fetch changes from the original repository first. The git
+protocol used with this is usually faster than importing from Perforce
+directly.
- git config git-p4.syncFromOrigin false
+This behaviour can be disabled by setting the "git-p4.syncFromOrigin" git
+configuration variable to "false".
Updating
========
@@ -91,7 +97,7 @@ Submitting
==========
git-p4 has support for submitting changes from a git repository back to the
-Perforce depot. This requires a Perforce checkout separate to your git
+Perforce depot. This requires a Perforce checkout separate from your git
repository. To submit all changes that are in the current git branch but not in
the "p4" branch (or "origin" if "p4" doesn't exist) simply call
@@ -109,17 +115,6 @@ continue importing the remaining changes with
git-p4 submit --continue
-After submitting you should sync your perforce import branch ("p4" or "origin")
-from Perforce using git-p4's sync command.
-
-If you have changes in your working directory that you haven't committed into
-git yet but that you want to commit to Perforce directly ("quick fixes") then
-you do not have to go through the intermediate step of creating a git commit
-first but you can just call
-
- git-p4 submit --direct
-
-
Example
=======
@@ -140,6 +135,62 @@ Example
git-p4 rebase
+Configuration parameters
+========================
+
+git-p4.user ($P4USER)
+
+Allows you to specify the username to use to connect to the Perforce repository.
+
+ git config [--global] git-p4.user public
+
+git-p4.password ($P4PASS)
+
+Allows you to specify the password to use to connect to the Perforce repository.
+Warning this password will be visible on the command-line invocation of the p4 binary.
+
+ git config [--global] git-p4.password public1234
+
+git-p4.port ($P4PORT)
+
+Specify the port to be used to contact the Perforce server. As this will be passed
+directly to the p4 binary, it may be in the format host:port as well.
+
+ git config [--global] git-p4.port codes.zimbra.com:2666
+
+git-p4.host ($P4HOST)
+
+Specify the host to contact for a Perforce repository.
+
+ git config [--global] git-p4.host perforce.example.com
+
+git-p4.client ($P4CLIENT)
+
+Specify the client name to use
+
+ git config [--global] git-p4.client public-view
+
+git-p4.allowSubmit
+
+ git config [--global] git-p4.allowSubmit false
+
+git-p4.syncFromOrigin
+
+A useful setup may be that you have a periodically updated git repository
+somewhere that contains a complete import of a Perforce project. That git
+repository can be used to clone the working repository from and one would
+import from Perforce directly after cloning using git-p4. If the connection to
+the Perforce server is slow and the working repository hasn't been synced for a
+while it may be desirable to fetch changes from the origin git repository using
+the efficient git protocol. git-p4 supports this setup by calling "git fetch origin"
+by default if there is an origin branch. You can disable this using:
+
+ git config [--global] git-p4.syncFromOrigin false
+
+git-p4.useclientspec
+
+ git config [--global] git-p4.useclientspec false
+
Implementation Details...
=========================
diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py
new file mode 100755
index 0000000000..c674fa2d1b
--- /dev/null
+++ b/contrib/fast-import/import-zips.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+## zip archive frontend for git-fast-import
+##
+## For example:
+##
+## mkdir project; cd project; git init
+## python import-zips.py *.zip
+## git log --stat import-zips
+
+from os import popen, path
+from sys import argv, exit
+from time import mktime
+from zipfile import ZipFile
+
+if len(argv) < 2:
+ print 'Usage:', argv[0], '<zipfile>...'
+ exit(1)
+
+branch_ref = 'refs/heads/import-zips'
+committer_name = 'Z Ip Creator'
+committer_email = 'zip@example.com'
+
+fast_import = popen('git fast-import --quiet', 'w')
+def printlines(list):
+ for str in list:
+ fast_import.write(str + "\n")
+
+for zipfile in argv[1:]:
+ commit_time = 0
+ next_mark = 1
+ common_prefix = None
+ mark = dict()
+
+ zip = ZipFile(zipfile, 'r')
+ for name in zip.namelist():
+ if name.endswith('/'):
+ continue
+ info = zip.getinfo(name)
+
+ if commit_time < info.date_time:
+ commit_time = info.date_time
+ if common_prefix == None:
+ common_prefix = name[:name.rfind('/') + 1]
+ else:
+ while not name.startswith(common_prefix):
+ common_prefix = name[:name.rfind('/') + 1]
+
+ mark[name] = ':' + str(next_mark)
+ next_mark += 1
+
+ printlines(('blob', 'mark ' + mark[name], \
+ 'data ' + str(info.file_size)))
+ fast_import.write(zip.read(name) + "\n")
+
+ committer = committer_name + ' <' + committer_email + '> %d +0000' % \
+ mktime(commit_time + (0, 0, 0))
+
+ printlines(('commit ' + branch_ref, 'committer ' + committer, \
+ 'data <<EOM', 'Imported from ' + zipfile + '.', 'EOM', \
+ '', 'deleteall'))
+
+ for name in mark.keys():
+ fast_import.write('M 100644 ' + mark[name] + ' ' +
+ name[len(common_prefix):] + "\n")
+
+ printlines(('', 'tag ' + path.basename(zipfile), \
+ 'from ' + branch_ref, 'tagger ' + committer, \
+ 'data <<EOM', 'Package ' + zipfile, 'EOM', ''))
+
+if fast_import.close():
+ exit(1)
diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py
index f68ef725d4..7b03204ed1 100755
--- a/contrib/hg-to-git/hg-to-git.py
+++ b/contrib/hg-to-git/hg-to-git.py
@@ -89,7 +89,7 @@ try:
if o in ('-v', '--verbose'):
verbose = True
if len(args) != 1:
- raise('params')
+ raise Exception('params')
except:
usage()
sys.exit(1)
@@ -106,7 +106,10 @@ if state:
else:
print 'State does not exist, first run'
-tip = os.popen('hg tip --template "{rev}"').read()
+sock = os.popen('hg tip --template "{rev}"')
+tip = sock.read()
+if sock.close():
+ sys.exit(1)
if verbose:
print 'tip is', tip
@@ -149,7 +152,7 @@ for cset in range(1, int(tip) + 1):
if not hgvers.has_key("0"):
print 'creating repository'
- os.system('git-init-db')
+ os.system('git init')
# loop through every hg changeset
for cset in range(int(tip) + 1):
@@ -191,10 +194,10 @@ for cset in range(int(tip) + 1):
if cset != 0:
if hgbranch[str(cset)] == "branch-" + str(cset):
print 'creating new branch', hgbranch[str(cset)]
- os.system('git-checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
+ os.system('git checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
else:
print 'checking out branch', hgbranch[str(cset)]
- os.system('git-checkout %s' % hgbranch[str(cset)])
+ os.system('git checkout %s' % hgbranch[str(cset)])
# merge
if mparent:
@@ -203,7 +206,7 @@ for cset in range(int(tip) + 1):
else:
otherbranch = hgbranch[parent]
print 'merging', otherbranch, 'into', hgbranch[str(cset)]
- os.system(getgitenv(user, date) + 'git-merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
+ os.system(getgitenv(user, date) + 'git merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
# remove everything except .git and .hg directories
os.system('find . \( -path "./.hg" -o -path "./.git" \) -prune -o ! -name "." -print | xargs rm -rf')
@@ -212,9 +215,9 @@ for cset in range(int(tip) + 1):
os.system('hg update -C %d' % cset)
# add new files
- os.system('git-ls-files -x .hg --others | git-update-index --add --stdin')
+ os.system('git ls-files -x .hg --others | git update-index --add --stdin')
# delete removed files
- os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')
+ os.system('git ls-files -x .hg --deleted | git update-index --remove --stdin')
# commit
os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)
@@ -222,20 +225,20 @@ for cset in range(int(tip) + 1):
# tag
if tag and tag != 'tip':
- os.system(getgitenv(user, date) + 'git-tag %s' % tag)
+ os.system(getgitenv(user, date) + 'git tag %s' % tag)
# delete branch if not used anymore...
if mparent and len(hgchildren[str(cset)]):
print "Deleting unused branch:", otherbranch
- os.system('git-branch -d %s' % otherbranch)
+ os.system('git branch -d %s' % otherbranch)
# retrieve and record the version
- vvv = os.popen('git-show --quiet --pretty=format:%H').read()
+ vvv = os.popen('git show --quiet --pretty=format:%H').read()
print 'record', cset, '->', vvv
hgvers[str(cset)] = vvv
if hgnewcsets >= opt_nrepack and opt_nrepack != -1:
- os.system('git-repack -a -d')
+ os.system('git repack -a -d')
# write the state for incrementals
if state:
diff --git a/contrib/hooks/setgitperms.perl b/contrib/hooks/setgitperms.perl
index dab7c8e3a1..a577ad095f 100644
--- a/contrib/hooks/setgitperms.perl
+++ b/contrib/hooks/setgitperms.perl
@@ -50,7 +50,7 @@ if ((@ARGV < 0) || !GetOptions(
)) { die $usage; }
die $usage unless ($read_mode xor $write_mode);
-my $topdir = `git-rev-parse --show-cdup` or die "\n"; chomp $topdir;
+my $topdir = `git rev-parse --show-cdup` or die "\n"; chomp $topdir;
my $gitdir = $topdir . '.git';
my $gitmeta = $topdir . '.gitmeta';
@@ -155,7 +155,7 @@ elsif ($read_mode) {
open (OUT, ">$gitmeta.tmp") or die "Could not open $gitmeta.tmp for writing: $!\n";
}
- my @files = `git-ls-files`;
+ my @files = `git ls-files`;
my %dirs;
foreach my $path (@files) {
diff --git a/contrib/stats/packinfo.pl b/contrib/stats/packinfo.pl
index f4a7b62cd9..be188c0f11 100755
--- a/contrib/stats/packinfo.pl
+++ b/contrib/stats/packinfo.pl
@@ -1,9 +1,9 @@
#!/usr/bin/perl
#
# This tool will print vaguely pretty information about a pack. It
-# expects the output of "git-verify-pack -v" as input on stdin.
+# expects the output of "git verify-pack -v" as input on stdin.
#
-# $ git-verify-pack -v | packinfo.pl
+# $ git verify-pack -v | packinfo.pl
#
# This prints some full-pack statistics; currently "all sizes", "all
# path sizes", "tree sizes", "tree path sizes", and "depths".
@@ -20,7 +20,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree
+# $ git verify-pack -v | packinfo.pl -tree
#
# the trees of objects are output along with the stats. This looks
# like:
@@ -43,7 +43,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree -filenames
+# $ git verify-pack -v | packinfo.pl -tree -filenames
#
# it adds filenames to the tree. Getting this information is slow:
#
@@ -58,7 +58,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -dump
+# $ git verify-pack -v | packinfo.pl -dump
#
# it prints out "sha1 size pathsize depth" for each sha1 in lexical
# order.
@@ -106,7 +106,7 @@ while (<STDIN>) {
}
if ($filenames && ($tree || $dump)) {
- open(NAMES, "git-name-rev --all|");
+ open(NAMES, "git name-rev --all|");
while (<NAMES>) {
if (/^(\S+)\s+(.*)$/) {
my ($sha1, $name) = ($1, $2);
@@ -117,7 +117,7 @@ if ($filenames && ($tree || $dump)) {
for my $commit (@commits) {
my $name = $names{$commit};
- open(TREE, "git-ls-tree -t -r $commit|");
+ open(TREE, "git ls-tree -t -r $commit|");
print STDERR "Plumbing tree $name\n";
while (<TREE>) {
if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
diff --git a/contrib/thunderbird-patch-inline/README b/contrib/thunderbird-patch-inline/README
new file mode 100644
index 0000000000..39f96aa115
--- /dev/null
+++ b/contrib/thunderbird-patch-inline/README
@@ -0,0 +1,20 @@
+appp.sh is a script that is supposed to be used together with ExternalEditor
+for Mozilla Thundebird. It will let you include patches inline in e-mails
+in an easy way.
+
+Usage:
+- Generate the patch with git format-patch.
+- Start writing a new e-mail in Thunderbird.
+- Press the external editor button (or Ctrl-E) to run appp.sh
+- Select the previosly generated patch file.
+- Finish editing the e-mail.
+
+Any text that is entered into the message editor before appp.sh is called
+will be moved to the section between the --- and the diffstat.
+
+All S-O-B:s and Cc:s in the patch will be added to the CC list.
+
+To set it up, just install External Editor and tell it to use appp.sh as the
+editor.
+
+Zenity is a required dependency.
diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh
new file mode 100755
index 0000000000..cc518f3c89
--- /dev/null
+++ b/contrib/thunderbird-patch-inline/appp.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2008 Lukas Sandström <luksan@gmail.com>
+#
+# AppendPatch - A script to be used together with ExternalEditor
+# for Mozilla Thunderbird to properly include pathes inline i e-mails.
+
+# ExternalEditor can be downloaded at http://globs.org/articles.php?lng=en&pg=2
+
+CONFFILE=~/.appprc
+
+SEP="-=-=-=-=-=-=-=-=-=# Don't remove this line #=-=-=-=-=-=-=-=-=-"
+if [ -e "$CONFFILE" ] ; then
+ LAST_DIR=`grep -m 1 "^LAST_DIR=" "${CONFFILE}"|sed -e 's/^LAST_DIR=//'`
+ cd "${LAST_DIR}"
+else
+ cd > /dev/null
+fi
+
+PATCH=$(zenity --file-selection)
+
+if [ "$?" != "0" ] ; then
+ #zenity --error --text "No patchfile given."
+ exit 1
+fi
+
+cd - > /dev/null
+
+SUBJECT=`sed -n -e '/^Subject: /p' "${PATCH}"`
+HEADERS=`sed -e '/^'"${SEP}"'$/,$d' $1`
+BODY=`sed -e "1,/${SEP}/d" $1`
+CMT_MSG=`sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}"`
+DIFF=`sed -e '1,/^---$/d' "${PATCH}"`
+
+CCS=`echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \
+ -e 's/^Signed-off-by: \(.*\)/\1,/gp'`
+
+echo "$SUBJECT" > $1
+echo "Cc: $CCS" >> $1
+echo "$HEADERS" | sed -e '/^Subject: /d' -e '/^Cc: /d' >> $1
+echo "$SEP" >> $1
+
+echo "$CMT_MSG" >> $1
+echo "---" >> $1
+if [ "x${BODY}x" != "xx" ] ; then
+ echo >> $1
+ echo "$BODY" >> $1
+ echo >> $1
+fi
+echo "$DIFF" >> $1
+
+LAST_DIR=`dirname "${PATCH}"`
+
+grep -v "^LAST_DIR=" "${CONFFILE}" > "${CONFFILE}_"
+echo "LAST_DIR=${LAST_DIR}" >> "${CONFFILE}_"
+mv "${CONFFILE}_" "${CONFFILE}"