Commit Graph

453 Commits

Author SHA1 Message Date
Augie Fackler
a7f25c02bf subrepo: remove superfluous pass statements 2017-09-30 07:45:51 -04:00
Yuya Nishihara
a71f259bd2 doctest: bulk-replace string literals with b'' for Python 3
Our code transformer can't rewrite string literals in docstrings, and I
don't want to make the transformer more complex.
2017-09-03 14:32:11 +09:00
Yuya Nishihara
a406b0a270 py3: fix type of regex literals in subrepo.py 2017-09-03 15:01:23 +09: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
Sean Farley
39898f2a8a subrepo: add tests for git rogue ssh urls (SEC)
'ssh://' has an exploit that will pass the url blindly to the ssh
command, allowing a malicious person to have a subrepo with
'-oProxyCommand' which could run arbitrary code on a user's machine. In
addition, at least on Windows, a pipe '|' is able to execute arbitrary
commands.

When this happens, let's throw a big abort into the user's face so that
they can inspect what's going on.
2017-07-31 14:55:11 -07:00
Sean Farley
da301ac6a0 subrepo: add tests for svn rogue ssh urls (SEC)
'ssh://' has an exploit that will pass the url blindly to the ssh
command, allowing a malicious person to have a subrepo with
'-oProxyCommand' which could run arbitrary code on a user's machine. In
addition, at least on Windows, a pipe '|' is able to execute arbitrary
commands.

When this happens, let's throw a big abort into the user's face so that
they can inspect what's going on.
2017-07-31 16:44:17 -07: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
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
Yuya Nishihara
eff4d5e967 cat: add formatter support
This is an example showing how formatter can handle the --output option.
git subrepo isn't supported for now.
2017-05-25 21:53:44 +09:00
Yuya Nishihara
1d54e26edc cat: pass filename template as explicit argument
I'll move the handling of the '-' filename to commands.cat().
2017-05-27 18:50:05 +09:00
Pulkit Goyal
c103b5a583 py3: abuse r'' to access keys in keyword arguments 2017-05-03 15:41:28 +05:30
Pulkit Goyal
5e026b2f2b py3: handle opts correctly for hg add
opts in add command were passed again to cmdutil.add() as kwargs so we need
to convert them again to str. Intstead we convert them to bytes when passing
scmutil.match(). Opts handling is also corrected for all the functions which
are called from cmdutil.add().
2017-04-25 01:52:30 +05:30
Matt Harbison
6d898e296f serve: add support for Mercurial subrepositories
I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths]
configuration for awhile without issue.  Let's ditch the need for the manual
configuration in this case, and limit the repos served to the actual subrepos.

This doesn't attempt to handle the case where a new subrepo appears while the
server is running.  That could probably be handled with a hook if somebody wants
it.  But it's such a rare case, it probably doesn't matter for the temporary
serves.

The main repo is served at '/', just like a repository without subrepos.  I'm
not sure why the duplicate 'adding ...' lines appear on Linux.  They don't
appear on Windows (see 3f4ff1bdf101), so they are optional.

Subrepositories that are configured with '../path' or absolute paths are not
cloneable from the server.  (They aren't cloneable locally either, unless they
also exist at their configured source, perhaps via the share extension.)  They
are still served, so that they can be browsed, or cloned individually.  If we
care about that cloning someday, we can probably just add the extra entries to
the webconf dictionary.  Even if the entries use '../' to escape the root, only
the related subrepositories would end up in the dictionary.
2017-04-15 18:05:40 -04:00
Augie Fackler
b97ca52d90 merge with stable 2017-03-21 18:36:14 -04:00
Simon Farnsworth
ddbe7287e7 subrepo: move prompts out of the if (issue5505)
Prompts weren't available in the else clause
2017-03-20 04:36:55 -07:00
Yuya Nishihara
02022fc3c5 util: wrap s.encode('string_escape') call for future py3 compatibility 2017-03-15 23:06:50 +09:00
Valters Vingolds
0b2827adb4 rebase: provide detailed hint to abort message if working dir is not clean
Detailed hint message is now provided when 'pull --rebase' operation detects
unclean working dir, for example:
  abort: uncommitted changes
  (cannot pull with rebase: please commit or shelve your changes first)

