{"thread":{"id":"7362","subject":"[PATCH] Bisect: implement \"git bisect run <cmd>...\" to automatically bisect.","startedAt":"2007-03-23T07:49:59Z","lastAt":"2007-03-23T07:49:59Z","messageCount":1,"participants":["Christian Couder"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"37787","messageId":"20070323084959.d6321f53.chriscool@tuxfamily.org","threadId":"7362","inReplyTo":null,"subject":"[PATCH] Bisect: implement \"git bisect run <cmd>...\" to automatically bisect.","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2007-03-23T07:49:59Z","receivedAt":"2007-03-23T07:49:59Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This idea was suggested by Bill Lear\n(Message-ID: <17920.38942.364466.642979@lisa.zopyra.com>)\nand I think it is a very good one.\n\nThis patch adds a new test file for \"git bisect run\", but there\nis currently only one basic test.\n\nThanks to Junio for the documentation and suggestions\n(Message-ID: <7vejnhwy0y.fsf@assigned-by-dhcp.cox.net>).\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n Documentation/git-bisect.txt |   29 +++++++++++++++++++++\n git-bisect.sh                |   54 +++++++++++++++++++++++++++++++++++++--\n t/t6030-bisect-run.sh        |   57 ++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 137 insertions(+), 3 deletions(-)\n create mode 100755 t/t6030-bisect-run.sh\n\ndiff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt\nindex 16ec726..36d690e 100644\n--- a/Documentation/git-bisect.txt\n+++ b/Documentation/git-bisect.txt\n@@ -22,6 +22,7 @@ depending on the subcommand:\n  git bisect visualize\n  git bisect replay <logfile>\n  git bisect log\n+ git bisect run <cmd>...\n \n This command uses 'git-rev-list --bisect' option to help drive\n the binary search process to find which change introduced a bug,\n@@ -121,6 +122,34 @@ like this:\n $ git bisect start arch/i386 include/asm-i386\n ------------\n \n+If you have a script or a shell command that can tell if the current\n+source code is good or bad, you can automatically bisect using:\n+\n+------------\n+$ git bisect run my_script_or_shell_command\n+------------\n+\n+Note that the \"run\" script or shell command should exit with code 0 in\n+case the current source code is good and with a code between 1 and 127\n+(included) in case the current source code is bad.\n+\n+Any other exit code (a program that does \"exit(-1)\" leaves $? = 255,\n+see exit(3) manual page, the value is chopped with \"& 0377\") will\n+abort the automatic bisect process.\n+\n+You may often find that during bisect you want to have near-constant\n+tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or\n+\"revision that does not have this commit needs this patch applied to\n+work around other problem this bisection is not interested in\")\n+applied to the revision being tested.\n+\n+To cope with such a situation, after the inner git-bisect finds the\n+next revision to test, with the \"run\" script, you can apply that tweak\n+before compiling, run the real test, and after the test decides if the\n+revision (possibly with the needed tweaks) passed the test, rewind the\n+tree to the pristine state.  Finally the \"run\" script can exit with\n+the status of the real test to let \"git bisect run\" command loop to\n+know the outcome.\n \n Author\n ------\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex b1c3a6b..baf2ad5 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -1,14 +1,15 @@\n #!/bin/sh\n \n-USAGE='[start|bad|good|next|reset|visualize|replay|log]'\n+USAGE='[start|bad|good|next|reset|visualize|replay|log|run]'\n LONG_USAGE='git bisect start [<pathspec>]\treset bisect state and start bisection.\n git bisect bad [<rev>]\t\tmark <rev> a known-bad revision.\n git bisect good [<rev>...]\tmark <rev>... known-good revisions.\n git bisect next\t\t\tfind next bisection to test and check it out.\n git bisect reset [<branch>]\tfinish bisection search and go back to branch.\n git bisect visualize            show bisect status in gitk.\n-git bisect replay <logfile>\treplay bisection log\n-git bisect log\t\t\tshow bisect log.'\n+git bisect replay <logfile>\treplay bisection log.\n+git bisect log\t\t\tshow bisect log.\n+git bisect run <cmd>... \tuse <cmd>... to automatically bisect.'\n \n . git-sh-setup\n require_work_tree\n@@ -185,6 +186,7 @@ bisect_reset() {\n \t\trm -f \"$GIT_DIR/refs/heads/bisect\" \"$GIT_DIR/head-name\"\n \t\trm -f \"$GIT_DIR/BISECT_LOG\"\n \t\trm -f \"$GIT_DIR/BISECT_NAMES\"\n+\t\trm -f \"$GIT_DIR/BISECT_RUN\"\n \tfi\n }\n \n@@ -220,6 +222,50 @@ bisect_replay () {\n \tbisect_auto_next\n }\n \n+bisect_run () {\n+    while true\n+    do\n+      echo \"running $@\"\n+      \"$@\"\n+      res=$?\n+\n+      # Check for really bad run error.\n+      if [ $res -lt 0 -o $res -ge 128 ]; then\n+\t  echo >&2 \"bisect run failed:\"\n+\t  echo >&2 \"exit code $res from '$@' is < 0 or >= 128\"\n+\t  exit $res\n+      fi\n+\n+      # Use \"bisect_good\" or \"bisect_bad\"\n+      # depending on run success or failure.\n+      if [ $res -gt 0 ]; then\n+\t  next_bisect='bisect_bad'\n+      else\n+\t  next_bisect='bisect_good'\n+      fi\n+\n+      # We have to use a subshell because bisect_good or\n+      # bisect_bad functions can exit.\n+      ( $next_bisect > \"$GIT_DIR/BISECT_RUN\" )\n+      res=$?\n+\n+      cat \"$GIT_DIR/BISECT_RUN\"\n+\n+      if [ $res -ne 0 ]; then\n+\t  echo >&2 \"bisect run failed:\"\n+\t  echo >&2 \"$next_bisect exited with error code $res\"\n+\t  exit $res\n+      fi\n+\n+      if grep \"is first bad commit\" \"$GIT_DIR/BISECT_RUN\" > /dev/null; then\n+\t  echo \"bisect run success\"\n+\t  exit 0;\n+      fi\n+\n+    done\n+}\n+\n+\n case \"$#\" in\n 0)\n     usage ;;\n@@ -244,6 +290,8 @@ case \"$#\" in\n \tbisect_replay \"$@\" ;;\n     log)\n \tcat \"$GIT_DIR/BISECT_LOG\" ;;\n+    run)\n+        bisect_run \"$@\" ;;\n     *)\n         usage ;;\n     esac\ndiff --git a/t/t6030-bisect-run.sh b/t/t6030-bisect-run.sh\nnew file mode 100755\nindex 0000000..39c7228\n--- /dev/null\n+++ b/t/t6030-bisect-run.sh\n@@ -0,0 +1,57 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 Christian Couder\n+#\n+test_description='Tests git-bisect run functionality'\n+\n+. ./test-lib.sh\n+\n+add_line_into_file()\n+{\n+    _line=$1\n+    _file=$2\n+\n+    if [ -f \"$_file\" ]; then\n+        echo \"$_line\" >> $_file || return $?\n+        MSG=\"Add <$_line> into <$_file>.\"\n+    else\n+        echo \"$_line\" > $_file || return $?\n+        git add $_file || return $?\n+        MSG=\"Create file <$_file> with <$_line> inside.\"\n+    fi\n+\n+    git-commit -m \"$MSG\" $_file\n+}\n+\n+HASH1=\n+HASH3=\n+HASH4=\n+\n+test_expect_success \\\n+    'set up basic repo with 1 file (hello) and 4 commits' \\\n+    'add_line_into_file \"1: Hello World\" hello &&\n+     add_line_into_file \"2: A new day for git\" hello &&\n+     add_line_into_file \"3: Another new day for git\" hello &&\n+     add_line_into_file \"4: Ciao for now\" hello &&\n+     HASH1=$(git rev-list HEAD | tail -1) &&\n+     HASH3=$(git rev-list HEAD | head -2 | tail -1) &&\n+     HASH4=$(git rev-list HEAD | head -1)'\n+\n+# We want to automatically find the commit that\n+# introduced \"Another\" into hello.\n+test_expect_success \\\n+    'git bisect run simple case' \\\n+    'echo \"#!/bin/sh\" > test_script.sh &&\n+     echo \"grep Another hello > /dev/null\" >> test_script.sh &&\n+     echo \"test \\$? -ne 0\" >> test_script.sh &&\n+     chmod +x test_script.sh &&\n+     git bisect start &&\n+     git bisect good $HASH1 &&\n+     git bisect bad $HASH4 &&\n+     git bisect run ./test_script.sh > my_bisect_log.txt &&\n+     grep \"$HASH3 is first bad commit\" my_bisect_log.txt'\n+\n+#\n+#\n+test_done\n+\n-- \n1.5.1.rc1.14.ge96a-dirty\n"}]}