Commit Graph

52 Commits

Author SHA1 Message Date
timeless
5129095046 test-transplant.t: improve test coverage
* ?, x, q
* not a parent
* --source
* outstanding local changes
* outstanding uncommitted merges
* no revision checked out
* checkopts all+branch+rev
* checkopts all-branch
* checkopts no-args
* checkopts continue+all
* revset:transplanted(...)
* filter corrupted changeset
2016-01-06 06:37:34 +00:00
timeless
e0d9e30d54 cleanup: remove superfluous space after space after equals (tests) 2015-12-31 08:17:28 +00:00
FUJIWARA Katsunori
2fb0db56cb transplant: restore dirstate correctly at unexpected failure
Before this patch, transplant can't restore dirstate as expected at
failure other than one while patching. This causes:

  - unexpected file status

  - dirstate refers already rollback-ed parent
    (only at failure of transplanting the 2nd or later revision)

To restore dirstate correctly also at unexpected failure, this patch
encloses scope of store lock and transaction by 'dirstateguard'.

This is temporary fixing for stable branch. See
DirstateTransactionPlan wiki page for detail about the future plan to
treat dirstate consistently around scope boundary of transaction.

    https://mercurial.selenic.com/wiki/DirstateTransactionPlan

This patch also adds 'if lock' examination for safety
'lock.release()', because creating 'dirstateguard' object may fail
unexpectedly (e.g. IOError for saving dirstate).

BTW, in the test script, putting section header '[extensions]' into
'.hg/hgrc' is needed to fix incomplete disabling 'abort' extension at
d0d06f4ca862.
2015-07-30 06:22:09 +09:00
FUJIWARA Katsunori
1dcc27a649 context: write dirstate out explicitly at the end of markcommitted
To detect change of a file without redundant comparison of file
content, dirstate recognizes a file as certainly clean, if:

  (1) it is already known as "normal",
  (2) dirstate entry for it has valid (= not "-1") timestamp, and
  (3) mode, size and timestamp of it on the filesystem are as same as
      ones expected in dirstate

This works as expected in many cases, but doesn't in the corner case
that changing a file keeps mode, size and timestamp of it on the
filesystem.

The timetable below shows steps in one of typical such situations:

  ---- ----------------------------------- ----------------
                                           timestamp of "f"
                                           ----------------
                                           dirstate   file-
  time          action                     mem  file  system
  ---- ----------------------------------- ---- ----- -----
   *                                             ***    ***
       - 'hg transplant REV1 REV2 ...'
         - transplanting REV1
           ....
   N
           - change "f", but keep size                   N
             (via 'patch.patch()')
           - 'dirstate.normal("f")'          N   ***
             (via 'repo.commit()')

         - transplanting REV2
           - change "f", but keep size                   N
             (via 'patch.patch()')
           - aborted while patching
  N+1
         - release wlock
           - 'dirstate.write()'              N    N      N

       - 'hg status' shows "r1" as "clean"   N    N      N
  ---- ----------------------------------- ---- ----- -----

The most important point is that 'dirstate.write()' is executed at N+1
or later. This causes writing dirstate timestamp N of "f" out
successfully. If it is executed at N, 'parsers.pack_dirstate()'
replaces timestamp N with "-1" before actual writing dirstate out.

This issue can occur when 'hg transplant' satisfies conditions below:

  - multiple revisions to be transplanted change the same file
  - those revisions don't change mode and size of the file, and
  - the 2nd or later revision of them fails after changing the file

The root cause of this issue is that files are changed without
flushing in-memory dirstate changes via 'repo.commit()' (even though
omitting 'dirstate.normallookup()' on files changed by 'patch.patch()'
for efficiency also causes this issue).

To detect changes of files correctly, this patch writes in-memory
dirstate changes out explicitly after marking files as clean in
'committablectx.markcommitted()', which is invoked via
'repo.commit()'.

After this change, timetable is changed as below:

  ---- ----------------------------------- ----------------
                                           timestamp of "f"
                                           ----------------
                                           dirstate   file-
  time          action                     mem  file  system
  ---- ----------------------------------- ---- ----- -----
   *                                             ***    ***
       - 'hg transplant REV1 REV2 ...'
         - transplanting REV1
           ....
   N
           - change "f", but keep size                   N
             (via 'patch.patch()')
           - 'dirstate.normal("f")'          N    ***
             (via 'repo.commit()')
       ----------------------------------- ---- ----- -----
           - 'dirsttate.write()'            -1    -1
       ----------------------------------- ---- ----- -----
         - transplanting REV2
           - change "f", but keep size                   N
             (via 'patch.patch()')
           - aborted while patching
  N+1
         - release wlock
           - 'dirstate.write()'              -1   -1     N

       - 'hg status' shows "r1" as "clean"   -1   -1     N
  ---- ----------------------------------- ---- ----- -----

