Commit Graph

19580 Commits

Author SHA1 Message Date
Jun Wu
eaaeecf0d5 revset: optimize "draft() & ::x" pattern
The `draft() & ::x` type query could be common for selecting one or more
draft feature branches being worked on.

Before this patch, `::x` may travel through the changelog DAG for a long
distance until it gets a smaller revision number than `min(draft())`. It
could be very slow on long changelog with distant (in terms of revision
numbers) drafts.

This patch adds a fast path for this situation, and will stop traveling the
changelog DAG once `::x` hits a non-draft revision.

The fast path also works for `secret()` and `not public()`.

To measure the performance difference, I used drawdag to create a repo that
emulates distant drafts:

          DRAFT4
           |
          DRAFT3 # draft
          /
  PUBLIC9999 # public
      |
  PUBLIC9998
      |
      .   DRAFT2
      .    |
      .   DRAFT1 # draft
      |   /
  PUBLIC0001 # public

And measured the performance using the repo:

  (BEFORE)
  $ hg perfrevset 'draft() & ::(DRAFT2+DRAFT4)'
  ! wall 0.017132 comb 0.010000 user 0.010000 sys 0.000000 (best of 156)
  $ hg perfrevset 'draft() & ::(all())'
  ! wall 0.024221 comb 0.030000 user 0.030000 sys 0.000000 (best of 113)
  (AFTER)
  $ hg perfrevset 'draft() & ::(DRAFT2+DRAFT4)'
  ! wall 0.000243 comb 0.000000 user 0.000000 sys 0.000000 (best of 9303)
  $ hg perfrevset 'draft() & ::(all())'
  ! wall 0.004319 comb 0.000000 user 0.000000 sys 0.000000 (best of 655)

Differential Revision: https://phab.mercurial-scm.org/D441
2017-08-28 14:49:00 -07:00
Kyle Lippincott
8cf1a22c40 wireproto: do not abort after successful lookup
As far as I can tell, this interface originally used 'return' here, so the
"fallthrough" to self._abort made sense. When it was switched to 'yield' this
didn't make sense, but doesn't impact most uses because the 'plain' wrapper in
peer.py's 'batchable' decorator only attempts to yield two items (args and
value).

When using iterbatch, however, it attempts to verify that the @batchable
generators only emit 2 results, by expecting a StopIteration when attempting to
access a third.

Differential Revision: https://phab.mercurial-scm.org/D608
2017-09-01 14:00:13 -07:00
Saurabh Singh
d84d216df1 amend: moving first assignment of newid closer to its use
newid was needlessly further away from where its intended to be used
leading to bad readability. This commit moves it to address the same. The end
goal is to remove the redundant commit in the amend code path and this commit
takes care of cleaning up some unrelated code before that change.

Test Plan:
ran the test suite

Differential Revision: https://phab.mercurial-scm.org/D597
2017-09-01 12:34:36 -07:00
Saurabh Singh
27a654fdd5 amend: rectify comment
Comment was ambiguous as there can be two parents of a changeset in mercurial.
This commit fixes the comment to clarify that the first parent is being
considered.

Test Plan:
ran the test suite

Differential Revision: https://phab.mercurial-scm.org/D595
2017-08-31 18:35:39 -07:00
Saurabh Singh
2e3d37be51 amend: removing redundant if condition
There is needless checking for the new commit hash not being equal to
the old commit hash. This condition will always be true at this point in the
code path and thus, can be removed safely. This commit removes the redundant
condition.

Test Plan:
ran the test suite.

Differential Revision: https://phab.mercurial-scm.org/D594
2017-09-01 15:08:54 -07:00
Michael Bolin
16648b82d6 editor: file created for diff action should have .diff suffix
This is a follow-up to https://phab.mercurial-scm.org/D464 (02b917f3e672) that
introduced the new file extension behavior. It erroneously changed `.diff` to
`.diff.hg.txt`.

Test Plan:
Verified `make tests` passes, particularly `test-editor-filename.t`.

Differential Revision: https://phab.mercurial-scm.org/D607
2017-09-01 20:28:26 +00:00
Gregory Szorc
7db45deab1 util: use set for reserved Windows filenames
Previously, we were performing membership testing against a
list. Change it to a set for a minor perf win. While we're at it,
explode the assignment in place so less work is needed at module
import time.

Differential Revision: https://phab.mercurial-scm.org/D600
2017-08-31 19:40:15 -07:00
Phil Cohen
28052d0586 context: add arbitraryfilectx, which can represent files outside the workdir
Move it from contrib/simplemerge so it can be re-used in the future.

Differential Revision: https://phab.mercurial-scm.org/D604
2017-09-01 11:52:20 -07:00
Phil Cohen
5b0c47fbe3 simplemerge: remove unused repo parameter
This is now no longer used or needed thanks to the `decodeddata()` context
function.

Differential Revision: https://phab.mercurial-scm.org/D602
2017-09-01 10:35:43 -07:00
Christophe de Vienne
87902af734 extensions: prohibit unicode defaults
If the default value of an option is a unicode string (something
than happen easily when using a 'from __future__ import unicode_literals'),
any value passed on the command line will be ignored because the fancyopts
module only checks for byte strings and not unicode strings.

Changing fancyopts behavior is easy but would make assumptions on how
the python3 port should be done, which is outside the scope of this patch.

The chosen approach is to stop an extension from being loaded when a unicode
default value is detected, with a hint for the developer.
2017-08-29 18:24:51 +02:00
Yuya Nishihara
6d9809531d revsetlang: remove unused functions
Superseded by the _match() function.
2017-08-19 22:04:03 +09:00
Pulkit Goyal
7ea95030b1 status: add a flag to terse the output (issue4119)
This adds an experimental flag -t/--terse which will terse the output. The terse flag
will respect other flags which filters the output. The flag takes a string
whose value can be a subsequence of "marduic" (the order does not matter here.)

Ignored files are not considered while tersing unless -i flag is passed or 'i'
is there is the terse flag value.

The flag is experimental for testing as there may be cases which will produce
strange results with the flag. We can set the terse on by default by simply
passing 'u' to the cmdutil.tersestatus().

This patch also adds a test file with tests covering the new feature.
2017-06-17 20:10:22 +05:30
Matt Harbison
312e37cc1e archive: add an experimental config to control the metadata file template
Experimental because given the possible complexity, it may be worth figuring out
how to load this from a file, similar to the style files for the log command,
instead of trying to stuff it on the command line.
2017-07-17 00:49:29 -04:00
Matt Harbison
9f1bd9a3e0 archive: use a templater to build the metadata file
There are no visible changes here.

I'm starting to wonder if adding the '+' to the 'node' line instead of a
separate key line in a4d42f6edc09 was the right thing to do.  The '{node}'
keyword never includes '+' elsewhere, and the way setup.py works, it would
truncate it anyway.  Additionally, the file is missing '{p2node}' when 'wdir()'
merges are archived.  I thought about adding an 'identify' line that would
correspond to `hg id -n`.  But the other nodes are the full 40 characters, and
the output most useful for versioning is the short form.  All of this cries out
for customization via templating.  (Although maybe having the short identify
line by default is still a good idea.)
2017-07-16 17:40:36 -04:00
Jun Wu
ba3af86825 commandserver: do not handle EINTR for selector.select
selectors2 library handles EINTR transparently so we don't need to handle
select.error ourselves.
2017-07-16 11:17:00 -07:00
Boris Feld
b989852f8f debugobsolete: also report the number of obsoleted changesets
This seems useful to have the number of obsoleted changesets when calling
debugobsolete.
2017-07-16 02:33:14 +02:00
Boris Feld
68ddce738e transaction-summary: display the summary for all transactions
Now that we records "all" changes happening in a transaction (in tr.changes)
we will be able to provide better report on various changes (phases turned
public, changeset obsoleted, branch merged or created, etc..)

This is far too late in the cycle to play with this, but having this existing
method called more widely will help extensions to play around with various
options during the 4.4 cycle.

Instead of calling registersummarycallback only for transactions we want, we
always call it and use the transaction name to decide when to report (eg: we
do not want `hg amend` to report new obsoleted changesets). Filtering on
transaction name does not seems great, but seems good enough for the moment.
We can change the API during the next cycle.

The previous manual call during unbundling of the bundle2 "obsmarkers" part is
no longer necessary and has been dropped.
2017-07-16 02:20:06 +02:00
Boris Feld
838490c3d7 share: share 'cachevfs' with the source clone (issue5108)
Share extension now also share caches reads and writes. Not sharing caches
results in costly caches recomputations which can takes up to minutes when
using shares on large repositories.

There are a couple of file in the '.hg/cache/' that depends of the current
visibility. Visibility can be affected by the working copy location, something
which is specific to each share. We ignores them for this series because they:

* are the minority,
* already have a good fallback to other precomputed caches,
* are only affected when people use the experimental evolution feature.
2017-07-15 23:49:22 +02:00
Boris Feld
7c41aa9dd4 cachevfs: add a devel warning for cache access though 'vfs'
This will help third party extensions to migrate to the new 'cachevfs'.
2017-07-15 23:05:15 +02:00
Boris Feld
822a3e705e cachevfs: migration the tags fnode cache to 'cachevfs'
This will help sharing the cache between shares.
2017-07-15 23:30:25 +02:00
Boris Feld
439a5e0f6f cachevfs: migrate tagscache to 'cachevfs'
This will help sharing the cache between shares.
2017-07-15 23:30:16 +02:00
Boris Feld
95cb3ea225 cachevfs: migration the revbranchcache to 'cachevfs'
This will help sharing the cache between shares.
2017-07-15 22:42:50 +02:00
Boris Feld
e7a65d1be8 cachevfs: use the new vfs in when computing branchmap cache
This will help sharing the cache between shares.
2017-07-15 22:42:31 +02:00
Boris Feld
7f091f15a2 cachevfs: add a vfs dedicated to cache
Most of the cache content lives in '.hg/cache/'. Moreover they are computed
exclusively from data in the '.hg/store' directory. This creates issues with
the share extension as the '.hg/store' directory is shared but the '.hg/cache'
is not. On large repositories, this makes this prevent some usage of the share
extension inefficient as some caches can take minutes to be recomputed.

To improve the situation, we introduce a new 'cachevfs' that will be dedicated
to cache reading and writing. In the next patches of this series, we'll
migrate the 4 existing caches to it and update the share extension.
2017-07-15 23:05:04 +02:00
Boris Feld
4d593bc1e9 vfsward: register 'write with no lock' warnings as 'check-locks' config
Update 'write with no lock' warnings in order to be better controlled by the
config.  We reuse the option used for lock order for these other lock related
message.

