Commit Graph

410 Commits

Author SHA1 Message Date
Boris Feld
87151ab0b0 exchange: propagate the subfunctions return
The parts generator can return a callback to handle server reply. We should
propagate the return for correctness.
2017-10-19 21:50:14 +02:00
Boris Feld
a5658f8623 phase: use a binary phase part to push through bundle2 (BC)
The part we are using for pull is now used for push too. As we no longer use
pushkey, pushkey hooks are no longer triggered. This is an obvious backward
incompatible change. We could artificially trigger the pushkey hook within the
bundle2 part, but this seemed too hacky to me.

An option would be to disable by default this new mechanism for a couple of
versions to help people migrate to `txnclose-phase`. I took the liberal and
optimistic path to just turn it on by default directly.

.. bc::

   Push no longer triggers a pushkey hook when updating phases. Use the new
   `txnclose-phase` and `txnclose-phase` hooks instead.
   (Applies when both server and client use version 4.4 or above).
2017-09-20 19:38:06 +02:00
Boris Feld
a3e217804d phase: isolate logic to update remote phrase through bundle2 pushkey
Move the logic to build bundle2 pushkey part into its dedicated function. It
will help to keep the logic clear when adding support for sending phases change
using 'phase-heads' part.
2017-09-20 19:17:37 +02:00
Boris Feld
e0099ff757 phase: generate a push-race detection part on push
We are about to switch phase pushing from using pushkey to using a the new
dedicated binary part. We introduce the push race detection on its own to help
detect potential impact.
2017-10-11 07:40:00 +02:00
Boris Feld
68629fa552 phase: gather remote phase information in a summary object
We keep useful phase information around. The data will be reused with detecting
push-race in later changesets.
2017-10-11 18:39:04 +02:00
Boris Feld
048b95b938 phase: simplify the check for issue3781 shortcut in discovery
We'll rework the code around this check. Limiting the entanglement will help
with later changesets
2017-10-11 18:39:34 +02:00
Boris Feld
02117664d7 exchange: fix issue3781 reference in the comment
This comment is about:

  issue3781: Courtesy Phases synchronisation to publishing server prevent
             subrepo push
Not about:

  issue3871: Slow hg log when template contains {file_adds}, {file_mods} and
             {file_dels}
2017-10-16 12:36:42 +02:00
Augie Fackler
c4411f7b18 exchange: remove superfluous pass statements 2017-09-30 07:43:53 -04:00
Boris Feld
76b0c9eaa7 exchange: fix test for remote support of binary phases
If the remote do not support phases, the "get" call will return None. We
change that default return to empty tuple to fix the membership testing.

This was a bug in the initial series. Thanks to yuja for catching this.
2017-09-30 10:09:29 +01:00
Gregory Szorc
23c7474f57 exchange: perform stream clone with clone bundle with --uncompressed
Previously, `hg clone --uncompressed` would always clone from the
origin server, even if a streaming clone bundle were available.

With this change, we invoke the clone bundle mechanism before the
stream clone mechanism, giving clone bundles the opportunity to
handle --uncompressed (which is mapped to pullop.streamclonepreferred).

The clone bundle filtering code now filters out entries that aren't
stream clones when a stream clone is requested. If a stream clone
clone bundle entry is present, it will be used. Otherwise, the client
will fall back to a server-based streaming clone.

.. feature::

   `hg clone --uncompressed` uses clone bundles when possible

Differential Revision: https://phab.mercurial-scm.org/D833
2017-09-28 15:24:54 +01:00
Boris Feld
88a253014b pull: remove inadequate use of operations records to update stepdone
The 'stepdone' set is design to be a client side mechanism. If the client used
some advanced capabilities to request necessary information (changeset,
obsmarkers, phases, etc). It marks the steps as done to avoid having a less
advanced mechanism issue a duplicated request.

So, the "stepdone.add('phases')" should be the result of a client choice,
because only the client can know it has requested all it needed to request. In
4a08cf1a2cfe this principle was broken because any phase-heads part sent by
the server to the client would declare the phases retrieval complete.

