This makes the client side pushes also include tree packs in the push.
Also adds a test to see that the tree parts round trip between two tree-only
clients.
stash | |
mitrandir |
Restricted Project |
This makes the client side pushes also include tree packs in the push.
Also adds a test to see that the tree parts round trip between two tree-only
clients.
Lint Skipped |
Unit Tests Skipped |
remotefilelog/shallowbundle.py | ||
---|---|---|
75 | This was needed to make the tests pass. Basically, if you're in treeonly mode you should also not be sending flat manifests. I think eventually I'll just delete the sendflat config. |
Path | Packages | |||
---|---|---|---|---|
M | infinitepush/__init__.py (19 lines) | |||
M | infinitepush/backupcommands.py (12 lines) | |||
M | infinitepush/bundleparts.py (17 lines) | |||
M | remotefilelog/shallowbundle.py (2 lines) | |||
A | M | tests/test-treemanifest-infinitepush.t (107 lines) |
import socket | import socket | ||||
import struct | import struct | ||||
import subprocess | import subprocess | ||||
import sys | import sys | ||||
import tempfile | import tempfile | ||||
import time | import time | ||||
from .bundleparts import ( | from .bundleparts import ( | ||||
getscratchbranchpart, | getscratchbranchparts, | ||||
scratchbookmarksparttype, | scratchbookmarksparttype, | ||||
scratchbranchparttype, | scratchbranchparttype, | ||||
) | ) | ||||
from . import ( | from . import ( | ||||
backupcommands, | backupcommands, | ||||
infinitepushcommands, | infinitepushcommands, | ||||
common, | common, | ||||
) | ) | ||||
# This parameter tells the server that the following bundle is an | # This parameter tells the server that the following bundle is an | ||||
# infinitepush. This let's it switch the part processing to our infinitepush | # infinitepush. This let's it switch the part processing to our infinitepush | ||||
# code path. | # code path. | ||||
bundler.addparam("infinitepush", "True") | bundler.addparam("infinitepush", "True") | ||||
nonforwardmove = pushop.force or pushop.ui.configbool(experimental, | nonforwardmove = pushop.force or pushop.ui.configbool(experimental, | ||||
confignonforwardmove) | confignonforwardmove) | ||||
scratchpart = getscratchbranchpart(pushop.repo, | scratchparts = getscratchbranchparts(pushop.repo, | ||||
pushop.remote, | pushop.remote, | ||||
pushop.outgoing, | pushop.outgoing, | ||||
nonforwardmove, | nonforwardmove, | ||||
pushop.ui, | pushop.ui, | ||||
bookmark, | bookmark, | ||||
create) | create) | ||||
for scratchpart in scratchparts: | |||||
bundler.addpart(scratchpart) | bundler.addpart(scratchpart) | ||||
def handlereply(op): | def handlereply(op): | ||||
# server either succeeds or aborts; no code to read | # server either succeeds or aborts; no code to read | ||||
pushop.cgresult = 1 | pushop.cgresult = 1 | ||||
return handlereply | return handlereply | ||||
bundle2.capabilities[scratchbranchparttype] = () | bundle2.capabilities[scratchbranchparttype] = () |
import re | import re | ||||
import socket | import socket | ||||
import stat | import stat | ||||
import subprocess | import subprocess | ||||
import time | import time | ||||
from .bundleparts import ( | from .bundleparts import ( | ||||
getscratchbookmarkspart, | getscratchbookmarkspart, | ||||
getscratchbranchpart, | getscratchbranchparts, | ||||
) | ) | ||||
from mercurial import ( | from mercurial import ( | ||||
bundle2, | bundle2, | ||||
changegroup, | changegroup, | ||||
commands, | commands, | ||||
discovery, | discovery, | ||||
encoding, | encoding, | ||||
error, | error, | ||||
# Wrap deltaparent function to make sure that bundle takes less space | # Wrap deltaparent function to make sure that bundle takes less space | ||||
# See _deltaparent comments for details | # See _deltaparent comments for details | ||||
wrapfunction(changegroup.cg2packer, 'deltaparent', _deltaparent) | wrapfunction(changegroup.cg2packer, 'deltaparent', _deltaparent) | ||||
try: | try: | ||||
bundler = _createbundler(ui, repo, other) | bundler = _createbundler(ui, repo, other) | ||||
backup = False | backup = False | ||||
if outgoing and outgoing.missing: | if outgoing and outgoing.missing: | ||||
backup = True | backup = True | ||||
bundler.addpart(getscratchbranchpart(repo, other, outgoing, | parts = getscratchbranchparts(repo, other, outgoing, | ||||
confignonforwardmove=False, | confignonforwardmove=False, | ||||
ui=ui, bookmark=None, | ui=ui, bookmark=None, | ||||
create=False)) | create=False) | ||||
for part in parts: | |||||
bundler.addpart(part) | |||||
if bookmarkstobackup: | if bookmarkstobackup: | ||||
backup = True | backup = True | ||||
bundler.addpart(getscratchbookmarkspart(other, bookmarkstobackup)) | bundler.addpart(getscratchbookmarkspart(other, bookmarkstobackup)) | ||||
if backup: | if backup: | ||||
_sendbundle(bundler, other) | _sendbundle(bundler, other) | ||||
_writelocalbackupstate(repo.vfs, afterbackupheads, | _writelocalbackupstate(repo.vfs, afterbackupheads, |
extensions, | extensions, | ||||
revsetlang, | revsetlang, | ||||
) | ) | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
scratchbranchparttype = 'b2x:infinitepush' | scratchbranchparttype = 'b2x:infinitepush' | ||||
scratchbookmarksparttype = 'b2x:infinitepushscratchbookmarks' | scratchbookmarksparttype = 'b2x:infinitepushscratchbookmarks' | ||||
def getscratchbranchpart(repo, peer, outgoing, confignonforwardmove, | def getscratchbranchparts(repo, peer, outgoing, confignonforwardmove, | ||||
ui, bookmark, create): | ui, bookmark, create): | ||||
if not outgoing.missing: | if not outgoing.missing: | ||||
raise error.Abort(_('no commits to push')) | raise error.Abort(_('no commits to push')) | ||||
if scratchbranchparttype not in bundle2.bundle2caps(peer): | if scratchbranchparttype not in bundle2.bundle2caps(peer): | ||||
raise error.Abort(_('no server support for %r') % scratchbranchparttype) | raise error.Abort(_('no server support for %r') % scratchbranchparttype) | ||||
_validaterevset(repo, revsetlang.formatspec('%ln', outgoing.missing), | _validaterevset(repo, revsetlang.formatspec('%ln', outgoing.missing), | ||||
if confignonforwardmove: | if confignonforwardmove: | ||||
params['force'] = '1' | params['force'] = '1' | ||||
# Do not send pushback bundle2 part with bookmarks if remotenames extension | # Do not send pushback bundle2 part with bookmarks if remotenames extension | ||||
# is enabled. It will be handled manually in `_push()` | # is enabled. It will be handled manually in `_push()` | ||||
if not isremotebooksenabled(ui): | if not isremotebooksenabled(ui): | ||||
params['pushbackbookmarks'] = '1' | params['pushbackbookmarks'] = '1' | ||||
parts = [] | |||||
try: | |||||
treemod = extensions.find('treemanifest') | |||||
parts.append(treemod.createtreepackpart(repo, outgoing, | |||||
treemod.TREEGROUP_PARTTYPE2)) | |||||
except KeyError: | |||||
pass | |||||
# .upper() marks this as a mandatory part: server will abort if there's no | # .upper() marks this as a mandatory part: server will abort if there's no | ||||
# handler | # handler | ||||
return bundle2.bundlepart( | parts.append(bundle2.bundlepart( | ||||
scratchbranchparttype.upper(), | scratchbranchparttype.upper(), | ||||
advisoryparams=params.iteritems(), | advisoryparams=params.iteritems(), | ||||
data=cg) | data=cg)) | ||||
return parts | |||||
def getscratchbookmarkspart(peer, bookmarks): | def getscratchbookmarkspart(peer, bookmarks): | ||||
if scratchbookmarksparttype not in bundle2.bundle2caps(peer): | if scratchbookmarksparttype not in bundle2.bundle2caps(peer): | ||||
raise error.Abort( | raise error.Abort( | ||||
_('no server support for %r') % scratchbookmarksparttype) | _('no server support for %r') % scratchbookmarksparttype) | ||||
return bundle2.bundlepart( | return bundle2.bundlepart( | ||||
scratchbookmarksparttype.upper(), | scratchbookmarksparttype.upper(), |
$ . "$TESTDIR/library.sh" | |||||
$ . "$TESTDIR/library-infinitepush.sh" | |||||
$ PYTHONPATH=$TESTDIR/..:$PYTHONPATH | |||||
$ export PYTHONPATH | |||||
$ setupcommon | |||||
$ hginit master | |||||
$ cd master | |||||
$ setupserver | |||||
$ cat >> .hg/hgrc <<EOF | |||||
> [extensions] | |||||
> pushrebase=$TESTDIR/../hgext3rd/pushrebase.py | |||||
> treemanifest=$TESTDIR/../treemanifest | |||||
> [remotefilelog] | |||||
> server=True | |||||
> [treemanifest] | |||||
> server=True | |||||
> EOF | |||||
$ echo x > x | |||||
$ hg commit -qAm 'add x' | |||||
$ cd .. | |||||
Push a scratch branch from one client | |||||
$ hgcloneshallow ssh://user@dummy/master client1 -q --config extensions.treemanifest=$TESTDIR/../treemanifest --config treemanifest.treeonly=True | |||||
1 trees fetched over * (glob) | |||||
1 trees fetched over * (glob) | |||||
1 files fetched over 1 fetches - (1 misses, 0.00% hit ratio) over * (glob) | |||||
$ cd client1 | |||||
$ cat >> .hg/hgrc <<EOF | |||||
> [extensions] | |||||
> treemanifest=$TESTDIR/../treemanifest | |||||
> | |||||
> [remotefilelog] | |||||
> usefastdatapack=True | |||||
> | |||||
> [treemanifest] | |||||
> treeonly=True | |||||
> EOF | |||||
$ mkdir subdir | |||||
$ echo "my change" >> subdir/a | |||||
$ hg commit -qAm 'add subdir/a' | |||||
$ hg push --to scratch/foo --create | |||||
pushing to ssh://user@dummy/master | |||||
searching for changes | |||||
remote: pushing 1 commit: | |||||
remote: 02c12aef64ff add subdir/a | |||||
$ cd .. | |||||
Pull a scratch branch from another client | |||||
$ hgcloneshallow ssh://user@dummy/master client2 -q --config extensions.treemanifest=$TESTDIR/../treemanifest --config treemanifest.treeonly=True | |||||
$ cd client2 | |||||
$ cat >> .hg/hgrc <<EOF | |||||
> [extensions] | |||||
> treemanifest=$TESTDIR/../treemanifest | |||||
> | |||||
> [remotefilelog] | |||||
> usefastdatapack=True | |||||
> | |||||
> [treemanifest] | |||||
> treeonly=True | |||||
> EOF | |||||
$ hg pull -r scratch/foo | |||||
pulling from ssh://user@dummy/master | |||||
searching for changes | |||||
adding changesets | |||||
adding manifests | |||||
adding file changes | |||||
added 1 changesets with 1 changes to 1 files | |||||
(run 'hg update' to get a working copy) | |||||
$ hg log -G | |||||
o changeset: 1:02c12aef64ff | |||||
| tag: tip | |||||
| user: test | |||||
| date: Thu Jan 01 00:00:00 1970 +0000 | |||||
| summary: add subdir/a | |||||
| | |||||
@ changeset: 0:085784c01c08 | |||||
user: test | |||||
date: Thu Jan 01 00:00:00 1970 +0000 | |||||
summary: add x | |||||
$ hg cat -r tip subdir/a | |||||
my change | |||||
$ ls_l .hg/store | |||||
-rw-r--r-- 257 00changelog.i | |||||
-rw-r--r-- 108 00manifesttree.i | |||||
drwxr-xr-x data | |||||
drwxrwxr-x packs | |||||
-rw-r--r-- 43 phaseroots | |||||
-rw-r--r-- 18 undo | |||||
-rw-r--r-- 17 undo.backupfiles | |||||
-rw-r--r-- 0 undo.phaseroots | |||||
$ cd .. | |||||
Verify its not on the server | |||||
$ cd master | |||||
$ hg log -G | |||||
@ changeset: 0:085784c01c08 | |||||
tag: tip | |||||
user: test | |||||
date: Thu Jan 01 00:00:00 1970 +0000 | |||||
summary: add x | |||||
Is it related?