mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 23:07:18 +03:00
Update markers during hg pullbackup
Summary: Before this change `hg pullbackup` did not set correct markers on commits. This change make possible to see what changes already landed even when we are restoring repository from backup. Before the change `fbclone` + `hg pullbackup` of repo with `C1` commit landed would result in: ``` o o C2 | | o o C1 | / | o ``` after: ``` o o C2 | | o x C1 | / | o ``` Reviewed By: StanislavGlebik Differential Revision: D7032572 fbshipit-source-id: ffee3c7cc23c24a3df9a89c999c9dd2de226dbff
This commit is contained in:
parent
af8ecd5f80
commit
4cfb665650
@ -118,6 +118,8 @@ class Client(object):
|
||||
}
|
||||
}
|
||||
}
|
||||
created_time
|
||||
updated_time
|
||||
differential_diffs {
|
||||
count
|
||||
}
|
||||
@ -147,6 +149,8 @@ class Client(object):
|
||||
if status == 'Closed':
|
||||
status = 'Committed'
|
||||
info['status'] = status
|
||||
info['created'] = node['created_time']
|
||||
info['updated'] = node['updated_time']
|
||||
|
||||
if 'latest_active_diff' not in node:
|
||||
continue
|
||||
|
@ -37,9 +37,14 @@
|
||||
# This information includes the local revision number and unix timestamp
|
||||
# of the last time we successfully made a backup.
|
||||
savelatestbackupinfo = False
|
||||
"""
|
||||
|
||||
# Enable creating obsolete markers when backup is restored.
|
||||
createlandedasmarkers = False
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import ConfigParser
|
||||
import collections
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
@ -49,10 +54,6 @@ import stat
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from .bundleparts import (
|
||||
getscratchbookmarkspart,
|
||||
getscratchbranchparts,
|
||||
)
|
||||
from mercurial import (
|
||||
bundle2,
|
||||
changegroup,
|
||||
@ -65,21 +66,17 @@ from mercurial import (
|
||||
hg,
|
||||
localrepo,
|
||||
lock as lockmod,
|
||||
node,
|
||||
phases,
|
||||
policy,
|
||||
registrar,
|
||||
scmutil,
|
||||
util,
|
||||
)
|
||||
|
||||
from collections import defaultdict, namedtuple
|
||||
from mercurial import policy
|
||||
from mercurial.extensions import wrapfunction, unwrapfunction
|
||||
from mercurial.node import bin, hex, nullrev, short
|
||||
from mercurial.i18n import _
|
||||
|
||||
from .. import shareutil
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
from . import bundleparts
|
||||
|
||||
osutil = policy.importmod(r'osutil')
|
||||
|
||||
@ -91,8 +88,8 @@ templatekeyword = registrar.templatekeyword()
|
||||
localoverridesfile = 'generated.infinitepushbackups.rc'
|
||||
secondsinhour = 60 * 60
|
||||
|
||||
backupbookmarktuple = namedtuple('backupbookmarktuple',
|
||||
['hostname', 'reporoot', 'localbookmark'])
|
||||
backupbookmarktuple = collections.namedtuple(
|
||||
'backupbookmarktuple', ['hostname', 'reporoot', 'localbookmark'])
|
||||
|
||||
class backupstate(object):
|
||||
def __init__(self):
|
||||
@ -204,7 +201,7 @@ def backupdisable(ui, repo, **opts):
|
||||
|
||||
timestamp = int(time.time()) + duration
|
||||
|
||||
config = ConfigParser()
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.add_section('infinitepushbackup')
|
||||
config.set('infinitepushbackup', 'disableduntil', timestamp)
|
||||
|
||||
@ -280,13 +277,21 @@ def restore(ui, repo, dest=None, **opts):
|
||||
if x not in backupstate.heads]
|
||||
if dest:
|
||||
pullopts['source'] = dest
|
||||
|
||||
maxrevbeforepull = len(repo.changelog)
|
||||
result = pullcmd(ui, repo, **pullopts)
|
||||
maxrevafterpull = len(repo.changelog)
|
||||
|
||||
if ui.config('infinitepushbackup', 'createlandedasmarkers', False):
|
||||
ext = extensions.find('pullcreatemarkers')
|
||||
ext.createmarkers(result, repo, maxrevbeforepull, maxrevafterpull,
|
||||
fromdrafts=False)
|
||||
|
||||
with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
|
||||
changes = []
|
||||
for book, hexnode in backupstate.localbookmarks.iteritems():
|
||||
if hexnode in repo:
|
||||
changes.append((book, bin(hexnode)))
|
||||
changes.append((book, node.bin(hexnode)))
|
||||
else:
|
||||
ui.warn(_('%s not found, not creating %s bookmark') %
|
||||
(hexnode, book))
|
||||
@ -315,7 +320,7 @@ def getavailablebackups(ui, repo, dest=None, **opts):
|
||||
sourcehostname, namingmgr)
|
||||
|
||||
if opts.get('json'):
|
||||
jsondict = defaultdict(list)
|
||||
jsondict = collections.defaultdict(list)
|
||||
for hostname, reporoot in allbackupstates.keys():
|
||||
jsondict[hostname].append(reporoot)
|
||||
# make sure the output is sorted. That's not an efficient way to
|
||||
@ -489,7 +494,7 @@ def smartlogsummary(ui, repo):
|
||||
ui.warn(_('note: %d changesets are not backed up.\n') % count)
|
||||
else:
|
||||
ui.warn(_('note: changeset %s is not backed up.\n') %
|
||||
short(repo[singleunbackeduprev].node()))
|
||||
node.short(repo[singleunbackeduprev].node()))
|
||||
ui.warn(_('Run `hg pushbackup` to perform a backup. If this fails,\n'
|
||||
'please report to the Source Control @ FB group.\n'))
|
||||
|
||||
@ -589,23 +594,23 @@ def _dobackup(ui, repo, dest, **opts):
|
||||
|
||||
# Wrap deltaparent function to make sure that bundle takes less space
|
||||
# See _deltaparent comments for details
|
||||
wrapfunction(changegroup.cg2packer, 'deltaparent', _deltaparent)
|
||||
extensions.wrapfunction(changegroup.cg2packer, 'deltaparent', _deltaparent)
|
||||
try:
|
||||
bundler = _createbundler(ui, repo, other)
|
||||
bundler.addparam("infinitepush", "True")
|
||||
backup = False
|
||||
if outgoing and outgoing.missing:
|
||||
backup = True
|
||||
parts = getscratchbranchparts(repo, other, outgoing,
|
||||
confignonforwardmove=False,
|
||||
ui=ui, bookmark=None,
|
||||
create=False)
|
||||
parts = bundleparts.getscratchbranchparts(
|
||||
repo, other, outgoing, confignonforwardmove=False,
|
||||
ui=ui, bookmark=None, create=False)
|
||||
for part in parts:
|
||||
bundler.addpart(part)
|
||||
|
||||
if bookmarkstobackup:
|
||||
backup = True
|
||||
bundler.addpart(getscratchbookmarkspart(other, bookmarkstobackup))
|
||||
bundler.addpart(bundleparts.getscratchbookmarkspart(
|
||||
other, bookmarkstobackup))
|
||||
|
||||
if backup:
|
||||
_sendbundle(bundler, other)
|
||||
@ -623,7 +628,8 @@ def _dobackup(ui, repo, dest, **opts):
|
||||
except Exception:
|
||||
ui.warn(_('remote connection cleanup failed\n'))
|
||||
ui.status(_('finished in %f seconds\n') % (time.time() - start))
|
||||
unwrapfunction(changegroup.cg2packer, 'deltaparent', _deltaparent)
|
||||
extensions.unwrapfunction(
|
||||
changegroup.cg2packer, 'deltaparent', _deltaparent)
|
||||
return 0
|
||||
|
||||
def _dobackgroundbackup(ui, repo, dest=None):
|
||||
@ -712,8 +718,8 @@ def _getlocalinfo(repo):
|
||||
|
||||
def _getlocalbookmarks(repo):
|
||||
localbookmarks = {}
|
||||
for bookmark, node in repo._bookmarks.iteritems():
|
||||
hexnode = hex(node)
|
||||
for bookmark, data in repo._bookmarks.iteritems():
|
||||
hexnode = node.hex(data)
|
||||
localbookmarks[bookmark] = hexnode
|
||||
return localbookmarks
|
||||
|
||||
@ -736,7 +742,7 @@ def _filterbookmarks(localbookmarks, repo, headstobackup):
|
||||
def _downloadbackupstate(ui, other, sourcereporoot, sourcehostname, namingmgr):
|
||||
pattern = namingmgr.getcommonuserprefix()
|
||||
fetchedbookmarks = other.listkeyspatterns('bookmarks', patterns=[pattern])
|
||||
allbackupstates = defaultdict(backupstate)
|
||||
allbackupstates = collections.defaultdict(backupstate)
|
||||
for book, hexnode in fetchedbookmarks.iteritems():
|
||||
parsed = _parsebackupbookmark(book, namingmgr)
|
||||
if parsed:
|
||||
@ -855,9 +861,9 @@ def _getcommandandoptions(command):
|
||||
def _deltaparent(orig, self, revlog, rev, p1, p2, prev):
|
||||
# This version of deltaparent prefers p1 over prev to use less space
|
||||
dp = revlog.deltaparent(rev)
|
||||
if dp == nullrev and not revlog.storedeltachains:
|
||||
if dp == node.nullrev and not revlog.storedeltachains:
|
||||
# send full snapshot only if revlog configured to do so
|
||||
return nullrev
|
||||
return node.nullrev
|
||||
return p1
|
||||
|
||||
def _getbookmarkstobackup(repo, newbookmarks, removedbookmarks,
|
||||
|
@ -17,6 +17,8 @@ from .extlib.phabricator import (
|
||||
graphql,
|
||||
)
|
||||
|
||||
COMMITTEDSTATUS = 'Committed'
|
||||
|
||||
def memoize(f):
|
||||
"""
|
||||
NOTE: This is a hack
|
||||
|
@ -11,12 +11,12 @@
|
||||
# relationship between a draft commit and its landed counterpart.
|
||||
# Thanks to these markers, less information is displayed and rebases can have
|
||||
# less irrelevant conflicts.
|
||||
|
||||
from mercurial import commands
|
||||
from mercurial import obsolete
|
||||
from mercurial import phases
|
||||
from mercurial import extensions
|
||||
from .extlib.phabricator import diffprops
|
||||
from .phabstatus import COMMITTEDSTATUS, getdiffstatus
|
||||
|
||||
def getdiff(rev):
|
||||
phabrev = diffprops.parserevfromcommitmsg(rev.description())
|
||||
@ -28,35 +28,62 @@ def extsetup(ui):
|
||||
def _pull(orig, ui, repo, *args, **opts):
|
||||
if not obsolete.isenabled(repo, obsolete.createmarkersopt):
|
||||
return orig(ui, repo, *args, **opts)
|
||||
|
||||
maxrevbeforepull = len(repo.changelog)
|
||||
r = orig(ui, repo, *args, **opts)
|
||||
maxrevafterpull = len(repo.changelog)
|
||||
|
||||
# Collect the diff number of the landed diffs
|
||||
landeddiffs = {}
|
||||
for rev in range(maxrevbeforepull, maxrevafterpull):
|
||||
n = repo[rev]
|
||||
if n.phase() == phases.public:
|
||||
diff = getdiff(n)
|
||||
if diff is not None:
|
||||
landeddiffs[diff] = n
|
||||
createmarkers(r, repo, maxrevbeforepull, maxrevafterpull)
|
||||
return r
|
||||
|
||||
def createmarkers(pullres, repo, start, stop, fromdrafts=True):
|
||||
landeddiffs = getlandeddiffs(repo, start, stop, onlypublic=fromdrafts)
|
||||
|
||||
if not landeddiffs:
|
||||
return r
|
||||
return
|
||||
|
||||
# Try to find match with the drafts
|
||||
tocreate = []
|
||||
unfiltered = repo.unfiltered()
|
||||
for rev in unfiltered.revs("draft() - obsolete()"):
|
||||
n = unfiltered[rev]
|
||||
diff = getdiff(n)
|
||||
if diff in landeddiffs and landeddiffs[diff].rev() != n.rev():
|
||||
tocreate.append((n, (landeddiffs[diff],)))
|
||||
tocreate = getmarkersfromdrafts(repo, landeddiffs) if fromdrafts else \
|
||||
getmarkers(repo, landeddiffs)
|
||||
|
||||
if not tocreate:
|
||||
return r
|
||||
return
|
||||
|
||||
unfiltered = repo.unfiltered()
|
||||
|
||||
with unfiltered.lock(), unfiltered.transaction('pullcreatemarkers'):
|
||||
obsolete.createmarkers(unfiltered, tocreate)
|
||||
|
||||
return r
|
||||
def getlandeddiffs(repo, start, stop, onlypublic=True):
|
||||
landeddiffs = {}
|
||||
|
||||
for rev in range(start, stop):
|
||||
rev = repo[rev]
|
||||
if not onlypublic or rev.phase() == phases.public:
|
||||
diff = getdiff(rev)
|
||||
if diff is not None:
|
||||
landeddiffs[diff] = rev
|
||||
return landeddiffs
|
||||
|
||||
def getmarkers(repo, landeddiffs):
|
||||
return [(landeddiffs[rev], tuple())
|
||||
for rev in getlandedrevsiter(repo, landeddiffs)]
|
||||
|
||||
def getmarkersfromdrafts(repo, landeddiffs):
|
||||
tocreate = []
|
||||
unfiltered = repo.unfiltered()
|
||||
|
||||
for rev in unfiltered.revs("draft() - obsolete()"):
|
||||
rev = unfiltered[rev]
|
||||
diff = getdiff(rev)
|
||||
|
||||
if diff in landeddiffs and landeddiffs[diff].rev() != rev.rev():
|
||||
marker = (rev, (landeddiffs[diff],))
|
||||
tocreate.append(marker)
|
||||
return tocreate
|
||||
|
||||
def getlandedrevsiter(repo, landeddiffs):
|
||||
statuses = (status for status in getdiffstatus(repo, *landeddiffs.keys())
|
||||
if status != 'Error')
|
||||
|
||||
return (diff for status, diff in zip(statuses, landeddiffs.keys())
|
||||
if status['status'] == COMMITTEDSTATUS)
|
||||
|
@ -16,6 +16,7 @@ setupcommon() {
|
||||
cat >> $HGRCPATH << EOF
|
||||
[extensions]
|
||||
infinitepush=
|
||||
pullcreatemarkers=
|
||||
[ui]
|
||||
ssh = python "$TESTDIR/dummyssh"
|
||||
[infinitepush]
|
||||
|
@ -122,7 +122,7 @@ New errors are not allowed. Warnings are strongly discouraged.
|
||||
hgext/morestatus.py:48:
|
||||
> os.getcwd()) for path in unresolvedlist])
|
||||
use pycompat.getcwd instead (py3)
|
||||
hgext/phabstatus.py:78:
|
||||
hgext/phabstatus.py:80:
|
||||
> repodir=os.getcwd(), ca_bundle=ca_certs, repo=repo)
|
||||
use pycompat.getcwd instead (py3)
|
||||
hgext/tweakdefaults.py:275:
|
||||
@ -163,6 +163,9 @@ New errors are not allowed. Warnings are strongly discouraged.
|
||||
Skipping tests/comprehensive/test-hgsubversion-verify-and-startrev.py it has no-che?k-code (glob)
|
||||
Skipping tests/conduithttp.py it has no-che?k-code (glob)
|
||||
Skipping tests/fixtures/rsvn.py it has no-che?k-code (glob)
|
||||
tests/test-fb-hgext-infinitepush-pullbackup-markers.t:166:
|
||||
> $ sed -i s/createlandedasmarkers=True// $HGRCPATH
|
||||
don't use 'sed -i', use a temporary file
|
||||
Skipping tests/test-fb-hgext-remotefilelog-bad-configs.t it has no-che?k-code (glob)
|
||||
tests/test-hggit-git-submodules.t:61:
|
||||
> $ grep 'submodule "subrepo2"' -A2 .gitmodules > .gitmodules-new
|
||||
|
@ -110,18 +110,7 @@ outputs, which should be fixed later.
|
||||
hgext/infinitepush/__init__.py:137: direct symbol import encodelist, decodelist from mercurial.wireproto
|
||||
hgext/infinitepush/__init__.py:137: symbol import follows non-symbol import: mercurial.wireproto
|
||||
hgext/infinitepush/__init__.py:137: imports from mercurial.wireproto not lexically sorted: decodelist < encodelist
|
||||
hgext/infinitepush/backupcommands.py:52: direct symbol import getscratchbookmarkspart, getscratchbranchparts from hgext.infinitepush.bundleparts
|
||||
hgext/infinitepush/backupcommands.py:74: relative import of stdlib module
|
||||
hgext/infinitepush/backupcommands.py:74: direct symbol import defaultdict, namedtuple from collections
|
||||
hgext/infinitepush/backupcommands.py:74: symbol import follows non-symbol import: collections
|
||||
hgext/infinitepush/backupcommands.py:76: direct symbol import wrapfunction, unwrapfunction from mercurial.extensions
|
||||
hgext/infinitepush/backupcommands.py:76: symbol import follows non-symbol import: mercurial.extensions
|
||||
hgext/infinitepush/backupcommands.py:76: imports from mercurial.extensions not lexically sorted: unwrapfunction < wrapfunction
|
||||
hgext/infinitepush/backupcommands.py:77: symbol import follows non-symbol import: mercurial.node
|
||||
hgext/infinitepush/backupcommands.py:78: symbol import follows non-symbol import: mercurial.i18n
|
||||
hgext/infinitepush/backupcommands.py:82: relative import of stdlib module
|
||||
hgext/infinitepush/backupcommands.py:82: direct symbol import ConfigParser from ConfigParser
|
||||
hgext/infinitepush/backupcommands.py:82: symbol import follows non-symbol import: ConfigParser
|
||||
hgext/infinitepush/backupcommands.py:76: symbol import follows non-symbol import: mercurial.i18n
|
||||
hgext/infinitepush/infinitepushcommands.py:18: direct symbol import cmdtable from hgext.infinitepush.backupcommands
|
||||
hgext/infinitepush/infinitepushcommands.py:31: direct symbol import downloadbundle from hgext.infinitepush.common
|
||||
hgext/infinitepush/infinitepushcommands.py:31: symbol import follows non-symbol import: hgext.infinitepush.common
|
||||
|
@ -44,7 +44,9 @@ Now progressively test the response handling for variations of missing data
|
||||
> [{"data": {"query": [{"results": {"nodes": [{
|
||||
> "number": 1,
|
||||
> "diff_status_name": "Needs Review",
|
||||
> "differential_diffs": {"count": 3}
|
||||
> "differential_diffs": {"count": 3},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg diff --since-last-arc-diff
|
||||
@ -54,7 +56,9 @@ Now progressively test the response handling for variations of missing data
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [{
|
||||
> "number": 1,
|
||||
> "diff_status_name": "Needs Review"
|
||||
> "diff_status_name": "Needs Review",
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg diff --since-last-arc-diff
|
||||
@ -75,7 +79,9 @@ there is no diff since what was landed.
|
||||
> ]
|
||||
> }
|
||||
> },
|
||||
> "differential_diffs": {"count": 1}
|
||||
> "differential_diffs": {"count": 1},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg diff --since-last-arc-diff
|
||||
@ -96,7 +102,9 @@ assert that we order the commits consistently based on the time field.
|
||||
> ]
|
||||
> }
|
||||
> },
|
||||
> "differential_diffs": {"count": 1}
|
||||
> "differential_diffs": {"count": 1},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg diff --since-last-arc-diff --nodates
|
||||
|
212
tests/test-fb-hgext-infinitepush-pullbackup-markers.t
Normal file
212
tests/test-fb-hgext-infinitepush-pullbackup-markers.t
Normal file
@ -0,0 +1,212 @@
|
||||
$ . helpers-usechg.sh
|
||||
|
||||
$ . "$TESTDIR/library.sh"
|
||||
$ . "$TESTDIR/infinitepush/library.sh"
|
||||
$ setupcommon
|
||||
$ cat >> $HGRCPATH << EOF
|
||||
> [extensions]
|
||||
> arcconfig=$TESTDIR/../hgext/extlib/phabricator/arcconfig.py
|
||||
> smartlog=
|
||||
> pullcreatemarkers=
|
||||
> phabstatus=
|
||||
> [infinitepushbackup]
|
||||
> createlandedasmarkers=True
|
||||
> logdir=$TESTTMP/logs
|
||||
> [experimental]
|
||||
> evolution= createmarkers
|
||||
> EOF
|
||||
|
||||
$ mkcommit() {
|
||||
> echo "$1" > "$1"
|
||||
> hg add "$1"
|
||||
> echo "add $1" > msg
|
||||
> echo "" >> msg
|
||||
> url="https://phabricator.fb.com"
|
||||
> if [ -n "$3" ]; then
|
||||
> url="$3"
|
||||
> fi
|
||||
> [ -z "$2" ] || echo "Differential Revision: $url/D$2" >> msg
|
||||
> hg ci -l msg
|
||||
> }
|
||||
|
||||
$ echo '{}' > .arcrc
|
||||
$ echo '{"config" : {"default" : "https://a.com/api"}, "hosts" : {"https://a.com/api/" : { "user" : "testuser", "cert" : "garbage_cert"}}}' > .arcconfig
|
||||
|
||||
Setup server
|
||||
$ hg init repo
|
||||
$ cd repo
|
||||
$ setupserver
|
||||
$ cd ..
|
||||
|
||||
Set up server repository
|
||||
$ cd repo
|
||||
$ mkcommit initial
|
||||
$ mkcommit secondcommit
|
||||
$ hg book master
|
||||
$ cd ..
|
||||
|
||||
Set up clients repository
|
||||
|
||||
$ hg clone ssh://user@dummy/repo client -q
|
||||
$ hg clone ssh://user@dummy/repo otherclient -q
|
||||
|
||||
Add two commits, one "pushed" to differential
|
||||
$ cd otherclient
|
||||
$ hg up 0
|
||||
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
|
||||
$ mkcommit b 123
|
||||
$ mkcommit c
|
||||
|
||||
$ cd ..
|
||||
|
||||
Add commit which mimics previous differential one merged to master
|
||||
$ cd client
|
||||
$ hg up master
|
||||
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
(activating bookmark master)
|
||||
$ mkcommit b 123
|
||||
$ hg push --to master
|
||||
pushing to ssh://user@dummy/repo
|
||||
searching for changes
|
||||
remote: adding changesets
|
||||
remote: adding manifests
|
||||
remote: adding file changes
|
||||
remote: added 1 changesets with 1 changes to 1 files
|
||||
updating bookmark master
|
||||
|
||||
$ cd ..
|
||||
|
||||
Push all pulled commit to backup
|
||||
$ cd otherclient
|
||||
$ hg pull
|
||||
pulling from ssh://user@dummy/repo
|
||||
searching for changes
|
||||
adding changesets
|
||||
adding manifests
|
||||
adding file changes
|
||||
added 1 changesets with 0 changes to 1 files
|
||||
updating bookmark master
|
||||
new changesets 948715751816
|
||||
(run 'hg update' to get a working copy)
|
||||
obsoleted 1 changesets
|
||||
$ hg pushbackup --config extensions.lockfail=$TESTDIR/lockfail.py
|
||||
starting backup .* (re)
|
||||
searching for changes
|
||||
remote: pushing 2 commits:
|
||||
remote: 9b3ead1d8005 add b
|
||||
remote: 3969cd9723d1 add c
|
||||
finished in \d+\.(\d+)? seconds (re)
|
||||
|
||||
$ cd ..
|
||||
|
||||
Clone fresh repo and try to restore from backup
|
||||
$ hg clone ssh://user@dummy/repo frombackup -q
|
||||
$ cd frombackup
|
||||
$ hg sl --all
|
||||
@ changeset: 2:948715751816
|
||||
| bookmark: master
|
||||
~ tag: tip
|
||||
user: test
|
||||
date: Thu Jan 01 00:00:00 1970 +0000
|
||||
summary: add b
|
||||
(re)
|
||||
|
||||
$ NOW=`date +%s`
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [{
|
||||
> "number": 123,
|
||||
> "diff_status_name": "Closed",
|
||||
> "created_time": 0,
|
||||
> "updated_time": ${NOW}
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg pullbackup
|
||||
pulling from ssh://user@dummy/repo
|
||||
searching for changes
|
||||
adding changesets
|
||||
adding manifests
|
||||
adding file changes
|
||||
added 2 changesets with 1 changes to 2 files (+1 heads)
|
||||
new changesets 9b3ead1d8005:3969cd9723d1
|
||||
(run 'hg heads' to see heads, 'hg merge' to merge)
|
||||
obsoleted 1 changesets
|
||||
$ hg sl --all
|
||||
@ changeset: 2:948715751816
|
||||
: bookmark: master
|
||||
: user: test
|
||||
: date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: summary: add b
|
||||
:
|
||||
: o changeset: 4:3969cd9723d1
|
||||
: | tag: tip
|
||||
: | user: test
|
||||
: | date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: | instability: orphan
|
||||
: | summary: add c
|
||||
: |
|
||||
: x changeset: 3:9b3ead1d8005
|
||||
:/ parent: 0:c255e4a1ae9d
|
||||
: user: test
|
||||
: date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: obsolete: pruned
|
||||
: summary: add b
|
||||
:
|
||||
o changeset: 0:c255e4a1ae9d
|
||||
user: test
|
||||
date: Thu Jan 01 00:00:00 1970 +0000
|
||||
summary: add initial
|
||||
(re)
|
||||
$ hg debugobsolete
|
||||
9b3ead1d8005d305582e9d72eb8a4c8959873249 0 {c255e4a1ae9dd17d77787816cff012162a122798} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
|
||||
|
||||
$ cd ..
|
||||
|
||||
Test createlandedasmarkers option disabled
|
||||
$ rm -r frombackup
|
||||
$ sed -i s/createlandedasmarkers=True// $HGRCPATH
|
||||
$ hg clone ssh://user@dummy/repo frombackup -q
|
||||
$ cd frombackup
|
||||
|
||||
$ NOW=`date +%s`
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [{
|
||||
> "number": 123,
|
||||
> "diff_status_name": "Closed",
|
||||
> "created_time": 0,
|
||||
> "updated_time": ${NOW}
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg pullbackup
|
||||
pulling from ssh://user@dummy/repo
|
||||
searching for changes
|
||||
adding changesets
|
||||
adding manifests
|
||||
adding file changes
|
||||
added 2 changesets with 1 changes to 2 files (+1 heads)
|
||||
new changesets 9b3ead1d8005:3969cd9723d1
|
||||
(run 'hg heads' to see heads, 'hg merge' to merge)
|
||||
$ hg sl --all
|
||||
@ changeset: 2:948715751816
|
||||
: bookmark: master
|
||||
: user: test
|
||||
: date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: summary: add b
|
||||
:
|
||||
: o changeset: 4:3969cd9723d1
|
||||
: | tag: tip
|
||||
: | user: test
|
||||
: | date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: | summary: add c
|
||||
: |
|
||||
: o changeset: 3:9b3ead1d8005
|
||||
:/ parent: 0:c255e4a1ae9d
|
||||
: user: test
|
||||
: date: Thu Jan 01 00:00:00 1970 +0000
|
||||
: summary: add b
|
||||
:
|
||||
o changeset: 0:c255e4a1ae9d
|
||||
user: test
|
||||
date: Thu Jan 01 00:00:00 1970 +0000
|
||||
summary: add initial
|
||||
(re)
|
||||
$ hg debugobsolete
|
@ -60,7 +60,7 @@ And now with bad responses:
|
||||
Missing status field is treated as an error
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [
|
||||
> {"number": 1}
|
||||
> {"number": 1, "created_time": 0, "updated_time": 2}
|
||||
> ]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{phabstatus}\n' -r .
|
||||
@ -72,7 +72,8 @@ And finally, the success case
|
||||
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [
|
||||
> {"number": 1, "diff_status_name": "Needs Review"}
|
||||
> {"number": 1, "diff_status_name": "Needs Review",
|
||||
> "created_time": 0, "updated_time": 2}
|
||||
> ]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{phabstatus}\n' -r .
|
||||
@ -82,7 +83,8 @@ Make sure the code works without the smartlog extensions
|
||||
|
||||
$ cat > $TESTTMP/mockduit << EOF
|
||||
> [{"data": {"query": [{"results": {"nodes": [
|
||||
> {"number": 1, "diff_status_name": "Needs Review"}
|
||||
> {"number": 1, "diff_status_name": "Needs Review",
|
||||
> "created_time": 0, "updated_time": 2}
|
||||
> ]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg --config 'extensions.smartlog=!' log -T '{phabstatus}\n' -r .
|
||||
|
@ -53,7 +53,9 @@ Missing status field is treated as an error
|
||||
> ]
|
||||
> }
|
||||
> },
|
||||
> "differential_diffs": {"count": 3}
|
||||
> "differential_diffs": {"count": 3},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{syncstatus}\n' -r .
|
||||
@ -73,7 +75,9 @@ Missing count field is treated as an error
|
||||
> {"property_value": "{\"lolwut\": {\"time\": 0, \"commit\": \"lolwut\"}}"}
|
||||
> ]
|
||||
> }
|
||||
> }
|
||||
> },
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{syncstatus}\n' -r .
|
||||
@ -94,7 +98,9 @@ Missing hash field is treated as unsync
|
||||
> ]
|
||||
> }
|
||||
> },
|
||||
> "differential_diffs": {"count": 3}
|
||||
> "differential_diffs": {"count": 3},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{syncstatus}\n' -r .
|
||||
@ -113,7 +119,9 @@ And finally, the success case
|
||||
> ]
|
||||
> }
|
||||
> },
|
||||
> "differential_diffs": {"count": 3}
|
||||
> "differential_diffs": {"count": 3},
|
||||
> "created_time": 123,
|
||||
> "updated_time": 222
|
||||
> }]}}]}}]
|
||||
> EOF
|
||||
$ HG_ARC_CONDUIT_MOCK=$TESTTMP/mockduit hg log -T '{syncstatus}\n' -r .
|
||||
|
Loading…
Reference in New Issue
Block a user