Now that there is an official phases related capability and code associated to
it. We do not need the change in 4a08cf1a2cfe anymore and we can back it out.
This brings back 'stepdone' management for 'phases' in line with the rest of
the code (including other phases handing).

Here is an example of potential misbehavior that 4a08cf1a2cfe introduced:

Imagine a server that pre-computes bundles. The bundles contains a changegroup
part and an (advisory) 'phase-heads' part. When a pull occurs, precomputed
bundled are reused if available. As the phase part is advisory it can be sent
to all clients.  However they could be relevant changesets without phase
information.  Either because they are already common or because they had no
precomputed bundle for them yet.

If receiving any 'phase-heads' parts disable subsequent phases re-trivial
parts, the client will not request phase data for all relevant changesets. For
example common changesets will not turn public.
2017-09-26 15:55:01 +02:00
Boris Feld
bbf23f4d9a pull: use 'phase-heads' to retrieve phase information
A new bundle2 capability 'phases' has been added. If 'heads' is part of the
supported value for 'phases', the server supports reading and sending 'phase-
heads' bundle2 part.

Server is now able to process a 'phases' boolean parameter to 'getbundle'. If
'True', a 'phase-heads' bundle2 part will be included in the bundle with phase
information relevant to the whole pulled set. If this method is available the
phases listkey namespace will no longer be listed.

Beside the more efficient encoding of the data, this new method will greatly
improve the phase exchange efficiency for repositories with non-served
changesets (obsolete, secret) since we'll no longer send data about the
filtered heads.

Add a new 'devel.legacy.exchange' config item to allow fallback to the old
'listkey in bundle2' method.

Reminder: the pulled set is not just the changesets bundled by the pull. It
also contains changeset selected by the "pull specification" on the client
side (eg: everything for bare pull). One of the reason why the 'pulled set' is
important is to make sure we can move -common- nodes to public.
2017-09-24 21:27:18 +02:00
Boris Feld
386e89884f discovery: avoid dropping remote heads hidden locally
An extra post processing was added to recognize remote heads that are hidden
locally as "common" instead of "unknown". However, this processing was
removing such hidden heads from the remote heads sets.

It had no impact because we used to pull phase information from all remote
heads.

This series will replace the phase pulling operation to a more efficient
process but requires the unmodified pulled set information.
2017-09-20 05:47:33 +02:00
Augie Fackler
fdaf985a63 bundles: turn nbchanges int into a bytestr using pycompat.bytestr
Fixes some python 3 failures.
2017-09-15 18:38:36 -04:00
Augie Fackler
20e593170c exchange: hit opargs with pycompat.strkwargs before **-ing it
Fixes Python 3 problems.
2017-09-16 11:09:08 -04:00
Augie Fackler
8585259ff1 exchange: use '%d' % x instead of str(x) to encode ints
Recommended by Yuya instead of using pycompat.bytestr() in this case.
2017-08-22 21:21:13 -04:00
Durham Goode
792f16d38c changegroup: avoid creating empty changegroup part
Previously this check happened in the changegroup code itself. Since its
refactor, this logic needs to move out to callers that care about it, such as
this one. Otherwise we get empty bundle devel-warnings in certain extensions.

Differential Revision: https://phab.mercurial-scm.org/D690
2017-09-12 09:13:02 -07:00
Durham Goode
792e177614 changegroup: remove external uses of getbundler
Now that makestream and makechangegroup are the primary creation methods for
changegroups, let's get rid of this rogue use of getbundler and getsubsetraw.

Differential Revision: https://phab.mercurial-scm.org/D670
2017-09-10 18:51:31 -07:00
Durham Goode
21faf618dc changegroup: replace getchangegroup with makechangegroup
As part of reducing the number of changegroup creation APIs, let's replace
getchangegroup with calls to makechangegroup. This is mostly a drop in
replacement, but it does change the version specifier to be required, so it's
more obvious which callers are creating old version 1 changegroups still.