Added tests for uncommitted merge, and for subrepo support verifying that same
hint is also passed to subrepo state check.
2017-01-10 09:32:27 +01:00
Pierre-Yves David
5e62e32b2e subrepo: directly use repo.vfs.join
The 'repo.join' method is about to be deprecated.
2017-03-08 16:53:47 -08:00
Pulkit Goyal
4780c32e4c py3: replace os.name with pycompat.osname (part 1 of 2)
os.name returns unicodes on py3 and we have pycompat.osname which returns
bytes. This series of 2 patches will change every ocurrence of os.name with
pycompat.osname.
2016-12-19 00:16:52 +05:30
Pulkit Goyal
1a4248666b py3: replace os.environ with encoding.environ (part 2 of 5) 2016-12-18 01:46:39 +05:30
Pulkit Goyal
5629f71f5b py3: replace os.sep with pycompat.ossep (part 3 of 4) 2016-12-17 20:14:24 +05:30
Pierre-Yves David
1d3281f64e vfs: use 'vfs' module directly in 'mercurial.subrepo'
Now that the 'vfs' classes moved in their own module, lets use the new module
directly. We update code iteratively to help with possible bisect needs in the
future.
2017-03-02 13:30:38 +01:00
Pierre-Yves David
be432559a1 color: move git-subrepo support into the subrepo module
Now that all ui instance carry a '_colormode' attribute, we can access and
comply to it directly in the subrepo code. The actual implementation could
probably be a bit smarter, but we stick close to the current one for the sake
of simplicity.
2017-02-21 17:50:04 +01:00
Matt Harbison
29208450f3 subrepo: run the repo decoders when archiving
The decoders were already run by default for the main repo, so this seemed like
an oversight.

The extdiff extension has been using 'archive' since a80ec1ea2694 to support -S,
and a colleague noticed that after diffing, making changes, and closing it, the
line endings were wrong for the diff-tool modified files in the subrepository.
(Files in the parent repo were correct, with the same .hgeol settings.)  The
editor (Visual Studio in this case) reloads the file, but doesn't notice the EOL
change.  It still adds new lines with the original EOL setting, and the file
ends up inconsistent.

Without this change, the first file `cat`d in the test prints '\r (esc)' EOL,
but the second doesn't on Windows or Linux.
2017-02-25 21:13:59 -05:00
Simon Farnsworth
dfbb92b63b merge: use labels in subrepo merge
This is the last place that doesn't respect conflict labels in merge output.
Teach subrepos to use subrepo merge output too.
2016-10-08 01:25:28 -07:00
Yuya Nishihara
2e776c55f7 error: make hintable exceptions reject unknown keyword arguments (API)
Previously they would accept any typos of the hint keyword.
2016-07-11 21:40:02 +09:00
liscju
c7ec9d159e i18n: translate abort messages
I found a few places where message given to abort is
not translated, I don't find any reason to not translate
them.
2016-06-14 11:53:55 +02:00
Augie Fackler
ad67b99d20 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
All versions of Python we support or hope to support make the hash
functions available in the same way under the same name, so we may as
well drop the util forwards.
2016-06-10 00:12:33 -04:00
FUJIWARA Katsunori
6c92609b0f subrepo: make a message translatable
This message has been overlooked by check-code, because it starts with
non-alphabet character ('%').

This is also a part of preparation for making "missing _() in ui
message" detection of check-code more exact.
2016-05-26 01:57:34 +09:00
Matt Harbison
3036220cae verify: don't init subrepo when missing one is referenced (issue5128) (API)
Initializing a subrepo when one doesn't exist is the right thing to do when the
parent is being updated, but in few other cases.  Unfortunately, there isn't
enough context in the subrepo module to distinguish this case.  This same issue
can be caused with other subrepo aware commands, so there is a general issue
here beyond the scope of this fix.

A simpler attempt I tried was to add an '_updating' boolean to localrepo, and
set/clear it around the call to mergemod.update() in hg.updaterepo().  That
mostly worked, but doesn't handle the case where archive will clone the subrepo
if it is missing.  (I vaguely recall that there may be other commands that will
clone if needed like this, but certainly not all do.  It seems both handy, and a
bit surprising for what should be a read only operation.  It might be nice if
all commands did this consistently, but we probably need Angel's subrepo caching
first, to not make a mess of the working directory.)

I originally handled 'Exception' in order to pick up the Aborts raised in
subrepo.state(), but this turns out to be unnecessary because that is called
once and cached by ctx.sub() when iterating the subrepos.

It was suggested in the bug discussion to skip looking at the subrepo links
unless -S is specified.  I don't really like that idea because missing a subrepo
or (less likely, but worse) a corrupt .hgsubstate is a problem of the parent
repo when checking out a revision.  The -S option seems like a better fit for
functionality that would recurse into each subrepo and do a full verification.

Ultimately, the default value for 'allowcreate' should probably be flipped, but
since the default behavior was to allow creation, this is less risky for now.
2016-04-27 22:45:52 -04:00
Matt Mackall
1d8233a89c subrepo: disable localizations when calling Git (issue5176)
Spotted by Aidar Sayfullin.
2016-04-16 15:14:25 -05:00
Matt Mackall
4a96519522 merge with stable 2016-03-29 12:29:00 -05:00
Mateusz Kwapich
e1c4c54543 subrepo: set GIT_ALLOW_PROTOCOL to limit git clone protocols (SEC)
CVE-2016-3068 (1/1)

Git's git-remote-ext remote helper provides an ext:: URL scheme that
allows running arbitrary shell commands. This feature allows
implementing simple git smart transports with a single shell shell
command. However, git submodules could clone arbitrary URLs specified
in the .gitmodules file. This was reported as CVE-2015-7545 and fixed
in git v2.6.1.

However, if a user directly clones a malicious ext URL, the git client
will still run arbitrary shell commands.

