Commit Graph

15982 Commits

Author SHA1 Message Date
FUJIWARA Katsunori
07d633b500 commands: advance current active bookmark at pull --update correctly
Before this patch, "hg pull --update" doesn't advance current active
bookmark correctly, if pulling itself doesn't advance it, even though
"hg pull" + "hg update" does so.

Existing test for "pull --update works the same as pull && update" in
test-bookmarks.t doesn't examine this case, because pulling itself
advance current active bookmark before actual updating the working
directory in that test case.

To advance current active bookmark at "hg pull --update" correctly,
this patch examines 'movemarkfrom' instead of 'not checkout'.

Even if 'not checkout' at the invocation of postincoming(), 'checkout'
is overwritten by "the revision to update to" value returned by
destutil.destupdate() in such case. Therefore, 'not checkout'
condition means "update destination is revision #0", and isn't
suitable for examining whether active bookmark should be advanced.

Even though examination around "movemarkfrom == repo['.'].node()" may
seem a little redundant just for this issue, this makes it easier to
compare (and unify in the future, maybe) with the same logic to update
bookmark at "hg update" below.

        if not ret and movemarkfrom:
            if movemarkfrom == repo['.'].node():
                pass # no-op update
            elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
                ui.status(_("updating bookmark %s\n") % repo._activebookmark)
            else:
                # this can happen with a non-linear update
                ui.status(_("(leaving bookmark %s)\n") %
                          repo._activebookmark)
                bookmarks.deactivate(repo)
2016-01-28 20:10:06 +09:00
Augie Fackler
db82034373 changegroup: fix treemanifest exchange code (issue5061)
There were two mistakes: one was accidental reuse of the fclnode
variable from the loop gathering file nodes, and the other (masked by
that bug) was not correctly handling deleted directories. Both cases
are now fixed and the test passes.
2016-01-27 10:24:25 -05:00
Matt Mackall
e2cfbb7c54 log: speed up single file log with hidden revs (issue4747)
On repos with lots of heads, the filelog() code could spend several
minutes decompressing manifests. This change instead tries to
efficiently scan the changelog for candidates and decompress as few
manifests as possible. This is a regression introduced in 3.3 by the
linkrev adjustment code. Prior to that, filelog was nearly instant.

For the repo in the bug report, this improves time of a simple log
command from ~3 minutes to ~.5 seconds, a 360x speedup.

For the main Mercurial repo, a log of commands.py slows down from
1.14s to 1.45s, a 27% slowdown. This is still faster than the file()
revset, which takes 2.1 seconds.
2016-01-22 12:08:20 -06:00
Matt Harbison
87e191502b commit: factor the post commit status check into a cmdutil method
The largefiles extension needs to set lfstatus for this status call.  Otherwise,
if a missing largefile is explicitly named, a confusing message is issued that
says the largefile wasn't found, followed by another that says nothing changed.
2016-01-23 23:24:30 -05:00
Martin von Zweigbergk
c04f1844f0 context: back out sneaky code change in documentation change
In a4119550f1e1 (context: clarify why we don't compare file contents
when nodeid differs, 2016-01-12), I also changed "node2 != _newnode"
into "self.rev() is not None". I don't remember why. They are similar,
but the former also catches the case where the file is clean in the
dirstate (so node2 is not _newnode), but different from the "other"
context. This resulted in unnecessary file content comparison a few
lines further down in the code. Let's just back out the code change.

Thanks to Durham Goode for spotting this.
2016-01-25 15:48:35 -08:00
timeless
d54666f50a setup: create a module for the modulepolicy
Instead of rewriting __init__ to define the modulepolicy,
write out a __modulepolicy__.py file like __version__.py

