Commit Graph

23518 Commits

Author SHA1 Message Date
Pierre-Yves David
451115c9e1 linkrev: also adjust linkrev when bootstrapping annotate (issue4305)
The annotate logic now use the new 'introrev' method to bootstrap its traversal.
This catches issues from linkrev-shadowing of the changeset introducing the
version of a file in source changeset.

More tests have been added to display pathological cases.
2014-12-24 03:26:48 -08:00
Pierre-Yves David
0344ecbf5b linkrev: also adjust linkrev when bootstrapping 'follow' revset
The follow revset (used by `hg log --follow`) now uses the new 'introrev'
method to bootstrap its traversal. This catches issues from linkrev-shadowing of
the changesets introducing the version of a file in source changeset.

A new test has been added to display pathological cases.

Another test is affected because it was meant to test this behavior but actually
failed to do so for half of the output. The output are now similar.
2014-12-29 23:40:24 -08:00
Pierre-Yves David
ca713b2bdd linkrev: introduce an 'introrev' method on filectx
The previous changeset properly fixed the ancestors computation, but we need to
ensure that the initial filectx is also using the right changeset.

When asking for log or annotation from a certain point, the first step is to
define the changeset that introduced the current file version. We cannot just
pick the "starting point" changesets as it may just "use" the file revision,
unchanged.

Currently, we were using 'linkrev' for this purpose, but this exposes us to
unexpected branch-jumping when the revision introducing the starting point
version is itself linkrev-shadowed. So we need to take the topology into
account again. Therefore, we introduce an 'introrev' function, returning the
changeset which introduced the file change in the current changeset.

This function will be used to fix linkrev-related issues when bootstrapping 'hg
log --follow' and 'hg annotate'.

It reuses the '_adjustlinkrev' function, extending it to allow introspection of
the initial changeset too. In the previous usage of the '_adjustlinkrev' the
starting rev was always using a children file revisions, so it could be safely
ignored in the search. In this case, the starting point is using the revision
of the file we are looking, and may be the changeset we are looking for.
2014-12-23 16:14:39 -08:00
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
FUJIWARA Katsunori
9e120db5e9 context: remove unreliable accessor methods from committablectx
There are two caching routes for (propertycache-ed) "_status" below in
committablectx:

  - invoking "status()":

    "dirstate.status()" is invoked, and the result of it is cached
    into "_status". In this case, any of "listignored", "listclean"
    and "listunknown" may be True.

  - accessing "_status" directly before "status()":

    Own "status()" is invoked, but all of "listignored", "listclean"
    and "listunknown" arguments are False, in this case.

"ignored"/"clean"/"unknown" accessor methods of "committablectx" use
corresponded fields of "_status", but these fields aren't reliable,
because these fields are empty when:

  - "_status" method is executed before accessors, or
  - "status()" is executed with "list*=False" before accessors

In addition to it, these accessors aren't used in the recent Mercurial
implementation. At least, removing them doesn't cause any test
failures.
2014-12-31 17:55:43 +09:00
FUJIWARA Katsunori
797fef3e65 context: cache self._status correctly at workingctx.status
Before this patch, "workingctx.status" always replaces "self._status"
by the recent result, even though:

  - status isn't calculated against the parent of the working directory, or

  - specified "match" isn't "always" one
    (status is only visible partially)

If "workingctx" object is shared between some procedures indirectly
referring "ctx._status", this incorrect caching may cause unexpected
result: for example, "ctx._status" is used via "manifest()", "files()"
and so on.

To cache "self._status" correctly at "workingctx.status", this patch
overwrites "self._status" in "workingctx._buildstatus" only when:

  - status is calculated against the parent of the working directory, and
  - specified "match" is "always" one

This patch can be applied (and effective) only on default branch,
because procedure around "basectx.status" is much different between
stable and default: for example, overwriting "self._status" itself is
executed not in "workingctx._buildstatus" but in
"workingctx._poststatus", on stable branch.
2014-12-31 17:55:43 +09:00
Pierre-Yves David
2662df0db5 filectx.parents: also fetch the filelog of rename source too
we are going to need this filelog for the linkrev adjustment, so we better
normalise the list and have the filelog in all case.

