Mercurial > hg
annotate contrib/simplemerge @ 42377:0546ead39a7e stable
manifest: avoid corruption by dropping removed files with pure (issue5801)
Previously, removed files would simply be marked by overwriting the first byte
with NUL and dropping their entry in `self.position`. But no effort was made to
ignore them when compacting the dictionary into text form. This allowed them to
slip into the manifest revision, since the code seems to be trying to minimize
the string operations by copying as large a chunk as possible. As part of this,
compact() walks the existing text based on entries in the `positions` list, and
consumed everything up to the next position entry. This typically resulted in
a ValueError complaining about unsorted manifest entries.
Sometimes it seems that files do get dropped in large repos- it seems to
correspond to there being a new entry that would take the same slot. A much
more trivial problem is that if the only changes were removals, `_compact()`
didn't even run because `__delitem__` doesn't add anything to `self.extradata`.
Now there's an explicit variable to flag this, both to allow `_compact()` to
run, and to avoid searching the manifest in cases where there are no removals.
In practice, this behavior was mostly obscured by the check in fastdelta() which
takes a different path that explicitly drops removed files if there are fewer
than 1000 changes. However, timeless has a repo where after rebasing tens of
commits, a totally different path[1] is taken that bypasses the change count
check and hits this problem.
[1] https://www.mercurial-scm.org/repo/hg/file/2338bdea4474/mercurial/manifest.py#l1511
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 23 May 2019 21:54:24 -0400 |
parents | d6b7c4e77bb4 |
children | 3c2799cbace4 |
rev | line source |
---|---|
4363
2e3c54fb79a3
actually port simplemerge to hg
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4362
diff
changeset
|
1 #!/usr/bin/env python |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
2 from __future__ import absolute_import |
4362
465b9ea02868
Import 3-way merge code from bzr
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
diff
changeset
|
3 |
30576
541949a10a68
fancyopts: switch from fancyopts.getopt.* to getopt.*
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30559
diff
changeset
|
4 import getopt |
19378
9de689d20230
cleanup: drop unused variables and an unused import
Simon Heimberg <simohe@besonet.ch>
parents:
19022
diff
changeset
|
5 import sys |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
6 |
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
7 import hgdemandimport |
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
8 hgdemandimport.enable() |
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
9 |
4363
2e3c54fb79a3
actually port simplemerge to hg
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4362
diff
changeset
|
10 from mercurial.i18n import _ |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
11 from mercurial import ( |
34051
d2fc88426d21
context: add arbitraryfilectx, which can represent files outside the workdir
Phil Cohen <phillco@fb.com>
parents:
34050
diff
changeset
|
12 context, |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
13 error, |
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
14 fancyopts, |
39791
1dd82ecb869b
py3: use pycompat.strkwargs() in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
39790
diff
changeset
|
15 pycompat, |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
16 simplemerge, |
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
17 ui as uimod, |
37120
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
34051
diff
changeset
|
18 ) |
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
34051
diff
changeset
|
19 from mercurial.utils import ( |
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
34051
diff
changeset
|
20 procutil, |
33895
aed91971d88c
simplemerge: update to conform with modern import conventions
Augie Fackler <raf@durin42.com>
parents:
30576
diff
changeset
|
21 ) |
4362
465b9ea02868
Import 3-way merge code from bzr
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
diff
changeset
|
22 |
39790
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
23 options = [(b'L', b'label', [], _(b'labels to use on conflict markers')), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
24 (b'a', b'text', None, _(b'treat all files as text')), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
25 (b'p', b'print', None, |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
26 _(b'print results instead of overwriting LOCAL')), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
27 (b'', b'no-minimal', None, _(b'no effect (DEPRECATED)')), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
28 (b'h', b'help', None, _(b'display help and exit')), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
29 (b'q', b'quiet', None, _(b'suppress output'))] |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
30 |
40265
d6b7c4e77bb4
py3: convert "usage" literal to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
40260
diff
changeset
|
31 usage = _(b'''simplemerge [OPTS] LOCAL BASE OTHER |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
32 |
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
33 Simple three-way file merge utility with a minimal feature set. |
5081
ea7b982b6c08
Remove trailing spaces
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4408
diff
changeset
|
34 |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
35 Apply to LOCAL the changes necessary to go from BASE to OTHER. |
5081
ea7b982b6c08
Remove trailing spaces
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4408
diff
changeset
|
36 |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
37 By default, LOCAL is overwritten with the results of this operation. |
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
38 ''') |
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
39 |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
40 class ParseError(Exception): |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
41 """Exception raised on errors in parsing the command line.""" |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
42 |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
43 def showhelp(): |
40265
d6b7c4e77bb4
py3: convert "usage" literal to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
40260
diff
changeset
|
44 pycompat.stdout.write(usage) |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
45 pycompat.stdout.write(b'\noptions:\n') |
4362
465b9ea02868
Import 3-way merge code from bzr
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
diff
changeset
|
46 |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
47 out_opts = [] |
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
48 for shortopt, longopt, default, desc in options: |
39790
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
49 out_opts.append((b'%2s%s' % (shortopt and b'-%s' % shortopt, |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
50 longopt and b' --%s' % longopt), |
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
51 b'%s' % desc)) |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
52 opts_len = max([len(opt[0]) for opt in out_opts]) |
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
53 for first, second in out_opts: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
54 pycompat.stdout.write(b' %-*s %s\n' % (opts_len, first, second)) |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
55 |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
56 try: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
57 for fp in (sys.stdin, pycompat.stdout, sys.stderr): |
37120
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
34051
diff
changeset
|
58 procutil.setbinary(fp) |
19022
cba222f01056
tests: run check-code on Python files without .py extension
Mads Kiilerich <madski@unity3d.com>
parents:
14233
diff
changeset
|
59 |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
60 opts = {} |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
61 try: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
62 bargv = [a.encode('utf8') for a in sys.argv[1:]] |
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
63 args = fancyopts.fancyopts(bargv, options, opts) |
30576
541949a10a68
fancyopts: switch from fancyopts.getopt.* to getopt.*
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30559
diff
changeset
|
64 except getopt.GetoptError as e: |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
65 raise ParseError(e) |
39790
d3e940a32be0
py3: add b'' prefixes in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
37120
diff
changeset
|
66 if opts[b'help']: |
4364
d5c3a70f8422
polish the simplemerge command; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
4363
diff
changeset
|
67 showhelp() |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
68 sys.exit(0) |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
69 if len(args) != 3: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
70 raise ParseError(_(b'wrong number of arguments').decode('utf8')) |
33903
ed6f64173121
contrib: make simplemerge script pass context-like objects
Phil Cohen <phillco@fb.com>
parents:
33895
diff
changeset
|
71 local, base, other = args |
ed6f64173121
contrib: make simplemerge script pass context-like objects
Phil Cohen <phillco@fb.com>
parents:
33895
diff
changeset
|
72 sys.exit(simplemerge.simplemerge(uimod.ui.load(), |
34051
d2fc88426d21
context: add arbitraryfilectx, which can represent files outside the workdir
Phil Cohen <phillco@fb.com>
parents:
34050
diff
changeset
|
73 context.arbitraryfilectx(local), |
d2fc88426d21
context: add arbitraryfilectx, which can represent files outside the workdir
Phil Cohen <phillco@fb.com>
parents:
34050
diff
changeset
|
74 context.arbitraryfilectx(base), |
d2fc88426d21
context: add arbitraryfilectx, which can represent files outside the workdir
Phil Cohen <phillco@fb.com>
parents:
34050
diff
changeset
|
75 context.arbitraryfilectx(other), |
39791
1dd82ecb869b
py3: use pycompat.strkwargs() in contrib/simplemerge
Pulkit Goyal <pulkit@yandex-team.ru>
parents:
39790
diff
changeset
|
76 **pycompat.strkwargs(opts))) |
28047
863075fd4cd0
misc: use modern exception syntax
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
77 except ParseError as e: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
78 if pycompat.ispy3: |
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
79 e = str(e).encode('utf8') |
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
80 pycompat.stdout.write(b"%s: %s\n" % (sys.argv[0].encode('utf8'), e)) |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
81 showhelp() |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
82 sys.exit(1) |
28047
863075fd4cd0
misc: use modern exception syntax
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
26587
diff
changeset
|
83 except error.Abort as e: |
40260
b54d93fc3ba8
simplemerge: port to Python 3
Augie Fackler <augie@google.com>
parents:
39791
diff
changeset
|
84 pycompat.stderr.write(b"abort: %s\n" % e) |
6002
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
85 sys.exit(255) |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
86 except KeyboardInterrupt: |
abd66eb0889e
merge: move the bulk of simplemerge into core
Matt Mackall <mpm@selenic.com>
parents:
5081
diff
changeset
|
87 sys.exit(255) |