The message can now be disabled using 'devel.check-locks = no' (in addition to
the usual 'devel.all-warnings = no').
2017-07-15 22:40:51 +02:00
Boris Feld
d46e1b04e2 color: drop the now useless color extension
all the extension features are provided by core since 4.2.
2017-07-15 14:17:35 +02:00
Boris Feld
776e7ed136 extensions: expand the builtins extensions declaration
This will future updates of the set cleaner and more readable.
2017-07-15 14:16:54 +02:00
Boris Feld
34737ca53d configitems: register the 'ui.mergemarkertemplate' config 2017-06-30 03:44:56 +02:00
Boris Feld
80b62eed4f configitems: register the 'ui.color' config 2017-07-15 14:14:53 +02:00
Boris Feld
23c3d582a2 color: drop the _enabledbydefault module variable
Since color is on by default, cleanup the now useless variable in both core
and color extension.
2017-07-15 14:14:46 +02:00
Boris Feld
7dff351e4d configitems: register the 'ui.forcecwd' config 2017-06-30 03:44:45 +02:00
Boris Feld
cc925277dc configitems: register the 'ui.fallbackencoding' config 2017-06-30 03:44:43 +02:00
Boris Feld
b4888b4190 bookmark: deprecate direct del of a bookmark value
We want all bookmark deletion to go through 'applychanges', so lets deprecate
legacy ways of doing bookmark deletion.
2017-07-10 21:49:37 +02:00
Boris Feld
532a41096b bookmark: deprecate direct set of a bookmark value
We want all bookmark update to go through 'applychanges', so lets deprecate
legacy ways of doing bookmark update.
2017-07-10 21:47:34 +02:00
Boris Feld
54f5d4d490 bookmark: track bookmark changes at the transaction level
The transaction has now a 'bookmarks' dictionary in tr.changes. The structure
of the dictionary is {BOOKMARK_NAME: (OLD_NODE, NEW_NODE)}. If a bookmark is
deleted NEW_NODE will be None. If a bookmark is created OLD_NODE will be None.

If the bookmark is updated multiple time, the initial value is preserved.
2017-07-10 20:26:53 +02:00
Boris Feld
2c35423dcc bookmark: deprecate 'recordchange' in favor of 'applychanges'
Now that we have migrated all in-core caller of 'recordchange' to
'applychanges', deprecate 'recordchange' so external callers will move to the
new unified method.
2017-07-10 20:10:03 +02:00
Boris Feld
1febed08be bookmark: drop deletedivergent
It has no caller anymore.
2017-07-10 20:06:15 +02:00
Boris Feld
34e0606eda bookmark: use 'divergent2delete' in checkconflict
checkconflict used to also do some bookmark deletion in case of divergence. It
is a bit suspicious given the function name, but it's not the goal of this
series.

In order to unify bookmarks changing, checkconflict now return the list of
divergent bookmarks to clean up and the callers must clean them by calling
applyphases.
2017-07-10 20:02:32 +02:00
Boris Feld
fa914baf0e bookmark: use 'divergent2delete' when updating a bookmark 2017-07-10 19:12:25 +02:00
Boris Feld
61090ffdb5 bookmark: use 'divergent2delete' in 'scmutil.cleanupnode' 2017-07-10 19:10:13 +02:00
Boris Feld
193cef9125 bookmark: split out target computation from 'deletedivergent'
We want to use applychanges in order to unify bookmark movement. We need a way
to compute divergence deletion without actually removing them.

We split the function in two in this patch while we migrate the existing users
of this code on next patches.
2017-07-10 19:08:17 +02:00
Boris Feld
358a0c58c3 bookmark: remove a useless 'recordchange' in the amend code
We do not touch the bookmarks store in this code, just the active bookmark, not
covered by the transaction. So it seems we can safely drop this call and the
tests agree with us.
2017-07-10 17:48:33 +02:00
Matt Harbison
02879187cc debugignore: eliminate inconsistencies with hg status (issue5222)
Using a matcher for this command allows processing the named file(s) as
relative to cwd.  It also leverages the icasefs normalization logic the same
way the status command does.  (However, a false indicator is given for a
nonexistent file in some cases, e.g. passing 'foo.REJ' when that file doesn't
exist, and the rule is '*.rej'.  Maybe the regex itself needs to be case
insensitive on these platforms, at least for the debug command.)  Finally, the
file printed is relative to cwd and uses platform specific slashes, so a few
(glob)s were needed in seemingly unrelated tests.
2017-07-15 15:23:29 -04:00
Jun Wu
6e6654564a commandserver: close selector explicitly
The selector does not have a __del__ method and needs a manual close. We can
also use "with selector" but that makes the code too indented. Therefore
append a "selector.close()" after the end of the main loop for now.
2017-07-16 04:39:32 -07:00
Yuya Nishihara
3c68035261 scmutil: remove duplicated import of i18n._() 2017-07-15 15:01:29 +09:00
Jun Wu
449129999d obsstore: let read marker API take a range of offsets
This allows us to read a customized range of markers, instead of loading all
of them.

The condition of stop is made consistent across C and Python implementation
so we will still read marker when offset=a, stop=a+1.
2017-06-04 10:02:09 -07:00
Jun Wu
414c6943ee commandserver: use selectors2
Previously, commandserver was using select.select. That could have issue if
_sock.fileno() >= FD_SETSIZE (usually 1024), which raises:

  ValueError: filedescriptor out of range in select()

We got that in production today, although it's the code opening that many
files to blame, it seems better for commandserver to work in this case.
There are multiple way to "solve" it, like preserving a fd with a small
number and swap it with sock using dup2(). But upgrading to a modern
selector supported by the system seems to be the most correct way.
2017-07-14 20:26:21 -07:00
Jun Wu
9e22912b3c selector2: vendor selector2 library
This library was a backport of the Python 3 "selectors" library. It is
useful to provide a better selector interface for Python2, to address some
issues of the plain old select.select, mentioned in the next patch.

The code [1] was ported using the MIT license, with some minor modifications
to make our test happy:

  1. "# no-check-code" was added since it's foreign code.
  2. "from __future__ import absolute_import" was added.
  3. "from collections import namedtuple, Mapping" changed to avoid direct
     symbol import.

[1]: d27dbd2fdc/selectors2.py

# no-check-commit
2017-07-14 20:19:46 -07:00
Matt Harbison
44fdb73d25 context: name files relative to cwd in warning messages
I was several directories deep in the kernel tree, ran `hg add`, and got the
warning about the size of one of the files.  I noticed that it suggested undoing
the add with a specific revert command.  The problem is, it would have failed
since the path printed was relative to the repo root instead of cwd.  While
here, I just fixed the other messages too.  As an added benefit, these messages
now look the same as the verbose/inexact messages for the corresponding command.

I don't think most of these messages are reachable (typically the corresponding
cmdutil function does the check).  I wasn't able to figure out why the keyword
tests were failing when using pathto()- I couldn't cause an absolute path to be
used by manipulating the --cwd flag on a regular add.  (I did notice that
keyword is adding the file without holding wlock.)
2017-07-11 00:40:29 -04:00
Jun Wu
e47f7dc2fa codemod: register core configitems using a script
This is done by a script [2] using RedBaron [1], a tool designed for doing
code refactoring. All "default" values are decided by the script and are
strongly consistent with the existing code.

There are 2 changes done manually to fix tests:

  [warn] mercurial/exchange.py: experimental.bundle2-output-capture: default needs manual removal
  [warn] mercurial/localrepo.py: experimental.hook-track-tags: default needs manual removal

Since RedBaron is not confident about how to indent things [2].

[1]: https://github.com/PyCQA/redbaron
[2]: https://github.com/PyCQA/redbaron/issues/100
[3]:

#!/usr/bin/env python
# codemod_configitems.py - codemod tool to fill configitems
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import, print_function

import os
import sys

import redbaron

def readpath(path):
    with open(path) as f:
        return f.read()

def writepath(path, content):
    with open(path, 'w') as f:
        f.write(content)

_configmethods = {'config', 'configbool', 'configint', 'configbytes',
                  'configlist', 'configdate'}

def extractstring(rnode):
    """get the string from a RedBaron string or call_argument node"""
    while rnode.type != 'string':
        rnode = rnode.value
    return rnode.value[1:-1]  # unquote, "'str'" -> "str"

def uiconfigitems(red):
    """match *.ui.config* pattern, yield (node, method, args, section, name)"""
    for node in red.find_all('atomtrailers'):
        entry = None
        try:
            obj = node[-3].value
            method = node[-2].value
            args = node[-1]
            section = args[0].value
            name = args[1].value
            if (obj in ('ui', 'self') and method in _configmethods
                and section.type == 'string' and name.type == 'string'):
                entry = (node, method, args, extractstring(section),
                         extractstring(name))
        except Exception:
            pass
        else:
            if entry:
                yield entry

def coreconfigitems(red):
    """match coreconfigitem(...) pattern, yield (node, args, section, name)"""
    for node in red.find_all('atomtrailers'):
        entry = None
        try:
            args = node[1]
            section = args[0].value
            name = args[1].value
            if (node[0].value == 'coreconfigitem' and section.type == 'string'
                and name.type == 'string'):
                entry = (node, args, extractstring(section),
                         extractstring(name))
        except Exception:
            pass
        else:
            if entry:
                yield entry

def registercoreconfig(cfgred, section, name, defaultrepr):
    """insert coreconfigitem to cfgred AST

    section and name are plain string, defaultrepr is a string
    """
    # find a place to insert the "coreconfigitem" item
    entries = list(coreconfigitems(cfgred))
    for node, args, nodesection, nodename in reversed(entries):
        if (nodesection, nodename) < (section, name):
            # insert after this entry
            node.insert_after(
                'coreconfigitem(%r, %r,\n'
                '    default=%s,\n'
                ')' % (section, name, defaultrepr))
            return

def main(argv):
    if not argv:
        print('Usage: codemod_configitems.py FILES\n'
              'For example, FILES could be "{hgext,mercurial}/*/**.py"')
    dirname = os.path.dirname
    reporoot = dirname(dirname(dirname(os.path.abspath(__file__))))

    # register configitems to this destination
    cfgpath = os.path.join(reporoot, 'mercurial', 'configitems.py')
    cfgred = redbaron.RedBaron(readpath(cfgpath))

    # state about what to do
    registered = set((s, n) for n, a, s, n in coreconfigitems(cfgred))
    toregister = {} # {(section, name): defaultrepr}
    coreconfigs = set() # {(section, name)}, whether it's used in core

    # first loop: scan all files before taking any action
    for i, path in enumerate(argv):
        print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
        iscore = ('mercurial' in path) and ('hgext' not in path)
        red = redbaron.RedBaron(readpath(path))
        # find all repo.ui.config* and ui.config* calls, and collect their
        # section, name and default value information.
        for node, method, args, section, name in uiconfigitems(red):
            if section == 'web':
                # [web] section has some weirdness, ignore them for now
                continue
            defaultrepr = None
            key = (section, name)
            if len(args) == 2:
                if key in registered:
                    continue
                if method == 'configlist':
                    defaultrepr = 'list'
                elif method == 'configbool':
                    defaultrepr = 'False'
                else:
                    defaultrepr = 'None'
            elif len(args) >= 3 and (args[2].target is None or
                                     args[2].target.value == 'default'):
                # try to understand the "default" value
                dnode = args[2].value
                if dnode.type == 'name':
                    if dnode.value in {'None', 'True', 'False'}:
                        defaultrepr = dnode.value
                elif dnode.type == 'string':
                    defaultrepr = repr(dnode.value[1:-1])
                elif dnode.type in ('int', 'float'):
                    defaultrepr = dnode.value
            # inconsistent default
            if key in toregister and toregister[key] != defaultrepr:
                defaultrepr = None
            # interesting to rewrite
            if key not in registered:
                if defaultrepr is None:
                    print('[note] %s: %s.%s: unsupported default'
                          % (path, section, name))
                    registered.add(key) # skip checking it again
                else:
                    toregister[key] = defaultrepr
                    if iscore:
                        coreconfigs.add(key)

    # second loop: rewrite files given "toregister" result
    for path in argv:
        # reconstruct redbaron - trade CPU for memory
        red = redbaron.RedBaron(readpath(path))
        changed = False
        for node, method, args, section, name in uiconfigitems(red):
            key = (section, name)
            defaultrepr = toregister.get(key)
            if defaultrepr is None or key not in coreconfigs:
                continue
            if len(args) >= 3 and (args[2].target is None or
                                   args[2].target.value == 'default'):
                try:
                    del args[2]
                    changed = True
                except Exception:
                    # redbaron fails to do the rewrite due to indentation
                    # see https://github.com/PyCQA/redbaron/issues/100
                    print('[warn] %s: %s.%s: default needs manual removal'
                          % (path, section, name))
            if key not in registered:
                print('registering %s.%s' % (section, name))
                registercoreconfig(cfgred, section, name, defaultrepr)
                registered.add(key)
        if changed:
            print('updating %s' % path)
            writepath(path, red.dumps())

    if toregister:
        print('updating configitems.py')
        writepath(cfgpath, cfgred.dumps())

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
2017-07-14 14:22:40 -07:00
Martin von Zweigbergk
bf770dc63d match: remove unused negatematcher
This was only used by the sparse extension's dirstate._ignore
override, which no longer exists.

