sapling/mercurial
Pierre-Yves David 3c79d53ced filectx.parents: enforce changeid of parent to be in own changectx ancestors
Because of the way filenodes are computed, you can have multiple changesets
"introducing" the same file revision. For example, in the changeset graph
below, changeset 2 and 3 both change a file -to- and -from- the same content.

  o 3: content = new
  |
  | o 2: content = new
  |/
  o 1: content = old

In such cases, the file revision is create once, when 2 is added, and just reused
for 3. So the file change in '3' (from "old" to "new)" has no linkrev pointing
to it).  We'll call this situation "linkrev-shadowing". As the linkrev is used for
optimization purposes when walking a file history, the linkrev-shadowing
results in an unexpected jump to another branch during such a walk.. This leads to
multiple bugs with log, annotate and rename detection.

One element to fix such bugs is to ensure that walking the file history sticks on
the same topology as the changeset's history. For this purpose, we extend the
logic in 'basefilectx.parents' so that it always defines the proper changeset
to associate the parent file revision with. This "proper" changeset has to be an
ancestor of the changeset associated with the child file revision.

This logic is performed in the '_adjustlinkrev' function. This function is
given the starting changeset and all the information regarding the parent file
revision. If the linkrev for the file revision is an ancestor of the starting
changeset, the linkrev is valid and will be used. If it is not, we detected a
topological jump caused by linkrev shadowing, we are going to walk the
ancestors of the starting changeset until we find one setting the file to the
revision we are trying to create.

The performance impact appears acceptable:

- We are walking the changelog once for each filelog traversal (as there should
  be no overlap between searches),

- changelog traversal itself is fairly cheap, compared to what is likely going
  to be perform on the result on the filelog traversal,

- We only touch the manifest for ancestors touching the file, And such
  changesets are likely to be the one introducing the file. (except in
  pathological cases involving merge),

- We use manifest diff instead of full manifest unpacking to check manifest
  content, so it does not involve applying multiple diffs in most case.

- linkrev shadowing is not the common case.

Tests for fixed issues in log, annotate and rename detection have been
added.

But this changeset does not solve all problems. It fixes -ancestry-
computation, but if the linkrev-shadowed changesets is the starting one, we'll
still get things wrong. We'll have to fix the bootstrapping of such operations
in a later changeset. Also, the usage of `hg log FILE`  without --follow still
has issues with linkrev pointing to hidden changesets, because it relies on the
`filelog` revset which implement its own traversal logic that is still to be
fixed.

Thanks goes to:
- Matt Mackall: for nudging me in the right direction
- Julien Cristau and Rémi Cardona: for keep telling me linkrev bug were an
  evolution show stopper for 3 years.
- Durham Goode: for finding a new linkrev issue every few weeks
- Mads Kiilerich: for that last rename bug who raise this topic over my
  anoyance limit.