This should work for both system-wide installation and in-place build. Therefore
we can avoid relying on two separate modulepolicy rules, '@MODULELOADPOLICY@'
and 'mercurial/modulepolicy'.
2016-03-09 15:47:01 +00:00
Yuya Nishihara
3e3e4eca75 graphlog: bring back color to node symbol template
Follows up 64cf8f39aac2. A ui object is required to render labels.
2016-03-09 23:57:15 +09:00
Yuya Nishihara
0703170780 revset: add inspection data to max() and min() functions
We are likely to be interested in how these functions build a result set.
2016-02-16 21:44:13 +09:00
Yuya Nishihara
80f2bcf6b5 revset: add inspection data to limit() and last() functions
We are likely to be interested in how these functions calculate a result set.
2016-02-16 21:43:51 +09:00
Yuya Nishihara
654d7bc89a revset: stub to add extra data to baseset for better inspection
We sometimes construct a baseset from filtering result. In that case, a
baseset can provide more precise information how it is constructed.
2016-02-16 21:32:00 +09:00
Yuya Nishihara
5ec1f7ff3f revset: add inspection data to all filter() calls
This is useful for debugging revset construction.
2016-02-13 20:05:57 +09:00
Yuya Nishihara
587a07dd40 revset: add extra data to filteredset for better inspection
A filteredset is heavily used, but it cannot provide a printable information
how given set is filtered because a condition is an arbitrary callable object.

This patch adds an optional "condrepr" object that is used only by repr(). To
minimize the maintaining/runtime overhead of "condrepr", its type is overloaded
as follows:

  type      example
  --------  ---------------------------------
  tuple     ('<not %r>', other)
  str       '<branch closed>'
  callable  lambda: '<branch %r>' % sorted(b)
  object    other
2016-02-13 19:25:11 +09:00
timeless
4ff3d8a36b templater: ignore orig/rej files
If your mercurial/templates/ directory is dirty, then the template system would
otherwise import duplicate templates from the .orig files and potentially try to
parse .rej files.

Since editing/reverting these templates isn't an unexpected action, and since
they're in .hgignore, it's best that the template system know to skip them."
2016-03-02 05:27:07 +00:00
timeless
1fcd9b7563 resolve: when pats do not match, hint about path:
Suggest a command that would probably work.
2015-12-24 04:31:34 +00:00
FUJIWARA Katsunori
905d970f59 revset: replace predicate by revsetpredicate of registrar
To make all built-in predicates be known to hggettext, loading
built-in predicates by loadpredicate() should be placed before fixing
i18nfunctions but after all of predicate decorating.
2016-03-08 23:04:53 +09:00
FUJIWARA Katsunori
60e9ee2742 revset: replace extpredicate by revsetpredicate of registrar
This patch consists of changes below (these can't be applied
separately).

  - replace revset.extpredicate by registrar.revsetpredicate in
    extensions

  - remove setup() on an instance named as revsetpredicate in
    uisetup()/extsetup() of each extensions

    registrar.revsetpredicate doesn't have setup() API.

  - put new entry for revsetpredicate into extraloaders in dispatch

    This causes implicit loading predicate functions at loading
    extension.

    This loading mechanism requires that an extension has an instance
    named as revsetpredicate, and this is reason why
    largefiles/__init__.py is also changed in this patch.

Before this patch, test-revset.t tests that all decorated revset
predicates are loaded by explicit setup() at once ("all or nothing").

Now, test-revset.t tests that any revset predicate isn't loaded at
failure of loading extension, because loading itself is executed by
dispatch and it can't be controlled on extension side.
2016-03-08 23:04:53 +09:00
FUJIWARA Katsunori
8227e106c7 registrar: define revsetpredicate to decorate revset predicate
revsetpredicate is used to replace revset.predicate and
revset.extpredicate in subsequent patches.

This patch also adds loadpredicate() to revset, because this
combination helps to figure out how the name of safe predicate is put
into safesymbols.

This patch still uses safesymbols set to examine whether the predicate
corresponded to the 'name' is safe from DoS attack or not, because
just setting func._safe property needs changes below for such
examination.

  before:
      name in revset.safesymbols

  after:
      getattr(revset.symbols.get(name, None), '_safe', False)

"automatic registration" described in help doc of revsetpredicate
class will be achieved by the subsequent patch, which lists
loadpredicate() up in dispatch.extraloaders.
2016-03-08 23:04:53 +09:00
FUJIWARA Katsunori
e72a9be81f registrar: introduce new class for registration to replace funcregistrar
_funcregistrarbase differs from funcregistrar in points below:

  - every code paths should use same class derived from
    _funcregistrarbase to register functions in a same category

    funcregistrar expects (3rd party) extensions to use (a class
    derived from) delayregistrar.

  - actual extra setup should be executed in another function

    For example, marking revset predicate as "safe" is executed in a
    class derived from _funcregistrarbase, but putting name of "safe"
    predicate into safesymbols is executed in another function for it.

    funcregistrar expects derived classes to do so.