Differential Revision: https://phab.mercurial-scm.org/D60
2017-07-11 10:46:55 -07:00
Jun Wu
d30e8ac7be patch: use devel.all-warnings to replace devel.all
It appears to be a misspell in patch.py.
2017-07-12 15:24:47 -07:00
Matt Harbison
d41b1d2ec2 sslutil: inform the user about how to fix an incomplete certificate chain
This is a Windows only thing.  Unfortunately, the socket is closed at this point
(so the certificate is unavailable to check the chain).  That means it's printed
out when verification fails as a guess, on the assumption that 1) most of the
time verification won't fail, and 2) sites using expired or certs that are too
new will be rare.  Maybe this is an argument for adding more functionality to
debugssl, to test for problems and print certificate info.  Or maybe it's an
argument for bundling certificates with the Windows builds.  That idea was set
aside when the enhanced SSL code went in last summer, and it looks like there
were issues with using certifi on Windows anyway[1].

This was tested by deleting the certificate out of certmgr.msc > "Third-Party
Root Certification Authorities" > "Certificates", seeing `hg pull` fail (with
the new message), trying this command, and then successfully performing the pull
command.

[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-October/089573.html
2017-07-12 18:37:13 -04:00
Matt Harbison
48f91ce813 debug: add a method to check the state of, and built an SSL cert chain
This is only useful on Windows, and avoids the need to use Internet Explorer to
build the certificate chain.  I can see this being extended in the future to
print information about the certificate(s) to help debug issues on any platform.
Maybe even perform some of the python checks listed on the secure connections
wiki page.  But for now, all I need is 1) a command that can be invoked in a
setup script to ensure the certificate is installed, and 2) a command that the
user can run if/when a certificate changes in the future.

It would have been nice to leverage the sslutil library to pick up host specific
settings, but attempting to use sslutil.wrapsocket() failed the
'not sslsocket.cipher()' check in it and aborted.

The output is a little more chatty than some commands, but I've seen the update
take 10+ seconds, and this is only a debug command.
2017-03-30 00:27:46 -04:00
Matt Harbison
96e146ce9c win32: add a method to trigger the Crypto API to complete a certificate chain
I started a thread[1] on the mailing list awhile ago, but the short version is
that Windows doesn't ship with a full list of certificates[2].  Even if the
server sends the whole chain, if Windows doesn't have the appropriate
certificate pre-installed in its "Third-Party Root Certification Authorities"
store, connections mysteriously fail with:

  abort: error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)

Windows expects the application to call the methods invoked here as part of the
certificate verification, triggering a call out to Windows update if necessary,
to complete the trust chain.  The python bug to add this support[3] hasn't had
any recent activity, and isn't targeting py27 anyway.

The only work around that I could find (besides figuring out the certificate and
walking through the import wizard) is to browse to the site in Internet
Explorer.  Opening the page with FireFox or Chrome didn't work.  That's a pretty
obscure way to fix a pretty obscure problem.  We go to great lengths to
demystify various SSL errors, but this case is clearly lacking.  Let's try to
make things easier to diagnose and fix.

When I had trouble figuring out how to get ctypes to work with all of the API
pointers, I found that there are other python projects[4] using this API to
achieve the same thing.

