[PATCH v2 1/2] rebase -i: clarify what happens on a failed `exec`

2018-10-10 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

We had not documented previously what happens when an `exec` command in
an interactive rebase fails. Now we do.

Signed-off-by: Johannes Schindelin 
---
 Documentation/git-rebase.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 091eb53faa..db2faca73c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -420,7 +420,8 @@ idea unless you know what you are doing (see BUGS below).
 --exec ::
Append "exec " after each line creating a commit in the
final history.  will be interpreted as one or more shell
-   commands.
+   commands. Anz command that fails will interrupt the rebase,
+   withe exit code 1.
 +
 You may execute several commands by either using one instance of `--exec`
 with several commands:
-- 
gitgitgadget



[PATCH 0/9] Offer to run CI/PR builds in Visual Studio Team Services

2018-09-03 Thread Johannes Schindelin via GitGitGadget
For a long time already, we have Git's source code continuously tested via
Travis CI, see e.g. https://travis-ci.org/git/git/builds/421738884. It has
served us well, and more and more developers actually pay attention and
benefit from the testing this gives us.

It is also an invaluable tool for contributors who can validate their code
contributions via PRs on GitHub, e.g. to verify that their tests do actually
run on macOS (i.e. with the BSD family of Unix tools instead of the GNU
one).

The one sad part about this is the Windows support. Travis lacks it, and we
work around that by using Visual Studio Team Services (VSTS) indirectly: one
phase in Travis would trigger a build, wait for its log, and then paste that
log.

As Git's Windows builds (and tests!) take quite a bit of time, Travis often
timed out, or somehow the trigger did not work, and for security reasons
(the Windows builds are performed in a private pool of containers), the
Windows builds are completely disabled for Pull Requests on GitHub.

One might ask why we did not use Visual Studio Team Services directly. There
were a couple of reasons for that:

 * most notably, VSTS's build logs could not be viewed anonymously,
 * while VSTS had Linux and Windows agents, it lacked macOS agents,
 * etc

