t / t3510-cherry-pick-sequence.shon commit xdiff: PATIENCE/HISTOGRAM are not independent option bits (307ab20)
   1#!/bin/sh
   2
   3test_description='Test cherry-pick continuation features
   4
   5  + yetanotherpick: rewrites foo to e
   6  + anotherpick: rewrites foo to d
   7  + picked: rewrites foo to c
   8  + unrelatedpick: rewrites unrelated to reallyunrelated
   9  + base: rewrites foo to b
  10  + initial: writes foo as a, unrelated as unrelated
  11
  12'
  13
  14. ./test-lib.sh
  15
  16pristine_detach () {
  17        git cherry-pick --quit &&
  18        git checkout -f "$1^0" &&
  19        git read-tree -u --reset HEAD &&
  20        git clean -d -f -f -q -x
  21}
  22
  23test_cmp_rev () {
  24        git rev-parse --verify "$1" >expect.rev &&
  25        git rev-parse --verify "$2" >actual.rev &&
  26        test_cmp expect.rev actual.rev
  27}
  28
  29test_expect_success setup '
  30        echo unrelated >unrelated &&
  31        git add unrelated &&
  32        test_commit initial foo a &&
  33        test_commit base foo b &&
  34        test_commit unrelatedpick unrelated reallyunrelated &&
  35        test_commit picked foo c &&
  36        test_commit anotherpick foo d &&
  37        test_commit yetanotherpick foo e &&
  38        git config advice.detachedhead false
  39
  40'
  41
  42test_expect_success 'cherry-pick persists data on failure' '
  43        pristine_detach initial &&
  44        test_must_fail git cherry-pick -s base..anotherpick &&
  45        test_path_is_dir .git/sequencer &&
  46        test_path_is_file .git/sequencer/head &&
  47        test_path_is_file .git/sequencer/todo &&
  48        test_path_is_file .git/sequencer/opts
  49'
  50
  51test_expect_success 'cherry-pick persists opts correctly' '
  52        pristine_detach initial &&
  53        test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&
  54        test_path_is_dir .git/sequencer &&
  55        test_path_is_file .git/sequencer/head &&
  56        test_path_is_file .git/sequencer/todo &&
  57        test_path_is_file .git/sequencer/opts &&
  58        echo "true" >expect &&
  59        git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
  60        test_cmp expect actual &&
  61        echo "1" >expect &&
  62        git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
  63        test_cmp expect actual &&
  64        echo "recursive" >expect &&
  65        git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
  66        test_cmp expect actual &&
  67        cat >expect <<-\EOF &&
  68        patience
  69        ours
  70        EOF
  71        git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
  72        test_cmp expect actual
  73'
  74
  75test_expect_success 'cherry-pick cleans up sequencer state upon success' '
  76        pristine_detach initial &&
  77        git cherry-pick initial..picked &&
  78        test_path_is_missing .git/sequencer
  79'
  80
  81test_expect_success '--quit does not complain when no cherry-pick is in progress' '
  82        pristine_detach initial &&
  83        git cherry-pick --quit
  84'
  85
  86test_expect_success '--abort requires cherry-pick in progress' '
  87        pristine_detach initial &&
  88        test_must_fail git cherry-pick --abort
  89'
  90
  91test_expect_success '--quit cleans up sequencer state' '
  92        pristine_detach initial &&
  93        test_must_fail git cherry-pick base..picked &&
  94        git cherry-pick --quit &&
  95        test_path_is_missing .git/sequencer
  96'
  97
  98test_expect_success '--quit keeps HEAD and conflicted index intact' '
  99        pristine_detach initial &&
 100        cat >expect <<-\EOF &&
 101        OBJID
 102        :100644 100644 OBJID OBJID M    unrelated
 103        OBJID
 104        :000000 100644 OBJID OBJID A    foo
 105        :000000 100644 OBJID OBJID A    unrelated
 106        EOF
 107        test_must_fail git cherry-pick base..picked &&
 108        git cherry-pick --quit &&
 109        test_path_is_missing .git/sequencer &&
 110        test_must_fail git update-index --refresh &&
 111        {
 112                git rev-list HEAD |
 113                git diff-tree --root --stdin |
 114                sed "s/$_x40/OBJID/g"
 115        } >actual &&
 116        test_cmp expect actual
 117'
 118
 119test_expect_success '--abort to cancel multiple cherry-pick' '
 120        pristine_detach initial &&
 121        test_must_fail git cherry-pick base..anotherpick &&
 122        git cherry-pick --abort &&
 123        test_path_is_missing .git/sequencer &&
 124        test_cmp_rev initial HEAD &&
 125        git update-index --refresh &&
 126        git diff-index --exit-code HEAD
 127'
 128
 129test_expect_success '--abort to cancel single cherry-pick' '
 130        pristine_detach initial &&
 131        test_must_fail git cherry-pick picked &&
 132        git cherry-pick --abort &&
 133        test_path_is_missing .git/sequencer &&
 134        test_cmp_rev initial HEAD &&
 135        git update-index --refresh &&
 136        git diff-index --exit-code HEAD
 137'
 138
 139test_expect_success 'cherry-pick --abort to cancel multiple revert' '
 140        pristine_detach anotherpick &&
 141        test_must_fail git revert base..picked &&
 142        git cherry-pick --abort &&
 143        test_path_is_missing .git/sequencer &&
 144        test_cmp_rev anotherpick HEAD &&
 145        git update-index --refresh &&
 146        git diff-index --exit-code HEAD
 147'
 148
 149test_expect_success 'revert --abort works, too' '
 150        pristine_detach anotherpick &&
 151        test_must_fail git revert base..picked &&
 152        git revert --abort &&
 153        test_path_is_missing .git/sequencer &&
 154        test_cmp_rev anotherpick HEAD
 155'
 156
 157test_expect_success '--abort to cancel single revert' '
 158        pristine_detach anotherpick &&
 159        test_must_fail git revert picked &&
 160        git revert --abort &&
 161        test_path_is_missing .git/sequencer &&
 162        test_cmp_rev anotherpick HEAD &&
 163        git update-index --refresh &&
 164        git diff-index --exit-code HEAD
 165'
 166
 167test_expect_success '--abort keeps unrelated change, easy case' '
 168        pristine_detach unrelatedpick &&
 169        echo changed >expect &&
 170        test_must_fail git cherry-pick picked..yetanotherpick &&
 171        echo changed >unrelated &&
 172        git cherry-pick --abort &&
 173        test_cmp expect unrelated
 174'
 175
 176test_expect_success '--abort refuses to clobber unrelated change, harder case' '
 177        pristine_detach initial &&
 178        echo changed >expect &&
 179        test_must_fail git cherry-pick base..anotherpick &&
 180        echo changed >unrelated &&
 181        test_must_fail git cherry-pick --abort &&
 182        test_cmp expect unrelated &&
 183        git rev-list HEAD >log &&
 184        test_line_count = 2 log &&
 185        test_must_fail git update-index --refresh &&
 186
 187        git checkout unrelated &&
 188        git cherry-pick --abort &&
 189        test_cmp_rev initial HEAD
 190'
 191
 192test_expect_success 'cherry-pick cleans up sequencer state when one commit is left' '
 193        pristine_detach initial &&
 194        test_must_fail git cherry-pick base..picked &&
 195        test_path_is_missing .git/sequencer &&
 196        echo "resolved" >foo &&
 197        git add foo &&
 198        git commit &&
 199        {
 200                git rev-list HEAD |
 201                git diff-tree --root --stdin |
 202                sed "s/$_x40/OBJID/g"
 203        } >actual &&
 204        cat >expect <<-\EOF &&
 205        OBJID
 206        :100644 100644 OBJID OBJID M    foo
 207        OBJID
 208        :100644 100644 OBJID OBJID M    unrelated
 209        OBJID
 210        :000000 100644 OBJID OBJID A    foo
 211        :000000 100644 OBJID OBJID A    unrelated
 212        EOF
 213        test_cmp expect actual
 214'
 215
 216test_expect_failure '--abort after last commit in sequence' '
 217        pristine_detach initial &&
 218        test_must_fail git cherry-pick base..picked &&
 219        git cherry-pick --abort &&
 220        test_path_is_missing .git/sequencer &&
 221        test_cmp_rev initial HEAD &&
 222        git update-index --refresh &&
 223        git diff-index --exit-code HEAD
 224'
 225
 226test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
 227        pristine_detach initial &&
 228        test_must_fail git cherry-pick base..anotherpick &&
 229        test-chmtime -v +0 .git/sequencer >expect &&
 230        test_must_fail git cherry-pick unrelatedpick &&
 231        test-chmtime -v +0 .git/sequencer >actual &&
 232        test_cmp expect actual
 233'
 234
 235test_expect_success '--continue complains when no cherry-pick is in progress' '
 236        pristine_detach initial &&
 237        test_must_fail git cherry-pick --continue
 238'
 239
 240test_expect_success '--continue complains when there are unresolved conflicts' '
 241        pristine_detach initial &&
 242        test_must_fail git cherry-pick base..anotherpick &&
 243        test_must_fail git cherry-pick --continue
 244'
 245
 246test_expect_success '--continue continues after conflicts are resolved' '
 247        pristine_detach initial &&
 248        test_must_fail git cherry-pick base..anotherpick &&
 249        echo "c" >foo &&
 250        git add foo &&
 251        git commit &&
 252        git cherry-pick --continue &&
 253        test_path_is_missing .git/sequencer &&
 254        {
 255                git rev-list HEAD |
 256                git diff-tree --root --stdin |
 257                sed "s/$_x40/OBJID/g"
 258        } >actual &&
 259        cat >expect <<-\EOF &&
 260        OBJID
 261        :100644 100644 OBJID OBJID M    foo
 262        OBJID
 263        :100644 100644 OBJID OBJID M    foo
 264        OBJID
 265        :100644 100644 OBJID OBJID M    unrelated
 266        OBJID
 267        :000000 100644 OBJID OBJID A    foo
 268        :000000 100644 OBJID OBJID A    unrelated
 269        EOF
 270        test_cmp expect actual
 271'
 272
 273test_expect_success '--continue respects opts' '
 274        pristine_detach initial &&
 275        test_must_fail git cherry-pick -x base..anotherpick &&
 276        echo "c" >foo &&
 277        git add foo &&
 278        git commit &&
 279        git cherry-pick --continue &&
 280        test_path_is_missing .git/sequencer &&
 281        git cat-file commit HEAD >anotherpick_msg &&
 282        git cat-file commit HEAD~1 >picked_msg &&
 283        git cat-file commit HEAD~2 >unrelatedpick_msg &&
 284        git cat-file commit HEAD~3 >initial_msg &&
 285        test_must_fail grep "cherry picked from" initial_msg &&
 286        grep "cherry picked from" unrelatedpick_msg &&
 287        grep "cherry picked from" picked_msg &&
 288        grep "cherry picked from" anotherpick_msg
 289'
 290
 291test_expect_success '--signoff is not automatically propagated to resolved conflict' '
 292        pristine_detach initial &&
 293        test_must_fail git cherry-pick --signoff base..anotherpick &&
 294        echo "c" >foo &&
 295        git add foo &&
 296        git commit &&
 297        git cherry-pick --continue &&
 298        test_path_is_missing .git/sequencer &&
 299        git cat-file commit HEAD >anotherpick_msg &&
 300        git cat-file commit HEAD~1 >picked_msg &&
 301        git cat-file commit HEAD~2 >unrelatedpick_msg &&
 302        git cat-file commit HEAD~3 >initial_msg &&
 303        test_must_fail grep "Signed-off-by:" initial_msg &&
 304        grep "Signed-off-by:" unrelatedpick_msg &&
 305        test_must_fail grep "Signed-off-by:" picked_msg &&
 306        grep "Signed-off-by:" anotherpick_msg
 307'
 308
 309test_expect_success 'malformed instruction sheet 1' '
 310        pristine_detach initial &&
 311        test_must_fail git cherry-pick base..anotherpick &&
 312        echo "resolved" >foo &&
 313        git add foo &&
 314        git commit &&
 315        sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
 316        cp new_sheet .git/sequencer/todo &&
 317        test_must_fail git cherry-pick --continue
 318'
 319
 320test_expect_success 'malformed instruction sheet 2' '
 321        pristine_detach initial &&
 322        test_must_fail git cherry-pick base..anotherpick &&
 323        echo "resolved" >foo &&
 324        git add foo &&
 325        git commit &&
 326        sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
 327        cp new_sheet .git/sequencer/todo &&
 328        test_must_fail git cherry-pick --continue
 329'
 330
 331test_done