Merge branch 'mt/patch-id-stable' (early part)
authorJunio C Hamano <gitster@pobox.com>
Mon, 16 Jun 2014 17:05:37 +0000 (10:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 16 Jun 2014 17:05:38 +0000 (10:05 -0700)
* 'mt/patch-id-stable' (early part):
patch-id-test: test stable and unstable behaviour
patch-id: make it stable against hunk reordering
test doc: test_write_lines does not split its arguments
test: add test_write_lines helper

1  2 
t/t4204-patch-id.sh
t/test-lib-functions.sh
diff --combined t/t4204-patch-id.sh
index 7940f6f0b952b5accd3f1263f08e131a018de140,fe011f83ff46064c4c287ecdc9bf27047c30672a..baa9d3c82e8a54dc7501d90bc9da0527f2a72b2e
@@@ -5,27 -5,44 +5,44 @@@ test_description='git patch-id
  . ./test-lib.sh
  
  test_expect_success 'setup' '
-       test_commit initial foo a &&
-       test_commit first foo b &&
-       git checkout -b same HEAD^ &&
-       test_commit same-msg foo b &&
-       git checkout -b notsame HEAD^ &&
-       test_commit notsame-msg foo c
+       as="a a a a a a a a" && # eight a
+       test_write_lines $as >foo &&
+       test_write_lines $as >bar &&
+       git add foo bar &&
+       git commit -a -m initial &&
+       test_write_lines $as b >foo &&
+       test_write_lines $as b >bar &&
+       git commit -a -m first &&
+       git checkout -b same master &&
+       git commit --amend -m same-msg &&
+       git checkout -b notsame master &&
+       echo c >foo &&
+       echo c >bar &&
+       git commit --amend -a -m notsame-msg &&
+       test_write_lines bar foo >bar-then-foo &&
+       test_write_lines foo bar >foo-then-bar
  '
  
  test_expect_success 'patch-id output is well-formed' '
-       git log -p -1 | git patch-id > output &&
+       git log -p -1 | git patch-id >output &&
        grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output
  '
  
+ #calculate patch id. Make sure output is not empty.
  calc_patch_id () {
-       git patch-id |
-               sed "s# .*##" > patch-id_"$1"
+       name="$1"
+       shift
+       git patch-id "$@" |
+       sed "s/ .*//" >patch-id_"$name" &&
+       test_line_count -gt 0 patch-id_"$name"
+ }
+ get_top_diff () {
+       git log -p -1 "$@" -O bar-then-foo --
  }
  
  get_patch_id () {
-       git log -p -1 "$1" | git patch-id |
-               sed "s# .*##" > patch-id_"$1"
+       get_top_diff "$1" | calc_patch_id "$@"
  }
  
  test_expect_success 'patch-id detects equality' '
@@@ -45,8 -62,8 +62,8 @@@ test_expect_success 'patch-id supports 
        git checkout same &&
        git format-patch -1 --stdout | calc_patch_id same &&
        test_cmp patch-id_master patch-id_same &&
 -      set `git format-patch -1 --stdout | git patch-id` &&
 -      test "$2" = `git rev-parse HEAD`
 +      set $(git format-patch -1 --stdout | git patch-id) &&
 +      test "$2" = $(git rev-parse HEAD)
  '
  
  test_expect_success 'whitespace is irrelevant in footer' '
        test_cmp patch-id_master patch-id_same
  '
  
+ cmp_patch_id () {
+       if
+               test "$1" = "relevant"
+       then
+               ! test_cmp patch-id_"$2" patch-id_"$3"
+       else
+               test_cmp patch-id_"$2" patch-id_"$3"
+       fi
+ }
+ test_patch_id_file_order () {
+       relevant="$1"
+       shift
+       name="order-${1}-$relevant"
+       shift
+       get_top_diff "master" | calc_patch_id "$name" "$@" &&
+       git checkout same &&
+       git format-patch -1 --stdout -O foo-then-bar |
+               calc_patch_id "ordered-$name" "$@" &&
+       cmp_patch_id $relevant "$name" "ordered-$name"
+ }
+ # combined test for options: add more tests here to make them
+ # run with all options
+ test_patch_id () {
+       test_patch_id_file_order "$@"
+ }
+ # small tests with detailed diagnostic for basic options.
+ test_expect_success 'file order is irrelevant with --stable' '
+       test_patch_id_file_order irrelevant --stable --stable
+ '
+ test_expect_success 'file order is relevant with --unstable' '
+       test_patch_id_file_order relevant --unstable --unstable
+ '
+ #Now test various option combinations.
+ test_expect_success 'default is unstable' '
+       test_patch_id relevant default
+ '
+ test_expect_success 'patchid.stable = true is stable' '
+       test_config patchid.stable true &&
+       test_patch_id irrelevant patchid.stable=true
+ '
+ test_expect_success 'patchid.stable = false is unstable' '
+       test_config patchid.stable false &&
+       test_patch_id relevant patchid.stable=false
+ '
+ test_expect_success '--unstable overrides patchid.stable = true' '
+       test_config patchid.stable true &&
+       test_patch_id relevant patchid.stable=true--unstable --unstable
+ '
+ test_expect_success '--stable overrides patchid.stable = false' '
+       test_config patchid.stable false &&
+       test_patch_id irrelevant patchid.stable=false--stable --stable
+ '
  test_expect_success 'patch-id supports git-format-patch MIME output' '
        get_patch_id master &&
        git checkout same &&
diff --combined t/test-lib-functions.sh
index 158e10a67e5878bb9031af2f28439b099b65fd50,213fd0f3c5542fcd34137d9239027c64597ca40d..f5815350d3e30fe16a229295eed67ad6969be639
@@@ -32,11 -32,6 +32,11 @@@ test_set_editor () 
        export EDITOR
  }
  
 +test_set_index_version () {
 +    GIT_INDEX_VERSION="$1"
 +    export GIT_INDEX_VERSION
 +}
 +
  test_decode_color () {
        awk '
                function name(n) {
@@@ -717,68 -712,15 +717,73 @@@ test_ln_s_add () 
        fi
  }
  
+ # This function writes out its parameters, one per line
+ test_write_lines () {
+       printf "%s\n" "$@"
+ }
  perl () {
        command "$PERL_PATH" "$@"
  }
  
 +# Is the value one of the various ways to spell a boolean true/false?
 +test_normalize_bool () {
 +      git -c magic.variable="$1" config --bool magic.variable 2>/dev/null
 +}
 +
 +# Given a variable $1, normalize the value of it to one of "true",
 +# "false", or "auto" and store the result to it.
 +#
 +#     test_tristate GIT_TEST_HTTPD
 +#
 +# A variable set to an empty string is set to 'false'.
 +# A variable set to 'false' or 'auto' keeps its value.
 +# Anything else is set to 'true'.
 +# An unset variable defaults to 'auto'.
 +#
 +# The last rule is to allow people to set the variable to an empty
 +# string and export it to decline testing the particular feature
 +# for versions both before and after this change.  We used to treat
 +# both unset and empty variable as a signal for "do not test" and
 +# took any non-empty string as "please test".
 +
 +test_tristate () {
 +      if eval "test x\"\${$1+isset}\" = xisset"
 +      then
 +              # explicitly set
 +              eval "
 +                      case \"\$$1\" in
 +                      '')     $1=false ;;
 +                      auto)   ;;
 +                      *)      $1=\$(test_normalize_bool \$$1 || echo true) ;;
 +                      esac
 +              "
 +      else
 +              eval "$1=auto"
 +      fi
 +}
 +
 +# Exit the test suite, either by skipping all remaining tests or by
 +# exiting with an error. If "$1" is "auto", we then we assume we were
 +# opportunistically trying to set up some tests and we skip. If it is
 +# "true", then we report a failure.
 +#
 +# The error/skip message should be given by $2.
 +#
 +test_skip_or_die () {
 +      case "$1" in
 +      auto)
 +              skip_all=$2
 +              test_done
 +              ;;
 +      true)
 +              error "$2"
 +              ;;
 +      *)
 +              error "BUG: test tristate is '$1' (real error: $2)"
 +      esac
 +}
 +
  # The following mingw_* functions obey POSIX shell syntax, but are actually
  # bash scripts, and are meant to be used only with bash on Windows.