The main two reasons no longer apply: macOS agents are available now
[https://docs.microsoft.com/en-us/vsts/release-notes/2018/jul-10-vsts], and
there is a limited preview of "public projects"
[https://blogs.msdn.microsoft.com/devops/2018/04/27/vsts-public-projects-limited-preview/]
, i.e. it is possible to configure a VSTS project so that anybody can view
the logs.

I had secured such a public project for Git for Windows already, and I
recently also got one for Git. For now, the latter is hooked up with my
personal git.git fork on GitHub, but it is my hope that I convince y'all
that these VSTS builds are a good idea, and then hook it up with 
https://github.com/git/git.

As a special treat, this patch series adds the ability to present the
outcome of Git's test suite as JUnit-style .xml files. This allows the VSTS
build to present fun diagrams, trends, and makes it a lot easier to drill
down to test failures than before. See for example 
https://git.visualstudio.com/git/_build/results?buildId=113=ms.vss-test-web.test-result-details
[https://git.visualstudio.com/git/_build/results?buildId=113=ms.vss-test-web.test-result-details]
 
(you can click on the label of the failed test, and then see the detailed
output in the right pane).

This patch series took way more time than I had originally planned, but I
think that in particular the advanced display of the test results was worth
it. Please let me know what you think about this.

Johannes Schindelin (9):
  ci: rename the library of common functions
  ci/lib.sh: encapsulate Travis-specific things
  test-date: add a subcommand to measure times in shell scripts
  tests: optionally write results as JUnit-style .xml
  ci/lib.sh: add support for VSTS CI
  Add a build definition for VSTS
  tests: include detailed trace logs with --write-junit-xml upon failure
  tests: record more stderr with --write-junit-xml in case of failure
  README: add a build badge (status of the VSTS build)

 .vsts-ci.yml   | 296 +
 README.md  |   2 +
 ci/install-dependencies.sh |   5 +-
 ci/{lib-travisci.sh => lib.sh} |  67 ++--
 ci/mount-fileshare.sh  |  26 +++
 ci/print-test-failures.sh  |   4 +-
 ci/run-build-and-tests.sh  |   2 +-
 ci/run-linux32-docker.sh   |   2 +-
 ci/run-static-analysis.sh  |   2 +-
 ci/run-windows-build.sh|   2 +-
 ci/test-documentation.sh   |   3 +-
 t/.gitignore   |   1 +
 t/helper/test-date.c   |  12 ++
 t/test-lib.sh  | 142 
 14 files changed, 544 insertions(+), 22 deletions(-)
 create mode 100644 .vsts-ci.yml
 rename ci/{lib-travisci.sh => lib.sh} (61%)
 create mode 100755 ci/mount-fileshare.sh


base-commit: 2f743933341f27603550fbf383a34dfcfd38
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-31%2Fdscho%2Fvsts-ci-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-31/dscho/vsts-ci-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/31
-- 
gitgitgadget


[PATCH 6/9] Add a build definition for VSTS

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

This commit adds a .vsts-ci.yml which is Visual Studio Team Services'
equivalent to Travis CI's .travis.yml.

To make things a bit easier to understand, we refrain from using the
`matrix` feature here because (while it is powerful) it can be a bit
confusing to users who are not familiar with CI setups. Therefore, we
use a separate phase even for similar configurations (such as GCC vs
Clang on Linux, GCC vs Clang on macOS).

Also, we make use of the shiny new feature we just introduced where the
test suite can output JUnit-style .xml files. This information is made
available in a nice UI that allows the viewer to filter by phase and/or
test number, and to see trends such as: number of (failing) tests, time
spent running the test suite, etc.

Signed-off-by: Johannes Schindelin 
---
 .vsts-ci.yml  | 296 ++
 ci/mount-fileshare.sh |  26 
 2 files changed, 322 insertions(+)
 create mode 100644 .vsts-ci.yml
 create mode 100755 ci/mount-fileshare.sh

diff --git a/.vsts-ci.yml b/.vsts-ci.yml
new file mode 100644
index 00..ff1d952df9
--- /dev/null
+++ b/.vsts-ci.yml
@@ -0,0 +1,296 @@
+resources:
+- repo: self
+  fetchDepth: 1
+
+phases:
+- phase: linux_clang
+  displayName: linux-clang
+  condition: succeeded()
+  queue:
+name: Hosted Ubuntu 1604
+  steps:
+  - bash: |
+   ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/vsts-cache 
gitfileshare "$(gitfileshare.pwd)" "$HOME/vsts-cache" || exit 1
+
+   sudo apt-get update
+   sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev 
libexpat-dev tcl tk gettext git-email zlib1g-dev apache2-bin
+
+   export CC=clang
+
+   ci/install-dependencies.sh
+   ci/run-build-and-tests.sh || {
+   ci/print-test-failures.sh
+   exit 1
+   }
+
+   sudo umount "$HOME/vsts-cache" || exit 1
+displayName: 'ci/run-build-and-tests.sh'
+  - task: PublishTestResults@2
+displayName: 'Publish Test Results **/TEST-*.xml'
+inputs:
+  mergeTestResults: true
+  testRunTitle: 'linux-clang'
+  platform: Linux
+  publishRunAttachments: false
+condition: succeededOrFailed()
+
+- phase: linux_gcc
+  displayName: linux-gcc
+  condition: succeeded()
+  queue:
+name: Hosted Ubuntu 1604
+  steps:
+  - bash: |
+   ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/vsts-cache 
gitfileshare "$(gitfileshare.pwd)" "$HOME/vsts-cache" || exit 1
+
+   sudo apt-get update
+   sudo apt-get -y install git gcc make libssl-dev libcurl4-openssl-dev 
libexpat-dev tcl tk gettext git-email zlib1g-dev apache2-bin
+
+   ci/install-dependencies.sh
+   ci/run-build-and-tests.sh || {
+   ci/print-test-failures.sh
+   exit 1
+   }
+
+   sudo umount "$HOME/vsts-cache" || exit 1
+displayName: 'ci/run-build-and-tests.sh'
+  - task: PublishTestResults@2
+displayName: 'Publish Test Results **/TEST-*.xml'
+inputs:
+  mergeTestResults: true
+  testRunTitle: 'linux-gcc'
+  platform: Linux
+  publishRunAttachments: false
+condition: succeededOrFailed()
+
+- phase: osx_clang
+  displayName: osx-clang
+  condition: succeeded()
+  queue:
+name: Hosted macOS
+  steps:
+  - bash: |
+   ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/vsts-cache 
gitfileshare "$(gitfileshare.pwd)" "$HOME/vsts-cache" || exit 1
+
+   export CC=clang
+
+   ci/install-dependencies.sh
+   ci/run-build-and-tests.sh || {
+   ci/print-test-failures.sh
+   exit 1
+   }
+
+   umount "$HOME/vsts-cache" || exit 1
+displayName: 'ci/run-build-and-tests.sh'
+  - task: PublishTestResults@2
+displayName: 'Publish Test Results **/TEST-*.xml'
+inputs:
+  mergeTestResults: true
+  testRunTitle: 'osx-clang'
+  platform: macOS
+  publishRunAttachments: false
+condition: succeededOrFailed()
+
+- phase: osx_gcc
+  displayName: osx-gcc
+  condition: succeeded()
+  queue:
+name: Hosted macOS
+  steps:
+  - bash: |
+   ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/vsts-cache 
gitfileshare "$(gitfileshare.pwd)" "$HOME/vsts-cache" || exit 1
+
+   ci/install-dependencies.sh
+   ci/run-build-and-tests.sh || {
+   ci/print-test-failures.sh
+   exit 1
+   }
+
+   umount "$HOME/vsts-cache" || exit 1
+displayName: 'ci/run-build-and-tests.sh'
+  - task: PublishTestResults@2
+displayName: 'Publish Test Results **/TEST-*.xml'
+inputs:
+  mergeTestResults: true
+  testRunTitle: 'osx-gcc'
+  platform: macOS
+  publishRunAttachments: false
+condition: succeededOrFailed()
+
+- phase: gettext_poison
+  displayName: GETTEXT_POISON
+  condition: succeeded()
+  queue:
+name: Hosted Ubuntu 1604
+  steps:
+  - bash: |
+   ci/mount-fileshare.sh //gitfileshare.file.core.windows.net/vsts-cache 
gitfileshare "$(gitfileshare.pwd)" "$HOME/vsts-cache" || exit 

[PATCH 4/9] tests: optionally write results as JUnit-style .xml

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

This will come in handy when publishing the results of Git's test suite
during an automated VSTS CI run.

Signed-off-by: Johannes Schindelin 
---
 t/.gitignore  |  1 +
 t/test-lib.sh | 98 +++
 2 files changed, 99 insertions(+)

diff --git a/t/.gitignore b/t/.gitignore
index 348715f0e4..91cf5772fe 100644
--- a/t/.gitignore
+++ b/t/.gitignore
@@ -2,3 +2,4 @@
 /test-results
 /.prove
 /chainlinttmp
+/out/
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 8bb0f4348e..50a65a600e 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -288,6 +288,9 @@ do
--verbose-log)
verbose_log=t
shift ;;
+   --write-junit-xml)
+   write_junit_xml=t
+   shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
@@ -431,11 +434,24 @@ trap 'exit $?' INT
 # the test_expect_* functions instead.
 
 test_ok_ () {
+   if test -n "$write_junit_xml"
+   then
+   write_junit_xml_testcase "$*"
+   fi
test_success=$(($test_success + 1))
say_color "" "ok $test_count - $@"
 }
 
 test_failure_ () {
+   if test -n "$write_junit_xml"
+   then
+   junit_insert=""
+   junit_insert="$junit_insert $(xml_attr_encode \
+   "$(printf '%s\n' "$@" | sed 1d)")"
+   junit_insert="$junit_insert"
+   write_junit_xml_testcase "$1" "  $junit_insert"
+   fi
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
@@ -444,11 +460,19 @@ test_failure_ () {
 }
 
 test_known_broken_ok_ () {
+   if test -n "$write_junit_xml"
+   then
+   write_junit_xml_testcase "$* (breakage fixed)"
+   fi
test_fixed=$(($test_fixed+1))
say_color error "ok $test_count - $@ # TODO known breakage vanished"
 }
 
 test_known_broken_failure_ () {
+   if test -n "$write_junit_xml"
+   then
+   write_junit_xml_testcase "$* (known breakage)"
+   fi
test_broken=$(($test_broken+1))
say_color warn "not ok $test_count - $@ # TODO known breakage"
 }
@@ -706,6 +730,10 @@ test_start_ () {
test_count=$(($test_count+1))
maybe_setup_verbose
maybe_setup_valgrind
+   if test -n "$write_junit_xml"
+   then
+   junit_start=$(test-tool date getnanos)
+   fi
 }
 
 test_finish_ () {
@@ -743,6 +771,13 @@ test_skip () {
 
case "$to_skip" in
t)
+   if test -n "$write_junit_xml"
+   then
+   message="$(xml_attr_encode "$skipped_reason")"
+   write_junit_xml_testcase "$1" \
+   "  "
+   fi
+
say_color skip >&3 "skipping test: $@"
say_color skip "ok $test_count # skip $1 ($skipped_reason)"
: true
@@ -758,9 +793,58 @@ test_at_end_hook_ () {
:
 }
 
+write_junit_xml () {
+   case "$1" in
+   --truncate)
+   >"$junit_xml_path"
+   junit_have_testcase=
+   shift
+   ;;
+   esac
+   printf '%s\n' "$@" >>"$junit_xml_path"
+}
+
+xml_attr_encode () {
+   # We do not translate CR to  because BSD sed does not handle
+   # \r in the regex. In practice, the output should not even have any
+   # carriage returns.
+   printf '%s\n' "$@" |
+   sed -e 's/&/\/g' -e "s/'/\/g" -e 's/"/\/g' \
+   -e 's//\/g' \
+   -e 's/  /\/g' -e 's/$/\/' -e '$s/$//' |
+   tr -d '\012\015'
+}
+
+write_junit_xml_testcase () {
+   junit_attrs="name=\"$(xml_attr_encode "$this_test.$test_count $1")\""
+   shift
+   junit_attrs="$junit_attrs classname=\"$this_test\""
+   junit_attrs="$junit_attrs time=\"$(test-tool \
+   date getnanos $junit_start)\""
+   write_junit_xml "$(printf '%s\n' \
+   "" "$@" "")"
+   junit_have_testcase=t
+}
+
 test_done () {
GIT_EXIT_OK=t
 
+   if test -n "$write_junit_xml" && test -n "$junit_xml_path"
+   then
+   test -n "$junit_have_testcase" || {
+   junit_start=$(test-tool date getnanos)
+   write_junit_xml_testcase "all tests skipped"
+   }
+
+   # adjust the overall time
+   junit_time=$(test-tool date getnanos $junit_suite_start)
+   sed "s/]*/& time=\"$junit_time\"/" \
+   <"$junit_xml_path" >"$junit_xml_path.new"
+   mv "$junit_xml_path.new" "$junit_xml_path"
+
+   write_junit_xml "  " ""
+   fi
+
if test -z "$HARNESS_ACTIVE"
then
test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
@@ -996,6 +1080,7 @@ then
 else
mkdir -p "$TRASH_DIRECTORY"
 fi
+
 # Use -P to resolve symlinks in our working 

[PATCH 7/9] tests: include detailed trace logs with --write-junit-xml upon failure

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The JUnit XML format lends itself to be presented in a powerful UI,
where you can drill down to the information you are interested in very
quickly.

For test failures, this usually means that you want to see the detailed
trace of the failing tests.

With Travis CI, we passed the `--verbose-log` option to get those
traces. However, that seems excessive, as we do not need/use the logs in
almost all of those cases: only when a test fails do we have a way to
include the trace.

So let's do something different in VSTS: let's run all the tests with
`--quiet` first, and only if a failure is encountered, try to trace the
commands as they are executed.

Of course, we cannot turn on `--verbose-log` after the fact. So let's
just re-run the test with all the same options, adding `--verbose-log`.
And then munging the output file into the JUnit XML on the fly.

Note: there is an off chance that re-running the test in verbose mode
"fixes" the failures (and this does happen from time to time!). That is
a possibility we should be able to live with. Ideally, we would label
this as "Passed upon rerun", and that outcome even exists on VSTS, but
it is not available when using the JUnit XML format for now:
https://github.com/Microsoft/vsts-agent/blob/master/src/Agent.Worker/TestResults/JunitResultReader.cs

This patch contains a slightly inelegant workaround for the p4 and
git-daemon tests: when we try to re-run the p4/git-daemon tests after
the daemon has been started already, we need to kill said daemon. We do
this by detecting the presence of the `kill_p4d` and `stop_git_daemon`
shell functions and calling them if available.

Signed-off-by: Johannes Schindelin 
---
 t/test-lib.sh | 40 +++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 50a65a600e..ea4ed250cc 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -85,6 +85,13 @@ done,*)
test "$(cat "$BASE.exit")" = 0
exit
;;
+*' --write-junit-xml '*)
+   # record how to call this script *with* --verbose-log, in case
+   # we encounter a breakage
+   junit_rerun_options_sq="$(printf '%s\n' "$0" --verbose-log -x "$@" |
+   sed -e "s/'/'''/g" -e "s/^/'/" -e "s/\$/'/" |
+   tr '\012' ' ')"
+   ;;
 esac
 
 # For repeatability, reset the environment to known value.