Differential Revision: https://phab.mercurial-scm.org/D669
2017-09-10 18:50:12 -07:00
Durham Goode
b470a6a2f1 changegroup: replace getlocalchangegroupraw with makestream
As part of reducing the number of changegroup creation apis, let's replace calls
to getlocalchangegroupraw with calls to makestream. Aside from one case of
checking if there are no outgoing commits and returning None, this is pretty
much a drop in replacement.

Differential Revision: https://phab.mercurial-scm.org/D666
2017-09-10 19:01:56 -07:00
Durham Goode
00542dbd45 changegroup: replace getsubset with makechangegroup
The current changegroup APIs are a bit of a mess. Currently you can use
getsubsetraw, getsubset, changegroupsubset, getlocalchangegroupraw,
getchangegroup, and getlocalchangroup to produce changegroups. This patch is the
beginning of a refactor to boil all of that away to just makechangegroup and
makestream.

The first step adds the new functions and replaces getsubset function with them.

Differential Revision: https://phab.mercurial-scm.org/D664
2017-09-10 18:39:02 -07:00
Martin von Zweigbergk
7603f48c32 exchange: don't attempt phase exchange if phase-heads was in bundle
The Mercurial core server doesn't yet include phase-heads parts in the
bundle, but our Google-internal server wants to do
that. Unfortunately, the usual exchange still happens even if
phase-heads part is included (including the short-circuited one for
old/publishing servers). That means that even if our server (again,
the Google-internal one, but also future Mercurial core servers)
includes a phase-heads part to indicate that some heads should be
drafts, that would still get overwritten by the phase updating that
happens after. So let's fix that by marking the phase step done if we
receive at least one phase-heads part in the bundle.

Differential Revision: https://phab.mercurial-scm.org/D440
2017-08-17 13:04:47 -07:00
Jun Wu
10555b029c pushvars: do not mangle repo state
Setting `repo._shellvars` works but is not a clean way to pass the pushvars
information from the push command to the exchange operation. Therefore
change it to actually pass `pushvars` as a push operation argument instead.

This makes third party extension like remotenames easier to support pushvars
cleanly. The key value parsing and verification code has been moved to a
lower level so it's harder to be bypassed and easier to be used in
remotenames which could replace `push` command entirely.

Differential Revision: https://phab.mercurial-scm.org/D423
2017-08-16 15:48:48 -07:00
Martin von Zweigbergk
5eeba3ed86 exchange: simplify unbundle locking using context managers
Differential Revision: https://phab.mercurial-scm.org/D393
2017-07-28 22:04:27 -07:00
Martin von Zweigbergk
e5ad1ba424 util: add base class for transactional context managers
We have at least three types with a close() and a release() method
where the close() method is supposed to be called on success and the
release() method is supposed to be called last, whether successful or
not. Two of them (transaction and dirstateguard) already have
identical implementations of __enter__ and __exit__. Let's extract a
base class for this, so we reuse the code and so the third type
(transactionmanager) can also be used as a context manager.

Differential Revision: https://phab.mercurial-scm.org/D392
2017-07-28 22:42:10 -07:00
Martin von Zweigbergk
503fee4003 exchange: remove need for "locked" variable
The transactionmanager() constructor just assigned a few variables and
cannot fail, so it's safe to move it inside the earlier try/except.

Differential Revision: https://phab.mercurial-scm.org/D391
2017-08-14 16:26:36 -07:00
Martin von Zweigbergk
2fd87dee7c exchange: drop now-unnecessary "local" from lock name variables
Since 6f17bd68a306 (exchange: drop support for lock-based unbundling
(BC), 2017-08-06), there is no more remote locking.

Differential Revision: https://phab.mercurial-scm.org/D390
2017-08-14 16:14:14 -07:00
Martin von Zweigbergk
96b9a2c44e exchange: remove 'locallocked' member from pushop object
The variable has been used only within a single function since
5d683cc9670f (push: elevate phase transaction to cover entire
operation, 2014-11-21), so there's no need to keep it on the pushop
object.

