view tests/test-merge-combination.t @ 44909:d452acc8cce8 stable

flags: account for flag change when tracking rename relevant to merge There are some logic filtering rename to the one relevant to the merge. That logic was oblivious of flag change, leading to exec flag being dropped when merged with a renamed. There are two others bugs affecting this scenario. This patch fix the was where there is not modification involved except for the flag change. Fixes for the other bug are coming in later changesets. Differential Revision: https://phab.mercurial-scm.org/D8531
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sat, 16 May 2020 20:37:56 +0200
parents 302dbc9d52be
children 8045e4aa366b
line wrap: on
line source

This file shows what hg says are "modified" files for a merge commit
(hg log -T {files}), somewhat exhaustively.
It shows merges that involves files contents changing, and merges that
involve executable bit changing, but not merges with multiple or zero
merge ancestors, nor copies/renames, and nor identical file contents
with different filelog revisions.

genmerges is the workhorse. Given:
- a range function describing the possible values for file a
- a isgood function to filter out uninteresting combination
- a createfile function to actually write the values for file a on the
filesystem
it print a series of lines that look like: abcd C: output of -T {files}
describing the file a at respectively the base, p2, p1, merge
revision. "C" indicates that hg merge had conflicts.
  $ genmerges () {
  >   for base in `range` -; do
  >     for r1 in `range $base` -; do
  >       for r2 in `range $base $r1` -; do
  >         for m in `range $base $r1 $r2` -; do
  >           line="$base$r1$r2$m"
  >           isgood $line || continue
  >           hg init repo
  >           cd repo
  >           make_commit () {
  >             v=$1; msg=$2; file=$3;
  >             if [ $v != - ]; then
  >               createfile $v
  >             else
  >               if [ -f a ]
  >               then rm a
  >               else touch $file
  >               fi
  >             fi
  >             hg commit -q -Am $msg || exit 123
  >           }
  >           echo foo > foo
  >           make_commit $base base b
  >           make_commit $r1 r1 c
  >           hg up -r 0 -q
  >           make_commit $r2 r2 d
  >           hg merge -q -r 1 > ../output 2>&1
  >           if [ $? -ne 0 ]; then rm -f *.orig; hg resolve -m --all -q; fi
  >           if [ -s ../output ]; then conflicts=" C"; else conflicts="  "; fi
  >           make_commit $m m e
  >           if [ $m = $r1 ] && [ $m = $r2 ]
  >           then expected=
  >           elif [ $m = $r1 ]
  >           then if [ $base = $r2 ]
  >                then expected=
  >                else expected=a
  >                fi
  >           elif [ $m = $r2 ]
  >           then if [ $base = $r1 ]
  >                then expected=
  >                else expected=a
  >                fi
  >           else expected=a
  >           fi
  >           got=`hg log -r 3 --template '{files}\n' | tr -d 'e '`
  >           if [ "$got" = "$expected" ]
  >           then echo "$line$conflicts: agree on \"$got\""
  >           else echo "$line$conflicts: hg said \"$got\", expected \"$expected\""
  >           fi
  >           cd ../
  >           rm -rf repo
  >         done
  >       done
  >     done
  >   done
  > }

