Commit Graph

33279 Commits

Author SHA1 Message Date
Yuya Nishihara
99466473c5 demandimport: drop hack for old Pythons which had no level argument
_import() was added by 1538e0df23b4, but it is identical to _origimport()
now.
2017-07-16 17:16:32 +09:00
Yuya Nishihara
f04eb5a8cd tests: drop "absimport" conditionals which should be always true 2017-07-16 17:47:10 +09: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
373ab13dab debugextensions: drop the color from the test
We are about to remove the extension so we remove trace of it in this specific
test to prevent it to be confused.
2017-07-15 20:31:52 +02:00
Boris Feld
6f1d2b38ba configitems: register the 'bugzilla.notify' config 2017-06-30 03:30:13 +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
e943b04ad3 test-phase-exchange: stabilize for Windows 2017-07-15 23:46:33 -04: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
Matt Harbison
bf865ea34e run-tests: disable color on Windows
More Windows sadness.  Maybe someone can figure out how to make win32 color
work, but I think we avoid importing stuff from the mercurial package in this
module.  On the plus side, this conditionalizes away a test failure.
2017-07-15 00:52:36 -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
Jun Wu
8847ceeedf phabricator: allow specifying reviewers on phabsend
Sometimes people want to specify reviewer explicitly for a stack. The
webpage only allows changing reviewer for one revision at a time. This patch
adds a `--reviewer` flag to make it easier to specify reviewers.

Test Plan:
On a test Phabricator instance, enable `differential.allow-self-accept`,
assign myself as a reviewer and make sure it works. Also try an invalid
username and make sure it raises.

Differential Revision: https://phab.mercurial-scm.org/D38
2017-07-11 08:52:55 -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
Martin von Zweigbergk
f3c48a5fe0 sparse: override dirstate.walk() instead of dirstate._ignore
Instead of treating files that are outside the sparse config as
ignored, this makes it so we list only those that are within the
sparse config by passing the sparse matcher to dirstate.walk().

Once we add support for narrow (sparseness applied to history, not
just working copy), we will need to do a similar restriction of the
walk over manifests, so this will be more consistent then. It also
simplifies the code a bit.

Note that a side-effect of this change is that files outside the
sparse config used to be listed as ignored, but they will now not be
listed at all. This can be seen in the test case where "hg purge" no
longer has any effect because it doesn't see that the files outside
the space config exist. To fix that, I think we should add an option
to dirstate.walk() to walk outside the sparse config. We might expose
that to the user as --no-sparse flag to e.g. "hg status" and "hg
purge", but that's work for another day.

Differential Revision: https://phab.mercurial-scm.org/D59
2017-07-11 10:46:35 -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
a55b1d3f9f bookmark: use 'applychanges' in the mq extension 2017-07-10 17:44:25 +02:00
Boris Feld
8cb892d933 bookmark: use 'applychanges' when stripping 2017-07-10 17:37:48 +02:00
Boris Feld
316d61deba bookmark: use 'applychanges' in the convert extension 2017-07-10 17:30:20 +02:00
Boris Feld
97880179f7 bookmark: use 'applychanges' when updating bookmark in histedit 2017-07-10 17:28:53 +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