New class is named as module private one, because code paths, which
register functions, should use not it directly but one derived from
it.
2016-03-08 23:04:53 +09:00
FUJIWARA Katsunori
f9e776bc8b dispatch: make loading extra information from extension extensible
This patch makes loading extra information from extension module at
dispatching extensible. Factoring 'loadcmdtable()' into commands.py is
a part of generalization of loading extra information.

This extensibility assumes registration of new function like below,
for example:

  - revset predicate
  - fileset predicate
  - template keyword
  - template filter
  - template function
  - internal merge tool
  - web command

This patch requires not loader function itself but container module
and the name of it, because listing loader function directly up
implies actual loading module of it, even if it isn't used at runtime
(for example, extensions don't always define revset predicate)
2016-03-08 23:04:53 +09:00
Durham Goode
f5bc3ca716 parsers: optimize filtered headrevs logic
The old native head revs logic would iterate over every node, starting from 0,
and check if every node was filtered (by testing it against the filteredrevs
python set). On large repos with hundreds of thousands of commits, this could
take 150ms.

This new logic iterates over the nodes in reverse order, and skips the filtered
check if we've seen an unfiltered child of the node. This saves approximately a
bagillion filteredrevs set checks, which shaves the time down from 150ms to
20ms during every branch cache write.
2016-03-08 00:20:08 -08:00
FUJIWARA Katsunori
9edf9953ec destutil: choose non-closed branch head at first (BC)
Before this patch, destupdate() returns the tipmost (descendant)
branch head regardless of closed or not. But updating to closed branch
head isn't reasonable for ordinary workflow, because:

  - "hg heads" doesn't show closed heads (= updated parent itself) by
    default

  - subsequent committing on it re-opens closed branch

    even if inactivation of closed head is needed, update destination
    isn't it, because it should be merged into to another branch in
    such case.

This patch chooses non-closed descendant branch head as default update
destination at first. If all descendant branch heads are closed,
destupdate() returns the tipmost closed branch head.

For simplicity, this patch chooses adding _destupdatebranchfallback()
instead largely changing _destupdatebranch().

This patch changes not only normal lookup code path, but also the "no
default branch" code path, for consistency.
2016-03-07 03:14:19 +09:00
Kostia Balytskyi
e31d7d20ae formatter: make labels work with templated output
To describe the bug this fix is addressing, one can do
   ``$ hg status -T "{label('red', path)}\n" --color=debug``
and observe that the label is not applied before my fix and applied with it.
2016-03-08 04:08:33 -08:00
Martijn Pieters
a7c9554a48 graphmod: augment the graph to include more information about the edges
The walker knows when an edge leads to a direct parent, a grandparent (skipping
revisions not part of the revset) and parents that are missing altogether
(neither it nor a grandparent is in the revset). Add this information to the
parents sequence yielded.
2016-03-04 14:44:32 +00:00
Martijn Pieters
a973afd498 graphmod: refactor state handling
Move ASCII graph state to a dictionary, to clarify what is being tracked. Move
the 'seen' state (tracking currently active edges) into this structure.
2016-03-04 14:44:32 +00:00
Yuya Nishihara
1f60c51fa5 templater: abort if infinite recursion detected while compiling
In this case, a template is parsed recursively with no thunk for lazy
evaluation. This patch prevents recursion by putting a dummy of the same name
into a cache that will be referenced while parsing if there's a recursion.

  changeset = {files % changeset}\n
                       ~~~~~~~~~
                        = [(_runrecursivesymbol, 'changeset')]
2015-07-23 23:41:29 +09:00
Yuya Nishihara
554208ae8f templater: abort if infinite recursion detected while evaluation (issue4758)
It would be nice if we could detect recursion at the parsing phase, but we
can't because a template can refer to a keyword of the same name. For example,
"rev = {rev}" is valid if rev is a keyword, and we don't know if rev is a
keyword or a template while parsing.
2015-07-22 23:29:41 +09:00
Martin von Zweigbergk
d1531da666 exchange: set 'treemanifest' param on pushed changegroups too
In 7a1ccfe03f74 (treemanifests: set bundle2 part parameter indicating
treemanifest, 2016-01-08), I didn't realize I had to set the parameter
separately for getbundle and unbundle. Having the parameter there on
push allows us to push to an empty repo and have the requirements
updated correctly.
2016-01-22 16:31:50 -08:00
Laurent Charignon
f5b5bd3884 crecord: fix help bar display issue (issue5063)
Before this patch, the help bar in crecord wouldn't be printed correctly when
the terminal window didn't have enough column to display it. This patch adds
logic to make sure that the help bar message is always displayed. We use an
ellipsis when it is not possible to display the complete message.
2016-01-25 11:37:02 -08:00
Laurent Charignon
f009465327 crecord: fix typo in the help text
In the crecord help dialog, the toggle all option was wrongfully documented.
Instead of using 'a', one must use 'A' to toggle all the hunks. The crecord
header that is always displayed on the screen contains the right shortcut and
does not need to be changed.
2016-01-25 10:13:03 -08:00
Mason Malone
081f032818 subrepo: better error messages in _ensuregit
This patch improves the error messages raised when an OSError occurs, since
simply re-raising the exception can be both confusing and misleading. For
example, if "hg identify" is run inside a repository that contains a Git
subrepository and the git binary could not be found, it'll exit with the message
"abort: No such file or directory". That implies "identify" has a problem
reading the repository itself. There's no way for the user to know what the
real problem is unless they dive into the Mercurial source, which is what I
ended up doing after spending hours debugging errors while provisioning a VM
with Ansible (turns out I forgot to install Git on it).

Descriptive errors are especially important on Windows, since it's common for
Windows users to forget to set the "Path" system variable after installing Git.
2016-01-17 22:53:57 -05:00
Anton Shestakov
f6e436f317 hgweb: update canvas.width before dynamically redrawing graph (issue2683)
After 313b8d61b548 graph canvas width is decided once on the initial rendering.
However, after graph page gets scrolled down to load more, it might need more
horizontal space to draw, so it needs to resize the canvas dynamically.

The exact problem that this patch solves can be seen using:

    hg init testfork
    cd testfork
    echo 0 > foo
    hg ci -Am0
    echo 1 > foo
    hg ci -m1
    hg up 0
    echo 2 > foo
    hg ci -m2
    hg gl -T '{rev}\n'

    @  2
    |
    | o  1
    |/
    o  0

    hg serve

And then by navigating to http://127.0.0.1:8000/graph/tip?revcount=1

"revcount=1" makes sure the initial graph contains only revision 2. And because
the initial canvas width takes only that one revision into count, after the
(immediate) AJAX update revision 1 will be cut off from the graph.

We can safely set canvas width to the new value we get from the AJAX request
because every time graph is updated, it is completely redrawn using all the
requested nodes (in the case above it will use /graph/2?revcount=61), so the
value is guaranteed not to decrease.

P.S.: Sorry for parsing HTML with regexes, but I didn't start it.
2016-01-23 17:31:31 +08:00
Martin von Zweigbergk
c28812c552 shelve: use cg3 for treemanifests
Similar to previous change, this teaches shelve to pick the right
changegroup version for repos that use treemanifests.
2016-01-19 15:37:07 -08:00
Martin von Zweigbergk
857d2206c3 repair: use cg3 for treemanifests
The newly created helper changegroup.safeversion() knows to pick
version 03 if the repo uses treemanifests, so just using that means we
pick the right changegroup version.
2016-01-19 15:38:24 -08:00
Martin von Zweigbergk
4208c8682a changegroup: introduce safeversion()
In a few places (at least repair.py and shelve.py), we want to find
the best changegroup version that we can assume users of the repo will
understand. For example, we choose version 01 by default, but if it's
a generaldelta repo, we expect clients to support version 02 anyway,
so we choose that for new bundles (for e.g. "hg strip"). Let's create
a helper for this functionality in changegroup, so we can reuse it
elsewhere later.
2016-01-19 15:32:32 -08:00
Martin von Zweigbergk
fb1b7626e4 changegroup: don't support versions 01 and 02 with treemanifests
Since it would be terribly expensive to convert between flat manifests
and treemanifests, we have decided to simply not support changegroup
version 01 and 02 with treemanifests. Therefore, let's stop announcing
that we support these versions on treemanifest repos.

Note that this means that older clients that try to clone from a
treemanifest repo will fail. What happens is that the server, after
this patch, finds that there are no common versions and raises
"ValueError: no common changegroup version". This results in "abort:
HTTP Error 500: Internal Server Error" on the client.

Before this patch, it was no better: The server would instead find
that there were directory manifest nodes to put in the changegroup 01
or 02 and raise an AssertionError on changegroup.py#668 (assert not
tmfnodes), which would also appear as a 500 to the client.
2016-01-19 14:27:18 -08:00
timeless
7c2842e773 copyright: update to 2016 2016-01-21 21:15:52 +00:00
Durham Goode
64267e6e4d transaction: abort transaction during hook exception
The new transaction context did not handle the case where an exception during
close should still call release. This cause pretxnclose hooks that failed to
cause the transaction to fail without aborting, thus requiring a hg recover.