To reproduce this issue in tests certainly, this patch emulates some
timing critical actions as below:

  - change "f" at N

    'patch.patch()' with 'fakepatchtime.py' explicitly changes mtime
    of patched files to "2000-01-01 00:00" (= N).

  - 'dirstate.write()' via 'repo.commit()' at N

    'fakedirstatewritetime.py' forces 'pack_dirstate()' to use
    "2000-01-01 00:00" as "now", only if 'pack_dirstate()' is invoked
    via 'committablectx.markcommitted()'.

  - 'dirstate.write()' via releasing wlock at N+1 (or "not at N")

    'pack_dirstate()' via releasing wlock uses actual timestamp at
    runtime as "now", and it should be different from the "2000-01-01
    00:00" of "f".

BTW, this patch doesn't test cases below, even though 'patch.patch()'
is used similarly in these cases:

  1. failure of 'hg import' or 'hg qpush'

  2. success of 'hg import', 'hg qpush' or 'hg transplant'

Case (1) above doesn't cause this kind of issue, because:

  - if patching is aborted by conflicts, changed files are committed

    changed files are marked as CLEAN, even though they are partially
    patched.

  - otherwise, dirstate are fully restored by 'dirstateguard'

    For example in timetable above, timestamp of "f" in .hg/dirstate
    is restored to -1 (or less than N), and subsequent 'hg status' can
    detect changes correctly.

Case (2) always causes 'repo.status()' invocation via 'repo.commit()'
just after changing files inside same wlock scope.

  ---- ----------------------------------- ----------------
                                           timestamp of "f"
                                           ----------------
                                           dirstate   file-
  time          action                     mem  file  system
  ---- ----------------------------------- ---- ----- -----
  N                                              ***   ***
       - make file "f" clean                            N

       - execute 'hg foobar'
         ....
         - 'dirstate.normal("f")'           N    ***
           (e.g. via dirty check
            or previous 'repo.commit()')

         - change "f", but keep size                    N
         - 'repo.status()' (*1)
           (via 'repo.commit()')
  ---- ----------------------------------- ---- ----- -----

At a glance, 'repo.status()' at (*1) seems to cause similar issue (=
"changed files are treated as clean"), but actually doesn't.

'dirstate._lastnormaltime' should be N at (*1) above, because
'dirstate.normal()' via dirty check is finished at N.

Therefore, "f" changed at N (= 'dirstate._lastnormaltime') is forcibly
treated as "unsure" at (*1), and changes are detected as expected (see
'dirstate.status()' for detail).

If 'hg import' is executed with '--no-commit', 'repo.status()' isn't
invoked just after changing files inside same wlock scope.

But preceding 'dirstate.normal()' is invoked inside another wlock
scope via 'cmdutil.bailifchanged()', and in-memory changes should be
flushed at the end of that scope.

Therefore, timestamp N of clean "f" should be replaced by -1, if
'dirstate.write()' is invoked at N. It means that condition of this
issue isn't satisfied.
2015-07-08 17:01:09 +09:00
Matt Mackall
b050378961 merge with stable 2015-07-01 16:33:31 -05:00
Pierre-Yves David
a7b191b4b3 transplant: only pull the transplanted revision (issue4692)
For some reason, transplant was pulling all remote revisions when transplanting
from a remote repository (unless --branch was
specified).
2015-06-29 19:09:42 -07:00
Pierre-Yves David
2558bde9af transplant: update test to use hash for remote transplant
Transplant is apparently allowing using revision numbers when transplanting
through http. I call this nonsense and update the test to use an explicit hash.

This "feature" will break in the next change fixing another bug.
2015-06-29 19:18:51 -07:00
Pierre-Yves David
171c6e502b transplant: properly skip empty changeset (issue4423)
If resolving a merge conflict result in an empty changesets, we now properly
skip the changeset instead of crashing.