@@ -445,10 +452,37 @@ test_ok_ () {
 test_failure_ () {
if test -n "$write_junit_xml"
then
+   if test -z "$GIT_TEST_TEE_OUTPUT_FILE"
+   then
+   case "$(type kill_p4d 2>/dev/null | head -n 1)" in
+   *function*) kill_p4d;;
+   esac
+
+   case "$(type stop_git_daemon 2>/dev/null |
+   head -n 1)" in
+   *function*) stop_git_daemon;;
+   esac
+
+   # re-run with --verbose-log
+   echo "# Re-running: $junit_rerun_options_sq" >&2
+
+   cd "$TEST_DIRECTORY" &&
+   eval "${TEST_SHELL_PATH}" "$junit_rerun_options_sq" \
+   >/dev/null 2>&1
+   status=$?
+
+   say_color "" "$(test 0 = $status ||
+   echo "not ")ok $test_count - (re-ran with 
trace)"
+   say "1..$test_count"
+   GIT_EXIT_OK=t
+   exit $status
+   fi
+
junit_insert=""
junit_insert="$junit_insert $(xml_attr_encode \
-   "$(printf '%s\n' "$@" | sed 1d)")"
+   "$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")"
+   >"$GIT_TEST_TEE_OUTPUT_FILE"
junit_insert="$junit_insert"
write_junit_xml_testcase "$1" "  $junit_insert"
fi
@@ -733,6 +767,10 @@ test_start_ () {
if test -n "$write_junit_xml"
then
junit_start=$(test-tool date getnanos)
+
+   # truncate output
+   test -z "$GIT_TEST_TEE_OUTPUT_FILE" ||
+   >"$GIT_TEST_TEE_OUTPUT_FILE"
fi
 }
 
-- 
gitgitgadget



[PATCH 1/9] ci: rename the library of common functions

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The name is hard-coded to reflect that we use Travis CI for continuous
testing.

In the next commits, we will extend this to be able use Visual Studio
Team Services, too.

So let's adjust the name to make it more generic.

Signed-off-by: Johannes Schindelin 
---
 ci/install-dependencies.sh | 2 +-
 ci/{lib-travisci.sh => lib.sh} | 0
 ci/print-test-failures.sh  | 2 +-
 ci/run-build-and-tests.sh  | 2 +-
 ci/run-linux32-docker.sh   | 2 +-
 ci/run-static-analysis.sh  | 2 +-
 ci/run-windows-build.sh| 2 +-
 ci/test-documentation.sh   | 2 +-
 8 files changed, 7 insertions(+), 7 deletions(-)
 rename ci/{lib-travisci.sh => lib.sh} (100%)

diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 75a9fd2475..961064658e 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -3,7 +3,7 @@
 # Install dependencies required to build and test Git on Linux and macOS
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 P4WHENCE=http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION
 
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
diff --git a/ci/lib-travisci.sh b/ci/lib.sh
similarity index 100%
rename from ci/lib-travisci.sh
rename to ci/lib.sh
diff --git a/ci/print-test-failures.sh b/ci/print-test-failures.sh
index d55460a212..7aef39a2fd 100755
--- a/ci/print-test-failures.sh
+++ b/ci/print-test-failures.sh
@@ -3,7 +3,7 @@
 # Print output of failing tests
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 # Tracing executed commands would produce too much noise in the loop below.
 set +x
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index 2a5bff4a1c..e28ac2fb9a 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -3,7 +3,7 @@
 # Build and test Git
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 ln -s "$cache_dir/.prove" t/.prove
 