I've added a test.
2016-01-19 15:18:21 -08:00
Martin von Zweigbergk
2e9366a5ee changegroup: cg3 has two empty groups *after* manifests
changegroup.getchunks() determines the end of the stream by looking
for an empty chunk group (two consecutive empty chunks). It ignores
empty groups in the first two groups. Changegroup 3 introduced an
empty chunk between the manifests and the files, which confuses
getchunks(). Since it comes after the first two, getchunks() will stop
there.

Fix by rewriting getchunks so it first counts two groups (empty or
not) and then keeps antostarts counting empty groups. With this counting,
changegroup 1 and 2 have exactly one empty group after the first two
groups, while changegroup 3 has two (one for directories and one for
files).

It's a little hard to test this at this point, but I have verified
that this patch fixes narrowhg (which was broken before this
patch). Also, future patches will fix "hg strip" with treemanifests,
and once that's done, getchunks() will be tested through tests of "hg
strip".
2016-01-19 17:44:25 -08:00
Laurent Charignon
7dcb9bf272 repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Before this patch if the hiddencache existed but was empty, it would crash
mercurial. This patch adds exception handling when reading the hiddencache to
avoid the issue.
When encountering a corrupted cache file we print a devel warning. There would
be no point in issuing a normal warning as the user wouldn't be able to do
anything about the situation.