This is done in a previous changeset to help readability.
2014-12-23 18:30:46 -08:00
Matt Mackall
3c097d24cf test-subrepo-git: ignore global git config
This was causing a test failure for people with company-wide settings.
Still need a way to ignore local config.
2014-12-30 15:51:14 -06:00
Siddharth Agarwal
3c683f5548 tests/autodiff.py: explicitly only honor feature diffopts
This test extension manages the opts it cares about on its own anyway.
2014-11-21 16:02:26 -08:00
Siddharth Agarwal
34aea9120f cmdutil.changeset_printer: explicitly honor all diffopts
This is used in hg log -p so the output is expected to be the same as that of
hg diff.
2014-11-21 16:01:55 -08:00
Siddharth Agarwal
84d6328fc1 export: explicitly honor all diffopts
This is slightly more controversial than diff, but we hope that HGPLAIN=1
covers all the format-breaking ones.

A possible alternative here that breaks BC is to honor all opts except the
whitespace ones.
2014-11-18 22:21:03 -08:00
Siddharth Agarwal
ed470d2b63 webcommands.annotate: explicitly only honor whitespace diffopts
The whitespace ones are the only ones the annotate logic cares about anyway, so
there's no visible impact.
2014-11-21 16:16:03 -08:00
Pierre-Yves David
1512377552 filectx.parents: filter nullrev parent sooner
We are going to introduce a linkrev-correction phases  when computing parents.
It will be more convenient to have the nullid parent filtered out earlier. I
had to make a minimal adjustment to the rename handling logic to keep it
functional.  That logic have been documented in the process since it took me
some time to check all the cases out.
2014-12-23 18:29:03 -08:00
Pierre-Yves David
a0aa329ab1 context: catch FilteredRepoLookupError instead of RepoLookupError
Now that we have a more specialised exception, lets use it when we meant to
catch the more specialised case.
2014-12-23 17:13:51 -08:00
Matt Harbison
21ca967140 narrowmatcher: propagate the rel() method
The full path is propagated to the original match object since this is often
used directly for printing a file name to the user.  This is cleaner than
requiring each caller to join the prefix with the file name prior to calling it,
and will lead to not having to pass the prefix around separately.  It is also
consistent with the bad() and abs() methods in terms of the required input.  The
uipath() method now inherits this path building property.

There is no visible change in path style for rel() because it ultimately calls
util.pathto(), which returns an os.sep based path.  (The previous os.path.join()
was violating the documented usage of util.pathto(), that its third parameter be
'/' separated.)  The doctest needed to be normalized to '/' separators to avoid
test differences on Windows, now that a full path is returned for a short
filename.

The test changes are to drop globs that are no longer necessary when printing an
absolute file in a subrepo, as returned from match.uipath().  Previously when
os.path.join() was used to add the prefix, the absolute path to a file in a
subrepo was printed with a mix of '/' and '\'.  The absolute path for a file not
in a subrepo, as returned from match.uipath(), is still purely '/' based.
2014-11-27 10:16:56 -05:00
Matt Harbison
e9dd83402c match: add the abs() method
This is a utility to make it easier for subrepos to convert a file name to the
full path rooted at the top repository.  It can replace the various path joining
lambdas, and doesn't require the prefix to be passed into the method that wishes
to build such a path.

The name is derived from the following pattern in annotate() and other places:

        name = ((pats and rel) or abs)

The pathname separator is not os.sep in part to avoid confusion with variables
named 'abs' or similar that _are_ '/' separated, and in part because some
methods like cmdutils.forget() and maybe cmdutils.add() need to build a '/'
separated path to the root repo.  This can replace the manual path building
there.
2014-11-28 20:15:46 -05:00
Matt Mackall
3406ce4956 merge with stable 2014-12-29 16:39:20 -06:00
Matt Mackall
bf17f56a67 sshpeer: more thorough shell quoting
This fixes an issue spotted by Jesse Hertz.
2014-12-29 14:27:02 -06:00
FUJIWARA Katsunori
ef3bad18bd i18n-ja: synchronized with 04d70d13ef9d 2014-12-29 15:59:56 +09:00
Wagner Bruna
1546a1d329 i18n-pt_BR: synchronized with 480699610f70 2014-12-26 17:21:08 -02:00
FUJIWARA Katsunori
f6bf07d36e posix: quote the specified string only when it may have to be quoted
This patch makes "posix.shellquote" examine the specified string and
quote it only when it may have to be quoted for safety, like as the
previous patch for "windows.shellquote".

