D1056: context: add a fast-comparision path between arbitraryfilectx and workingfilectx

phillco (Phil Cohen) phabricator at mercurial-scm.org
Mon Oct 16 14:03:38 EDT 2017


phillco added inline comments.

INLINE COMMENTS

> phillco wrote in context.py:2567
> Ryan and I talked offline -- but surprisingly, the default `filectx.cmp` function only compares contents:
> 
>   1:~/1$ repo['.']['A'].cmp(repo['.']['B'])
>   Out[1]: False
>   
>   2:~/1$ repo['.']['A'].cmp(repo['.']['A'])
>   Out[2]: False
>   
>   3:~/1$ repo['.']['A'].cmp(repo['.']['C'])
>   Out[3]: True
> 
> (here, `A` and `B` have the same content).
> 
> And `filecmp` seems to behave the same way:
> 
>   7:~/1$ filecmp.cmp('A', 'B')
>   Out[7]: True
>   
>   8:~/1$ filecmp.cmp('A', 'A')
>   Out[8]: True
>   
>   9:~/1$ filecmp.cmp('A', 'C')
>   Out[9]: False
> 
> That doesn't mean that it's wrong, but I think it's consistent.

Ah, but some experimenting revealed that `filecmp` does follow symlinks, but our `filectx` comparators do not. Otherwise, both `filecmp` and `filectx.cmp` ignore any flag differences.

Thus, you can demonstrate a discrepancy:

  A contains "foo"
  real_A contains "A"
  sym_A link to A
  
  repo['.']['real_A'].cmp(repo['.']['sym_A']) # claims the same
  filecmp.cmp('real_A', 'sym_A') # claims a difference, because "foo" != "A"

Note this simpler case doesn't trigger the discrepancy, because the linked file is otherwise identical:

  A contains "A"
  sym_A link to A
  
  repo['.']['A'].cmp(repo['.']['sym_A']) # claims the same
  filecmp.cmp('A', 'sym_A') # claims the same

The easiest fix is just to skip the fast-comparison path if either side is a symlink, and that's what I'll do unless others have other ideas. (@ryanmce thought we should think about what this API _should_ do).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D1056

To: phillco, #hg-reviewers, durin42
Cc: ryanmce, mercurial-devel


More information about the Mercurial-devel mailing list