The warning looks like:

devel-warn: corrupted hidden cache, removing it at: /path/to/repoview.py
2016-01-20 13:43:01 -08:00
Laurent Charignon
71a4d24c5d repoview: add missing newline character in debug prints 2016-01-20 13:40:59 -08:00
Yuya Nishihara
558df9ce0f commandserver: drop tell() and seek() from channels (issue5049)
These operations are obviously invalid for file-like channels because they
will read or write protocol headers.

This patch works around the issue that "hg archive" generates a corrupted
zip file on Windows commandserver because of unusable tell() implementation.
But the problem still occurs without using a commandserver.

  $ hg archive -R not-small-repo -t zip - | cat > invalid.zip

So, this patch cannot fix the issue5049 completely.
2016-01-20 00:08:00 +09:00
Laurent Charignon
9f20d61491 crecord: edit during hg crecord should preserve cursor position (issue5041)
This patch adds a variable to keep track of what hunk was selected
before the edit. We use that variable to select the hunk or its
replacement after the edit.
2016-01-20 11:21:13 -08:00
FUJIWARA Katsunori
cd5e04a455 templates: use canvaswidth instead of fixed width for canvas (issue2683)
Before this patch, template files for "graph" web page use fixed width
size "480" for canvas element.

This causes pruned lanes and invisible vertexes, if there are 16 or
more vertical lanes at once. In such case, part of graph in right side
area over 480 is invisible, even though corresponded summary text
blocks are visible correctly.

This limitation isn't reasonable for workflow using many branches at
once (e.g. "one branch per issue" workflow).

There were changes below related to width of canvas:

  - 6c855f5350cd (templates: widen the graph canvas (issue2683)),
    released as a part of Mercurial 1.8.2

    According to the description, this assumed that 15 parallel
    branches was enough for ordinary workflow, and bumped width of
    canvas up from 224 to 480.

  - f5506d2a674c (hgweb: make graph data suitable for template usage),
    released as a part of Mercurial 2.3

    This introduced "canvaswidth" template keyword as a part of
    refactoring around graph rendering.

    But 'width="480"' of canvas element in template files wasn't
    replaced by 'width="{canvaswidth}"' in it (or subsequent one).

This patch uses dynamic value "{canvaswidth}" instead of fixed width
size "480" for canvas element.

This is posted for "stable", because:

  - this is re-fixing issue2683

  - this is simple enough for stable

  - using "{canvaswidth}" doesn't require any additional cost

    Calculation of canvaswidth is already implied as a part of "graph"
    web command.