Differential Revision: https://phab.mercurial-scm.org/D389
2017-07-28 21:49:44 -07:00
Boris Feld
b4ef988c72 context: rename troubled into isunstable
As we changed the meaning of unstable between the old vocabulary and the new
one, we can't reuse the unstable method name at the risk of breaking
extensions calling unstable and getting a wrong result.

Instead rename troubled into isunstable so extensions will continue to work.

The renaming is done according to
https://www.mercurial-scm.org/wiki/CEDVocabulary.

Differential Revision: https://phab.mercurial-scm.org/D242
2017-08-02 19:13:56 +02:00
Boris Feld
b03347ff01 context: rename troubles into instabilities
Rename troubles context method into instabilities.

Copy the old troubles method and add a deprecation warning. This way
extensions calling troubles will see the deprecation warning but will not
break due to new return values.

The renaming is done according to
https://www.mercurial-scm.org/wiki/CEDVocabulary.

Differential Revision: https://phab.mercurial-scm.org/D238
2017-08-02 18:34:39 +02:00
Gregory Szorc
e464f2d82b exchange: access requirements on repo instead of peer
As part of formalizing the peer interface, I audited for attribute
accesses for non-internal names to find API violations. This
uncovered the code changed in this commit.

localpeer.requirements is just an alias to the repo's requirements
attribute. So, change the code to get the data from the source
instead of relying on a one-off attribute in the localpeer type.

Differential Revision: https://phab.mercurial-scm.org/D265
2017-08-05 15:15:20 -07:00
Gregory Szorc
59e773f0f6 exchange: drop support for lock-based unbundling (BC)
Locking over the wire protocol and the "addchangegroup" wire
protocol command has been deprecated since f8e443eb02c9, which was
first part of Mercurial 0.9.1.

Support for handling these commands from sshserver was dropped in
93297d5f4df2 in 2015, effectively locking out pre 0.9.1 clients
from new servers.

However, client-side code for calling lock and addchangegroup is
still present in exchange.py and the various peer classes to
facilitate pushing to pre 0.9.1 servers.

The lock-based pushing mechanism is extremely brittle. 0.9.1 was
released in July 2006 and I highly doubt anyone is still running
such an ancient version of Mercurial on a server. I'm about to
refactor the peer API and I don't think it is worth keeping
support for this ancient protocol feature. So, this commit removes
client support for the lock-based pushing mechanism. This means
modern clients will no longer be able to push to pre 0.9.1 servers.

Differential Revision: https://phab.mercurial-scm.org/D264
2017-08-06 17:44:56 -07:00
Pulkit Goyal
89fd642a01 pushvars: move fb extension pushvars to core
pushvars extension in fbext adds a --pushvars flag to push command using which
one send strings to server which becomes environment variables there prepended
with HG_USERVAR_. These variables can then be used to run hooks on the server.
The extension is moved directly to core and unbundling of the strings and
converting them to environment variables at server is disabled by default for
security reasons. One can turn that on by following config:

[push]
pushvars.server = true

This patch also adds the test for the extension.

Differential Revision: https://phab.mercurial-scm.org/D210
2017-07-31 09:59:42 +05:30
Boris Feld
ec878e1923 evolution: rename bumped to phase-divergent
Rename bumped to phase-divergent in all external user-facing output. Only
update user-facing output for the moment, variables names, templates keyword
and potentially configuration would be done in later series.

The renaming is done according to
https://www.mercurial-scm.org/wiki/CEDVocabulary.

Differential Revision: https://phab.mercurial-scm.org/D216
2017-08-01 18:07:34 +02:00
Boris Feld
aad1c3543a evolution: rename divergent to content-divergent
Rename divergent to content-divergent in all external user-facing output. Only
update user-facing output for the moment, variables names, templates keyword
and potentially configuration would be done in later series.

The renaming is done according to
https://www.mercurial-scm.org/wiki/CEDVocabulary.

Differential Revision: https://phab.mercurial-scm.org/D215
2017-08-01 17:58:20 +02:00
Boris Feld
10f4bd6001 evolution: rename unstable to orphan
Rename unstable to orphan in all external user-facing output. Only update
user-facing output for the moment, variables names, templates keyword and
potentially configuration would be done in later series.