diff --git a/ci/run-linux32-docker.sh b/ci/run-linux32-docker.sh
index 21637903ce..751acfcf8a 100755
--- a/ci/run-linux32-docker.sh
+++ b/ci/run-linux32-docker.sh
@@ -3,7 +3,7 @@
 # Download and run Docker image to build and test 32-bit Git
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 docker pull daald/ubuntu32:xenial
 
diff --git a/ci/run-static-analysis.sh b/ci/run-static-analysis.sh
index 5688f261d0..dc189c7456 100755
--- a/ci/run-static-analysis.sh
+++ b/ci/run-static-analysis.sh
@@ -3,7 +3,7 @@
 # Perform various static code analysis checks
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 make --jobs=2 coccicheck
 
diff --git a/ci/run-windows-build.sh b/ci/run-windows-build.sh
index d99a180e52..a73a4eca0a 100755
--- a/ci/run-windows-build.sh
+++ b/ci/run-windows-build.sh
@@ -6,7 +6,7 @@
 # supported) and a commit hash.
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 test $# -ne 2 && echo "Unexpected number of parameters" && exit 1
 test -z "$GFW_CI_TOKEN" && echo "GFW_CI_TOKEN not defined" && exit
diff --git a/ci/test-documentation.sh b/ci/test-documentation.sh
index a20de9ca12..d3cdbac73f 100755
--- a/ci/test-documentation.sh
+++ b/ci/test-documentation.sh
@@ -3,7 +3,7 @@
 # Perform sanity checks on documentation and build it.
 #
 
-. ${0%/*}/lib-travisci.sh
+. ${0%/*}/lib.sh
 
 gem install asciidoctor
 
-- 
gitgitgadget



[PATCH 5/9] ci/lib.sh: add support for VSTS CI

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

This patch introduces a conditional arm that defines some environment
variables and a function that displays the URL given the job id (to
identify previous runs for known-good trees).

Signed-off-by: Johannes Schindelin 
---
 ci/lib.sh | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/ci/lib.sh b/ci/lib.sh
index 657ff88672..f2f6d70c72 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -19,6 +19,29 @@ then
BREW_INSTALL_PACKAGES="git-lfs gettext"
export GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
export GIT_TEST_OPTS="--verbose-log -x --immediate"
+elif test -n "$SYSTEM_TASKDEFINITIONSURI"
+then
+   # We are running in VSTS CI
+   CI_BRANCH="$BUILD_SOURCEBRANCH"
+   CI_COMMIT="$BUILD_SOURCEVERSION"
+   CI_JOB_ID="$BUILD_BUILDID"
+   CI_JOB_NUMBER="$BUILD_BUILDNUMBER"
+   CI_OS_NAME="$(echo "$AGENT_OS" | tr A-Z a-z)"
+   test darwin != "$CI_OS_NAME" || CI_OS_NAME=osx
+   CI_REPO_SLUG="$(expr "$BUILD_REPOSITORY_URI" : '.*/\([^/]*/[^/]*\)$')"
+   CC="${CC:-gcc}"
+
+   # use a subdirectory of the cache dir (because the file share is shared
+   # among *all* phases)
+   cache_dir="$HOME/vsts-cache/$SYSTEM_PHASENAME"
+
+   url_for_job_id () {
+   echo 
"$SYSTEM_TASKDEFINITIONSURI$SYSTEM_TEAMPROJECT/_build/results?buildId=$1"
+   }
+
+   BREW_INSTALL_PACKAGES=
+   export GIT_PROVE_OPTS="--timer --jobs 10 --state=failed,slow,save"
+   export GIT_TEST_OPTS="--quiet --write-junit-xml"
 fi
 
 skip_branch_tip_with_tag () {
-- 
gitgitgadget



[PATCH 8/9] tests: record more stderr with --write-junit-xml in case of failure

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

Sometimes, failures in a test case are actually caused by issues in
earlier test cases.

To make it easier to see those issues, let's attach the output from
before the failing test case (i.e. stdout/stderr since the previous
failing test case, or the start of the test script). This will be
visible in the "Attachments" of the details of the failed test.

Signed-off-by: Johannes Schindelin 
---
 t/test-lib.sh | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index ea4ed250cc..6fc03d5a3b 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -484,6 +484,9 @@ test_failure_ () {
"$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")"
>"$GIT_TEST_TEE_OUTPUT_FILE"
junit_insert="$junit_insert"
+   junit_insert="$junit_insert$(xml_attr_encode \
+   "$(cat "$GIT_TEST_TEE_OUTPUT_FILE.err")")"
+   >"$GIT_TEST_TEE_OUTPUT_FILE.err"
write_junit_xml_testcase "$1" "  $junit_insert"
fi
test_failure=$(($test_failure + 1))
@@ -768,9 +771,12 @@ test_start_ () {
then
junit_start=$(test-tool date getnanos)
 
-   # truncate output
-   test -z "$GIT_TEST_TEE_OUTPUT_FILE" ||
-   >"$GIT_TEST_TEE_OUTPUT_FILE"
+   # append to future ; truncate output
+   test -z "$GIT_TEST_TEE_OUTPUT_FILE" || {
+   cat "$GIT_TEST_TEE_OUTPUT_FILE" \
+   >>"$GIT_TEST_TEE_OUTPUT_FILE.err"
+   >"$GIT_TEST_TEE_OUTPUT_FILE"
+   }
fi
 }
 
-- 
gitgitgadget



[PATCH 3/9] test-date: add a subcommand to measure times in shell scripts

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

In the next commit, we want to teach Git's test suite to optionally
output test results in JUnit-style .xml files. These files contain
information about the time spent. So we need a way to measure time.

While we could use `date +%s` for that, this will give us only seconds,
i.e. very coarse-grained timings.

GNU `date` supports `date +%s.%N` (i.e. nanosecond-precision output),
but there is no equivalent in BSD `date` (read: on macOS, we would not
be able to obtain precise timings).

So let's introduce `test-tool date getnanos`, with an optional start
time, that outputs preciser values.

Granted, it is a bit pointless to try measuring times accurately in
shell scripts, certainly to nanosecond precision. But it is better than
second-granularity.

Signed-off-by: Johannes Schindelin 
---
 t/helper/test-date.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index a0837371ab..792a805374 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -7,6 +7,7 @@ static const char *usage_msg = "\n"
 "  test-tool date parse [date]...\n"
 "  test-tool date approxidate [date]...\n"
 "  test-tool date timestamp [date]...\n"
+"  test-tool date getnanos [start-nanos]\n"
 "  test-tool date is64bit\n"
 "  test-tool date time_t-is64bit\n";
 
@@ -82,6 +83,15 @@ static void parse_approx_timestamp(const char **argv, struct 
timeval *now)
}
 }
 