2016-01-21 02:42:01 +09:00
Ruslan Sayfutdinov
f9fd350906 backout: fix --no-commit option (issue5054) 2016-01-20 08:16:58 -08:00
Durham Goode
4ce51c3927 bundle: exit early when there are no commits to bundle
Previously, if you passed a revset that resolved to no nodes, it would get
interpreted by the changegroup discovery logic as 'bundle all my heads', which
is not what the user asked.

Let's exit early when we notice this case.

It could be argued that the changeset discovery logic should be smarter and only
assume 'all heads' if the incoming heads parameter is None, but that's a much
riskier change.
2016-01-19 13:43:50 -08:00
Gregory Szorc
b16347f628 localrepo: don't reference transaction from hook closure (issue5043)
Before, the hook() closure (which is called as part of locking hooks)
would maintain a reference to a transaction instance (which should be
finalized by the time lock hooks are called). Because we accumulate
hook() instances when there are multiple transactions per lock, this
would result in holding references to the transaction instances which
would lead to higher memory utilization.

Creating a reference to the hook arguments dict minimizes the number
of objects that are kept alive until the lock release hook runs,
minimizing memory "leaks."
2016-01-17 14:14:15 -08:00
Gregory Szorc
fbab5f0c4c context: don't use util.cachefunc due to cycle creation (issue5043)
util.cachefunc stores all arguments as the cache key. For filectxfn
functions, the arguments include the memctx instance. This creates a
cycle where memctx._filectxfn references self. This causes a memory
leak.

We break the cycle by implementing our own memoizing function that
only uses the path as the cache key. Since each memctx has its own
cache instance, there is no concern about invalid cache hits.
2016-01-17 12:10:30 -08:00
Martin von Zweigbergk
216d0e41ef diff: don't crash when merged-in addition is copied
Similar to what was explained in the previous commit, the diff code
expected copy source to be in "ctx1", which is not always the case
during a merge. This has been broken since before hg 2.0.

Also similar to the previous commit, we fix the problem by fixing up
the copy dict.
2016-01-14 10:22:55 -08:00
Martin von Zweigbergk
0c3407d70e diff: don't crash when merged-in addition was removed (issue4786)
During a merge, if the user removes a file that came from parent 2 and
did not exist in parent 1, the file's status will be "removed". This
surprises the diff code, which crashes because it expects removed
files exist in parent 1. This has been broken since ff976121fb34
(trydiff: use 'not in addedset' for symmetry with 'not in removedset',
2014-12-23).