Original patch from Robert Collins <robertc@robertcollins.net>.
2015-01-08 21:36:12 -08:00
Matt Mackall
b709208c37 tests: drop DAEMON_PIDS from killdaemons calls 2015-06-08 14:55:40 -05:00
Matt Mackall
3ad28905f6 tests: drop explicit $TESTDIR from executables
$TESTDIR is added to the path, so this is superfluous. Also,
inconsistent use of quotes means we might have broken on tests with
paths containing spaces.
2015-06-08 14:44:30 -05:00
Siddharth Agarwal
b06bac1ae7 transplant: don't honor whitespace and format-changing diffopts
transplant uses diff purely internally.
2014-11-18 21:49:05 -08:00
FUJIWARA Katsunori
bcb1d86a49 tests: introduce "checkeditform-n-cat.sh" script to invoke "cat" in it safely
Before this patch, a part of "test-transplant.t" fails unexpectedly on
Windows environment, because semicolon (";") in HGEDITOR isn't
recognized as the command separator by "cmd.exe".

This patch newly introduces "checkeditform-n-cat.sh" script to invoke
"cat" in it safely anywhere.
2014-10-28 00:19:18 +09:00
Augie Fackler
a5ddb1dcfe tests: use $PYTHON instead of hardcoding python
This makes running the testsuite with pypy possible.
2014-10-15 15:35:59 -04:00
Mads Kiilerich
29285eb86d ui: show prompt choice if input is not a tty but is forced to be interactive
The tests often set ui.interactive to control normally interactive prompts from
stdin. That gave an output where it was non-obvious what prompts got which
which response, and the output lacked the newline users would see after input.

Instead, if the input not is a tty, write the selection and a newline.
2014-10-01 01:04:18 +02:00
FUJIWARA Katsunori
67129a7816 transplant: change "editform" to distinguish merge commits from others
"editform" argument for "getcommiteditor" is decided according to the
format below:

  EXTENSION[.COMMAND][.ROUTE]

  - EXTENSION: name of extension
  - COMMAND: name of command, if there are two or more commands in EXTENSION
  - ROUTE: name of route, if there are two or more routes in COMMAND

This patch newly adds "normal" and "merge" as ROUTE, to distinguish
merge commits from other.

This patch adds 4 test patterns to test combination of "merge"(x2) and
"--continue"(x2).
2014-08-16 10:43:59 +09:00
Matt Mackall
11be5cc27c tests: replace exit 80 with #require 2014-08-06 11:43:59 -05:00
FUJIWARA Katsunori
71a4736498 transplant: use "getcommiteditor()" instead of explicit editor choice
This patch also enhances "test-transplant.t", because "hg transplant"
hasn't been explicitly tested around editor invocation and "--edit"
option.
2014-05-11 00:49:35 +09:00
Mads Kiilerich
0e8795ccd6 spelling: fixes from spell checker 2014-04-13 19:01:00 +02:00
FUJIWARA Katsunori
636302d19b transplant: use "ui.extractchoices()" to show the list of available responses
Before this patch, transplant extension shows the list of available
responses by specific string, even though the prompt string passed to
"ui.promptchoice()" has enough (maybe i18n-ed) information.

This patch uses "ui.extractchoices()" to show the list of available
responses.
2013-12-02 00:50:30 +09:00
FUJIWARA Katsunori
ecea0f8fc0 transplant: use "ui.promptchoice()" for interactive transplant
Before this patch, transplant extension uses "ui.prompt()" for
interactive transplant, and has to check whether user response
returned by "ui.prompt()" is valid or not in own code.

In addition to it, transplant extension uses response characters
(e.g. "y", "n", and so on) directly in own code, and this disallows to
use another response characters by translation, even though the help
shown by '?'  typing is translatable.

This patch uses "ui.promptchoice()" instead of "ui.prompt()" to
resolve problems above.
2013-12-02 00:50:30 +09:00
FUJIWARA Katsunori
b4f116c4e3 transplant: add test for interactive transplant 2013-12-02 00:50:30 +09:00
FUJIWARA Katsunori
90dd1201ec transplant: use peer of source repository as "remote" for "repo.pull()"
Before this patch, transplant with "--merge" option fails with
traceback unexpectedly, if it causes pull from the source repository
on the local host.

"discovery.findcommonincoming()" invokes "capable()" method on the
object given from "localrepository.pull()", but it is
"localrepository" object in this case and doesn't have such method.

This patch uses peer object of source repository as "remote" argument
for "localrepository.pull()" invocation like other invocations of it
in transplant.py.
2013-11-16 23:14:20 +09:00
Mads Kiilerich
861c915f14 bundlerepo: don't return the peer without bundlerepo from getremotechanges
Problem:
getremotechanges would return the 'other' repo if nothing was incoming and
there thus wasn't any bundle to base the repo on. The 'other' could be a http
peer which only implement the functionality available over the http protocol.
Transplant could thus fail with
  TypeError: argument of type 'httppeer' is not iterable

