diff --git a/Documentation/RelNotes-1.6.0.3.txt b/Documentation/RelNotes-1.6.0.3.txt index 46e13a450a..edd5e45c95 100644 --- a/Documentation/RelNotes-1.6.0.3.txt +++ b/Documentation/RelNotes-1.6.0.3.txt @@ -13,33 +13,83 @@ Fixes since v1.6.0.2 * Continuing "git rebase -i" was also very confused when the user left some staged changes in the index after "edit". +* "git rebase -i" now honors the pre-rebase hook, just like the + other rebase implementations "git rebase" and "git rebase -m". + * Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code" with the output redirected to /dev/null. +* "git diff --no-index" on binary files no longer outputs a bogus + "diff --git" header line. + +* Hunk headers in "git diff" default to using extended regular + expressions, fixing some of the internal patterns on non-GNU + platforms. + +* New config "diff.*.xfuncname" exposes extended regular expressions + for user specified hunk header patterns. + * "git stash apply sash@{1}" was fixed to error out. Prior versions would have applied stash@{0} incorrectly. +* "git stash apply" now offers a better suggestion on how to continue + if the working tree is currently dirty. + * "git for-each-ref --format=%(subject)" fixed for commits with no no newline in the message body. * "git remote" fixed to protect printf from user input. +* "git remote show -v" now displays all URLs of a remote. + * "git checkout -q" once again suppresses the locally modified file list. +* "git clone -q", "git fetch -q" asks remote side to not send + progress messages, actually making their output quiet. + * Cross-directory renames are no longer used when creating packs. This allows more graceful behavior on filesystems like sshfs. * Stale temporary files under $GIT_DIR/objects/pack are now cleaned up automatically by "git prune". +* "git merge" once agrain removes directories after the last file has + been removed from it during the merge. + +* "git blame -C -C" no longer segfaults while trying to pass blame if + it encounters a submodule reference. + +* "git svn" fixed to display an error message when 'set-tree' failed, + instead of a Perl compile error. + +* "git submodule" fixed to handle checking out a different commit + than HEAD after initializing the submodule. + +* The "git commit" error message when there are still unmerged + files present was clarified to match "git write-tree". + +* Some segfaults due to uncaught NULL pointers were fixed multiple + tools such as apply, reset, update-index. + +* Solaris bulds now default to OLD_ICONV=1 to avoid compile warnings. + * "Git.pm" tests relied on unnecessarily more recent version of Perl. * "gitweb" triggered undef warning on commits without log messages. +* "gitweb" triggered undef warnings on missing trees. + +* "gitweb" now removes PATH_INFO from its URLs so users don't have + to manually set the url in the gitweb configuration. + +* Bash completion removed support for legacy "git-fetch", "git-push" + and "git-pull" as these are no longer installed. Dashless form + ("git fetch") is still however supported. + Many other documentation updates. -- exec >/var/tmp/1 -O=v1.6.0.2-41-g7fe4a72 +O=v1.6.0.2-76-gd70b4a8 echo O=$(git describe maint) git shortlog --no-merges $O..maint diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 7fefdb1f45..5faaaa5fed 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -130,6 +130,13 @@ parameter, and is invoked after a commit is made. This hook is meant primarily for notification, and cannot affect the outcome of 'git-commit'. +pre-rebase +---------- + +This hook is called by 'git-rebase' and can be used to prevent a branch +from getting rebased. + + post-checkout ----------- diff --git a/builtin-blame.c b/builtin-blame.c index 6b7b9f4466..df537593d0 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -1132,6 +1132,8 @@ static int find_copy_in_parent(struct scoreboard *sb, if (!DIFF_FILE_VALID(p->one)) continue; /* does not exist in parent */ + if (S_ISGITLINK(p->one->mode)) + continue; /* ignore git links */ if (porigin && !strcmp(p->one->path, porigin->path)) /* find_move already dealt with this path */ continue; diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 93f088189e..15073d4c9f 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -785,14 +785,9 @@ _git_fetch () { local cur="${COMP_WORDS[COMP_CWORD]}" - case "${COMP_WORDS[0]},$COMP_CWORD" in - git-fetch*,1) + if [ "$COMP_CWORD" = 2 ]; then __gitcomp "$(__git_remotes)" - ;; - git,2) - __gitcomp "$(__git_remotes)" - ;; - *) + else case "$cur" in *:*) local pfx="" @@ -811,8 +806,7 @@ _git_fetch () __gitcomp "$(__git_refs2 "$remote")" ;; esac - ;; - esac + fi } _git_format_patch () @@ -1049,36 +1043,25 @@ _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)" - ;; - *) + else local remote case "${COMP_WORDS[0]}" in git-pull) remote="${COMP_WORDS[1]}" ;; git) remote="${COMP_WORDS[2]}" ;; esac __gitcomp "$(__git_refs "$remote")" - ;; - esac + fi } _git_push () { local cur="${COMP_WORDS[COMP_CWORD]}" - case "${COMP_WORDS[0]},$COMP_CWORD" in - git-push*,1) + if [ "$COMP_CWORD" = 2 ]; then __gitcomp "$(__git_remotes)" - ;; - git,2) - __gitcomp "$(__git_remotes)" - ;; - *) + else case "$cur" in *:*) local remote @@ -1102,8 +1085,7 @@ _git_push () __gitcomp "$(__git_refs)" ;; esac - ;; - esac + fi } _git_rebase () diff --git a/diff.c b/diff.c index 4e4e439e03..02e948c9dd 100644 --- a/diff.c +++ b/diff.c @@ -1509,6 +1509,10 @@ static void builtin_diff(const char *name_a, b_prefix = o->b_prefix; } + /* Never use a non-valid filename anywhere if at all possible */ + name_a = DIFF_FILE_VALID(one) ? name_a : name_b; + name_b = DIFF_FILE_VALID(two) ? name_b : name_a; + a_one = quote_two(a_prefix, name_a + (*name_a == '/')); b_two = quote_two(b_prefix, name_b + (*name_b == '/')); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index edb6ec6ed0..3350f90cb1 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -65,6 +65,16 @@ output () { esac } +run_pre_rebase_hook () { + if test -x "$GIT_DIR/hooks/pre-rebase" + then + "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { + echo >&2 "The pre-rebase hook refused to rebase." + exit 1 + } + fi +} + require_clean_work_tree () { # test if working tree is dirty git rev-parse --verify HEAD > /dev/null && @@ -507,6 +517,7 @@ first and then run 'git rebase --continue' again." ;; --) shift + run_pre_rebase_hook ${1+"$@"} test $# -eq 1 -o $# -eq 2 || usage test -d "$DOTEST" && die "Interactive rebase already started" diff --git a/git-rebase.sh b/git-rebase.sh index 528b604cd5..a30d40c005 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -144,6 +144,16 @@ is_interactive () { done && test -n "$1" } +run_pre_rebase_hook () { + if test -x "$GIT_DIR/hooks/pre-rebase" + then + "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { + echo >&2 "The pre-rebase hook refused to rebase." + exit 1 + } + fi +} + test -f "$GIT_DIR"/rebase-apply/applying && die 'It looks like git-am is in progress. Cannot rebase.' @@ -320,13 +330,7 @@ onto_name=${newbase-"$upstream_name"} onto=$(git rev-parse --verify "${onto_name}^0") || exit # If a hook exists, give it a chance to interrupt -if test -x "$GIT_DIR/hooks/pre-rebase" -then - "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { - echo >&2 "The pre-rebase hook refused to rebase." - exit 1 - } -fi +run_pre_rebase_hook ${1+"$@"} # If the branch to rebase is given, that is the branch we will rebase # $branch_name -- branch being rebased, or HEAD (already detached) diff --git a/setup.c b/setup.c index 2e3248a0c4..78a8041ff0 100644 --- a/setup.c +++ b/setup.c @@ -110,9 +110,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) if (strncmp(sanitized, work_tree, len) || (sanitized[len] != '\0' && sanitized[len] != '/')) { error_out: - error("'%s' is outside repository", orig); - free(sanitized); - return NULL; + die("'%s' is outside repository", orig); } if (sanitized[len] == '/') len++; @@ -216,10 +214,7 @@ const char **get_pathspec(const char *prefix, const char **pathspec) prefixlen = prefix ? strlen(prefix) : 0; while (*src) { const char *p = prefix_path(prefix, prefixlen, *src); - if (p) - *(dst++) = p; - else - exit(128); /* error message already given */ + *(dst++) = p; src++; } *dst = NULL; diff --git a/t/t3409-rebase-hook.sh b/t/t3409-rebase-hook.sh new file mode 100755 index 0000000000..bc93dda8fd --- /dev/null +++ b/t/t3409-rebase-hook.sh @@ -0,0 +1,126 @@ +#!/bin/sh + +test_description='git rebase with its hook(s)' + +. ./test-lib.sh + +test_expect_success setup ' + echo hello >file && + git add file && + test_tick && + git commit -m initial && + echo goodbye >file && + git add file && + test_tick && + git commit -m second && + git checkout -b side HEAD^ && + echo world >git && + git add git && + test_tick && + git commit -m side && + git checkout master && + git log --pretty=oneline --abbrev-commit --graph --all && + git branch test side +' + +test_expect_success 'rebase' ' + git checkout test && + git reset --hard side && + git rebase master && + test "z$(cat git)" = zworld +' + +test_expect_success 'rebase -i' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master && + test "z$(cat git)" = zworld +' + +test_expect_success 'setup pre-rebase hook' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <.git/PRE-REBASE-INPUT +EOF + chmod +x .git/hooks/pre-rebase +' + +test_expect_success 'pre-rebase hook gets correct input (1)' ' + git checkout test && + git reset --hard side && + git rebase master && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster, + +' + +test_expect_success 'pre-rebase hook gets correct input (2)' ' + git checkout test && + git reset --hard side && + git rebase master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (3)' ' + git checkout test && + git reset --hard side && + git checkout master && + git rebase master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (4)' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster, + +' + +test_expect_success 'pre-rebase hook gets correct input (5)' ' + git checkout test && + git reset --hard side && + EDITOR=true git rebase -i master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'pre-rebase hook gets correct input (6)' ' + git checkout test && + git reset --hard side && + git checkout master && + EDITOR=true git rebase -i master test && + test "z$(cat git)" = zworld && + test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test +' + +test_expect_success 'setup pre-rebase hook that fails' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <binary && + (:# hide error code from diff, which just indicates differences + git diff --binary --no-index /dev/null binary >current || + true + ) && + rm binary && + git apply --binary expected && + nul_to_q actual && + test_cmp expected actual +' + test_done diff --git a/transport.c b/transport.c index f7db5d9110..5110c56c4e 100644 --- a/transport.c +++ b/transport.c @@ -643,8 +643,8 @@ static int fetch_refs_via_pack(struct transport *transport, args.use_thin_pack = data->thin; args.include_tag = data->followtags; args.verbose = (transport->verbose > 0); - args.quiet = args.no_progress = (transport->verbose < 0); - args.no_progress = !isatty(1); + args.quiet = (transport->verbose < 0); + args.no_progress = args.quiet || !isatty(1); args.depth = data->depth; for (i = 0; i < nr_heads; i++)