[PATCH 4 of 4 mergedriver] mergestate: handle additional record types specially

Martin von Zweigbergk martinvonz at google.com
Wed Nov 18 18:40:33 UTC 2015


On Tue, Nov 17, 2015 at 10:45 PM Siddharth Agarwal <sid0 at fb.com> wrote:

> # HG changeset patch
> # User Siddharth Agarwal <sid0 at fb.com>
> # Date 1447804144 28800
> #      Tue Nov 17 15:49:04 2015 -0800
> # Node ID c95cea9046503b32461910270ed8966d7b790073
> # Parent  5a8a002259aa129e3c3a332df860d09db62c2964
> # Available At http://42.netv6.net/sid0-wip/hg/
> #              hg pull http://42.netv6.net/sid0-wip/hg/ -r c95cea904650
> mergestate: handle additional record types specially
>
> This works around a bug in older Mercurial versions' handling of the v2
> merge
> state.
>
> We also add a bunch of tests that make sure that
> (1) we correctly abort when the merge state has an unsupported record type
> (2) aborting the merge, rebase or histedit continues to work.
>
> diff --git a/mercurial/merge.py b/mercurial/merge.py
> --- a/mercurial/merge.py
> +++ b/mercurial/merge.py
> @@ -65,6 +65,8 @@ class mergestate(object):
>         (experimental)
>      m: the external merge driver defined for this merge plus its run state
>         (experimental)
> +    X: unsupported mandatory record type (used in tests)
> +    x: unsupported advisory record type (used in tests)
>
>      Merge driver run states (experimental):
>      u: driver-resolved files unmarked -- needs to be run next time we're
> about
> @@ -226,7 +228,15 @@ class mergestate(object):
>      def _readrecordsv2(self):
>          """read on disk merge state for version 2 file
>
> -        returns list of record [(TYPE, data), ...]
> +        Mercurial versions prior to 3.7 have a bug where if there are
> +        unsupported mandatory merge records, attempting to clear out the
> merge
> +        state with hg update --clean or similar aborts. The 't' record
> type
> +        works around that by writing out what those versions treat as an
> +        advisory record, but later versions interpret as special: the
> first
> +        character is the 'real' record type and everything onwards is the
> data.
> +
> +        Returns list of records [(TYPE, data), ...].
> +
>          """
>          records = []
>          try:
> @@ -241,6 +251,8 @@ class mergestate(object):
>                  off += 4
>                  record = data[off:(off + length)]
>                  off += length
> +                if rtype == 't':
> +                    rtype, record = record[0], record[1:]
>                  records.append((rtype, record))
>              f.close()
>          except IOError as err:
> @@ -322,10 +334,16 @@ class mergestate(object):
>          f.close()
>
>      def _writerecordsv2(self, records):
> -        """Write current state on disk in a version 2 file"""
> +        """Write current state on disk in a version 2 file
> +
> +        See the docstring for _readrecordsv2 for why we use 't'."""
> +        # these are the records that all version 2 clients can read
> +        whitelist = 'LOF'
>          f = self._repo.vfs(self.statepathv2, 'w')
>          for key, data in records:
>              assert len(key) == 1
> +            if key not in whitelist:
> +                key, data = 't', '%s%s' % (key, data)
>              format = '>sI%is' % len(data)
>              f.write(_pack(format, key, len(data), data))
>          f.close()
> diff --git a/tests/test-histedit-non-commute-abort.t
> b/tests/test-histedit-non-commute-abort.t
> --- a/tests/test-histedit-non-commute-abort.t
> +++ b/tests/test-histedit-non-commute-abort.t
> @@ -75,10 +75,45 @@ edit the history
>    warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
>    Fix up the change and run hg histedit --continue
>
> +insert unsupported advisory merge record
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -x
>

Should this patch include a fakemergerecord.py?


> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758
> +  other: e860deea161a2f77de56603b340ebbb4536308ae
> +  unrecognized entry: x        advisory record
> +  file: e (record type "F", state "u", hash
> 58e6b3a414a1e090dfc6029add0f3555ccba127f)
> +    local path: e (flags "")
> +    ancestor path: e (node 0000000000000000000000000000000000000000)
> +    other path: e (node 6b67ccefd5ce6de77e7ead4f5292843a0255329f)
> +  $ hg resolve -l
> +  U e
>
> -abort the edit
> +insert unsupported mandatory merge record
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -X
> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758
> +  other: e860deea161a2f77de56603b340ebbb4536308ae
> +  file: e (record type "F", state "u", hash
> 58e6b3a414a1e090dfc6029add0f3555ccba127f)
> +    local path: e (flags "")
> +    ancestor path: e (node 0000000000000000000000000000000000000000)
> +    other path: e (node 6b67ccefd5ce6de77e7ead4f5292843a0255329f)
> +  unrecognized entry: X        mandatory record
> +  $ hg resolve -l
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +  $ hg resolve -ma
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +
> +abort the edit (should clear out merge state)
>    $ hg histedit --abort 2>&1 | fixbundle
>    2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg debugmergestate
> +  no merge state found
>
>  log after abort
>    $ hg resolve -l
> diff --git a/tests/test-rebase-abort.t b/tests/test-rebase-abort.t
> --- a/tests/test-rebase-abort.t
> +++ b/tests/test-rebase-abort.t
> @@ -68,11 +68,49 @@ Conflicting rebase:
>    unresolved conflicts (see hg resolve, then hg rebase --continue)
>    [1]
>
> -Abort:
> +Insert unsupported advisory merge record:
> +
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -x
> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
> +  other: 46f0b057b5c061d276b91491c22151f78698abd2
> +  unrecognized entry: x        advisory record
> +  file: common (record type "F", state "u", hash
> 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
> +    local path: common (flags "")
> +    ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6)
> +    other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5)
> +  $ hg resolve -l
> +  U common
> +
> +Insert unsupported mandatory merge record:
> +
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -X
> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
> +  other: 46f0b057b5c061d276b91491c22151f78698abd2
> +  file: common (record type "F", state "u", hash
> 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
> +    local path: common (flags "")
> +    ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6)
> +    other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5)
> +  unrecognized entry: X        mandatory record
> +  $ hg resolve -l
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +  $ hg resolve -ma
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +
> +Abort (should clear out unsupported merge state):
>
>    $ hg rebase --abort
>    saved backup bundle to
> $TESTTMP/a/.hg/strip-backup/3e046f2ecedb-6beef7d5-backup.hg (glob)
>    rebase aborted
> +  $ hg debugmergestate
> +  no merge state found
>
>    $ hg tglog
>    @  4:draft 'L2'
> diff --git a/tests/test-resolve.t b/tests/test-resolve.t
> --- a/tests/test-resolve.t
> +++ b/tests/test-resolve.t
> @@ -226,9 +226,69 @@ resolve <file> should do nothing if 'fil
>    $ cat file1
>    resolved
>
> +insert unsupported advisory merge record
> +
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -x
> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 57653b9f834a4493f7240b0681efcb9ae7cab745
> +  other: dc77451844e37f03f5c559e3b8529b2b48d381d1
> +  unrecognized entry: x        advisory record
> +  file: file1 (record type "F", state "r", hash
> 60b27f004e454aca81b0480209cce5081ec52390)
> +    local path: file1 (flags "")
> +    ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd)
> +    other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d)
> +  file: file2 (record type "F", state "u", hash
> cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523)
> +    local path: file2 (flags "")
> +    ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd)
> +    other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d)
> +  $ hg resolve -l
> +  R file1
> +  U file2
> +
> +insert unsupported mandatory merge record
> +
> +  $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py
> fakemergerecord -X
> +  $ hg debugmergestate
> +  * version 2 records
> +  local: 57653b9f834a4493f7240b0681efcb9ae7cab745
> +  other: dc77451844e37f03f5c559e3b8529b2b48d381d1
> +  file: file1 (record type "F", state "r", hash
> 60b27f004e454aca81b0480209cce5081ec52390)
> +    local path: file1 (flags "")
> +    ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd)
> +    other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d)
> +  file: file2 (record type "F", state "u", hash
> cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523)
> +    local path: file2 (flags "")
> +    ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd)
> +    other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d)
> +  unrecognized entry: X        mandatory record
> +  $ hg resolve -l
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +  $ hg resolve -ma
> +  abort: unsupported merge state records: X
> +  (see https://mercurial-scm.org/wiki/MergeStateRecords for more
> information)
> +  [255]
> +  $ hg summary
> +  parent: 2:57653b9f834a
> +   append baz to files
> +  parent: 1:dc77451844e3
> +   append bar to files
> +  branch: default
> +  warning: merge state has unsupported record types: X
> +  commit: 2 modified, 2 unknown (merge)
> +  update: 2 new changesets (update)
> +  phases: 5 draft
> +
> +update --clean shouldn't abort on unsupported records
> +
> +  $ hg up -qC 1
> +  $ hg debugmergestate
> +  no merge state found
> +
>  test crashed merge with empty mergestate
>
> -  $ hg up -qC 1
>    $ mkdir .hg/merge
>    $ touch .hg/merge/state
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-devel/attachments/20151118/1dd88ea4/attachment-0002.html>


More information about the Mercurial-devel mailing list