In fact, on POSIX environment, quoting itself doesn't cause issues
like issue4463. But (almost) equivalent quoting policy can avoid
examining test result differently on POSIX and Windows (even though
showing command line with "%r" causes such examination in
"test-extdiff.t").

The last hunk for "test-extdiff.t" in this patch isn't needed for the
previous patch for "windows.shellquote", because the code path of it
is executed only "#if execbit" (= avoided on Windows).
2014-12-25 23:33:26 +09:00
FUJIWARA Katsunori
1623722bb9 windows: quote the specified string only when it has to be quoted
Before this patch, "windows.shellquote" (as used as "util.shellquote")
always quotes specified strings with double quotation marks, for
external process invocation.

But some problematic applications can't work correctly, when command
line arguments are quoted: see issue4463 for detail.

On the other hand, quoting itself is needed to specify arguments
containing whitespaces and/or some special characters exactly.

This patch makes "windows.shellquote" examine the specified string and
quote it only when it may have to be quoted for safety.
2014-12-25 23:33:26 +09:00
FUJIWARA Katsunori
557f94c70c extdiff: rename the name of an argument for readability
To reduce amount of changes for review-ability, previous patch uses
"args" as argument name of "dodiff()", even though "args" includes
also the name of command to be executed (or full-path of it).

This patch replaces "args" by more appropriate name "cmdline".
2014-12-25 23:33:26 +09:00
FUJIWARA Katsunori
203706516b extdiff: avoid unexpected quoting arguments for external tools (issue4463)
Before this patch, all command line arguments for external tools are
quoted by the combination of "shlex.split" and "util.shellquote". But
this causes some problems.

  - some problematic commands can't work correctly with quoted arguments

    For example, 'WinMerge /r ....' is OK, but 'WinMerge "/r" ....' is
    NG. See also below for detail about this problem.

        https://bitbucket.org/tortoisehg/thg/issue/3978/

  - quoting itself may change semantics of arguments

    For example, when the environment variable CONCAT="foo bar baz':

      - mydiff $CONCAT   => mydiff foo bar baz   (taking 3 arguments)
      - mydiff "$CONCAT" => mydiff "foo bar baz" (taking only 1 argument)

    For another example, single quoting (= "util.shellquote") on POSIX
    environment prevents shells from expanding environment variables,
    tilde, and so on:

      - mydiff "$HOME" => mydiff /home/foobar
      - mydiff '$HOME' => mydiff $HOME

  - "shlex.split" can't handle some special characters correctly

    It just splits specified command line by whitespaces.

    For example, "echo foo;echo bar" is split into ["echo",
    "foo;echo", "bar"].

On the other hand, if quoting itself is omitted, users can't specify
options including space characters with "--option" at runtime.

The root cause of this issue is that "shlex.split + util.shellquote"
combination loses whether users really want to quote each command line
elements or not, even though these can be quoted arbitrarily in
configurations.

To resolve this problem, this patch does:

  - prevent configurations from being processed by "shlex.split" and
    "util.shellquote"

    only (possibly) "findexe"-ed or "findexternaltool"-ed command path
    is "util.shellquote", because it may contain whitespaces.

  - quote options specified by "--option" via command line at runtime

This patch also makes "dodiff()" take only one "args" argument instead
of "diffcmd" and "diffopts. It also omits applying "util.shellquote"
on "args", because "args" should be already stringified in "extdiff()"
and "mydiff()".