Solution:
Return the local repo instead of the remote peer if there is no reason to place
a bundlerepo on top of the local repo.
2012-12-28 11:16:01 +01:00
Patrick Mezard
3f23aa6a3f tests: enable more server tests on Windows 2012-09-12 22:21:54 +02:00
Patrick Mezard
4da0fafc00 transplant: fix emptied changeset message
- Append an EOL
- State the changeset is skipped
2012-08-01 14:08:19 +02:00
Patrick Mezard
ba210ae123 transplant: handle non-empty patches doing nothing (issue2806)
If patch.patch() reports patched files when applying a changeset and the
following commit says nothing changed, transplant used to abort with a
RuntimeError, assuming something went wrong with patching.

The mismatch is patch.patch() reports patched files, not changed ones.
It could be modified to report changed files but it means duplicating
work from status, may be expensive in the case of binary files, and is
probably not that useful at API level. For instance, if two patches are
applied on the working directory, the outcome may be nothing changed
while each call would have returned modified files. The caller would
have to call status() itself again.

This patch fixes the issue by trusting patching code: if the patch
succeeded and commit reports nothing changed, then nothing changed,
patch() did not "dropped changes on the floor".
2012-07-31 17:39:32 +02:00
Matt Harbison
223186cb48 revset: add destination() predicate
This predicate is used to find csets that were created because of a graft,
transplant or rebase --keep.  An optional revset can be supplied, in which case
the result will be limited to those copies which specified one of the revs as
the source for the command.

    hg log -r destination()                 # csets copied from anywhere
    hg log -r destination(branch(default))  # all csets copied from default

    hg log -r origin(x) or destination(origin(x))  # all instances of x

This predicate will follow a cset through different types of copies.  Given a
repo with a cset 'S' that is grafted to create G(S), which itself is
transplanted to become T(G(S)):

    o-S
   /
  o-o-G(S)
   \
    o-T(G(S))

    hg log -r destination( S )    # { G(S), T(G(S)) }
    hg log -r destination( G(S) ) # { T(G(S)) }

The implementation differences between the three different copy commands (see
the origin() predicate) are not intentionally exposed, however if the
transplant was a graft instead:

	hg log -r destination( G(S) )   # {}

because the 'extra' field in G(G(S)) is S, not G(S).  The implementation cannot
correct this by following sources before G(S) and then select the csets that
reference those sources because the cset provided to the predicate would also
end up selected.  If there were more than two copies, sources of the argument
would also get selected.

Note that the convert extension does not currently update the 'extra' map in its
destination csets, and therefore copies made prior to the convert will be
missing from the resulting set.

Instead of the loop over 'subset', the following almost works, but does not
select a transplant of a transplant.  That is, 'destination(S)' will only
select T(S).

    dests = set([r for r in subset if _getrevsource(repo, r) in args])
2012-07-07 00:47:55 -04:00
Mads Kiilerich
a90ec570cc tests: add some missing #if's / hghave requirements
Seen on Linux with FAT.
2012-06-15 00:02:27 +02:00
Mads Kiilerich
9355854f8a tests: cleanup of tests that got lost in their own nested directories
Some tests ended up in a directory several directories deeper than $TESTTMP,
usually because some 'cd ..' had been forgotten between different test cases.

Add 'cd ..' where they are missing so the tests get back where they started.
2012-06-11 01:38:32 +02:00
Levi Bard
23f20d7bd7 transplant: manually transplant pullable changesets with --log 2012-05-11 17:26:58 +02:00
Patrick Mezard
7ca23e70fa transplant: do not rollback on patching error (issue3379)
Otherwise, all transplanted revisions are gone and the failing one cannot be
fixed (unless it is the first one).

I do not know what is the expected behaviour with rollback, probably something
pull-like. Non-conflicting cases should work as previously. But something like:

  $ hg transplant r1 r2
  commiting r1 as c1
  failing r2
  $ hg transplant --continue
  committing r2 as c2
  $ hg rollback