2014-12-23 15:30:38 -08:00
..
default.d config: move mergetools configuration from contrib to default configuration 2014-10-19 03:22:23 +02:00
help ignore: resolve ignore files relative to repo root (issue4473) (BC) 2014-12-16 14:34:53 -08:00
hgweb webcommands.annotate: explicitly only honor whitespace diffopts 2014-11-21 16:16:03 -08:00
httpclient httpclient: apply upstream revision da7579b034a4 to fix SSL problems (issue4038) 2013-09-18 14:45:28 -04:00
pure parsers: inline fields of dirstate values in C version 2014-05-27 14:27:41 -07:00
templates templates: fix broken "less" & "more" links in paper style (issue4460) 2014-11-21 13:58:49 +08:00
__init__.py
ancestor.py ancestor: add a way to remove ancestors of bases from a given set 2014-11-14 19:40:30 -08:00
archival.py archive: store number of changes since latest tag as well 2014-12-12 15:27:13 -08:00
base85.c base85: cast Py_ssize_t values to int (issue3481) 2012-06-04 16:59:34 +02:00
bdiff.c bdiff: avoid a memory error on malloc failure 2013-10-30 16:03:42 -05:00
bookmarks.py bookmarks: fix formatting of exchange message (issue4439) 2014-11-05 17:25:00 +00:00
branchmap.py branchmap: pre-filter topological heads before ancestors based filtering 2014-08-30 12:33:12 +02:00
bundle2.py bundle2.bundlepart: make mandatory part flag explicit in API 2014-12-17 21:14:19 -08:00
bundlerepo.py incoming: handle phases the same as pull 2014-12-18 12:33:17 -08:00
byterange.py byterange: remove now-unused sys import 2013-02-09 07:44:22 -06:00
changegroup.py changegroup: fix file linkrevs during reorders (issue4462) 2014-11-20 16:30:57 -08:00
changelog.py changelog: use headrevsfiltered 2014-10-26 12:14:12 +01:00
cmdutil.py cmdutil.changeset_printer: explicitly honor all diffopts 2014-11-21 16:01:55 -08:00
commands.py help: fix typo in files help 2014-12-01 15:04:34 -06:00
commandserver.py cmdserver: include pid of server handling requests in hello message 2014-10-18 12:24:50 +09:00
config.py config: use util.re.compile instead of util.compilere 2014-07-15 14:50:58 -07:00
context.py filectx.parents: enforce changeid of parent to be in own changectx ancestors 2014-12-23 15:30:38 -08:00
copies.py amend: fix amending rename commit with diverged topologies (issue4405) 2014-10-16 06:35:06 -07:00
dagparser.py en-us: labeled 2012-08-17 13:58:18 -07:00
dagutil.py dagutil: fix id/ix typos in docstrings 2014-10-24 16:26:44 -04:00
demandimport.py demandimport: blacklist distutils.msvc9compiler (issue4475) 2014-12-22 17:27:31 -05:00
diffhelpers.c diffhelpers: use Py_ssize_t in testhunk() 2012-05-12 14:00:51 +02:00
dirs.c parsers: inline fields of dirstate values in C version 2014-05-27 14:27:41 -07:00
dirstate.py ignore: resolve ignore files relative to repo root (issue4473) (BC) 2014-12-16 14:34:53 -08:00
discovery.py discovery: prevent crash on unknown remote heads with old repo (issue4337) 2014-08-14 16:26:41 -07:00
dispatch.py dispatch: check shell alias again after loading extensions (issue4355) 2014-09-10 00:41:44 +09:00
dummycert.pem ssl: on OS X, use a dummy cert to trick Python/OpenSSL to use system CA certs 2014-09-26 02:19:48 +02:00
encoding.py encoding: add hfsignoreclean to clean out HFS-ignored characters 2014-12-16 13:06:41 -05:00
error.py hook: raise a more specialized HookAbort exception when a hook fails 2014-11-29 19:13:35 -08:00
exchange.py bundle2: lowercase part types 2014-12-17 15:11:26 -08:00
exewrapper.c exewrapper: adapt for legacy HackableMercurial 2012-08-07 11:04:41 +02:00
extensions.py version: show enabled extensions (issue4209) 2014-06-10 13:44:37 +03:00
fancyopts.py fancyopts: restore use of callable() since it was readded in Python 3.2 2014-06-23 09:24:16 -04:00
filelog.py filelog: censored files compare against empty data, have 0 size 2014-09-14 20:32:34 -04:00
filemerge.py filemerge: switch the default name for internal tools from internal:x to :x 2014-09-28 17:15:28 +02:00
fileset.py i18n: add i18n comment to error messages of filesets predicates 2014-11-01 02:43:08 +09:00
formatter.py formatter: add general way to switch hex/short functions 2014-10-03 22:20:02 +09:00
graphmod.py graphmod: attempt to clarify documentation of groupbranchiter() 2014-12-09 09:35:04 -05:00
hbisect.py bisect: report "both good and bad" as such, not as "not directly related" 2013-11-10 18:51:21 +01:00
help.py help: suggest '-v -e' to get built-in aliases for extensions (issue4461) 2014-12-22 03:20:50 +01:00
hg.py share: add option to share bookmarks 2014-12-13 11:32:46 -08:00
hook.py hook: raise a more specialized HookAbort exception when a hook fails 2014-11-29 19:13:35 -08:00
httpconnection.py httpconnection: properly inject ssl_wrap_socket into httpclient (issue4038) 2013-09-20 09:16:07 -04:00
httppeer.py httppeer: close the temporary bundle file after two-way streaming it 2014-10-25 21:34:49 -04:00
i18n.py i18n: cache the result of every gettext call 2014-10-17 13:52:10 -04:00
ignore.py ignore: process hgignore files in deterministic order 2012-12-17 15:57:02 -08:00
keepalive.py util: move md5 back next to sha1 and allow to call it without an argument 2014-09-24 16:00:47 +09:00
localrepo.py localrepo: use the vfs join method to implement the localrepo join method 2014-12-23 19:48:38 +01:00
lock.py lock: while releasing, unlink lockfile even if the release function throws 2014-10-16 19:15:51 -07:00
lsprof.py profiling: replace '+' markup of nested lines with indentation 2013-02-08 22:54:48 +01:00
lsprofcalltree.py
mail.py mail: actually use the verifycert config value 2014-11-05 18:31:39 +00:00
manifest.py manifest: disallow setting the node id of an entry to None 2014-12-12 13:40:44 -05:00
match.py match: add the abs() method 2014-11-28 20:15:46 -05:00
mdiff.py mdiff.unidiff: add support for noprefix 2014-11-12 23:29:14 -08:00
merge.py merge: move checking of unknown files out of manifestmerge() 2014-12-18 09:22:09 -08:00
minirst.py help: show all nested subsections of a section with hg help foo.section 2014-10-06 07:35:53 -04:00
mpatch.c mpatch: rewrite pointer overflow checks 2013-12-11 18:33:42 -06:00
namespaces.py namespaces: add nodemap property 2014-12-15 00:24:23 -08:00
node.py
obsolete.py obsstore: record data as floating point in fm0 format 2014-10-16 14:46:37 -07:00
osutil.c osutil: tab damage, how i hate thee 2012-12-03 13:17:01 -08:00
parser.py parser: allow passing a lookup function to a tokenizer 2014-03-18 17:17:23 -05:00
parsers.c parsers: introduce headrevsfiltered in C extension 2014-10-26 12:14:10 +01:00
patch.py trydiff: use 'ctx1.flags()' for symmetry with 'ctx2.flags()' 2014-12-23 16:16:26 -08:00
pathencode.c pathencode: eliminate signed integer warnings 2014-02-19 13:11:24 -08:00
pathutil.py pathauditor: check for Windows shortname aliases 2014-12-18 14:18:28 -06:00
peer.py peer: delete double definition of method peer 2012-07-28 22:36:22 +02:00
phases.py bundlerepo: implement safe phasecache 2014-12-18 11:38:48 -08:00
posix.py posix: quote the specified string only when it may have to be quoted 2014-12-25 23:33:26 +09:00
pushkey.py obsolete: add exchange option 2014-10-14 13:26:01 -07:00
pvec.py pvec: use the correct name for an identifier 2013-04-12 17:20:09 -07:00
py3kcompat.py py3kcompat: drop unused export 2014-05-13 15:22:36 -05:00
repair.py repair: use first instead of direct indexing 2014-10-07 00:09:50 -07:00
repoview.py repoview: backout 542a704cdc0f 2014-12-17 12:21:07 -08:00
revlog.py revlog: move references to revlog.hash to inside the revlog class 2014-09-24 15:14:44 -04:00
revset.py revset: fix first and last for generatorset (issue4465) 2014-12-01 05:18:12 -08:00
scmposix.py config: don't read the same config file twice 2014-09-04 21:36:35 +02:00
scmutil.py narrowmatcher: propagate the rel() method 2014-11-27 10:16:56 -05:00
scmwindows.py config: don't read the same config file twice 2014-09-04 21:36:35 +02:00
setdiscovery.py discovery: indices between sample and yesno must match (issue4438) 2014-11-05 13:05:32 +01:00
similar.py cleanup: eradicate long lines 2012-05-12 15:54:54 +02:00
simplemerge.py simplemerge: remove dead code 2014-08-07 12:51:45 -04:00
sshpeer.py merge with stable 2014-12-29 16:39:20 -06:00
sshserver.py changegroup: rename bundle-related functions and classes 2014-09-02 12:11:36 +02:00
sslutil.py sslutil: only support TLS (BC) 2014-10-21 17:01:23 -04:00
statichttprepo.py namespaces: remove weakref; always pass in repo 2014-12-14 19:11:44 -08:00
store.py store: drop unused existing list 2014-04-03 12:59:12 -05:00
strutil.py
subrepo.py subrepo: add forgotten annotation for reverting git subrepos 2014-12-28 23:59:57 +01:00
tagmerge.py filemerge: add internal:tagmerge merge tool 2014-06-26 01:20:25 +02:00
tags.py tags: introduce _readtaghist function 2014-06-28 01:42:39 +02:00
templatefilters.py templater: add count template filter, plus tests 2014-09-09 22:14:13 +09:00
templatekw.py templatekw: remove unneeded showtags 2014-12-15 09:40:02 -08:00
templater.py templater: don't overwrite the keyword mapping in runsymbol() (issue4362) 2014-11-03 12:08:03 -05:00
transaction.py vfs: add a 'split' method 2014-12-15 13:32:34 -08:00
treediscovery.py discovery: stop using nodemap for membership testing 2013-11-15 23:28:43 -05:00
ui.py ui: separate option to show prompt echo, enabled only in tests (issue4417) 2014-10-21 23:16:46 +09:00
unionrepo.py config: set a 'source' in most cases where config don't come from file but code 2014-03-19 02:45:14 +01:00
url.py proxy: remove unneeded _set_hostport for compatibility with Python 2.7.7rc1 2014-05-22 22:05:26 +09:00
util.h util.h: declare dirstateTupleType variable instead of defining it 2014-07-03 19:05:04 +02:00
util.py util.fspath: use a dict rather than a linear scan for lookups 2014-10-24 11:39:39 -07:00
verify.py verify: report censored nodes if configured policy is abort 2014-10-14 16:16:04 -04:00
win32.py win32: backout 6891e5c66508 2014-05-03 10:33:54 +02:00
windows.py windows: quote the specified string only when it has to be quoted 2014-12-25 23:33:26 +09:00
wireproto.py bundle2: lowercase part types 2014-12-17 15:11:26 -08:00
worker.py cleanup: avoid _ for local unused tmp variables - that is reserved for i18n 2014-08-15 16:20:47 +02:00