Mercurial is similarly effected. Mercurial allows specifying git
repositories as subrepositories. Git ext:: URLs can be specified as
Mercurial subrepositories allowing arbitrary shell commands to be run
on `hg clone ...`.


The Mercurial community would like to thank Blake Burkhart for
reporting this issue. The description of the issue is copied from
Blake's report.

This commit changes submodules to pass the GIT_ALLOW_PROTOCOL env
variable to git commands  with the same list of allowed protocols that
git submodule is using.

When the GIT_ALLOW_PROTOCOL env variable is already set, we just pass it
to git without modifications.
2016-03-20 21:52:21 -07:00
Matt Mackall
f8bc5de07b merge with stable 2016-03-25 16:23:23 -05:00
Martin von Zweigbergk
734edd8a4a subrepo: adapt to git's recent renames-by-default
Git turned on renames by default in commit 5404c11 (diff: activate
diff.renames by default, 2016-02-25). The change is destined for
release in git 2.8.0. The change breaks test-subrepo-git, which test
specifically that a moved file is reported as a removal and an
addition. Fix by passing --no-renames (available in git since mid
2006) to the diff commands that don't use --quiet (should make no
difference for those).
2016-03-24 09:38:11 -07:00
timeless
f5abb39053 remove: queue warnings until after status messages (issue5140) (API)
Before this change, warnings were interspersed with (and easily drowned out by)
status messages.

API:
abstractsubrepo.removefiles has an extra argument warnings,
into which callees should append their warnings.
  Note: Callees should not assume that there will be items in the list,
  today, I'm lazily including any other subrepos warnings, but
  that may change.

cmdutil.remove has an extra optional argument warnings,
into which it will place warnings.
If warnings is omitted, warnings will be reported via ui.warn()
as before this change (albeit, after any status messages).
2016-03-17 18:19:36 +00:00
Mason Malone
081f032818 subrepo: better error messages in _ensuregit
This patch improves the error messages raised when an OSError occurs, since
simply re-raising the exception can be both confusing and misleading. For
example, if "hg identify" is run inside a repository that contains a Git
subrepository and the git binary could not be found, it'll exit with the message
"abort: No such file or directory". That implies "identify" has a problem
reading the repository itself. There's no way for the user to know what the
real problem is unless they dive into the Mercurial source, which is what I
ended up doing after spending hours debugging errors while provisioning a VM
with Ansible (turns out I forgot to install Git on it).

Descriptive errors are especially important on Windows, since it's common for
Windows users to forget to set the "Path" system variable after installing Git.
2016-01-17 22:53:57 -05:00
Bryan O'Sullivan
d5d9f6c78a with: use context manager in subrepo storeclean 2016-01-15 13:14:50 -08:00
Bryan O'Sullivan
65a1bc16a6 with: use context manager in subrepo _cachestorehash 2016-01-15 13:14:50 -08:00
Siddharth Agarwal
0efe3372e4 origpath: move from cmdutil to scmutil
This is a lower-level function so it doesn't need to be in cmdutil, and putting
it here avoids a bunch of potential import cycle issues.
2016-01-02 03:02:57 -08:00
Martin von Zweigbergk
c84bb33a89 match: rename "narrowmatcher" to "subdirmatcher" (API)
I keep mistaking "narrowmatcher" for narrowhg's
narrowmatcher. "subdirmatcher" seems more to the point anyway.
2016-02-05 21:09:32 -08:00
Christian Delahousse
49f274e0e0 git-subrepos: revert respects specified location to save .orig files
This patch makes revert in git subrepos save .orig files where the user wants
them by using the cmdutil.origpath function.
2015-11-10 14:29:13 -08:00
Mads Kiilerich
09567db49a spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
Pierre-Yves David
30913031d4 error: get Abort from 'error' instead of 'util'
The home of 'Abort' is 'error' not 'util' however, a lot of code seems to be
confused about that and gives all the credit to 'util' instead of the
hardworking 'error'. In a spirit of equity, we break the cycle of injustice and
give back to 'error' the respect it deserves. And screw that 'util' poser.

For great justice.
2015-10-08 12:55:45 -07:00
Gregory Szorc
b89d7e1505 subrepo: use absolute_import 2015-08-08 20:03:58 -07:00
Matt Mackall
af90fd51ba subrepo: mark internal-only option 2015-06-25 17:57:26 -05:00
FUJIWARA Katsunori
0fc6d6032b subrepo: use vfs.dirname instead of os.path.dirname
This patch uses "wvfs of the parent repository" ('pwvfs') instead of
'wvfs' of own repository, because 'self._path' is the path to this
subrepository as seen from the parent repository.
2015-07-10 00:59:51 +09:00
FUJIWARA Katsunori
48e4a30e20 subrepo: use vfs.basename instead of os.path.basename 2015-07-10 00:59:51 +09:00
FUJIWARA Katsunori
78eff9a5a8 subrepo: use repo.pathto instead of util.pathto to simplify invocation
This centralization into 'repo.pathto()' should reduce the cost of vfs
migration around 'getcwd()' and so on in the future.
2015-07-10 00:59:51 +09:00