[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-April/096501.html
[2] https://support.microsoft.com/en-us/help/931125/how-to-get-a-root-certificate-update-for-windows
[3] https://bugs.python.org/issue20916
[4] 3b86bce206/source/updateCheck.py (L511)
2017-03-29 23:45:23 -04:00
Boris Feld
96405b1fb4 bookmarks: use 'applychanges' for bookmark update
There is still some use of 'deletedivergent' bookmark here. They will be taken
care of later. The 'deletedivergent' code needs some rework before fitting in
the new world.
2017-07-10 19:40:23 +02:00
Boris Feld
31cf043735 bookmark: use 'applychanges' in 'repair.strip' 2017-07-10 17:46:47 +02:00
Boris Feld
b7adc75632 bookmark: use 'applychanges' when updating a bookmark through pushkey 2017-07-10 17:24:28 +02:00
Boris Feld
dad7a93fa0 bookmark: use 'applychanges' when updating from a remote 2017-07-10 17:22:17 +02:00
Boris Feld
2412116437 bookmark: use 'applychanges' for adding new bookmark 2017-07-10 17:10:56 +02:00
Boris Feld
589c9fd183 bookmark: use 'applychanges' for bookmark renaming 2017-07-10 17:08:20 +02:00
Boris Feld
58af188cbd bookmark: use 'applychanges' for bookmark deletion 2017-07-10 17:04:16 +02:00
Boris Feld
e5368fffb1 bookmark: introduce a 'applychanges' function to gather bookmark movement
We want to track bookmark movement within a transaction. For this we need a
more centralized way to update bookmarks.

For this purpose we introduce a new 'applychanges' method that apply a list of
changes encoded as '(name, node)'. We'll cover all bookmark updating code to
this new method in later changesets and add bookmark move in the transaction
when all will be migrated.
2017-07-10 17:01:34 +02:00
Jun Wu
888ed86eaf obsstore: keep self._data updated with _addmarkers
This makes sure obsstore._data is still correct with added markers.

The '_data' propertycache was added in 17ce57b7873f.
2017-06-03 21:56:23 -07:00
Durham Goode
d4313959ab match: make base matcher return True for visitdir
If a matcher doesn't implement visitdir, we should be returning True so that
tree traversals are not prematurely pruned. The old value of False would prevent
tree traversals when using any matcher that didn't implement visitdir.

Differential Revision: https://phab.mercurial-scm.org/D83
2017-07-14 10:57:36 -07:00
Yuya Nishihara
46a6e6a290 templatekw: hide {peerpaths} keyword for 4.3
Thinking a bit further about list/dict subscript operation (proposed by
issue 5534), I noticed the current data structure, a dict of dicts, might
not be ideal.

For example, if there were "'[' index ']'" and "'.' key" operators,
"{parents[0]}" would return "{p1rev}:{p1node}", and we would probably want to
write "{parents[0].desc}" to get the first element of "{parents % "{desc}"}".
This will basically execute parents[0].makemap()['desc'] in Python.

Given the rule above, "{peerpaths.default.pushurl}" will be translated to
peerpaths['default'].makemap()['pushurl'], which means {peerpaths} should
be a single-level dict and sub-options should be makemap()-ed.

  "{peerpaths % "{name} = {url}, {pushurl}, ..."}"

(Well, it could be peerpaths['default']['pushurl'], but in which case,
peerpaths['default'] should be a plain dict, not a hybrid object.)

So, let's mark the current implementation experimental and revisit it later.
2017-07-15 00:38:57 +09:00
Sune Foldager
dca90c364e parsers: fix invariant bug in find_deepest (issue5623)
find_deepest is used to find the "best" ancestors given a list. In the main
loop it keeps an invariant called 'ninteresting' which is supposed to contain
the number of non-zero entries in the 'interesting' array. This invariant is
incorrectly maintained, however, which leads the the algorithm returning an
empty result for certain graphs. This has been fixed.

Also, the 'interesting' array is supposed to fit 2^ancestors values, but is
incorrectly allocated to twice that size. This has been fixed as well.

The tests in test-ancestor.py compare the Python and C versions of the code,
and report the error correctly, since the Python version works correct. Even
so, I have added an additional test against the expected result, in the event
that both algorithms have an identical error in the future.

This fixes issue5623.
2017-07-14 13:48:17 +02:00
Boris Feld
15d613159e configitems: register the 'worker.backgroundclose' config 2017-06-30 03:45:57 +02:00
Boris Feld
3dafe93b4f configitems: register the 'progress.width' config 2017-06-30 03:44:05 +02:00
Boris Feld
98f63065b7 configitems: register the 'color.pagermode' config 2017-07-12 23:36:28 +02:00
Boris Feld
40b893532b configitems: handle case were the default value is not static
In some case, the default of one value is derived from other value. We add a
way to register them anyway and an associated devel-warning.

The registration is very naive for the moment. We might be able to have a
better way for registering each of these cases but it could be done later.
2017-07-12 23:36:10 +02:00
Boris Feld
0949aa4c6f changegroup: stop returning and recording added nodes in 'cg.apply'
cg.apply used to returns the added nodes. Callers doesn't have a use for it
anymore, remove the added node and stops recording it in the current
operation.

This information was added in the current release cycle so no extensions
breakage should happens.
2017-07-13 21:08:06 +02:00
Boris Feld
f2e89981fb phases: remove trace of addednodes in the 'phase-heads' handling
updatephases have no use of the 'addednodes' parameter since 44be3dc1fec8.
However caller are still passing it for nothing, remove the parameter and
remove computing of the added nodes in caller.
2017-07-13 21:10:55 +02:00
Boris Feld
b9cdddd1ce phases: track phase changes from 'retractboundary'
We adds new computation to find and record the revision affected by the
boundary retraction. This add more complication to the function but this seems
fine since it is only used in a couple of rare and explicit cases (`hg phase
--force` and `hg qimport`).

Having strong tracking of phase changes is worth the effort.
2017-07-12 20:11:00 +02:00
Boris Feld
87cd8ac872 phases: detect when boundaries has been actually retracted
It is useful to detect noop and avoid expensive operations in this case.

We return the information to inform the caller of a possible update. Top level
function might need to react to the phase update (eg: invalidating some
caches, tracking phase change).
2017-07-12 23:15:09 +02:00
Boris Feld
6ee0c66cd0 phases: rework phase movement code in 'cg.apply' to use 'registernew'
We rework the code to call 'registernew' before any other phase advancement.
This make 'changegroup.apply' register correct phase movement for the added
and bundled nodes.
2017-07-11 01:17:36 +02:00
Boris Feld
9d590cdd8f localrepo: use the 'registernew' function to set the phase of new commit 2017-07-11 01:05:27 +02:00
Boris Feld
a6e00b1e49 phases: add a 'registernew' method to set new phases
This new function will be used by code that adds new changesets. It ajusts the
phase boundary to make sure added changesets are at least in their target
phase (they end up in an higher phase if their parents are in a higher phase).

Having a dedicated function also simplify the phases tracking. All the new
nodes are passed as argument, so we know that all of them needs to have their
new phase registered. We also know that no other nodes will be affected, so no
extra computation are needed.

This function differ from 'retractboundary' where some nodes might change
phase while some other might not. It can also affect nodes not passed as
parameters.

These simplification also apply to the computation itself. For now we use
'_retractboundary' there by convenience, but we may introduces simpler code
later.

While registering new revisions, we still need to check the actual phases of
the added node because it might be higher than the target phase (eg: target is
draft but parent is secret).

We will migrate users over the next changesets.
2017-07-11 03:47:25 +02:00
Boris Feld
3de612f757 phases: extract the core of boundary retraction in '_retractboundary'
At the moment the 'retractboundary' function is called for multiple reasons:

First, actually retracting boundaries. There are only two cases for theses:
'hg phase --force' and 'hg qimport'. This will need extra graph computation to
retrieve the phase changes.

Second, setting the phases of newly added changesets. In this case we already
know all the affected nodes and we just needs to register different
information (old phase is None).

Third, when reducing the set of roots when advancing phase. The phase are
already properly tracked so we do not needs anything else in this case.

To deal with this difference in phase tracking, we extract the core logic into
a private method that all three cases can use.
2017-07-10 23:50:16 +02:00
Boris Feld
794ac05dda phases: track phase movements in 'advanceboundary'
Makes advanceboundary record the phase movement of affected revisions in
tr.changes['phases'].

The tracking is not usable yet because the 'retractboundary' function can also
affect phases.

We'll improve that in the coming changesets.
2017-07-11 02:39:52 +02:00
Boris Feld
e0ae9be376 phases: extract the intermediate set of affected revs
When advancing phases, we compute the new roots for the phases above. During
this process, we need to compute all the revisions that change phases (to the
new target phases). Extract these revisions into a separate variable. This
will be useful to record the phase changes in the transaction.
2017-07-10 22:18:41 +02:00
Boris Feld
7dd5b39982 phase: put retractboundary out of the loop in advanceboundary
It seems that we were calling retractboundary for each phases to process.
Putting the retractboundary out of the loop reduce the number of calls,
helping tracking the phases changes.
2017-07-10 22:22:42 +02:00
Martin von Zweigbergk
2ff08ff937 match: make unionmatcher a proper matcher
unionmatcher is currently used where only a limited subset of its
functions will be called. Specifically, visitdir() is never
called. The next patch will pass it to dirstate.walk() where it will
matter that visitdir() is correctly implemented, so let's fix
that. Also add the explicitdir etc that will also be assumed by
dirstate.walk() to exist on a matcher.

Differential Revision: https://phab.mercurial-scm.org/D58
2017-07-11 10:46:10 -07:00
Martin von Zweigbergk
3c2e121c63 match: write forceincludematcher using unionmatcher
The forceincludematcher is simply a unionmatcher of a includematcher
(matching paths recursively) with the given matcher. Since the
forceincludematcher is only used by sparse, move it there.

I don't have a good sparse repo setup to test performance impact on.

Differential Revision: https://phab.mercurial-scm.org/D57
2017-07-07 14:39:59 -07:00
Martin von Zweigbergk
cce08d0996 histedit: extract InterventionRequired transaction handling to utils
rebase will have similar logic, so let's extract it. Besides, it makes
the histedit code more readable.

We may want to parametrize acceptintervention() by the exception(s)
that should result in transaction close.

Differential Revision: https://phab.mercurial-scm.org/D66
2017-07-12 13:57:03 -07:00
Adam Simpkins
2a467faccd dirstate: update backup functions to take full backup filename
Update the dirstate functions so that the caller supplies the full backup
filename rather than just a prefix and suffix.

The localrepo code was already hard-coding the fact that the backup name must
be (exactly prefix + "dirstate" + suffix): it relied on this in _journalfiles()
and undofiles().  Making the caller responsible for specifying the full backup
name removes the need for the localrepo code to assume that dirstate._filename
is always "dirstate".

Differential Revision: https://phab.mercurial-scm.org/D68
2017-07-12 15:24:07 -07:00
Martin von Zweigbergk
dde7459563 util: remove unused ctxmanager
This was meant as a substitute for Python's "with" with multiple
context managers before we moved to Python 2.7. We're now on 2.7, so
we should have no reason to keep ctxmanager. "hg grep --all
ctxmanager" says that it was never used anyway.

Differential Revision: https://phab.mercurial-scm.org/D73
2017-07-13 09:51:50 -07:00
Jun Wu
c41f5ca68e codemod: simplify nested withs
This is the result of running:

  python codemod_nestedwith.py **/*.py

where codemod_nestedwith.py looks like this:

#!/usr/bin/env python
# codemod_nestedwith.py - codemod tool to rewrite nested with
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import, print_function

import sys

import redbaron

def readpath(path):
    with open(path) as f:
        return f.read()

def writepath(path, content):
    with open(path, 'w') as f:
        f.write(content)

def main(argv):
    if not argv:
        print('Usage: codemod_nestedwith.py FILES')

    for i, path in enumerate(argv):
        print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
        changed = False
        red = redbaron.RedBaron(readpath(path))
        processed = set()
        for node in red.find_all('with'):
            if node in processed or node.type != 'with':
                continue
            top = node
            child = top[0]
            while True:
                if len(top) > 1 or child.type != 'with':
                    break
                # estimate line length after merging two "with"s
                new = '%swith %s:' % (top.indentation, top.contexts.dumps())
                new += ', %s' % child.contexts.dumps()
                # only do the rewrite if the end result is within 80 chars
                if len(new) > 80:
                    break
                processed.add(child)
                top.contexts.extend(child.contexts)
                top.value = child.value
                top.value.decrease_indentation(4)
                child = child[0]
                changed = True
        if changed:
            print('updating %s' % path)
            writepath(path, red.dumps())

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))


Differential Revision: https://phab.mercurial-scm.org/D77
2017-07-13 18:31:35 -07:00
Boris Feld
ca27090453 reposvfs: add a ward to check if locks are properly taken
we wrap 'repo.svfs.audit' to check for the store lock when accessing file in
'.hg/store' for writing. This caught a couple of instance where the transaction
was released after the lock, we should probably have a dedicated checker for
that case.
2016-08-08 18:14:42 +02:00
Boris Feld
c9fe43d98b repovfs: add a ward to check if locks are properly taken
When the appropriate developer warnings are enabled, We wrap 'repo.vfs.audit' to
check for locks when accessing file in '.hg' for writing. Another changeset will
add a 'ward' for the store vfs (svfs).

This check system has caught a handful of locking issues that have been fixed
in previous series (mostly in 4.0). I expect another batch to be caught in third
party extensions.

We introduce two real exceptions from extensions 'blackbox.log' (because a lot of
read-only operations add entry to it), and 'last-email.txt' (because 'hg email'
is currently a read only operation and there is value to keep it this way).

In addition we are currently allowing bisect to operate outside of the lock
because the current code is a bit hard to get properly locked for now. Multiple
clean up have been made but there is still a couple of them to do and the freeze
is coming.
2017-07-11 12:38:17 +02:00
Boris Feld
71ca1ed413 vfs: allow to pass more argument to audit
We want to be able to do more precise check when auditing a path depending of
the intend of the file access (eg read versus write). So we now pass the 'mode'
value to 'audit' and update the audit function to accept them.

This will be put to use in the next changeset.
2017-07-11 12:27:58 +02:00
Phil Cohen
92de40e6df tagmerge: use workingfilectx to write merged tags
This function already does an excellent job of reading from context objects;
we simply need to change the single write call to eliminate all uses of the
wvfs.

As with past changes, the effect should be a no-op but opens the door to
in-memory merge later by using different context objects.
2017-07-11 16:48:15 -07:00
Matt Harbison
dbfcbcfa2b win32: work around a WinError problem handling HRESULT types
I ran into this ctypes bug while working with the Crypto API.  While this could
be an issue with any Win32 API in theory, the handful of things that we call are
older functions that are unlikely to return COM errors, so I didn't retrofit
this everywhere.
2017-03-30 00:33:00 -04:00
Yuya Nishihara
9955f11c5c revset: add experimental ancestors/descendants relation subscript
The relation name is 'generations' now, which may be changed in future.
2017-07-08 13:15:17 +09:00
Yuya Nishihara
ad66ada8bf revset: add experimental relation and subscript operators
The proposed syntax [1] was originally 'set{n rel}', but it seemed slightly
confusing if template is involved. On the other hand, we want to keep 'set[n]'
for future extension. So this patch introduces 'set#rel[n]' ternary operator.
I chose '#' just because it looks like applying an attribute.

This also adds stubs for 'set[n]' and 'set#rel' operators since these syntax
elements are fundamental for constructing 'set#rel[n]'.

 [1]: https://www.mercurial-scm.org/wiki/RevsetOperatorPlan#ideas_from_mpm
2017-07-08 13:07:59 +09:00
Yuya Nishihara
f742cb36a6 revset: do not compute weight for integer literal argument
In x^n and x~n, n isn't a set expression. There's no need to optimize the
right-hand side.
2017-07-08 12:49:46 +09:00
Yuya Nishihara
963c78d353 templatekw: export ui.paths as {peerpaths}
It's sometimes useful to show hyperlinks in log output.

  "{get(peerpaths, "default")}/rev/{node}"

Since each path may have sub options, "{peerpaths}" is structured as a dict
of dicts, but the inner dict is rendered as if it were a string URL. The
implementation is ad-hoc, so there are some weird behaviors described in
the test. We might need to introduce a proper way of handling a hybrid
scalar object.

This patch adds _hybrid.__getitem__() so d['path']['url'] works.

The keyword is named as "peerpaths" since "paths" seemed too generic in
log context.
2017-07-13 00:35:54 +09:00
Yuya Nishihara
17207a3d76 summary: fix type of empty unresolved list
It was okay because tested as a boolean prior to calling len(), but looked
incorrect.
2017-07-07 23:13:04 +09:00
Yuya Nishihara
12efb6fc0b vfs: rename auditvfs to proxyvfs
Since we've removed mustaudit property, auditvfs has no auditing business.
It's just a utility class for vfs wrappers.
2017-07-07 23:40:00 +09:00
Yuya Nishihara
027352b7a8 streamclone: comment why path auditing is disabled in generatev1()
Copied from 8809f5acb29a. I wasn't sure whether it's for optimization or
suppressing unwanted error.
2017-07-07 23:19:31 +09:00
Yuya Nishihara
954fcd3b6c streamclone: close large revlog files explicitly in generatev1() 2017-07-07 23:25:16 +09:00
Boris Feld
015cfc156e bundle2: no longer use 'retractboundary' in updatephases
The new 'phase-heads' forced all added node to secret before advancing the
boundary to work around the fact changesets were added as draft by default.
This is no longer necessary since the changegroup part can now use the
'targetphase' parameter.

Not doing this retract boundary call has a couple of advantages:

* This makes implementing phases change tracking in the transaction much
  simpler since retract boundary can become a rare case.

* Bundling secret changesets is not the norm. Exchange never does that and
  even for strip, the use-case is not common.Skipping the retract boundary
  will avoid useless work here.

* Sending phase update on push can be simplified since we can rely on the
  behavior of 'cg.apply' for most of it.
  This means less phases update send for example.

* We no longer needs to track and use the addednodes during unbundling. This
  make it possible to have multiple 'changegroup' and 'phase-heads' parts in the
  same bundle without them interfering with each others.

The new part has not been part of any release yet so we do not offer backward
compatibility yet. It is important to update this semantic before the 4.3
freeze happens.
2017-07-11 05:06:01 +02:00
Boris Feld
20ea8cb94b bundle2: automatically add 'targetphase' parameter in writenewbundle
If we are bundling secret changeset and the bundle will contain phase, we
request the changegroup to be applied as secret.

It will be useful for next patch as we are now sure that secrets changesets
are applied as secret and not applied as draft then forced to secret.
2017-07-11 05:12:03 +02:00
Boris Feld
438579760f bundle2: support the 'targetphase' parameter for the changegroup part
By default unbundled changesets are drafts. We want to reduce the number of
phases changes during unbundling by giving the possibility to the bundle to
indicate the phase of unbundled changesets.

The longer terms goal is to add phase movement tracking in tr.changes and the
'retractboundary' call is making it more complicated than we want.
2017-07-11 05:11:52 +02:00
Boris Feld
1c00e3fb58 changegroup: stop treating strip as special when dealing with phases
Since 26d535788092, the strip bundle includes the phases of the stripping
node. Hence we don't need this special case anymore.

Dropping it will helps make the phase behavior more consistent across all
exchanges medium.
2017-07-11 04:52:56 +02:00
Martin von Zweigbergk
209d8095b3 match: inverse _anypats(), making it _prefix() 2017-07-11 09:42:32 -07:00
Martin von Zweigbergk
bf2a3c6ad8 py3: make localrepo filtered repo cache work on py3
I don't know if this is the right fix, but it makes
test-py3-commands.t pass again.

Differential Revision: https://phab.mercurial-scm.org/D56
2017-07-11 11:21:04 -07:00
Alex Gaynor
119e84a2a0 revlog: use struct.Struct instances for slight performance wins
Differential Revision: https://phab.mercurial-scm.org/D32
2017-07-10 16:41:13 -04:00
Alex Gaynor
c6f81cfa87 revlog: micro-optimize the computation of hashes
Differential Revision: https://phab.mercurial-scm.org/D31
2017-07-10 16:39:28 -04:00
Denis Laxalde
e4402fa19c hgweb: re-implement followlines UI selection using buttons
This changeset attempts to solve two issues with the "followlines" UI in
hgweb. First the "followlines" action is currently not easily discoverable
(one has to hover on a line for some time, wait for the invite message to
appear and then perform some action). Second, it gets in the way of natural
line selection, especially in filerevision view.

This changeset introduces an additional markup element (a <button
class="btn-followlines">) alongside each content line of the view. This button
now holds events for line selection that were previously plugged onto content
lines directly. Consequently, there's no more action on content lines, hence
restoring the "natural line selection" behavior (solving the second problem).
These buttons are hidden by default and get displayed upon hover of content
lines; then upon hover of a button itself, a text inviting followlines section
shows up. This solves the first problem (discoverability) as we now have a
clear visual element indicating that "some action could be perform" (i.e. a
button) and that is self-documented.

In followlines.js, all event listeners are now attached to these <button>
elements. The custom "floating tooltip" element is dropped as <button>
elements are now self-documented through a "title" attribute that changes
depending on preceding actions (selection started or not, in particular).

The new <button> element is inserted in followlines.js script (thus only
visible if JavaScript is activated); it contains a "+" and "-" with a
"diff-semantics" style; upon hover, it scales up.

To find the parent element under which to insert the <button> we either rely
on the "data-selectabletag" attribute (which defines the HTML tag of children
of class="sourcelines" element e.g. <span> for filerevision view and <tr> for
annotate view) or use a child of the latter elements if we find an element
with class="followlines-btn-parent" (useful for annotate view, for which we
have to find the <td> in which to insert the <button>).

On noticeable change in CSS concerns the "margin-left" of span:before
pseudo-elements in filelog view that has been increased a bit in order to
leave space for the new button to appear between line number column and
line content one.
Also note the "z-index" addition for "annotate-info" box so that the latter
appears on top of new buttons (instead of getting hidden).

In some respect, the UI similar to line commenting feature that is implemented
in popular code hosting site like GitHub, BitBucket or Kallithea.
2017-07-03 13:49:03 +02:00
Gregory Szorc
c0447df5a2 localrepo: cache types for filtered repos (issue5043)
Python introduces a reference cycle on dynamically created types
via __mro__, making them very easy to leak. See
https://bugs.python.org/issue17950.

Previously, repo.filtered() created a type on every invocation.
Long-running processes (like `hg convert`) could call this
function thousands of times, leading to a steady memory leak.

Since we're Unable to stop the leak because this is a bug in
Python, the next best thing is to contain it.

This patch adds a cache of of the dynamically generated repoview/filter
types on the localrepo object. Since we only generate each type
once, we cap the amount of memory that can leak to something
reasonable.

After this change, `hg convert` no longer leaks memory on every
revision. The process will likely grow memory usage over time due
to e.g. larger manifests. But there are no leaks.
2017-07-01 20:51:19 -07:00
FUJIWARA Katsunori
63fd3449f5 localrepo: add isfilecached to check filecache-ed property is already cached
isfilecached() encapsulates internal implementation of filecache-ed
property.

"name in repo.unfiltered().__dict__" or so can't be used for this
purpose, because corresponded entry in __dict__ might be discarded by
repo.invalidate(), repo.invalidatedirstate() or so (fsmonitor does so,
for example).

This patch makes isfilecached() return not only whether filecache-ed
property is already cached, but also already cached value (or None),
in order to avoid subsequent access to cached object via "repo.NAME",
which prevents main Mercurial procedure after reposetup() from
validating cache.
2017-07-10 23:09:51 +09:00
Gregory Szorc
596098a717 sslutil: check for missing certificate and key files (issue5598)
Currently, sslutil._hostsettings() performs validation that web.cacerts
exists. However, client certificates are passed in to the function
and not all callers may validate them. This includes
httpconnection.readauthforuri(), which loads the [auth] section.

If a missing file is specified, the ssl module will raise a generic
IOException. And, it doesn't even give us the courtesy of telling
us which file is missing! Mercurial then prints a generic
"abort: No such file or directory" (or similar) error, leaving users
to scratch their head as to what file is missing.

This commit introduces explicit validation of all paths passed as
arguments to wrapsocket() and wrapserversocket(). Any missing file
is alerted about explicitly.

We should probably catch missing files earlier - as part of loading
the [auth] section. However, I think the sslutil functions should
check for file presence regardless of what callers do because that's
the only way to be sure that missing files are always detected.
2017-07-10 21:09:46 -07:00
Martin von Zweigbergk
0b6160ac83 match: override matchfn instead of __call__ for consistency
The matchers that were recently moved into core from the sparse
extension override __call__, while the previously existing matchers
override matchfn. Let's switch to the latter for consistency.
2017-07-07 08:55:12 -07:00
Martin von Zweigbergk
57baaf4707 match: express anypats(), not prefix(), in terms of the others
When I added prefix() in 559ee9ecae07 (match: introduce boolean
prefix() method, 2014-10-28), we already had always(), isexact(), and
anypats(), so it made sense to write it in terms of them (a prefix
matcher is one that isn't any of the other types). It's only now that
I realize that it's much more natural to define prefix() explicitly
(it's one that uses path: patterns, roughly speaking) and let
anypats() be defined in terms of the others. Remember that these
methods are all used for determining which fast paths are
possible. anypats() simply means that no fast paths are possible (it
could be called complex() instead). Further evidence is that
rootfilesin:some/dir does not have any patterns, but it's still
considered to be an anypats() matcher. That's because anypats() really
just means that it's not a prefix() matcher (and not always() and not
isexact()).

This patch thus changes prefix() to return False by default and
anypats() to return True only if the other three are False. Having
anypats() be True by default also seems like a good thing, because it
means forgetting to override it will lead only to performance bugs,
not correctness bugs.

Since the base class's implementation changes, we're also forced to
update the subclasses. That change exposed and fixed a bug in the
differencematcher: for example when both its two input matchers were
prefix matchers, we would say that the result was also a prefix
matcher, which is incorrect, because e.g "path:dir - path:dir/foo" no
longer matches everything under "dir" (which is what prefix() means).
2017-07-09 17:02:09 -07:00
Martin von Zweigbergk
82311df2ab match: make nevermatcher an exact matcher and a prefix matcher
The m.isexact() and m.prefix() methods are used by callers to
determine whether m.files() can be used for fast paths. It seems safe
to let callers to any fast paths it can that rely on the empty
m.files().
2017-07-09 15:19:27 -07:00
Jun Wu
573f8d2389 revset: define successors revset
This revset returns all successors, including transit nodes and the source
nodes (to be consistent with existing revsets like "ancestors").

To filter out transit nodes, use `successors(X)-obsolete()`.
To filter out divergent case, use `successors(X)-divergent()-obsolete()`.

The revset could be useful to define rebase destination, like:
`max(successors(BASE)-divergent()-obsolete())`. The `max` is to deal with
splits.

There are other implementations where `successors` returns just one level of
successors, and `allsuccessors` returns everything. I think `successors`
returning all successors by default is more user friendly. We have seen
cases in production where people use 1-level `successors` while they really
want `allsuccessors`. So it seems better to just have one single revset
returning all successors by default to avoid user errors.

In the future we might want to add `depth` keyword argument to it and for
other revsets like `ancestors` etc. Or even build some flexible indexing
syntax [1] to satisfy people having the depth limit requirement.

[1]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-July/101140.html
2017-07-10 10:56:40 -07:00
Gregory Szorc
2777ae7399 sparse: shorten try..except block in updateconfig()
It now only covers refreshwdir(). This is what importfromfiles()
does. I think it is the more appropriate behavior.
2017-07-10 21:55:43 -07:00
Gregory Szorc
28576724a2 sparse: clean up updateconfig()
* Use context manager for wlock
* Rename oldsparsematch to oldmatcher
* Always call parseconfig() because parsing an empty string yields
  the same result as the old code
2017-07-10 21:43:19 -07:00
Gregory Szorc
0ee6ecfbec sparse: move config updating function into core
As part of the move, the ui argument was dropped.

Additional fixups will be made in a follow-up commit.
2017-07-10 21:39:49 -07:00
Gregory Szorc
a7c49e2ec2 dirstate: expose a sparse matcher on dirstate (API)
The sparse extension performs a lot of monkeypatching of dirstate
to make it sparse aware. Essentially, various operations need to
take the active sparse config into account. They do this by obtaining
a matcher representing the sparse config and filtering paths through
it.

The monkeypatching is done by stuffing a reference to a repo on
dirstate and calling sparse.matcher() (which takes a repo instance)
during each function call. The reason this function takes a repo
instance is because resolving the sparse config may require resolving
file contents from filelogs, and that requires a repo. (If the
current sparse config references "profile" files, the contents of
those files from the dirstate's parent revisions is resolved.)

I seem to recall people having strong opinions that the dirstate
object not have a reference to a repo. So copying what the sparse
extension does probably won't fly in core. Plus, the dirstate
modifications shouldn't require a full repo: they only need a matcher.
So there's no good reason to stuff a reference to the repo in
dirstate.

This commit exposes a sparse matcher to dirstate via a property that
when looked up will call a function that eventually calls
sparse.matcher(). The repo instance is bound in a closure, so it
isn't exposed to dirstate.

This approach is functionally similar to what the sparse extension does
today, except it hides the repo instance from dirstate. The approach
is not optimal because we have to call a proxy function and
sparse.matcher() on every property lookup. There is room to cache
the matcher instance in dirstate. After all, the matcher only changes
if the dirstate's parents change or if the sparse config changes. It
feels like we should be able to detect both events and update the
matcher when this occurs. But for now we preserve the existing
semantics so we can move the dirstate sparseness bits into core. Once
in core, refactoring becomes a bit easier since it will be clearer how
all these components interact.

The sparse extension has been updated to use the new property.
Because all references to the repo on dirstate have been removed,
the code for setting it has been removed.
2017-07-08 16:18:04 -07:00
Gregory Szorc
6155516e71 sparse: move code for importing rules from files into core
This is a pretty straightforward port. Some code cleanup was
performed. But no major changes to the logic were made.

I'm not a huge fan of this function because it does multiple
things. I'd like to get things into core first to facilitate
refactoring later.

Please also note the added inline comment about the oddities
of writeconfig() and the try..except to undo it. This is because
of the hackiness in which the sparse matcher is obtained by
various consumers, notably dirstate. We'll need a massive
refactor to address this. That refactor is effectively blocked
on having the sparse dirstate hacks live in core.
2017-07-08 14:15:07 -07:00
Gregory Szorc
21d9237e1c sparse: refactor activeprofiles into a generic function (API)
activeprofiles() is a special case of a more generic function.
Furthermore, that generic function is essentially already
implemented inline in the sparse extension.

So, refactor activeprofiles() to a generic activeconfig(). Change
the only consumer of activeprofiles() to use it. And have the
inline implementation in the sparse extension use it.
2017-07-08 14:01:32 -07:00
Matt Harbison
86a2e6550a subrepo: make the output references to subrepositories consistent
Well, mostly.  The annotation on subrepo functions tacks on a parenthetical to
the abort message, which seems reasonable for a generic mechanism.  But now all
messages consistently spell out 'subrepository', and double quote the name of
the repo.  I noticed the inconsistency in the change for the last commit.
2017-07-09 16:13:30 -04:00
Matt Harbison
557dc0142f subrepo: consider the parent repo dirty when a file is missing
This simply passes the 'missing' argument down from the context of the parent
repo, so the same rules apply.  subrepo.bailifchanged() is hardcoded to care
about missing files, because cmdutil.bailifchanged() is too.

In the end, it looks like this addresses inconsistencies with 'archive',
'identify', blackbox logs, 'merge', and 'update --check'.  I wasn't sure how to
implement this in git, so that's left for someone more familiar with it.
2017-07-09 02:55:46 -04:00
Matt Harbison
5a0fd7acbc archival: flag missing files as a dirty wdir() in the metadata file (BC)
Since the identify command adds a '+' for missing files, it's reasonable that
this does too.  Perhaps the node field's hex value should be p1+p2 for merges?
2017-07-09 02:46:03 -04:00
Matt Harbison
c645ca08ec cmdutil: simplify the dirty check in howtocontinue()
This is equivalent to the previous code.  But it seems to me that if the user is
going to be prompted that a commit is needed, missing files should be ignored,
but branch and merge changes shouldn't be.
2017-07-09 00:53:16 -04:00
Matt Harbison
bd2183b5bc identify: simplify the dirty check
This is equivalent to the previous code, but it seems better to be explicit
about what aspects of dirty are being ignored.  Perhaps they shouldn't be, since
the help text says 'followed by a "+" if the working directory has uncommitted
changes'.  Both merges and branch changes are committable, even if the files are
unchanged.

Additionally, this will make the `identify` command notice missing subrepo
files, once subrepos are taught to look for missing files.
2017-07-09 00:19:03 -04:00
Martin von Zweigbergk
3a5a9ff76e match: combine regex code for path: and relpath:
The regexes for path: and relpath: patterns are the same (since the
paths have already been normalized at the point we create the
regexes).

I don't think the "if pat == '.'" will have any effect relpath:
because relpath: patterns will have the root directory already
normalized to '' by pathutil.canonpath() (unlike path:, for which the
root gets normalized to '.' by util.normpath()).
2017-07-09 23:01:11 -07:00
Martin von Zweigbergk
8c3e639b61 match: remove unnecessary '^' from regexes
The regexes are passed to re.match(), which matches against the
beginning of the input, so the '^' doesn't do anything.

Note that unrooted patterns, such as globs and regexes from .hgignore
are instead achieved by adding '.*' to the expression given by the
user. (That's unless the user's expression started with '^', in which
case the '.*' is not added, perhaps to keep the regex cleaner?)
2017-07-09 22:53:02 -07:00
Martin von Zweigbergk
fa470fc7e5 sparse: access status fields by name instead of deconstructing it
The status tuples has had named fields for a few years now.
2017-07-06 22:20:38 -07:00
Gregory Szorc
d86e3657d2 sparse: move printing of sparse config changes function into core
As part of the port, all arguments now have default values of 0.
Strings are now also given the i18n treatment.
2017-07-08 13:34:19 -07:00
Gregory Szorc
519ece1048 sparse: move code for clearing rules to core
This is a pretty straightforward port.
2017-07-08 13:19:38 -07:00
Gregory Szorc
2689134340 sparse: move post commit actions into core
Instead of wrapping committablectx.markcommitted(), we inline
the call into workingctx.markcommitted().

Per smf's review, workingctx is the proper location for this
code, as committablectx is the shared base class for it and
memctx. Since this code touches the working directory, it belongs
in workingctx.
2017-07-07 11:51:10 -07:00
Octobus
f2b2c89b93 cleanupnode: do not use generator for node mapping
The 'successors' part of the mappings used of be a tuple. This avoid issue from
code consuming the generator "by mistake". For example, an extension inspecting the
mapping content used to be able to iterate over the successors mapping without
consequence.

Since the mapping are small we do not expect any performance impact we use tuple
again for this.
2017-07-09 15:11:19 +02:00
Jun Wu
f50841989e revset: make repo.anyrevs accept customized alias override (API)
Previously repo.anyrevs only expand aliases in [revsetalias] config. This
patch makes it more flexible to accept a customized dict defining aliases
without having to couple with ui.

revsetlang.expandaliases now has the signature (tree, aliases, warn=None)
which is more consistent with templater.expandaliases. revsetlang.py is now
free from "ui", which seems to be a good thing.
2017-06-24 15:29:42 -07:00
Jun Wu
41049ab36d amend: use scmutil.cleanupnodes (BC)
This is marked as BC because the strip backup file name has changed.
2017-06-26 15:28:28 -07:00
Jun Wu
daadde7a5c scmutil: make cleanupnodes delete divergent bookmarks
cleanupnodes takes care of bookmark movement, and bookmark movement could
cause bookmark divergent resolution as a side effect. This patch adds such
bookmark divergent resolution logic so future rebase migration will be
easier.

The revset is carefully written to be equivalent to what rebase does today.
Although I think it might make sense to remove divergent bookmarks more
aggressively, for example:

    F   book@1
    |
    E   book@2
    |
    | D book
    | |
    | C
    |/
    B   book@3
    |
    A

When rebase -s C -d E, "book@1" will be removed, "book@3" will be kept,
and the end result is:

    D   book
    |
    C
    |
    F
    |
    E   book@2 (?)
    |
    B   book@3
    |
    A

The question is should we keep book@2? The current logic keeps it. If we
choose not to (makes some sense to me), the "deleterevs" revset could be
simplified to "newnode % oldnode".

For now, I just make it compatible with the existing behavior. If we want to
make the "deleterevs" revset simpler, we can always do it in the future.
2017-06-26 13:13:51 -07:00
Jun Wu
74bc654a08 scmutil: make cleanupnodes handle filtered node
In some valid usecases, the "mapping" received by scmutil.cleanupnodes have
filtered nodes. Use unfiltered repo to access them correctly.

The added test case will fail with the old cleanupnodes code.

This is important to migrate histedit to use the cleanupnodes API.
2017-06-26 15:08:37 -07:00
David Demelier
d324b7a9bf configitems: add alias support in config
Aliases define optional alternatives to existing options. For example the old
option ui.user was deprecated and replaced by ui.username. With this mechanism,
it's even possible to create an alias to an option in a different section.

Add ui.user as alias to ui.username as an example of this concept.

The old alternates principle in ui.config is removed as it was used only for
this option.
2017-07-07 08:33:10 +02:00
David Demelier
7369cb3896 hgweb: use ui._unset to prevent a warning in configitems 2017-07-03 13:04:35 +02:00
Martin von Zweigbergk
d4520a7687 dispatch: fix typo suggestion for disabled extension
If the matching command lives in an in-tree extension (which is all we
scan for), and the user has disabled that extension with
"extensions.<name>=!", we were not finding it, because the path in
_disabledextensions was the empty string. If the user had set
"extensions.<name>=!<valid path>" it would work, so it seems like just
a mistake that it didn't work.
2017-07-07 00:13:53 -07:00
Gregory Szorc
87044d7937 sparse: inline signature cache clearing
It is a trivial one-liner. No need to have a separate function.
2017-07-06 16:10:28 -07:00
Gregory Szorc
793c8fb431 sparse: move working directory refreshing into core
This is a pretty straightforward move of the code.

I converted the "force" argument to a keyword argument.

Like other recent changes, this code is tightly coupled with
working directory update code in merge.py. I suspect the code
will become more tightly coupled over time, possibly even moved
to merge.py. For now, let's get the code in core.
2017-07-06 14:53:08 -07:00
Gregory Szorc
7fec603f86 sparse: refactor update actions filtering and call from core
merge.calculateupdates() now filters the update actions through sparse
by default.

The filtering no-ops if sparse isn't enabled or no sparse config
is defined.

The function has been refactored to behave more like a filter
instead of a wrapper of merge.calculateupdates().

We should arguably take sparse into account earlier in
merge.calculateupdates(). This patch preserves the old behavior
of applying sparse at the end of update calculation, which is the
simplest and safest approach.
2017-07-06 16:29:31 -07:00
Gregory Szorc
7fff0417c9 sparse: move update action filtering into core
This is a relatively straight port of the function. It is pretty large.
So refactoring will be postponed to a subsequent commit.
2017-07-06 16:17:35 -07:00
Gregory Szorc
6dce563cd3 sparse: move pruning of temporary includes into core
This was our last method on the custom repo type, meaning we could
remove that custom type and inline the 2 lines of code into
reposetup().

As part of the move, instead of wrapping merge.update() from
the sparse extension, we inline the function call. The ported
function now no-ops if sparse isn't enabled, making it safe to
always call.

The call site in update() may not be the most appropriate. But
it matches the previous behavior, which is the safest thing
to do. It can be improved later.
2017-07-06 14:33:18 -07:00
Gregory Szorc
26fd8a7af7 sparse: move function for resolving sparse matcher into core
As part of the move, the function arguments changed so revs are
passed as a list instead of *args. This allows us to use keyword
arguments properly.

Since the plan is to integrate sparse into core and have it
enabled by default, we need to prepare for a sparse matcher
to always be obtained and operated on. As part of the move,
we inserted code that returns an always matcher if sparse
isn't enabled. Some callers in the sparse extension take this
into account and conditionally perform matching depending on
whether the special always matcher is seen. I /think/ this
may have sped up some operations where the extension is
installed but no sparse config is activated.

One thing I'm ensure of in this code is whether os.path.dirname()
is semantically correct. os.posixpath.dirname() (which is
exported as pathutil.dirname) might be a better choise because
all patterns should be using posix directory separators (/)
instead of Windows (\). There's an inline comment that implies
Windows was tested. So hopefully it won't be a problem. We
can improve this in a follow-up. I've added a TODO to track it.
2017-07-06 17:41:45 -07:00
Gregory Szorc
16c192411d match: move matchers from sparse into core
The sparse extension contains some matcher types that are
generic and can exist in core.

As part of the move, the classes now inherit from basematcher.
always(), files(), and isexact() have been dropped because
they match the default implementations in basematcher.
2017-07-06 17:39:24 -07:00
Gregory Szorc
6b6712c33f sparse: clean up config signature code
Before, 0 was being used as the default signature value and we cast
the int to a string. We also handled I/O exceptions manually.

The new code uses cfs.tryread() so we always feed data into the
hasher. The empty string does hash and and should be suitable
for input into a cache key.

The changes made the code simple enough that the separate checksum
function could be inlined.
2017-07-06 16:01:36 -07:00
Gregory Szorc
0338e1f32a sparse: move config signature logic into core
This is a pretty straightforward port. It will be cleaned up in
a subsequent commit.
2017-07-06 16:11:56 -07:00
Yuya Nishihara
48edce65ce revsetlang: match tree by helper function on optimize
This should make optimize() more readable and less error-prone, but it doubles
the parsing cost.

  (original)
  $ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
  'L.optimize(L.analyze(L.parse("ancestors(x) and not ancestors(y)")))'
  10000 loops, best of 3: 79.3 usec per loop

  (this patch)
  $ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
  'L._treecache.clear(); \
   L.optimize(L.analyze(L.parse("ancestors(x) and not ancestors(y)")))'
  10000 loops, best of 3: 201 usec per loop
2016-02-17 21:40:59 +09:00
Yuya Nishihara
27c162ca6b parser: add helper function to test if pattern matches parsed tree
This function will be used as follows:

  match('ancestors(_) and not ancestors(_)', x)

See the next patch for details.
2016-02-17 21:31:09 +09:00
Yuya Nishihara
63d5f35621 revsetlang: build optimized tree by helper function
This should make optimize() more readable, but it doubles the parsing cost.

  (original)
  $ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
  'L.optimize(L.analyze(L.parse("::tip")))'
  10000 loops, best of 3: 18.1 usec per loop

  (this patch)
  $ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
  'L._treecache.clear(); L.optimize(L.analyze(L.parse("::tip")))'
  10000 loops, best of 3: 48.4 usec per loop

30usec isn't dominant compared to the revset evaluation, but that is a cost.
That's why a parsed tree is cached, which can benefit in hgweb or chg server.
2016-02-17 21:38:25 +09:00
Yuya Nishihara
ee31d80d0f parser: add helper function that constructs parsed tree from template
This function will be used as follows:

  build('only(_, _)', x, y)

See the next patch for details.
2016-02-17 21:30:04 +09:00
Pulkit Goyal
5caf86603b patch: take messages out of the function so that extensions can add entries
Extensions will want to have interactive thing for more operations or
particulary want to show more verbs. So this patch takes out the message thing
from the function so that extensions can add verbs to this. The curses one is
also not in any function so extensions can add more actions and verbs there.

Differential Revision: https://phab.mercurial-scm.org/D567
2017-08-30 18:19:14 +05:30
Phil Cohen
630437a97b merge: move some of the logic in batchget() to workingfilectx
We will use this logic in two places with in-memory merge.

Differential Revision: https://phab.mercurial-scm.org/D444
2017-08-31 11:28:59 -07:00
Phil Cohen
f42b3c5264 filemerge: add _restorebackup
Differential Revision: https://phab.mercurial-scm.org/D404
2017-08-31 11:28:59 -07:00
Phil Cohen
347cf25043 filemerge: reduce creation of tempfiles until needed
This restricts the creation of temporary files to just `_xmerge`, when we call
an external tool.

Differential Revision: https://phab.mercurial-scm.org/D403
2017-08-31 11:28:59 -07:00
Phil Cohen
2c5a4f03fb filemerge: add _workingpath
This reduces any reliance on `a`.

Differential Revision: https://phab.mercurial-scm.org/D401
2017-08-31 11:28:59 -07:00
Phil Cohen
7790af6f63 filemerge: move a util copy call to filectx.write
This way a future in-memory-merge context can intercept them.

Differential Revision: https://phab.mercurial-scm.org/D400
2017-08-31 11:28:59 -07:00
Phil Cohen
bea82440f1 filemerge: eliminate most uses of tempfiles
Emphasize that they're unused so we can more easily remove them later.

Differential Revision: https://phab.mercurial-scm.org/D399
2017-08-31 11:28:59 -07:00
Phil Cohen
ed389219ff filemerge: extract _maketemp and _makebackup
These functions will be modified by in-memory merge, so let's extract them first and add some comments.

This also shortens `_filemerge` a bit.

Differential Revision: https://phab.mercurial-scm.org/D388
2017-08-31 11:05:19 -07:00
Yuya Nishihara
9b22314380 encoding: check overflow while calculating size of JSON escape buffer
The minimum input size to exploit is ~682MB (= INT_MAX / len('\\u0000') * 2)
on 32bit system, which isn't easy to achieve using Python str in 2GB process
address space, but probably doable.
2017-08-31 21:56:40 +09:00
Michael Bolin
094c271fff editor: use an unambiguous path suffix for editor files
Changes the API of `ui.edit()` to take an optional `action` argument,
which is used when constructing the suffix of the temp file.
Previously, it was possible to set the suffix by specifying a `suffix` to the
optional `extra` dict that was passed to `ui.edit()`, but the goal is to
drop support for `extra.suffix` and make `action` a required argument.
To this end, `ui.edit()` now yields a `develwarn()` if `action` is not set
or if `extra.suffix` is set.

I updated all calls to `ui.edit()` I could find in `hg-crew` to specify the
appropriate `action`. This means that when creating a commit, instead
of the path to the editor file being something like:

`/tmp/hg-editor-XXXXXX.txt`

it is now something like:

`/tmp/hg-editor-XXXXXX.commit.hg.txt`

Some editors (such as Atom) make it possible to statically define a [TextMate]
grammar for files with a particular suffix. For example, because Git reliably
uses `.git/COMMIT_EDITMSG` and `.git/MERGE_MSG` as the paths for commit-type
messages, it is trivial to define a grammar that is applied when files of
either name are opened in Atom:

https://github.com/atom/language-git/blob/v0.19.1/grammars/git%20commit%20message.cson#L4-L5

Because Hg historically used a generic `.txt` suffix, it was much harder to
disambiguate whether a file was an arbitrary text file as opposed to one
created for the specific purpose of authoring an Hg commit message.

This also makes it easier to add special support for `histedit`, as it has its own
suffix that is distinct from a commit:

`/tmp/hg-histedit-XXXXXX.histedit.hg.txt`

Test Plan:
Added an integration test: `test-editor-filename.t`.

Manually tested: ran `hg ci --amend` for this change and saw that it
used `/tmp/hg-editor-ZZjcz0.commit.hg.txt` as the path instead of
`/tmp/hg-editor-ZZjcz0.txt` as the path.

Verified `make tests` passes.

Differential Revision: https://phab.mercurial-scm.org/D464
2017-08-30 20:25:56 +00:00
Martin von Zweigbergk
54312c2822 revlog: move check for wdir from changelog to revlog
Yuya said he preferred this (to keep them in one place, I think).

Differential Revision: https://phab.mercurial-scm.org/D569
2017-08-30 09:21:31 -07:00
Augie Fackler
58925444d0 revlog: use pycompat.bytestr() to reliably have a %s-able value 2017-08-22 21:21:43 -04:00
Augie Fackler
52fb3124b4 debugcommands: stabilize output of debugbundle by having a custom repr
We handle all dict-like things the same, and don't worry about it
actually being a repr.
2017-08-22 23:11:35 -04:00
Augie Fackler
48dbe73629 python3: replace sorted(<dict>.iterkeys()) with sorted(<dict>) 2017-08-22 20:06:58 -04:00
Augie Fackler
e2774d9258 python3: wrap all uses of <exception>.strerror with strtolocal
Our string literals are bytes, and we mostly want to %-format a
strerror into a one of those literals, so this fixes a ton of issues.
2017-08-22 20:03:07 -04:00
Jun Wu
bd039f3688 pager: do not start pager if ui has been pushbuffer-ed
The `pushbuffer`, `popbuffer` APIs are intended to capture internal output.
They will prevent `ui.write` from writing to the actual `ui.fout`. So a
pager won't receive the output and do the right thing. In general, it does
not make sense to start a pager if ui is in the "pushbuffer" mode.

Differential Revision: https://phab.mercurial-scm.org/D574
2017-08-30 14:04:55 -07:00
Jun Wu
4cd80fdd9c revset: do not flip "and" arguments when optimizing
Rewrite `flipand(y, x)` to `andsmally(x, y)` so the AST order is unchanged,
which could be more friendly to developers.

Differential Revision: https://phab.mercurial-scm.org/D579
2017-08-30 16:05:12 -07:00
Yuya Nishihara
507a4c9e22 revset: make match function follow given subset if specified (API)
This should be sensible default since mfunc(subset) is roughly equivalent
to 'subset & mfunc'. The order argument is still there so we can specify
'anyorder' if the order doesn't really matter.
2017-08-30 22:51:28 +09:00
Yuya Nishihara
abe6c88072 revset: move order argument to run-time match function
We no longer need the order flag to build a parsed tree.
2017-08-30 22:41:36 +09:00
Yuya Nishihara
389688d31e revset: fix example describing how ordering is determined
It was 'X & !Y' before.
2017-08-30 23:53:30 +09:00
Yuya Nishihara
3de7eef1fb revset: move order constants from revsetlang
Thanks to the recent refactor, the ordering rule is fully processed at
runtime.
2017-08-30 22:32:47 +09:00
Denis Laxalde
5c30bad3cd tag: use filtered repo when creating new tags (issue5539)
When pruning a changeset that added a tag and then adding another tag, the
"pruned" tag gets restored. This is because the tag creation step (tags._tag()
call in tags.tag()) is currently done on the unfiltered repo. This behavior
has been there from ba5c1b80e99a which backs out 39c37a1a9e2d with no clear
reason but caution on unthought situations at that time. In this changeset, we
pass the filtered repo to tags._tag(), preventing "pruned" tags to reappear.
This somehow restores 39c37a1a9e2d, though now we arguably have a valid use
case for.
2017-08-29 11:25:22 +02:00
Martin von Zweigbergk
45124be9f2 extensions: add wrappedfunction() context manager
Several extensions exist that temporarily want to wrap a function (at
least narrowhg, any many of the extensions in hg-experimental). That's
why we have the unwrapfunction() that was introduced in c8cda8f6f043
(extensions: add unwrapfunction to undo wrapfunction, 2016-08-10).

This patch adds a simple wrappedfunction() that returns a context
manager.

Differential Revision: https://phab.mercurial-scm.org/D472
2017-08-21 16:46:05 -07:00
David Soria Parra
6d9f90fa8d mdiff: add a --ignore-space-at-eol option
Add an option that only ignores whitespaces at EOL. The name of the option is
the same as Git.

.. feature::

   Added `--ignore-space-at-eol` diff option to ignore whitespace differences
   at line endings.

Differential Revision: https://phab.mercurial-scm.org/D422
2017-08-29 18:20:50 -07:00
Jun Wu
a2849aacae revset: improve documentation about ordering handling
The old documentation is a bit confusing. Namely, it's unclear whether
`define` means "I should ALWAYS define a new order", or "I should SOMETIMES
define a new order", and if it's the latter, what's the difference between
`define` and `any`?

This patch clarifies that and adds more examples.

Differential Revision: https://phab.mercurial-scm.org/D523
2017-08-25 11:20:34 -07:00
Jun Wu
647a38e249 revset: remove order information from tree (API)
Keeping `order` in tree makes AST operation harder. And there could be
invalid cases if trees could be generated and compounded freely, like:

  SetA(order=define) & SetB(order=define)
                                  ^^^^^^ couldn't be satisfied

This patch changes the code to calculate order on the fly, during tree
traversal. Optimization of reordering `and` arguments is preserved by
introducing a new internal operation `flipand`.

.. api::

   revset.stringset() now takes 'order' as the last argument.

Differential Revision: https://phab.mercurial-scm.org/D451
2017-08-20 10:55:11 -07:00
Jun Wu
31517054b3 revset: drop optimization about reordering "or" set elements
The reordering optimization is more important for "and" than "or", given the
implementation details about "addset" and "filteredset" - reordering "or"
may help "__contains__" test but not iteration, reordering "and" could help
both. We are going to simplify the tree to remove ordering information.
Removing "or" reordering optimization would make things simpler.

This effectively reverts 6820a8a645ef. It tracks back to the "orset"
function added by the initial commit of revset (c9ce8ecd6).

In the future, we might consider optimization at runtime (ex. do reordering
and rewrites inside "orset").

Differential Revision: https://phab.mercurial-scm.org/D561
2017-08-28 23:44:47 -07:00
Jun Wu
973c4f76d4 rebase: initial support for multiple destinations
This patch defines `SRC` (a single source revision) and `ALLSRC` (all source
revisions) to be valid names in  `--dest` revset if `--src` or `--rev` is
used. So destination could be defined differently according to source
revisions. The names are capitalized to make it clear they are "dynamically
defined", distinguishable from normal revsets (Thanks Augie for the
suggestion).

This is useful, for example, `-r 'orphan()' -d 'calc-dest(SRC)'` to solve
instability, which seems to be a highly wanted feature.

The feature is not completed, namely if `-d` overlaps with `-r`, things
could go wrong. A later patch will handle that case.

The feature is also gated by `experimental.rebase.multidest` config option
which is default off.

Differential Revision: https://phab.mercurial-scm.org/D469
2017-08-29 17:27:37 -07:00
Michael Bolin
d92f944789 util: use ~ as a suffix for a temp file in the same directory as a source file
Tools like Buck have patterns to ignore the creation of files (in the working
copy) that match certain patterns:

39278a4f07/src/com/facebook/buck/cli/Main.java (L259-L299)

When Buck sees a new source file (as reported by Watchman), it has to invalidate
a number of caches associated with the directory that contains the file.
Using a standard suffix, such as `~`, would make it easier for Buck and others
to filter out these types of file creation events.

The other uses of `tempfile.mkstemp()` in Hg do not appear to be problematic
because they (generally speaking) do not specify the `dir` parameter, so the
new file is created in the system-appropriate temp directory, which is outside
the working copy.

Test Plan:
`make tests`

Differential Revision: https://phab.mercurial-scm.org/D468
2017-08-22 00:38:38 +00:00
Martin von Zweigbergk
9e0298dbb7 morestatus: simplify check for unresolved merge conflicts
Differential Revision: https://phab.mercurial-scm.org/D546
2017-08-28 14:47:18 -07:00
Jun Wu
3f18e3a17c metadataonlyctx: don't crash when reusing the manifest with deletions
This was originally fixed by Mateusz Kwapich for the `metaedit` command in
fb-hgext with a test for the `metaedit` command. It didn't get upstreamed
because `metaedit` was not in core.

This patch fixes the crash and adds a test about `metadataonlyctx` to
avoid future regressions.

Differential Revision: https://phab.mercurial-scm.org/D550
2017-08-28 16:58:59 -07:00
Jun Wu
795e6cde00 context: make parents and text optional in metadataonlyctx
The metadataonlyctx is to copy an existing context with some minor metadata
changes. If the caller only wants to change "extra", or "user", ideally it
does not have to read and pass "parents" and "text" information.

This patch makes "parents" and "text" optionally to convenient callers.

Differential Revision: https://phab.mercurial-scm.org/D548
2017-08-28 16:49:41 -07:00
Boris Feld
75dd8c8d61 template: better prune support in obsfate
successorssets don't returns good results for pruned commit, add a workaround
for simple cases.

A proper fix would require a large rework of successorssets algorithm, I will
send a separate series for this refactoring.
2017-07-03 17:38:56 +02:00
Boris Feld
f0beef3fad template: compute dates in obsfatedate
Extract the dates from obsmarkers. Compute the min and max date from the
obsmarker range list.
2017-07-03 15:34:10 +02:00
Boris Feld
6c65874220 template: compute user in obsfateusers
Extract, deduplicate users informations from obs markers in order to display
them.

Print all users for the moment, we might want to display users only in verbose
mode later.
2017-07-03 15:34:00 +02:00
Boris Feld
26b4084486 template: compute verb in obsfateverb
Add a template function obsfateverb which use the markers information to
compute a better obsfate verb.

The current logic behind the obsfate verb is simple for the moment:

- If the successorsets is empty, the changeset has been pruned, for example:

    Obsfate: pruned

- If the successorsets length is 1, the changeset has been rewritten without
  divergence, for example:

    Obsfate: rewritten as 2:337fec4d2edc, 3:f257fde29c7a

- If the successorsets length is more than 1, the changeset has diverged, for
  example:

    Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a

As the divergence might occurs on a subset of successors, we might see some
successors twice:

    Obsfate: split as 9:0b997eb7ceee, 5:dd800401bd8c, 10:eceed8f98ffc; split
    as 8:b18bc8331526, 5:dd800401bd8c, 10:eceed8f98ffc
2017-07-03 15:33:27 +02:00
Augie Fackler
16ad9b6bae merge with stable 2017-08-28 17:40:03 -04:00
Michael Bolin
3b574ea901 dirstate: perform transactions with _copymap using single call, where possible
This replaces patterns such as this:

```
if f in self._copymap:
    del self._copymap[f]
```

with this:

```
self._copymap.pop(f, None)
```

Although eliminating the extra lookup/call may be a negligible performance win
in the standard dirstate, alternative implementations, such as
[sqldirstate](https://bitbucket.org/facebook/hg-experimental/src/default/sqldirstate/)
may see a bigger win where each of these calls results in an RPC,
so the savings is greater.

Test Plan:
`make tests`

Differential Revision: https://phab.mercurial-scm.org/D493
2017-08-23 18:24:57 +00:00
Jun Wu
f873da355e pull: do not prompt "hg update" if update.requiredest is set
Previously, after pull, we show:

  (run 'hg update' to get a working copy)

unconditionally. People might run `hg update` and get an exception if
`update.requiredest` is set, and get a bit frustrated. This patch changes
the code to not prompt `hg update` in that case.

Differential Revision: https://phab.mercurial-scm.org/D516
2017-08-24 20:25:16 -07:00
Martin von Zweigbergk
75ce730bf8 changelog: abort on attempt to write wdir revision
Similar to the previous patch which prevented writing the null
revision to any revlog, but this is for the wdir revision.

Thanks to Jun for pointing this out.

Differential Revision: https://phab.mercurial-scm.org/D524
2017-08-25 22:05:10 -07:00
Peter Vitt
0725932203 record: make the m key open an editor for the commit message (issue5667)
With the former crecord extension, the user could edit the commit
message while he was de-/selecting hunks. By pressing 'm', an editor
showed up to edit the commit message.

With record being part of mercurial, this feature is not available
anymore. However, the help text still mentions it.

As the infrastructure needed is still present, this feature is quite
easily ported from the crecord extension to mercurial.

It seems there is no test coverage for record ui, so I tested this patch
manually on my local machine.
2017-08-28 13:43:31 +02:00
Boris Feld
6cbbcf714c obsolete: fix old typo
Clean an old typo in successorssets.

Differential Revision: https://phab.mercurial-scm.org/D531
2017-07-03 03:56:53 +02:00
Boris Feld
6f2f6266d0 obsolete: move merge logic on the smaller object
Refactor some logic in _succs in order to clean successorssets code.

Differential Revision: https://phab.mercurial-scm.org/D530
2017-07-03 03:54:24 +02:00
Martin von Zweigbergk
9255a8ef24 revlog: abort on attempt to write null revision
My repo got corrupted yesterday by something that ended up writing the
null revision to the revlog (nullid hash, not nullrev index, of
course).  We use many extensions internally (narrowhg, remotefilelog,
evolve, internal extensions) and treemanifests are on. The null
revision was written to the changelog, the root manifest log, and one
subdirectory manifest log. I have no idea exactly why the null
revision was written, but it seems cheap enough to check that we
should fail instead of corrupting the repo.

Differential Revision: https://phab.mercurial-scm.org/D522
2017-08-25 15:50:07 -07:00
Martin von Zweigbergk
17b65783ad context: remove unnecessary default values for matchers (API)
ctx._dirstatestatus() is called only from workingctx._buildstatus()
and that function, in turn, is called only from
basectx.status(). basectx.status() will always pass a matcher to
_buildstatus(), so there's no need to handle a None matcher there.

Differential Revision: https://phab.mercurial-scm.org/D492
2017-08-22 23:39:05 -07:00