All the merges of various file contents.

  $ range () {
  >   max=0
  >   for i in $@; do
  >     if [ $i = - ]; then continue; fi
  >     if [ $i -gt $max ]; then max=$i; fi
  >   done
  >   $TESTDIR/seq.py `expr $max + 1`
  > }
  $ isgood () { true; }
  $ createfile () {
  >   if [ -f a ] && [ "`cat a`" = $1 ]
  >   then touch $file
  >   else echo $v > a
  >   fi
  > }

  $ genmerges
  1111  : agree on ""
  1112  : agree on "a"
  111-  : agree on "a"
  1121  : agree on "a"
  1122  : agree on ""
  1123  : agree on "a"
  112-  : agree on "a"
  11-1  : hg said "", expected "a"
  11-2  : agree on "a"
  11--  : agree on ""
  1211  : agree on "a"
  1212  : agree on ""
  1213  : agree on "a"
  121-  : agree on "a"
  1221  : agree on "a"
  1222  : agree on ""
  1223  : agree on "a"
  122-  : agree on "a"
  1231 C: agree on "a"
  1232 C: agree on "a"
  1233 C: agree on "a"
  1234 C: agree on "a"
  123- C: agree on "a"
  12-1 C: agree on "a"
  12-2 C: hg said "", expected "a"
  12-3 C: agree on "a"
  12-- C: agree on "a"
  1-11  : hg said "", expected "a"
  1-12  : agree on "a"
  1-1-  : agree on ""
  1-21 C: agree on "a"
  1-22 C: hg said "", expected "a"
  1-23 C: agree on "a"
  1-2- C: agree on "a"
  1--1  : agree on "a"
  1--2  : agree on "a"
  1---  : agree on ""
  -111  : agree on ""
  -112  : agree on "a"
  -11-  : agree on "a"
  -121 C: agree on "a"
  -122 C: agree on "a"
  -123 C: agree on "a"
  -12- C: agree on "a"
  -1-1  : agree on ""
  -1-2  : agree on "a"
  -1--  : agree on "a"
  --11  : agree on ""
  --12  : agree on "a"
  --1-  : agree on "a"
  ---1  : agree on "a"
  ----  : agree on ""

All the merges of executable bit.

  $ range () {
  >   max=a
  >   for i in $@; do
  >     if [ $i = - ]; then continue; fi
  >     if [ $i > $max ]; then max=$i; fi
  >   done
  >   if [ $max = a ]; then echo f; else echo f x; fi
  > }
  $ isgood () { case $line in *f*x*) true;; *) false;; esac; }
  $ createfile () {
  >   if [ -f a ] && (([ -x a ] && [ $v = x ]) || (! [ -x a ] && [ $v != x ]))
  >   then touch $file
  >   else touch a; if [ $v = x ]; then chmod +x a; else chmod -x a; fi
  >   fi
  > }

#if execbit
  $ genmerges
  fffx  : agree on "a"
  ffxf  : agree on "a"
  ffxx  : agree on ""
  ffx-  : agree on "a"
  ff-x  : hg said "", expected "a"
  fxff  : hg said "", expected "a"
  fxfx  : hg said "a", expected ""
  fxf-  : agree on "a"
  fxxf  : agree on "a"
  fxxx  : agree on ""
  fxx-  : agree on "a"
  fx-f  : hg said "", expected "a"
  fx-x  : hg said "", expected "a"
  fx--  : hg said "", expected "a"
  f-fx  : agree on "a"
  f-xf  : agree on "a"
  f-xx  : hg said "", expected "a"
  f-x-  : agree on "a"
  f--x  : agree on "a"
  -ffx  : agree on "a"
  -fxf C: agree on "a"
  -fxx C: hg said "", expected "a"
  -fx- C: agree on "a"
  -f-x  : hg said "", expected "a"
  --fx  : agree on "a"
#endif

Files modified or cleanly merged, with no greatest common ancestors:

  $ hg init repo; cd repo
  $ touch a0 b0; hg commit -qAm 0
  $ hg up -qr null; touch a1 b1; hg commit -qAm 1
  $ hg merge -qr 0; rm b*; hg commit -qAm 2
  $ hg log -r . -T '{files}\n'
  b0 b1
  $ cd ../
  $ rm -rf repo

A few cases of criss-cross merges involving deletions (listing all
such merges is probably too much). Both gcas contain $files, so we
expect the final merge to behave like a merge with a single gca
containing $files.

  $ hg init repo; cd repo
  $ files="c1 u1 c2 u2"
  $ touch $files; hg commit -qAm '0 root'
  $ for f in $files; do echo f > $f; done; hg commit -qAm '1 gca1'
  $ hg up -qr0; hg revert -qr 1 --all; hg commit -qAm '2 gca2'
  $ hg up -qr 1; hg merge -qr 2; rm *1; hg commit -qAm '3 p1'
  $ hg up -qr 2; hg merge -qr 1; rm *2; hg commit -qAm '4 p2'
  $ hg merge -qr 3; echo f > u1; echo f > u2; rm -f c1 c2
  $ hg commit -qAm '5 merge with two gcas'
  $ hg log -r . -T '{files}\n' # expecting u1 u2
  
  $ cd ../
  $ rm -rf repo