would reset the repository to its state before the "transplant --continue"
instead of the whole transplant session. To fix this we might need a way to
open an existing journal file, not sure this is worth the pain.
2012-04-22 16:40:38 +02:00
Steven Stallion
4915686ba1 transplant: permit merge changesets via --parent
This change permits the transplant extension to operate on merge
changesets by way of --parent.  This is particularly useful for
workflows which cherrypick branch merges rather than each commit
within a branch.
2012-04-10 23:24:12 -07:00
Mads Kiilerich
8415df7277 tests: use 'hghave serve' to guard tests that requires serve daemon management 2011-11-07 03:24:53 +01:00
Greg Ward
aac3e5d5ea transplant: wrap a transaction around the whole command 2011-10-04 19:43:45 -04:00
Matt Mackall
2f01bc4c58 merge with stable 2011-05-06 11:51:18 -05:00
Idan Kamara
9afabe8fdd transplant: fix revset doc 2011-05-06 15:37:38 +03:00
Patrick Mezard
7b07c85acf test-transplant: fix missing file addition 2011-04-25 21:11:28 +02:00
Patrick Mezard
614c31dde4 merge with stable 2011-04-25 21:20:44 +02:00
Brendan Cully
f05749f48c Fix transplant error message to correspond with test 2011-03-28 21:36:29 -07:00
Luke Plant
bd1d8463c8 transplant: fix crash if filter script munges log file
This fixes an UnboundLocalError crash if the filter script removes the
'User' or 'Date' lines from the log file.
2011-03-28 21:17:32 +01:00
Mads Kiilerich
8e085520f4 tests: use (esc) instead of other kinds of string escaping 2010-11-08 01:41:42 +01:00
Kevin Bullock
15da3ac7f2 pull: silence spurious 'requesting all changes' message
When issuing `hg pull -r REV` in a repo with no common ancestor with the
remote repo, the message 'requesting all changes' is printed, even though only
the changese that are ancestors of REV are actually requested. This can be
confusing for users (see
http://www.selenic.com/pipermail/mercurial/2010-October/035508.html).

This silences the message if (and only if) the '-r' option was passed.
2010-10-20 17:38:21 -05:00
Patrick Mezard
dd00c736bd test-transplant: test transplanted() revset 2010-10-22 22:58:17 +02:00
Martin Geisler
3d112b3042 tests: added a short description to issue numbers
Many tests already had a short line to describe what IssueXXX is
about. I find that quite useful when reading a test.
2010-09-24 10:13:49 +02:00
Brodie Rao
b5fe0d906e tests: add glob matching for unified tests
This adds a " (glob)" marker that works like a simpler version of
(re): "*" is converted to ".*", and "?" is converted to ".".

Both special characters can be escaped using "\", and the backslash
itself can be escaped as well.

Other glob-style syntax, like "**", "[chars]", or "[!chars]", isn't
supported.
2010-09-22 16:06:02 -05:00
Brodie Rao
7d7d96bd74 tests: require regexes in unified tests to be marked with " (re)"
Consider this test:

  $ hg glog --template '{rev}:{node|short} "{desc}"\n'
  @  2:20c4f79fd7ac "3"
  |
  | o  1:38f24201dcab "2"
  |/
  o  0:2a18120dc1c9 "1"

Because each line beginning with "|" can be compiled as a regular
expression (equivalent to ".*|"), they will match any output.

Similarly:

  $ echo foo


The blank output line can be compiled as a regular expression and will
also match any output.

With this patch, none of the above output lines will be matched as
regular expressions. A line must end in " (re)" in order to be matched
as one.

Lines are still matched literally first, so the following will pass:

  $ echo 'foo (re)'
  foo (re)
2010-09-22 16:06:00 -05:00
Matt Mackall
08439e0f2d tests: add exit codes to unified tests 2010-09-16 17:51:32 -05:00
Martin Geisler
cc612c476f tests: remove unneeded -d flags
Many tests fixed the commit date of their changesets at '1000000 0' or
similar. However testing with "Mon Jan 12 13:46:40 1970 +0000" is not
better than testing with "Thu Jan 01 00:00:00 1970 +0000", which is
the default run-tests.py installs.

Removing the unnecessary flag removes some clutter and will hopefully
make it clearer what the tests are really trying to test. Some tests
did not even change their output when the dates were changed, in which
case the -d flag was truly irrelevant.

Dates used in sequence (such as '0 0', '1 0', etc...) were left alone
since they may make the test easier to understand.
2010-09-02 23:22:51 +02:00
Martin Geisler
cb36142754 Merge with stable 2010-08-29 22:55:37 +02:00
Nicolas Dumazet
6e81695eb4 tests: unify test-transplant 2010-08-12 22:14:19 +09:00