The last hunk for "test-extdiff.t" replaces two whitespaces by single
whitespace, because change of "' '.join()" logic causes omitting
redundant whitespaces.
2014-12-25 23:33:26 +09:00
Mathias De Maré
55a6b1081b subrepo: add forgotten annotation for reverting git subrepos
Support for reverting git subrepos was added earlier,
but the annotation to handle any subrepo errors was forgotten.
2014-12-28 23:59:57 +01:00
Mathias De Maré
4aa7ae08d9 subrepo: add full revert support for git subrepos
Previously, revert was only possible if the '--no-backup'
switch was specified.
Now, to support backups, we explicitly go over all modified
files in the subrepo.
2014-12-28 10:42:25 +01:00
Ludovic Chabant
8128d9e633 setup: don't fail when Python doesn't have the cygwinccompiler package
Some Python installations like the ones available from the optware
project
for the Synology DiskStation NASes don't have that package, which means
running the setup script will crash and exit right away. Instead, we now
just use an empty/fake class for the HackedMingw32CCompiler, which we
likely won't use anyway.
2014-12-23 19:54:48 -08:00
Thomas Klausner
57f4b24f7a tests: adapt glob pattern to fix test with NetBSD's sh(1) (issue4484) 2014-12-28 23:50:08 +01:00
Thomas Klausner
e27adfc3f1 tests: run 'cvs init' only on non-existent directories (issue4482)
Do not create cvsroot directory since cvs-1.12 errors out
if CVSROOT exists before 'cvs init'.
2014-12-28 21:30:52 +01:00
Matt Harbison
c2203f42d7 remove: use vfs instead of os.path + match.rel() for filesystem checks 2014-12-25 21:50:35 -05:00
Matt Harbison
5632d06d85 forget: use vfs instead of os.path + match.rel() for filesystem checks 2014-12-25 21:43:45 -05:00
Matt Harbison
8e87aedc01 tests: make a multi-statement hook in bundle2-exchange Windows compatible
This is similar to the fix in ab91e34fea50.
2014-12-24 12:07:59 -05:00
Matt Mackall
b08c6cab93 merge with stable 2014-12-29 13:10:47 -06:00
Angel Ezquerra
9da7dc5b00 localrepo: use the vfs join method to implement the localrepo join method
This will make it possible to customize the behavior of the join method by
changing the vfs class (e.g. by using the altvfs" class introduced recently).

Note that we could have modified the VFS join methods to acept a set of optional
paths in the same way thta the localrepo join method does. However it seemed
simpler to simply call os.path.join before calling self.vfs.join.
2014-12-23 19:48:38 +01:00
Augie Fackler
ffd2cf1dba demandimport: blacklist distutils.msvc9compiler (issue4475)
This module depends on _winreg, which is windows-only. Recent versions
of setuptools load distutils.msvc9compiler and expect it to
ImportError immediately when on non-Windows platforms, so we need to
let them do that. This breaks in an especially mystifying way, because
setuptools uses vars() on the imported module. We then throw an
exception, which vars doesn't pick up on well. For example:

In [3]: class wat(object):
   ...:     @property
   ...:     def __dict__(self):
   ...:         assert False
   ...:

In [4]: vars(wat())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-2781ada5ffe6> in <module>()
----> 1 vars(wat())

TypeError: vars() argument must have __dict__ attribute

Which is similar to the problem we run into.
2014-12-22 17:27:31 -05:00
Matt Harbison
93382de245 largefiles: fix a spurious missing file warning with forget (issue4053)
If an uncommitted and deleted file was forgotten, a warning would be emitted,
even though the operation was successful.  See the previous patch for
'remove -A' for the exact circumstances, and details about the cause.
2014-12-21 15:06:54 -05:00
Matt Harbison
8edc086e01 largefiles: fix a spurious missing file warning with 'remove -A' (issue4053)
The bug report doesn't mention largefiles, but the given recipe doesn't fail
unless the largefiles extension is loaded.  The problem only affected normal
files, whether or not any largefiles are committed, and only files that have
not been committed yet.  (Files with an 'a' state are dropped from dirstate,
not marked removed.)  Further, if the named normal file never existed, the
warning would be printed out twice.

The problem is that the core implementation of remove() calls repo.status(),
which eventually triggers a dirstate.walk().  When the file isn't seen in the
filesystem during the walk, the exception handling finds the file in
dirstate, so it doesn't complain.  However, the largefiles implementation
called status() again with all of the original files (including the normal
ones, just dropped).  This time, the exception handler doesn't find the file
in dirstate and does complain.  This simply excludes the normal files from
the second repo.status() call, which the largefiles extension has no interest
is processing anyway.
2014-12-21 15:04:13 -05:00
Matt Harbison
572104a185 largefiles: introduce the 'composelargefilematcher()' method
This is a copy/paste (with the necessary tweaks) of the composenormalfilematcher
method currently on default, which does the inverse- this trims the normal files
out of the matcher.  It will be used in the next patch.
2014-12-21 14:42:46 -05:00
Angel Ezquerra
1a80984319 localrepo: introduce shared method to check if a repository is shared
Up until now we compared the "path" and "sharedpath" repository properties to
check if a repository is shared. This was relying an implementation detail of
shared repositories. In order to make it possible to change the way shared
repositories are implemented, we encapsulate this check into its own localrepo
method, called shared.

This new method returns None if the repository is shared, and something else
(for now a string describing the short of share) otherwise.

The reason why I did not call this method "isshared" and made it return a
boolean is that I plan to introduce a new type of shared repository soon.

# NOTES:

This is the first patch in a series whose purpose is to add support for
creating "full repository shares", which are repositories that share everything
with the repository source except their current revision, branch and bookmark.

This series is RFC because I am not very sure of some of the solutions I took.
Comments are welcome!
2014-12-21 00:19:10 +01:00
Martin von Zweigbergk
d21c241927 trydiff: use 'ctx1.flags()' for symmetry with 'ctx2.flags()' 2014-12-23 16:16:26 -08:00
Martin von Zweigbergk
0154ee1c3e trydiff: use 'not in addedset' for symmetry with 'not in removedset'
With the previous change in place, we can safely use 'addedset'.
2014-12-23 16:25:00 -08:00
Martin von Zweigbergk
a69f913d1d trydiff: simplify checking for additions
In the body of the loop in trydiff(), there are conditions like:

  addedset or (f in modifiedset and to is None)

The second half of that expression is to account for the fact that
merge-in additions appear as additions. By instead fixing up the sets
of modified and added files to compensate for this fact, we can
simplify the body of the loop. It also fixes one case where the
addedset was checked without the additional check (the "have we
already reported a copy above?" case in the code, also see fixed test
case).

The similar condition with 'removedset' in it seems to have served no
purpose even before this change, so it could have been simplified even
before.
2014-12-23 16:12:54 -08:00
Martin von Zweigbergk
12fa2d93ff trydiff: extract 'date2' variable like existing 'date1'
Note that there is a comment saying "ctx2 date may be dynamic". The
comment was introduced in 8ed3d2a60500 (patch: use contexts for diff,
2006-12-25), but it seems like it stopped being dynamic in that very
changeset -- before that changeset, the date seems to have been the
file's mtime, but after the changeset, it seems to be the changeset's
timestamp (current time for workingctx). Since no one seems to have
missed the "dynamicness", let's simplify and extract a date2 for
symmetry with date1.
2014-12-23 14:56:30 -08:00
Martin von Zweigbergk
c7f4a068b8 trydiff: use sets, not lists, for containment checks
This only has a noticeable effect on diffs touching A LOT of
files. For example, it takes

  hg diff -r FIREFOX_AURORA_30_BASE -r FIREFOX_AURORA_35_BASE

from 1m55.465s to 1m32.354s. That diff has over 50k files.
2014-12-23 10:41:45 -08:00
Matt Mackall
1b740668bf largefiles: fix unused import
Caught by pyflakes.
2014-12-24 13:33:01 -06:00
Matt Mackall
fcca668c77 Added signature for changeset ac36055e3c9c 2014-12-18 14:59:28 -06:00
Matt Mackall
8b83dfc480 pathauditor: check for Windows shortname aliases 2014-12-18 14:18:28 -06:00
Augie Fackler
13206234f4 pathauditor: check for codepoints ignored on OS X 2014-12-16 13:08:17 -05:00
Augie Fackler
c1fe89f64f darwin: omit ignorable codepoints when normcase()ing a file path
This lets us avoid some nasty case collision problems in OS X with
invisible codepoints.
2014-12-16 13:07:10 -05:00
Augie Fackler
3c9e7fcc66 encoding: add hfsignoreclean to clean out HFS-ignored characters
According to Apple Technote 1150 (unavailable from Apple as far as I
can tell, but archived in several places online), HFS+ ignores sixteen
specific unicode runes when doing path normalization. We need to
handle those cases, so this function lets us efficiently strip the
offending characters from a UTF-8 encoded string (which is the only
way it seems to matter on OS X.)
2014-12-16 13:06:41 -05:00