The renaming is done according to
https://www.mercurial-scm.org/wiki/CEDVocabulary.

Differential Revision: https://phab.mercurial-scm.org/D214
2017-08-01 17:53:48 +02: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
Pierre-Yves David
240af74d9c pushrace: avoid crash on bare push when using concurrent push mode
If the remote is empty, we do now bother computing head changes and the
'pushbranchmap' attribute stays at None.

We now handle and tests this case.
2017-06-28 17:41:25 +02:00
Martin von Zweigbergk
2625447afc bundle: make applybundle() delegate v1 bundles to applybundle1() 2017-06-22 15:00:19 -07:00
Martin von Zweigbergk
c4273872d0 bundle: make applybundle1() return a bundleoperation
See previous commit for motivation. It already lets us share a little
bit more code in commands.py.
2017-06-21 21:08:48 -07:00
Martin von Zweigbergk
eae1a1d9e5 bundle: add a applybundle1() method
This is one step towards removing a bunch of "if isinstance(gen,
unbundle20)" by treating bundle1 and bundle2 more similarly.

The name may sounds ironic for a method in the bundle2 module, but I
didn't think it was worth it yet to create a new 'bundle' module that
depends on the 'bundle2' module. Besides, we'll inline the method
again later.
2017-06-16 10:25:11 -07:00
Martin von Zweigbergk
cd9d73f57a bundle: make combinechangegroupresults() take a bundleoperation
Both callers have a bundleoperation. Passing it in lets us share a bit
more code.
2017-06-22 14:04:13 -07:00
Martin von Zweigbergk
80bc6d2e40 bundle: move combineresults() from changegroup to bundle2
The results only need to be combined if they come from a bundle2. More
importantly, we'll change its argument to a bundleoperation soon, and
then it definitely will no longer belong in changegroup.py.
2017-06-22 13:58:20 -07:00
Martin von Zweigbergk
3015c0a9a8 bundle2: record changegroup data in 'op.records' (API)
When adding support for bundling and unbundling phases, it will be
useful to have the list of added changesets. To do that, we return the
list from changegroup.apply().
2017-06-16 16:56:16 -07:00
Pulkit Goyal
3e9e1184d1 py3: convert kwargs' keys' to str using pycompat.strkwargs()
On Python 3, we must have keys of keyword arguments as str.
2017-06-22 03:16:16 +05:30
Pulkit Goyal
6b29e8fbdd py3: convert kwargs keys' back to bytes using pycompat.byteskwargs() 2017-06-22 03:10:24 +05:30
Pierre-Yves David
8f6dde9279 configitems: register 'ui.clonebundleprefers' as example for 'configlist'
This exercise the default value handling in 'configlist'.
2017-06-17 13:25:42 +02:00
Martin von Zweigbergk
305dfd098c clonebundle: update hook arguments (BC)
By calling applybundle() with 'clonebundles' and the url instead of
calling processbundle(), the hooks will get different arguments:
HG_SOURCE will be 'clonebundles' instead of 'bundle2' and HG_URL will
be the url instead of 'bundle2'. This is consistent with the bundle1
behavior and seems like a bug fix, but I'm marking it BC anyway.
2017-06-19 22:14:37 -07:00
Martin von Zweigbergk
560e5ce4f1 changegroup: let callers pass in transaction to apply() (API)
I think passing in the transaction makes it a little clearer and more
consistent with bundle2.
2017-06-15 22:46:38 -07:00
Martin von Zweigbergk
350d0dfe2e exchange: create transaction for bundle1 unbundling earlier
changegroup.apply() currently creates a transation if there isn't
already one. Having the callers of that method pass in an existing
transaction seems a little cleaner. To do that, we need to make sure
all callers have a transaction. Since the transaction name is used as
a hook argument (HG_TXNNAME), we need to match the name from
changegroup.apply().
2017-06-15 16:10:53 -07:00