diff options
author | Junio C Hamano <junkio@cox.net> | 2007-03-23 17:38:22 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-03-23 23:38:04 -0700 |
commit | 1c2c6112a4bf655faa768ddfca067945edf2809e (patch) | |
tree | 985973c2d5ac3611db6e25f702eecacf7cb41939 | |
parent | bab36bf57d7a565e0077e1f5d2e3a10afa319ecc (diff) | |
parent | b08bbae7e1676e5a47fa9054e268ff14ee819a3a (diff) | |
download | git-1c2c6112a4bf655faa768ddfca067945edf2809e.tar.gz git-1c2c6112a4bf655faa768ddfca067945edf2809e.tar.xz |
Merge branch 'master' into jc/bisect
This is to merge in the fix for path-limited bisection
from the 'master' branch.
-rw-r--r-- | Documentation/git-am.txt | 2 | ||||
-rw-r--r-- | Documentation/git-bisect.txt | 130 | ||||
-rw-r--r-- | Documentation/technical/pack-format.txt | 10 | ||||
-rw-r--r-- | builtin-apply.c | 17 | ||||
-rw-r--r-- | builtin-rev-list.c | 4 | ||||
-rwxr-xr-x | git-bisect.sh | 62 | ||||
-rwxr-xr-x | git-checkout.sh | 12 | ||||
-rwxr-xr-x | git-merge.sh | 4 | ||||
-rwxr-xr-x | git-rebase.sh | 8 | ||||
-rwxr-xr-x | gitk | 4 | ||||
-rwxr-xr-x | gitweb/gitweb.perl | 2 | ||||
-rw-r--r-- | refs.c | 21 | ||||
-rwxr-xr-x | t/t4118-apply-empty-context.sh | 3 | ||||
-rwxr-xr-x | t/t6030-bisect-run.sh | 57 | ||||
-rw-r--r-- | templates/hooks--update | 6 |
15 files changed, 274 insertions, 68 deletions
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 4fb1d8441..13a738986 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -70,7 +70,7 @@ default. You could use `--no-utf8` to override this. the patch. -C<n>, -p<n>:: - These flag are passed to the `git-apply` program that applies + These flags are passed to the `git-apply` program that applies the patch. --interactive:: diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 16ec7269b..b2bc58d85 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -12,8 +12,8 @@ SYNOPSIS DESCRIPTION ----------- -The command takes various subcommands, and different options -depending on the subcommand: +The command takes various subcommands, and different options depending +on the subcommand: git bisect start [<paths>...] git bisect bad <rev> @@ -22,30 +22,34 @@ depending on the subcommand: git bisect visualize git bisect replay <logfile> git bisect log + git bisect run <cmd>... -This command uses 'git-rev-list --bisect' option to help drive -the binary search process to find which change introduced a bug, -given an old "good" commit object name and a later "bad" commit -object name. +This command uses 'git-rev-list --bisect' option to help drive the +binary search process to find which change introduced a bug, given an +old "good" commit object name and a later "bad" commit object name. + +Basic bisect commands: start, bad, good +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The way you use it is: ------------------------------------------------ $ git bisect start -$ git bisect bad # Current version is bad -$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version - # tested that was good +$ git bisect bad # Current version is bad +$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version + # tested that was good ------------------------------------------------ -When you give at least one bad and one good versions, it will -bisect the revision tree and say something like: +When you give at least one bad and one good versions, it will bisect +the revision tree and say something like: ------------------------------------------------ Bisecting: 675 revisions left to test after this ------------------------------------------------ -and check out the state in the middle. Now, compile that kernel, and boot -it. Now, let's say that this booted kernel works fine, then just do +and check out the state in the middle. Now, compile that kernel, and +boot it. Now, let's say that this booted kernel works fine, then just +do ------------------------------------------------ $ git bisect good # this one is good @@ -57,12 +61,15 @@ which will now say Bisecting: 337 revisions left to test after this ------------------------------------------------ -and you continue along, compiling that one, testing it, and depending on -whether it is good or bad, you say "git bisect good" or "git bisect bad", -and ask for the next bisection. +and you continue along, compiling that one, testing it, and depending +on whether it is good or bad, you say "git bisect good" or "git bisect +bad", and ask for the next bisection. + +Until you have no more left, and you'll have been left with the first +bad kernel rev in "refs/bisect/bad". -Until you have no more left, and you'll have been left with the first bad -kernel rev in "refs/bisect/bad". +Bisect reset +~~~~~~~~~~~~ Oh, and then after you want to reset to the original head, do a @@ -70,10 +77,13 @@ Oh, and then after you want to reset to the original head, do a $ git bisect reset ------------------------------------------------ -to get back to the master branch, instead of being in one of the bisection -branches ("git bisect start" will do that for you too, actually: it will -reset the bisection state, and before it does that it checks that you're -not using some old bisection branch). +to get back to the master branch, instead of being in one of the +bisection branches ("git bisect start" will do that for you too, +actually: it will reset the bisection state, and before it does that +it checks that you're not using some old bisection branch). + +Bisect visualize +~~~~~~~~~~~~~~~~ During the bisection process, you can say @@ -83,9 +93,17 @@ $ git bisect visualize to see the currently remaining suspects in `gitk`. -The good/bad input is logged, and `git bisect -log` shows what you have done so far. You can truncate its -output somewhere and save it in a file, and run +Bisect log and bisect replay +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The good/bad input is logged, and + +------------ +$ git bisect log +------------ + +shows what you have done so far. You can truncate its output somewhere +and save it in a file, and run ------------ $ git bisect replay that-file @@ -94,12 +112,16 @@ $ git bisect replay that-file if you find later you made a mistake telling good/bad about a revision. -If in a middle of bisect session, you know what the bisect -suggested to try next is not a good one to test (e.g. the change -the commit introduces is known not to work in your environment -and you know it does not have anything to do with the bug you -are chasing), you may want to find a near-by commit and try that -instead. It goes something like this: +Avoiding to test a commit +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If in a middle of bisect session, you know what the bisect suggested +to try next is not a good one to test (e.g. the change the commit +introduces is known not to work in your environment and you know it +does not have anything to do with the bug you are chasing), you may +want to find a near-by commit and try that instead. + +It goes something like this: ------------ $ git bisect good/bad # previous round was good/bad. @@ -109,18 +131,52 @@ $ git reset --hard HEAD~3 # try 3 revs before what # was suggested ------------ -Then compile and test the one you chose to try. After that, -tell bisect what the result was as usual. +Then compile and test the one you chose to try. After that, tell +bisect what the result was as usual. -You can further cut down the number of trials if you know what -part of the tree is involved in the problem you are tracking -down, by giving paths parameters when you say `bisect start`, -like this: +Cutting down bisection by giving path parameter to bisect start +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can further cut down the number of trials if you know what part of +the tree is involved in the problem you are tracking down, by giving +paths parameters when you say `bisect start`, like this: ------------ $ git bisect start arch/i386 include/asm-i386 ------------ +Bisect run +~~~~~~~~~~ + +If you have a script that can tell if the current source code is good +or bad, you can automatically bisect using: + +------------ +$ git bisect run my_script +------------ + +Note that the "run" script (`my_script` in the above example) should +exit with code 0 in case the current source code is good and with a +code between 1 and 127 (included) in case the current source code is +bad. + +Any other exit code will abort the automatic bisect process. (A +program that does "exit(-1)" leaves $? = 255, see exit(3) manual page, +the value is chopped with "& 0377".) + +You may often find that during bisect you want to have near-constant +tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or +"revision that does not have this commit needs this patch applied to +work around other problem this bisection is not interested in") +applied to the revision being tested. + +To cope with such a situation, after the inner git-bisect finds the +next revision to test, with the "run" script, you can apply that tweak +before compiling, run the real test, and after the test decides if the +revision (possibly with the needed tweaks) passed the test, rewind the +tree to the pristine state. Finally the "run" script can exit with +the status of the real test to let "git bisect run" command loop to +know the outcome. Author ------ diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index 0e1ffb242..9ce3c473a 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -21,11 +21,11 @@ GIT pack format which looks like this: (undeltified representation) - n-byte type and length (4-bit type, (n-1)*7+4-bit length) + n-byte type and length (3-bit type, (n-1)*7+4-bit length) compressed data (deltified representation) - n-byte type and length (4-bit type, (n-1)*7+4-bit length) + n-byte type and length (3-bit type, (n-1)*7+4-bit length) 20-byte base object name compressed delta data @@ -102,11 +102,13 @@ trailer | | packfile checksum | Pack file entry: <+ packed object header: - 1-byte type (upper 4-bit) + 1-byte size extension bit (MSB) + type (next 3 bit) size0 (lower 4-bit) n-byte sizeN (as long as MSB is set, each 7-bit) size0..sizeN form 4+7+7+..+7 bit integer, size0 - is the most significant part. + is the least significant part, and sizeN is the + most significant part. packed object data: If it is not DELTA, then deflated bytes (the size above is the size before compression). diff --git a/builtin-apply.c b/builtin-apply.c index dfa171679..27a182bfa 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2355,7 +2355,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { - int fd; + int fd, converted; char *nbuf; unsigned long nsize; @@ -2364,17 +2364,18 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, * terminated. */ return symlink(buf, path); + + fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666); + if (fd < 0) + return -1; + nsize = size; nbuf = (char *) buf; - if (convert_to_working_tree(path, &nbuf, &nsize)) { - free((char *) buf); + converted = convert_to_working_tree(path, &nbuf, &nsize); + if (converted) { buf = nbuf; size = nsize; } - - fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666); - if (fd < 0) - return -1; while (size) { int written = xwrite(fd, buf, size); if (written < 0) @@ -2386,6 +2387,8 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, } if (close(fd) < 0) die("closing file %s: %s", path, strerror(errno)); + if (converted) + free(nbuf); return 0; } diff --git a/builtin-rev-list.c b/builtin-rev-list.c index b395ffeb0..09e3a60bf 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -182,9 +182,9 @@ static struct commit_list *find_bisection(struct commit_list *list, nr++; p = p->next; } - *all = nr; - closest = 0; + closest = -1; best = list; + *all = nr; for (p = list; p; p = p->next) { int distance, reach; diff --git a/git-bisect.sh b/git-bisect.sh index b1c3a6b1c..936b4a4b8 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -1,14 +1,15 @@ #!/bin/sh -USAGE='[start|bad|good|next|reset|visualize|replay|log]' +USAGE='[start|bad|good|next|reset|visualize|replay|log|run]' LONG_USAGE='git bisect start [<pathspec>] reset bisect state and start bisection. git bisect bad [<rev>] mark <rev> a known-bad revision. git bisect good [<rev>...] mark <rev>... known-good revisions. git bisect next find next bisection to test and check it out. git bisect reset [<branch>] finish bisection search and go back to branch. git bisect visualize show bisect status in gitk. -git bisect replay <logfile> replay bisection log -git bisect log show bisect log.' +git bisect replay <logfile> replay bisection log. +git bisect log show bisect log. +git bisect run <cmd>... use <cmd>... to automatically bisect.' . git-sh-setup require_work_tree @@ -49,7 +50,7 @@ bisect_start() { head=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD) || die "Bad HEAD - I need a symbolic ref" case "$head" in - refs/heads/bisect*) + refs/heads/bisect) if [ -s "$GIT_DIR/head-name" ]; then branch=`cat "$GIT_DIR/head-name"` else @@ -85,7 +86,7 @@ bisect_bad() { 0) rev=$(git-rev-parse --verify HEAD) ;; 1) - rev=$(git-rev-parse --verify "$1") ;; + rev=$(git-rev-parse --verify "$1^{commit}") ;; *) usage ;; esac || exit @@ -104,7 +105,7 @@ bisect_good() { esac for rev in $revs do - rev=$(git-rev-parse --verify "$rev") || exit + rev=$(git-rev-parse --verify "$rev^{commit}") || exit echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" echo "# good: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" @@ -140,7 +141,7 @@ bisect_next() { bad=$(git-rev-parse --verify refs/bisect/bad) && good=$(git-rev-parse --sq --revs-only --not \ $(cd "$GIT_DIR" && ls refs/bisect/good-*)) && - rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit + rev=$(eval "git-rev-list --bisect $good $bad -- $(cat "$GIT_DIR/BISECT_NAMES")") || exit if [ -z "$rev" ]; then echo "$bad was both good and bad" exit 1 @@ -185,6 +186,7 @@ bisect_reset() { rm -f "$GIT_DIR/refs/heads/bisect" "$GIT_DIR/head-name" rm -f "$GIT_DIR/BISECT_LOG" rm -f "$GIT_DIR/BISECT_NAMES" + rm -f "$GIT_DIR/BISECT_RUN" fi } @@ -220,6 +222,50 @@ bisect_replay () { bisect_auto_next } +bisect_run () { + while true + do + echo "running $@" + "$@" + res=$? + + # Check for really bad run error. + if [ $res -lt 0 -o $res -ge 128 ]; then + echo >&2 "bisect run failed:" + echo >&2 "exit code $res from '$@' is < 0 or >= 128" + exit $res + fi + + # Use "bisect_good" or "bisect_bad" + # depending on run success or failure. + if [ $res -gt 0 ]; then + next_bisect='bisect_bad' + else + next_bisect='bisect_good' + fi + + # We have to use a subshell because bisect_good or + # bisect_bad functions can exit. + ( $next_bisect > "$GIT_DIR/BISECT_RUN" ) + res=$? + + cat "$GIT_DIR/BISECT_RUN" + + if [ $res -ne 0 ]; then + echo >&2 "bisect run failed:" + echo >&2 "$next_bisect exited with error code $res" + exit $res + fi + + if grep "is first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then + echo "bisect run success" + exit 0; + fi + + done +} + + case "$#" in 0) usage ;; @@ -244,6 +290,8 @@ case "$#" in bisect_replay "$@" ;; log) cat "$GIT_DIR/BISECT_LOG" ;; + run) + bisect_run "$@" ;; *) usage ;; esac diff --git a/git-checkout.sh b/git-checkout.sh index 3c9b1bb05..a7390e808 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -163,6 +163,13 @@ cd_to_toplevel detached= detach_warn= +describe_detached_head () { + test -n "$quiet" || { + printf >&2 "$1 " + GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" + } +} + if test -z "$branch$newbranch" && test "$new" != "$old" then detached="$new" @@ -173,9 +180,9 @@ If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new_branch_name>" fi -elif test -z "$oldbranch" && test -z "$quiet" +elif test -z "$oldbranch" then - echo >&2 "Previous HEAD position was $old" + describe_detached_head 'Previous HEAD position was' "$old" fi if [ "X$old" = X ] @@ -275,6 +282,7 @@ if [ "$?" -eq 0 ]; then then echo >&2 "$detach_warn" fi + describe_detached_head 'HEAD is now at' HEAD fi rm -f "$GIT_DIR/MERGE_HEAD" else diff --git a/git-merge.sh b/git-merge.sh index 8759c5a7e..fa4589173 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -108,6 +108,10 @@ merge_name () { 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 diff --git a/git-rebase.sh b/git-rebase.sh index b51d19d12..aadd580f8 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -265,6 +265,10 @@ upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || die "invalid upstream $upstream_name" +# Make sure the branch to rebase onto is valid. +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 @@ -291,10 +295,6 @@ case "$#" in esac branch=$(git-rev-parse --verify "${branch_name}^0") || exit -# Make sure the branch to rebase onto is valid. -onto_name=${newbase-"$upstream_name"} -onto=$(git-rev-parse --verify "${onto_name}^0") || exit - # Now we are rebasing commits $upstream..$branch on top of $onto # Check if we are already based on $onto, but this should be @@ -1906,7 +1906,7 @@ proc do_file_hl {serial} { } else { set gdtargs [list "-S$highlight_files"] } - set cmd [concat | git-diff-tree -r -s --stdin $gdtargs] + set cmd [concat | git diff-tree -r -s --stdin $gdtargs] set filehighlight [open $cmd r+] fconfigure $filehighlight -blocking 0 fileevent $filehighlight readable readfhighlight @@ -1958,7 +1958,7 @@ proc readfhighlight {} { } if {[eof $filehighlight]} { # strange... - puts "oops, git-diff-tree died" + puts "oops, git diff-tree died" catch {close $filehighlight} unset filehighlight } diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 27b5970bc..5214050a8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3719,7 +3719,7 @@ sub git_commit { $formats_nav .= '(merge: ' . join(' ', map { - $cgi->a({-href => href(action=>"commitdiff", + $cgi->a({-href => href(action=>"commit", hash=>$_)}, esc_html(substr($_, 0, 7))); } @$parents ) . @@ -980,6 +980,27 @@ int write_ref_sha1(struct ref_lock *lock, unlock_ref(lock); return -1; } + if (strcmp(lock->orig_ref_name, "HEAD") != 0) { + /* + * Special hack: If a branch is updated directly and HEAD + * points to it (may happen on the remote side of a push + * for example) then logically the HEAD reflog should be + * updated too. + * A generic solution implies reverse symref information, + * but finding all symrefs pointing to the given branch + * would be rather costly for this rare event (the direct + * update of a branch) to be worth it. So let's cheat and + * check with HEAD only which should cover 99% of all usage + * scenarios (even 100% of the default ones). + */ + unsigned char head_sha1[20]; + int head_flag; + const char *head_ref; + head_ref = resolve_ref("HEAD", head_sha1, 1, &head_flag); + if (head_ref && (head_flag & REF_ISSYMREF) && + !strcmp(head_ref, lock->ref_name)) + log_ref_write("HEAD", lock->old_sha1, sha1, logmsg); + } if (commit_lock_file(lock->lk)) { error("Couldn't set %s", lock->ref_name); unlock_ref(lock); diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 690a18200..27cc6f2b8 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -23,7 +23,8 @@ test_expect_success setup ' cat file2 >file2.orig git add file1 file2 && sed -e "/^B/d" <file1.orig >file1 && - sed -e "/^B/d" <file2.orig >file2 && + sed -e "/^[BQ]/d" <file2.orig >file2 && + echo Q | tr -d "\\012" >>file2 && cat file1 >file1.mods && cat file2 >file2.mods && git diff | diff --git a/t/t6030-bisect-run.sh b/t/t6030-bisect-run.sh new file mode 100755 index 000000000..39c72283b --- /dev/null +++ b/t/t6030-bisect-run.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2007 Christian Couder +# +test_description='Tests git-bisect run functionality' + +. ./test-lib.sh + +add_line_into_file() +{ + _line=$1 + _file=$2 + + if [ -f "$_file" ]; then + echo "$_line" >> $_file || return $? + MSG="Add <$_line> into <$_file>." + else + echo "$_line" > $_file || return $? + git add $_file || return $? + MSG="Create file <$_file> with <$_line> inside." + fi + + git-commit -m "$MSG" $_file +} + +HASH1= +HASH3= +HASH4= + +test_expect_success \ + 'set up basic repo with 1 file (hello) and 4 commits' \ + 'add_line_into_file "1: Hello World" hello && + add_line_into_file "2: A new day for git" hello && + add_line_into_file "3: Another new day for git" hello && + add_line_into_file "4: Ciao for now" hello && + HASH1=$(git rev-list HEAD | tail -1) && + HASH3=$(git rev-list HEAD | head -2 | tail -1) && + HASH4=$(git rev-list HEAD | head -1)' + +# We want to automatically find the commit that +# introduced "Another" into hello. +test_expect_success \ + 'git bisect run simple case' \ + 'echo "#!/bin/sh" > test_script.sh && + echo "grep Another hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH3 is first bad commit" my_bisect_log.txt' + +# +# +test_done + diff --git a/templates/hooks--update b/templates/hooks--update index 8f6c4fea2..1a6077389 100644 --- a/templates/hooks--update +++ b/templates/hooks--update @@ -56,6 +56,12 @@ recipients=$(git-repo-config hooks.mailinglist) announcerecipients=$(git-repo-config hooks.announcelist) allowunannotated=$(git-repo-config --bool hooks.allowunannotated) +# check for no description +if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb" ]; then + echo "*** Project description file hasn't been set" >&2 + exit 1 +fi + # --- Check types newrev_type=$(git-cat-file -t $newrev) |