+static void getnanos(const char **argv, struct timeval *now)
+{
+   double seconds = getnanotime() / 1.0e9;
+
+   if (*argv)
+   seconds -= strtod(*argv, NULL);
+   printf("%lf\n", seconds);
+}
+
 int cmd__date(int argc, const char **argv)
 {
struct timeval now;
@@ -108,6 +118,8 @@ int cmd__date(int argc, const char **argv)
parse_approxidate(argv+1, );
else if (!strcmp(*argv, "timestamp"))
parse_approx_timestamp(argv+1, );
+   else if (!strcmp(*argv, "getnanos"))
+   getnanos(argv+1, );
else if (!strcmp(*argv, "is64bit"))
return sizeof(timestamp_t) == 8 ? 0 : 1;
else if (!strcmp(*argv, "time_t-is64bit"))
-- 
gitgitgadget



[PATCH 9/9] README: add a build badge (status of the VSTS build)

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

Just like so many other OSS projects, we now also have a build badge.

Signed-off-by: Johannes Schindelin 
---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index f920a42fad..f260e78042 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+[![Build 
Status](https://git.visualstudio.com/git/_apis/build/status/test-git.git)](https://git.visualstudio.com/git/_build/latest?definitionId=2)
+
 Git - fast, scalable, distributed revision control system
 =
 
-- 
gitgitgadget


[PATCH 2/9] ci/lib.sh: encapsulate Travis-specific things

2018-09-03 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The upcoming patches will allow building git.git via VSTS CI, where
variable names and URLs look a bit different than in Travis CI.

Signed-off-by: Johannes Schindelin 
---
 ci/install-dependencies.sh |  3 ++-
 ci/lib.sh  | 44 +++---
 ci/print-test-failures.sh  |  2 +-
 ci/test-documentation.sh   |  1 +
 4 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 961064658e..6d92cc1cba 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -28,7 +28,8 @@ osx-clang|osx-gcc)
brew update --quiet
# Uncomment this if you want to run perf tests:
# brew install gnu-time
-   brew install git-lfs gettext
+   test -z "$BREW_INSTALL_PACKAGES" ||
+   eval brew install $BREW_INSTALL_PACKAGES
brew link --force gettext
brew install caskroom/cask/perforce
;;
diff --git a/ci/lib.sh b/ci/lib.sh
index 06970f7213..657ff88672 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -1,5 +1,26 @@
 # Library of functions shared by all CI scripts
 
+if test -n "$TRAVIS_COMMIT"
+then
+   # We are running within Travis CI
+   CI_BRANCH="$TRAVIS_BRANCH"
+   CI_COMMIT="$TRAVIS_COMMIT"
+   CI_JOB_ID="$TRAVIS_JOB_ID"
+   CI_JOB_NUMBER="$TRAVIS_JOB_NUMBER"
+   CI_OS_NAME="$TRAVIS_OS_NAME"
+   CI_REPO_SLUG="$TRAVIS_REPO_SLUG"
+
+   cache_dir="$HOME/travis-cache"
+
+   url_for_job_id () {
+   echo "https://travis-ci.org/$CI_REPO_SLUG/jobs/$1;
+   }
+
+   BREW_INSTALL_PACKAGES="git-lfs gettext"
+   export GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
+   export GIT_TEST_OPTS="--verbose-log -x --immediate"
+fi
+
 skip_branch_tip_with_tag () {
# Sometimes, a branch is pushed at the same time the tag that points
# at the same commit as the tip of the branch is pushed, and building
@@ -13,10 +34,10 @@ skip_branch_tip_with_tag () {
# we can skip the build because we won't be skipping a build
# of a tag.
 
-   if TAG=$(git describe --exact-match "$TRAVIS_BRANCH" 2>/dev/null) &&
-   test "$TAG" != "$TRAVIS_BRANCH"
+   if TAG=$(git describe --exact-match "$CI_BRANCH" 2>/dev/null) &&
+   test "$TAG" != "$CI_BRANCH"
then
-   echo "$(tput setaf 2)Tip of $TRAVIS_BRANCH is exactly at 
$TAG$(tput sgr0)"
+   echo "$(tput setaf 2)Tip of $CI_BRANCH is exactly at $TAG$(tput 
sgr0)"
exit 0
fi
 }
@@ -25,7 +46,7 @@ skip_branch_tip_with_tag () {
 # job if we encounter the same tree again and can provide a useful info
 # message.
 save_good_tree () {
-   echo "$(git rev-parse $TRAVIS_COMMIT^{tree}) $TRAVIS_COMMIT 
$TRAVIS_JOB_NUMBER $TRAVIS_JOB_ID" >>"$good_trees_file"
+   echo "$(git rev-parse $CI_COMMIT^{tree}) $CI_COMMIT $CI_JOB_NUMBER 
$CI_JOB_ID" >>"$good_trees_file"
# limit the file size
tail -1000 "$good_trees_file" >"$good_trees_file".tmp
mv "$good_trees_file".tmp "$good_trees_file"
@@ -35,7 +56,7 @@ save_good_tree () {
 # successfully before (e.g. because the branch got rebased, changing only
 # the commit messages).
 skip_good_tree () {
-   if ! good_tree_info="$(grep "^$(git rev-parse $TRAVIS_COMMIT^{tree}) " 
"$good_trees_file")"
+   if ! good_tree_info="$(grep "^$(git rev-parse $CI_COMMIT^{tree}) " 
"$good_trees_file")"
then
# Haven't seen this tree yet, or no cached good trees file yet.
# Continue the build job.
@@ -45,18 +66,18 @@ skip_good_tree () {
echo "$good_tree_info" | {
read tree prev_good_commit prev_good_job_number prev_good_job_id
 
-   if test "$TRAVIS_JOB_ID" = "$prev_good_job_id"
+   if test "$CI_JOB_ID" = "$prev_good_job_id"
then
cat <<-EOF
-   $(tput setaf 2)Skipping build job for commit 
$TRAVIS_COMMIT.$(tput sgr0)
+   $(tput setaf 2)Skipping build job for commit 
$CI_COMMIT.$(tput sgr0)
This commit has already been built and tested 
successfully by this build job.
To force a re-build delete the branch's cache and then 
hit 'Restart job'.
EOF
else
cat <<-EOF
-   $(tput setaf 2)Skipping build job for commit 
$TRAVIS_COMMIT.$(tput sgr0)
+   $(tput setaf 2)Skipping build job for commit 
$CI_COMMIT.$(tput sgr0)
This commit's tree has already been built and tested 
successfully in build job $prev_good_job_number for commit $prev_good_commit.
-   The log of that build job is available at 
https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$prev_good_job_id
+   The log of that build job is available at 
$(url_for_job_id 

[PATCH 1/1] rebase: fix GIT_REFLOG_ACTION regression

2018-11-29 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The scripted version (partially) heeded the `GIT_REFLOG_ACTION` and when
we converted to a built-in, this regressed.

Fix that, and add a regression test, both with `GIT_REFLOG_ACTION` set
and unset.

Note: the reflog message for "rebase finished" did *not* heed
GIT_REFLOG_ACTION, and as we are very late in the v2.20.0-rcN phase, we
leave that bug for later (as it seems that that bug has been with us
from the very beginning).

Reported by Ian Jackson.

Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c  | 29 ++---
 t/t3406-rebase-message.sh | 26 ++
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..ba0c3c954b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -776,6 +776,23 @@ static void NORETURN 
error_on_missing_default_upstream(void)
exit(1);
 }
 
+static void set_reflog_action(struct rebase_options *options)
+{
+   const char *env;
+   struct strbuf buf = STRBUF_INIT;
+
+   if (!is_interactive(options))
+   return;
+
+   env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
+   if (env && strcmp("rebase", env))
+   return; /* only override it if it is "rebase" */
+
+   strbuf_addf(, "rebase -i (%s)", options->action);
+   setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
+   strbuf_release();
+}
+
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
struct rebase_options options = {
@@ -978,6 +995,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
 
if (action != NO_ACTION && !in_progress)
die(_("No rebase in progress?"));
+   setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
 
if (action == ACTION_EDIT_TODO && !is_interactive())
die(_("The --edit-todo action can only be used during "
@@ -990,6 +1008,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
int fd;
 
options.action = "continue";
+   set_reflog_action();
 
/* Sanity check */
if (get_oid("HEAD", ))
@@ -1018,6 +1037,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
struct string_list merge_rr = STRING_LIST_INIT_DUP;
 
options.action = "skip";
+   set_reflog_action();
 
rerere_clear(_rr);
string_list_clear(_rr, 1);
@@ -1033,6 +1053,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
case ACTION_ABORT: {
struct string_list merge_rr = STRING_LIST_INIT_DUP;
options.action = "abort";
+   set_reflog_action();
 
rerere_clear(_rr);
string_list_clear(_rr, 1);
@@ -1440,11 +1461,12 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
}
 
strbuf_reset();
-   strbuf_addf(, "rebase: checkout %s",
+   strbuf_addf(, "%s: checkout %s",
+   
getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
options.switch_to);
if (reset_head(, "checkout",
   options.head_name, 0,
-  NULL, NULL) < 0) {
+  NULL, buf.buf) < 0) {
ret = !!error(_("could not switch to "
"%s"),
  options.switch_to);
@@ -1508,7 +1530,8 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
printf(_("First, rewinding head to replay your work on top of "
 "it...\n"));
 
-   strbuf_addf(, "rebase: checkout %s", options.onto_name);
+   strbuf_addf(, "%s: checkout %s",
+   getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
if (reset_head(>object.oid, "checkout", NULL,
   RESET_HEAD_DETACH, NULL, msg.buf))
die(_("Could not detach HEAD"));
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..db8505eb86 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -91,4 +91,30 @@ test_expect_success 'error out early upon -C or 
--whitespace=' '
test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'GIT_REFLOG_ACTION' '
+   git checkout start &&
+   test_commit reflog-onto &&
+   git checkout -b reflog-topic start &&
+   test_commit reflog-to-rebase &&
+
+   git rebase reflog-onto &&
+   git log -g --format=%gs -3 >actual &&
+   cat >expect <<-\EOF &&
+   rebase finished: 

[PATCH 0/1] Fix built-in rebase regression noticed by Debian's dgit

2018-11-29 Thread Johannes Schindelin via GitGitGadget
It has been reported on the Debian bug tracker
[https://bugs.debian.org/914695] that the built-in rebase regresses on the
scripted version, and later details emerged that this has something to do
with the reflog messages: they were different with the built-in rebase than
with the scripted one.

This here patch fixes that.

Johannes Schindelin (1):
  rebase: fix GIT_REFLOG_ACTION regression

 builtin/rebase.c  | 29 ++---
 t/t3406-rebase-message.sh | 26 ++
 2 files changed, 52 insertions(+), 3 deletions(-)


base-commit: 7068cbc4abac53d9c3675dfba81c1e97d25e8eeb
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-91%2Fdscho%2Ffix-reflog-action-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-91/dscho/fix-reflog-action-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/91
-- 
gitgitgadget


[PATCH v2 0/1] Fix git rebase --stat -i

2018-11-29 Thread Johannes Schindelin via GitGitGadget
We're really entering obscure territory here, I would say.

To trigger the bug, two things have to come together: the user must have
asked for a diffstat afterwards, and the commits need to have been rebased
onto a completely unrelated commit history (i.e. there must exist no merge
base between the pre-rebase HEAD and the post-rebase HEAD).

Please note that this bug existed already in the scripted rebase, but it was
never detected because the scripted version would not even perform any error
checking.

It will make Junio very happy that I squashed the regression test in to the
patch that fixes it. The reason, however, was not to make Junio happy (I
hope to make him happy by fixing bugs), but simply that an earlier iteration
of test would only fail with the built-in rebase, but not with the scripted
version. The current version would fail with the scripted version, but I'll
save the time to split the patch again now.

Changes since v1:

 * The commit message now talks more about what we should do in case that
   there is no merge base, rather than stressing the differences between the
   way scripted vs built-in rebase handled it (both buggy, and fixed by this
   patch).
 * In case that there is no merge base, it no longer reports "Changes from
   (empty) to ..." but "Changes to ...", which should be a lot less
   controversial.

Johannes Schindelin (1):
  rebase --stat: fix when rebasing to an unrelated history

 builtin/rebase.c  | 18 --
 git-legacy-rebase.sh  | 10 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 30 insertions(+), 8 deletions(-)


base-commit: a1598010f775d82b5adf12c29d0f5bc9b41434c6
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-88%2Fdscho%2Frebase-stat-fix-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-88/dscho/rebase-stat-fix-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/88

Range-diff vs v1:

 1:  680385e4bd ! 1:  190c7856ad rebase --stat: fix when rebasing to an 
unrelated history
 @@ -3,22 +3,21 @@
  rebase --stat: fix when rebasing to an unrelated history
  
  When rebasing to a commit history that has no common commits with the
 -current branch, there is no merge base. The scripted version of the 
`git
 -rebase` command was not prepared for that and spewed out
 +current branch, there is no merge base. In diffstat mode, this means
 +that we cannot compare to the merge base, but we have to compare to 
the
 +empty tree instead.
  
 -fatal: ambiguous argument '': unknown revision or path not in
 -the working tree.
 +Also, if running in verbose diffstat mode, we should not output
  
 -but then continued (due to lack of error checking).
 +Changes from  to 
  
 -The built-in version of the `git rebase` command blindly translated 
that
 -shell script code, assuming that there is no need to test whether 
there
 -*was* a merge base, and due to its better error checking, exited with 
a
 -fatal error (because it tried to read the object with hash ...
 -as a tree).
 +as that does not make sense without any merge base.
  
 -Fix both scripted and built-in versions to output something sensibly,
 -and add a regression test to keep this working in all eternity.
 +Note: neither scripted nor built-in versoin of `git rebase` were
 +prepared for this situation well. We use this opportunity not only to
 +fix the bug(s), but also to make both versions' output consistent in
 +this instance. And add a regression test to keep this working in all
 +eternity.
  
  Reported-by: Ævar Arnfjörð Bjarmason 
  Signed-off-by: Johannes Schindelin 
 @@ -27,15 +26,25 @@
  --- a/builtin/rebase.c
  +++ b/builtin/rebase.c
  @@
 +  if (options.flags & REBASE_DIFFSTAT) {
 +  struct diff_options opts;
   
 -  if (options.flags & REBASE_VERBOSE)
 -  printf(_("Changes from %s to %s:\n"),
 +- if (options.flags & REBASE_VERBOSE)
 +- printf(_("Changes from %s to %s:\n"),
  - oid_to_hex(_base),
 -+ is_null_oid(_base) ?
 -+ "(empty)" : oid_to_hex(_base),
 -  oid_to_hex(>object.oid));
 +- oid_to_hex(>object.oid));
 ++ if (options.flags & REBASE_VERBOSE) {
 ++ if (is_null_oid(_base))
 ++ printf(_("Changes to %s:\n"),
 ++oid_to_hex(>object.oid));
 ++ else
 ++ printf(_("Changes from %s to %s:\n"),
 ++oid_to_hex(_base),
 ++ 

[PATCH v2 1/1] rebase --stat: fix when rebasing to an unrelated history

2018-11-29 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

When rebasing to a commit history that has no common commits with the
current branch, there is no merge base. In diffstat mode, this means
that we cannot compare to the merge base, but we have to compare to the
empty tree instead.

Also, if running in verbose diffstat mode, we should not output

Changes from  to 

as that does not make sense without any merge base.

Note: neither scripted nor built-in versoin of `git rebase` were
prepared for this situation well. We use this opportunity not only to
fix the bug(s), but also to make both versions' output consistent in
this instance. And add a regression test to keep this working in all
eternity.

Reported-by: Ævar Arnfjörð Bjarmason 
Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c  | 18 --
 git-legacy-rebase.sh  | 10 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..1c6f817f4b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1481,10 +1481,15 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
if (options.flags & REBASE_DIFFSTAT) {
struct diff_options opts;
 
-   if (options.flags & REBASE_VERBOSE)
-   printf(_("Changes from %s to %s:\n"),
-   oid_to_hex(_base),
-   oid_to_hex(>object.oid));
+   if (options.flags & REBASE_VERBOSE) {
+   if (is_null_oid(_base))
+   printf(_("Changes to %s:\n"),
+  oid_to_hex(>object.oid));
+   else
+   printf(_("Changes from %s to %s:\n"),
+  oid_to_hex(_base),
+  oid_to_hex(>object.oid));
+   }
 
/* We want color (if set), but no pager */
diff_setup();
@@ -1494,8 +1499,9 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME;
diff_setup_done();
-   diff_tree_oid(_base, >object.oid,
- "", );
+   diff_tree_oid(is_null_oid(_base) ?
+ the_hash_algo->empty_tree : _base,
+ >object.oid, "", );
diffcore_std();
diff_flush();
}
diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
index b97ffdc9dd..b4c7dbfa57 100755
--- a/git-legacy-rebase.sh
+++ b/git-legacy-rebase.sh
@@ -718,10 +718,16 @@ if test -n "$diffstat"
 then
if test -n "$verbose"
then
-   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+   if test -z "$mb"
+   then
+   echo "$(eval_gettext "Changes to \$onto:")"
+   else
+   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+   fi
fi
+   mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
# We want color (if set), but no pager
-   GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+   GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
 fi
 
 test -n "$interactive_rebase" && run_specific_rebase
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..c2c9950568 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -91,4 +91,14 @@ test_expect_success 'error out early upon -C or 
--whitespace=' '
test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'rebase -i onto unrelated history' '
+   git init unrelated &&
+   test_commit -C unrelated 1 &&
+   git -C unrelated remote add -f origin "$PWD" &&
+   git -C unrelated branch --set-upstream-to=origin/master &&
+   git -C unrelated -c core.editor=true rebase -i -v --stat >actual &&
+   test_i18ngrep "Changes to " actual &&
+   test_i18ngrep "5 files changed" actual
+'
+
 test_done
-- 
gitgitgadget


[PATCH 0/1] legacy-rebase: fix "regression"

2018-11-20 Thread Johannes Schindelin via GitGitGadget
This is a backport, really, to accommodate a new regression test that was
introduced when the built-in rebase learned to validate the -C and 
--whitespace= arguments early.

Johannes Schindelin (1):
  legacy-rebase: backport -C and --whitespace= checks

 git-legacy-rebase.sh | 8 
 1 file changed, 8 insertions(+)


base-commit: bb75be6cb916297f271c846f2f9caa3daaaec718
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-86%2Fdscho%2Fscripted-rebase-Cn-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-86/dscho/scripted-rebase-Cn-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/86
-- 
gitgitgadget


[PATCH 1/1] legacy-rebase: backport -C and --whitespace= checks

2018-11-20 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

Since 04519d720114 (rebase: validate -C and --whitespace=
parameters early, 2018-11-14), the built-in rebase validates the -C and
--whitespace arguments early. As this commit also introduced a
regression test for this, and as a later commit introduced the
GIT_TEST_REBASE_USE_BUILTIN mode to run tests, we now have a
"regression" in the scripted version of `git rebase` on our hands.

Backport the validation to fix this.

Reported-by: Ævar Arnfjörð Bjarmason 
Signed-off-by: Johannes Schindelin 
---
 git-legacy-rebase.sh | 8 
 1 file changed, 8 insertions(+)

diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
index 75a08b2683..ced0635326 100755
--- a/git-legacy-rebase.sh
+++ b/git-legacy-rebase.sh
@@ -337,6 +337,11 @@ do
fix|strip)
force_rebase=t
;;
+   warn|nowarn|error|error-all)
+   ;; # okay, known whitespace option
+   *)
+   die "Invalid whitespace option: '${1%*=}'"
+   ;;
esac
;;
--ignore-whitespace)
@@ -352,6 +357,9 @@ do
git_am_opt="$git_am_opt $1"
force_rebase=t
;;
+   -C*[!0-9]*)
+   die "switch \`C' expects a numerical value"
+   ;;
-C*)
git_am_opt="$git_am_opt $1"
;;
-- 
gitgitgadget


[PATCH 0/1] Fix Windows build of next

2018-11-22 Thread Johannes Schindelin via GitGitGadget
The topic ot/ref-filter-object-info broke the Windows build since it entered 
pu, and as a consequence we have no test coverage of the other topics in pu.

Sadly, this topic now advanced to next. Junio, I would like to ask you to
merge this fix down to next and to advance to master together with 
ot/ref-filter-object-info.

Johannes Schindelin (1):
  ref-filter: replace unportable `%lld` format

 ref-filter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


base-commit: d364d6b33e15dbc6e57d83f9f1457a8e8fe77046
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-87%2Fdscho%2Fno-percent-lld-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-87/dscho/no-percent-lld-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/87
-- 
gitgitgadget


[PATCH 1/1] ref-filter: replace unportable `%lld` format

2018-11-22 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The `%lld` format is supported on Linux and macOS, but not on Windows.
This issue has been reported ten days ago (Message-ID:
nycvar.qro.7.76.6.1811121300520...@tvgsbejvaqbjf.bet), but the
corresponding topic still advanced to `next` in the meantime, breaking
the Windows build.

Let's use `PRIdMAX` and a cast to `intmax_t` instead, which unbreaks the
build, and imitates how we do things e.g. in `json-writer.c` already.

Signed-off-by: Johannes Schindelin 
---
 ref-filter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ref-filter.c b/ref-filter.c
index 3cfe01a039..69cdf2dbb5 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -897,7 +897,7 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct expand_
v->s = xstrdup(type_name(oi->type));
else if (!strcmp(name, "objectsize:disk")) {
v->value = oi->disk_size;
-   v->s = xstrfmt("%lld", (long long)oi->disk_size);
+   v->s = xstrfmt("%"PRIdMAX, (intmax_t)oi->disk_size);
} else if (!strcmp(name, "objectsize")) {
v->value = oi->size;
v->s = xstrfmt("%lu", oi->size);
-- 
gitgitgadget


[PATCH 1/1] rebase: warn about the correct tree's OID

2018-11-20 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

This was a simple copy/paste error, and an obvious one at that: if we
cannot fill the tree descriptor, we should show an error message about
*that* tree, not another one.

Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 1a2758756a..5b3e5baec8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -582,7 +582,8 @@ static int reset_head(struct object_id *oid, const char 
*action,
}
 
if (!reset_hard && !fill_tree_descriptor([nr++], _oid)) {
-   ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
+   ret = error(_("failed to find tree of %s"),
+   oid_to_hex(_oid));
goto leave_reset_head;
}
 
-- 
gitgitgadget


[PATCH 0/1] rebase: warn about the correct tree's OID

2018-11-20 Thread Johannes Schindelin via GitGitGadget
A quick fix for a recent topic. Not overly critical, but I would deem this
v2.20.0-rc1 material.

Johannes Schindelin (1):
  rebase: warn about the correct tree's OID

 builtin/rebase.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


base-commit: bb75be6cb916297f271c846f2f9caa3daaaec718
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-85%2Fdscho%2Freset_head-typo-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-85/dscho/reset_head-typo-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/85
-- 
gitgitgadget


[PATCH 1/1] rebase --stat: fix when rebasing to an unrelated history

2018-11-27 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

When rebasing to a commit history that has no common commits with the
current branch, there is no merge base. The scripted version of the `git
rebase` command was not prepared for that and spewed out

fatal: ambiguous argument '': unknown revision or path not in
the working tree.

but then continued (due to lack of error checking).

The built-in version of the `git rebase` command blindly translated that
shell script code, assuming that there is no need to test whether there
*was* a merge base, and due to its better error checking, exited with a
fatal error (because it tried to read the object with hash ...
as a tree).

Fix both scripted and built-in versions to output something sensibly,
and add a regression test to keep this working in all eternity.

Reported-by: Ævar Arnfjörð Bjarmason 
Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c  |  8 +---
 git-legacy-rebase.sh  |  6 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..9e4b0b564f 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1483,7 +1483,8 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
 
if (options.flags & REBASE_VERBOSE)
printf(_("Changes from %s to %s:\n"),
-   oid_to_hex(_base),
+   is_null_oid(_base) ?
+   "(empty)" : oid_to_hex(_base),
oid_to_hex(>object.oid));
 
/* We want color (if set), but no pager */
@@ -1494,8 +1495,9 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME;
diff_setup_done();
-   diff_tree_oid(_base, >object.oid,
- "", );
+   diff_tree_oid(is_null_oid(_base) ?
+ the_hash_algo->empty_tree : _base,
+ >object.oid, "", );
diffcore_std();
diff_flush();
}
diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
index b97ffdc9dd..be3b241676 100755
--- a/git-legacy-rebase.sh
+++ b/git-legacy-rebase.sh
@@ -718,10 +718,12 @@ if test -n "$diffstat"
 then
if test -n "$verbose"
then
-   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+   mb_display="${mb:-(empty)}"
+   echo "$(eval_gettext "Changes from \$mb_display to \$onto:")"
fi
+   mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
# We want color (if set), but no pager
-   GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+   GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
 fi
 
 test -n "$interactive_rebase" && run_specific_rebase
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..a1ee912118 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -91,4 +91,14 @@ test_expect_success 'error out early upon -C or 
--whitespace=' '
test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'rebase -i onto unrelated history' '
+   git init unrelated &&
+   test_commit -C unrelated 1 &&
+   git -C unrelated remote add -f origin "$PWD" &&
+   git -C unrelated branch --set-upstream-to=origin/master &&
+   git -C unrelated -c core.editor=true rebase -i -v --stat >actual &&
+   test_i18ngrep "Changes from (empty)" actual &&
+   test_i18ngrep "5 files changed" actual
+'
+
 test_done
-- 
gitgitgadget


[PATCH 0/1] Fix git rebase --stat -i

2018-11-27 Thread Johannes Schindelin via GitGitGadget
We're really entering obscure territory here, I would say.

To trigger the bug, two things have to come together: the user must have
asked for a diffstat afterwards, and the commits need to have been rebased
onto a completely unrelated commit history (i.e. there must exist no merge
base between the pre-rebase HEAD and the post-rebase HEAD).

Please note that this bug existed already in the scripted rebase, but it was
never detected because the scripted version would not even perform any error
checking.

It will make Junio very happy that I squashed the regression test in to the
patch that fixes it. The reason, however, was not to make Junio happy (I
hope to make him happy by fixing bugs), but simply that an earlier iteration
of test would only fail with the built-in rebase, but not with the scripted
version. The current version would fail with the scripted version, but I'll
save the time to split the patch again now.

Johannes Schindelin (1):
  rebase --stat: fix when rebasing to an unrelated history

 builtin/rebase.c  |  8 +---
 git-legacy-rebase.sh  |  6 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 19 insertions(+), 5 deletions(-)


base-commit: a1598010f775d82b5adf12c29d0f5bc9b41434c6
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-88%2Fdscho%2Frebase-stat-fix-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-88/dscho/rebase-stat-fix-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/88
-- 
gitgitgadget


<    1   2   3   4