Fix by fixing up the list of removed file, similar to how we currently
fix up the list of modified and added files during a merge.
2016-01-14 10:14:24 -08:00
Martin von Zweigbergk
cf817770b1 diff: move status fixup earlier, out of _filepairs()
This prepares for future patches, and it also lets us remove the ugly
"ctx1" argument to _filepairs() (ugly because of its assymmetry --
there's no "ctx2" argument).
2016-01-14 10:02:34 -08:00
Mads Kiilerich
9f1efa7c96 graft: warn when -r is combined with revisions as positional arguments
The behaviour in this case is undefined. Instead of silently doing something
"random" and surprising, at least issue a warning.

(This should perhaps be considered a "deprecation" and turned into an error in
a future release.)
2016-01-17 19:33:02 +01:00
Mads Kiilerich
200157f1b5 graft: clarify in help that -r is not just optional
Positional parameters are also treated as revisions, but the order of revisions
matters and it will often be wrong if the user understands it as `-r` taking
multiple revisions as `-r REV1 REV2`.

(Alternatively, `-r` could be turned into a no-op flag as the documentation
suggests. That would however be less "semantic markup" and I agree with the
implementation in 40cbb25097c8 but not the documentation.)
2016-01-17 19:33:02 +01:00
Gregory Szorc
a05892eae0 streamclone: use backgroundfilecloser (issue4889)
Closing files that have been appended to is slow on Windows/NTFS.
CloseHandle() calls on this platform often take 1-10ms - and that's
on my i7-6700K Skylake processor with a modern and fast SSD. Contrast
with other I/O operations, such as writing data, which take <100us.

This means that creating/appending thousands of files can add
significant overhead. For example, cloning mozilla-central creates
~232,000 revlog files. Assuming 1ms per CloseHandle(), that yields
232s (3:52) of wall time waiting for file closes!

The impact of this overhead can be measured most directly when applying
stream clone bundles. Applying these files is effectively uncompressing
a tar archive (read: it's very fast).

Using a RAM disk (read: no I/O wait), the difference in wall time for a
`hg debugapplystreamclonebundle` for a ~1731 MB mozilla-central bundle
between Windows and Linux from the same machine is drastic:

Linux:    ~12.8s (128MB/s)
Windows: ~352.0s (4.7MB/s)

Windows is ~27.5x slower. Yikes!

After this patch:

Linux:    ~12.8s (128MB/s)
Windows: ~102.1s (16.1MB/s)

Windows is now ~3.4x faster. Unfortunately, it is still ~8x slower than
Linux. Profiling reveals a few hot code paths that could likely be
improved. But those are for other patches.

This patch introduces test-clone-uncompressed.t because existing tests
of `clone --uncompressed` are scattered about and adding a variation for
background thread closing to e.g. test-http.t doesn't feel correct.
2016-01-14 13:44:01 -08:00
Gregory Szorc
ba2d05e908 streamclone: indent code
This will make the subsequent patch easier to read.
2016-01-02 16:11:36 -08:00
Gregory Szorc
49c61f06be scmutil: support background file closing
Closing files that have been appended to is relatively slow on
Windows/NTFS. This makes several Mercurial operations slower on
Windows.

The workaround to this issue is conceptually simple: use multiple
threads for I/O. Unfortunately, Python doesn't scale well to multiple
threads because of the GIL. And, refactoring our code to use threads
everywhere would be a huge undertaking. So, we decide to tackle this
problem by starting small: establishing a thread pool for closing
files.

This patch establishes a mechanism for closing file handles on separate
threads. The coordinator object is basically a queue of file handles to
operate on and a thread pool consuming from the queue.

When files are opened through the VFS layer, the caller can specify
that delay closing is allowed.

A proxy class for file handles has been added. We must use a proxy
because it isn't possible to modify __class__ on built-in types. This
adds some overhead. But as future patches will show, this overhead
is cancelled out by the benefit of closing file handles on background
threads.
2016-01-14 13:34:59 -08:00
Yuya Nishihara
c998aff68a templatekw: add {namespaces} keyword
This provides a general-purpose interface to all custom namespaces.

The {namespaces} keyword honors the definition order of namespaces as they
are kept by sortdict.
2016-01-12 23:56:48 +09:00
Yuya Nishihara
dbf185d983 templatekw: move shownames() helper to be sorted alphabetically
I'll add shownamespaces(), which is similar to this function. I want to put
them nearby.
2016-01-12 23:53:56 +09:00
Yuya Nishihara
e2a7f69128 templater: make get(dict, key) return a single value
This is necessary to obtain a _hybrid object from a dict. If get() yields
a value, it would be stringified.

I see no benefit to make get() lazy, so this patch just changes "yield" to
"return".
2016-01-16 13:53:32 +09:00
Yuya Nishihara
20aed11e76 templater: make _hybrid not callable to avoid conflicting semantics
In templater, a callable symbol exists for lazy evaluation, which should have
f(**mapping) signature. On the other hand, _hybrid.__call__(), which was
introduced by 4e182fb53989, generates mapping for each element.

This patch renames _hybrid.__call__() to _hybrid.itermaps() so that a _hybrid
object can be a value of a mapping dict.

  {namespaces % "{namespace}: {names % "{name }"}\n"}
                               ~~~~~
                               a _hybrid object
2016-01-16 13:42:37 +09:00
Ruslan Sayfutdinov
3f980f0f17 backout: commit changeset by default (BC)
Add --no-commit flag to prevent it. This should make the hg user
experience a little better. Some discussion can be found here:
http://markmail.org/message/7jm7ro2ias6hxywy
2016-01-15 13:46:33 -08:00
Danek Duvall
66247223e5 help: move Windows 9x information to appropriate place 2016-01-15 13:01:37 -08:00
Gregory Szorc
05359af187 commands: document clone bundles hooks and rollback behavior
The added content is inside a verbose container.

I figure it makes sense to explicitly document behavior, including
with the caveat it may change later. People can't say they weren't
warned!
2016-01-14 21:21:59 -08:00
Gregory Szorc
3a890f3e32 commands: teach debugbundle to print bundle specification
This seems like the most logical place to put this functionality.

Test coverage over existing known bundle specs has been added.
2016-01-14 22:57:55 -08:00
Gregory Szorc
274b1c944c commands: use context manager for opened bundle file 2016-01-14 21:27:53 -08:00
Gregory Szorc
6a6f7ee7dc exchange: implement function for inferring bundle specification
We don't currently have a mechanism for inferring bundle spec strings
from bundle files. This patch adds one.

This will eventually be used to make the producing of clone bundles
manifests easier.
2016-01-14 22:49:03 -08:00
Gregory Szorc
9128d3d945 streamclone: extract code for reading header fields
So it can be called from another consumer in a future patch.
2016-01-14 22:48:54 -08:00
Yuya Nishihara
6727c29486 encoding: escape U+007F (DEL) character in JSON
RFC 7159 does not state that U+007F must be escaped, but it is widely
considered a control character. As '\x7f' is invisible on a terminal, and
Python's json.dumps() escapes '\x7f', let's do the same.
2016-01-16 18:30:01 +09:00
Augie Fackler
54446bb7e0 cleanup: use modern @property/@foo.setter property specification
We can use this now that we're 2.6+, and this is more idiomatic modern
Python.
2016-01-16 10:50:28 -05:00
Matt Mackall
4343a7194d mac: ignore resource fork when checking file sizes
Some evil evil awful tool adds resource forks to files it's comparing.
Our Mac-specific code to do bulk stats was accidentally using "total
size" which includes those forks in the file size, causing them to be
reported as modified. This changes it to only care about the normal
data size and thus agree with what Mercurial's expecting.
2016-01-14 12:37:15 -06:00
Matt Mackall
a8fcfbf03d copies: fix detection of divergent directory renames
If we move all the files out of one directory, but into two different
directories, we should not consider it a directory rename. The
detection of this case was broken.
2016-01-13 10:10:05 -06:00
Bryan O'Sullivan
541db2c882 with: use context manager for transaction in strip 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
fd04392cbc with: use context manager for transaction in pushphase 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
8bfeb98530 with: use context manager for transaction in strip 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
da377129a6 with: use context manager in rebuildfncache 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
13360de2f3 with: use context manager for transaction in consumev1 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
c72a4fb771 with: use context manager in amend 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
337c3199e2 with: use context manager for transaction in changegroup apply
(This needs some line wrapping due to the additional indent level. -mpm)
2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
31c9d97ad8 transaction: turn a transaction into a Python context manager
This lets us greatly simply acquire/release cycles.

If the block completes without raising an exception, the transaction
is closed.

Code pattern before:

  try:
    tr = repo.transaction('x')
    # zillions of lines of code
    tr.close()
  finally:
    tr.release()

And after:

  with tr.transaction('x'):
    # ...
2016-01-15 13:14:47 -08:00
Bryan O'Sullivan
2c9c32a10b with: use context manager for lock in pushphase 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
155e1de602 with: use context manager in rebuildfncache again 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
cde011507a with: use context manager in streamclone consumev1 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
f646cafad4 with: use context manager in manifest 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
2caa7d79a8 with: use context manager in rename 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
f32abc8e35 with: use context manager in resolve 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
fa514efcb7 with: use context manager in unbundle 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
44384e880c with: use context manager in update 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
9e950df349 with: use context manager in bisect save_state 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
ff05835c28 with: use context manager in merge update 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
51b6f1d59f with: use context manager in _markchanges 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
9b486e52cc with: use context manager in maybeperformlegacystreamclone 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
1d0c7077f2 with: use context manager in verify 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
b5f5cce8ca with: use context manager in localrepo recover 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
721f51151e with: use context manager in streamclone generatev1 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
d5d9f6c78a with: use context manager in subrepo storeclean 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
65a1bc16a6 with: use context manager in subrepo _cachestorehash 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
dc202a7844 with: use context manager for wlock in checklookup 2016-01-15 13:14:46 -08:00
Bryan O'Sullivan
c12335032a with: use context manager for wlock in copy 2016-01-15 13:14:46 -08:00
Bryan O'Sullivan
0d3b3841ab with: use context manager for wlock in workingctx.undelete 2016-01-15 13:14:46 -08:00
Bryan O'Sullivan
e93769dccc with: use context manager for wlock in workingctx.forget 2016-01-15 13:14:46 -08:00
Bryan O'Sullivan
521cb71d13 with: use context manager for wlock in workingctx.add 2016-01-15 13:14:46 -08:00