mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 23:07:18 +03:00
commitcloud: sync obsmarkers
Summary: Add obsmarkers to the things that are synced. For the LocalService, obsmarkers are stored base64-encoded using version 1 of the obsmarker binary format. This is sufficient for unit tests. Differential Revision: D7181399 fbshipit-source-id: 61377105986de561622a160134d20fdbd54bb88f
This commit is contained in:
parent
6660438ea2
commit
4cea23b3a9
@ -19,6 +19,35 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from mercurial import (
|
||||
obsolete,
|
||||
util,
|
||||
)
|
||||
|
||||
from . import commitcloudcommands
|
||||
|
||||
cmdtable = commitcloudcommands.cmdtable
|
||||
|
||||
def reposetup(ui, repo):
|
||||
def finalize(tr):
|
||||
if util.safehasattr(tr, '_commitcloudskippendingobsmarkers'):
|
||||
return
|
||||
markers = tr.changes['obsmarkers']
|
||||
if markers:
|
||||
f = tr.opener('commitcloudpendingobsmarkers', 'ab')
|
||||
try:
|
||||
offset = f.tell()
|
||||
tr.add('commitcloudpendingobsmarkers', offset)
|
||||
# offset == 0: new file - add the version header
|
||||
data = b''.join(obsolete.encodemarkers(markers, offset == 0,
|
||||
obsolete._fm1version))
|
||||
f.write(data)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
class commitcloudrepo(repo.__class__):
|
||||
def transaction(self, *args, **kwargs):
|
||||
tr = super(commitcloudrepo, self).transaction(*args, **kwargs)
|
||||
tr.addfinalize('commitcloudobsmarkers', finalize)
|
||||
return tr
|
||||
repo.__class__ = commitcloudrepo
|
||||
|
@ -13,6 +13,7 @@ from mercurial.i18n import _
|
||||
from mercurial import (
|
||||
commands,
|
||||
node,
|
||||
obsolete,
|
||||
registrar,
|
||||
)
|
||||
|
||||
@ -47,12 +48,18 @@ def cloudsync(ui, repo, **opts):
|
||||
if not synced:
|
||||
# The local repo has changed. We must send these changes to the
|
||||
# cloud.
|
||||
obsmarkers = []
|
||||
if repo.svfs.exists('commitcloudpendingobsmarkers'):
|
||||
with repo.svfs.open('commitcloudpendingobsmarkers') as f:
|
||||
_version, obsmarkers = obsolete._readmarkers(f.read())
|
||||
synced, cloudrefs = serv.updatereferences(
|
||||
lastsyncstate.version, lastsyncstate.heads, localheads,
|
||||
lastsyncstate.bookmarks, localbookmarks)
|
||||
lastsyncstate.bookmarks, localbookmarks, obsmarkers)
|
||||
if synced:
|
||||
lastsyncstate.update(cloudrefs.version, localheads,
|
||||
localbookmarks)
|
||||
if obsmarkers:
|
||||
repo.svfs.unlink('commitcloudpendingobsmarkers')
|
||||
|
||||
def _applycloudchanges(ui, repo, lastsyncstate, cloudrefs):
|
||||
pullcmd, pullopts = _getcommandandoptions('^pull')
|
||||
@ -64,6 +71,9 @@ def _applycloudchanges(ui, repo, lastsyncstate, cloudrefs):
|
||||
# Merge cloud bookmarks into the repo
|
||||
_mergebookmarks(ui, repo, cloudrefs.bookmarks, lastsyncstate.bookmarks)
|
||||
|
||||
# Merge obsmarkers
|
||||
_mergeobsmarkers(ui, repo, cloudrefs.obsmarkers)
|
||||
|
||||
# We have now synced the repo to the cloud version. Store this.
|
||||
lastsyncstate.update(cloudrefs.version, cloudrefs.heads,
|
||||
cloudrefs.bookmarks)
|
||||
@ -107,6 +117,11 @@ def _mergebookmarks(ui, repo, cloudbookmarks, lastsyncbookmarks):
|
||||
changes.append((name, None))
|
||||
repo._bookmarks.applychanges(repo, tr, changes)
|
||||
|
||||
def _mergeobsmarkers(ui, repo, obsmarkers):
|
||||
with repo.wlock(), repo.lock(), repo.transaction('commitcloud-obs') as tr:
|
||||
tr._commitcloudskippendingobsmarkers = True
|
||||
repo.obsstore.add(tr, obsmarkers)
|
||||
|
||||
def _forkname(ui, name, othernames):
|
||||
hostname = ui.config('commitcloud', 'hostname', socket.gethostname())
|
||||
|
||||
|
@ -5,15 +5,18 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import base64
|
||||
import collections
|
||||
import json
|
||||
import os
|
||||
|
||||
from mercurial import (
|
||||
error,
|
||||
obsolete,
|
||||
)
|
||||
|
||||
References = collections.namedtuple('References', 'version heads bookmarks')
|
||||
References = collections.namedtuple('References',
|
||||
'version heads bookmarks obsmarkers')
|
||||
|
||||
class LocalService(object):
|
||||
"""Local commit-cloud service implemented using files on disk.
|
||||
@ -42,13 +45,18 @@ class LocalService(object):
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(data, f)
|
||||
|
||||
def _makereferences(self, data):
|
||||
def _makereferences(self, data, baseversion):
|
||||
"""Makes a References object from JSON data"""
|
||||
version = data['version']
|
||||
newheads = [h.encode() for h in data['heads']]
|
||||
newbookmarks = {n.encode('utf-8'): v.encode()
|
||||
for n, v in data['bookmarks'].items()}
|
||||
return References(version, newheads, newbookmarks)
|
||||
encobsmarkers = sum((data['obsmarkers'][str(n + 1)]
|
||||
for n in range(baseversion, version)), [])
|
||||
decobsmarkers = b''.join([base64.b64decode(m) for m in encobsmarkers])
|
||||
obsmarkers = obsolete._fm1readmarkers(decobsmarkers,
|
||||
0, len(decobsmarkers))
|
||||
return References(version, newheads, newbookmarks, obsmarkers)
|
||||
|
||||
def getreferences(self, baseversion):
|
||||
"""Gets the current references if they differ from the base version
|
||||
@ -59,16 +67,16 @@ class LocalService(object):
|
||||
self._ui.debug(
|
||||
'commitcloud local service: '
|
||||
'get_references for current version %s\n' % version)
|
||||
return References(version, None, None)
|
||||
return References(version, None, None, None)
|
||||
else:
|
||||
self._ui.debug(
|
||||
'commitcloud local service: '
|
||||
'get_references for versions from %s to %s\n'
|
||||
% (baseversion, version))
|
||||
return self._makereferences(data)
|
||||
return self._makereferences(data, baseversion)
|
||||
|
||||
def updatereferences(self, version, oldheads, newheads, oldbookmarks,
|
||||
newbookmarks):
|
||||
newbookmarks, newobsmarkers):
|
||||
"""Updates the references to a new version.
|
||||
|
||||
If the update was successful, returns `(True, references)`, where
|
||||
@ -80,16 +88,21 @@ class LocalService(object):
|
||||
"""
|
||||
data = self._load()
|
||||
if version != data['version']:
|
||||
return False, self._makereferences(data)
|
||||
data['version'] = data['version'] + 1
|
||||
return False, self._makereferences(data, version)
|
||||
newversion = data['version'] + 1
|
||||
data['version'] = newversion
|
||||
data['heads'] = newheads
|
||||
data['bookmarks'] = newbookmarks
|
||||
encodedmarkers = [base64.b64encode(m)
|
||||
for m in obsolete.encodemarkers(newobsmarkers, False,
|
||||
obsolete._fm1version)]
|
||||
data['obsmarkers'][str(newversion)] = encodedmarkers
|
||||
self._ui.debug(
|
||||
'commitcloud local service: '
|
||||
'update_references to %s (%s heads, %s bookmarks)\n'
|
||||
% (data['version'], len(data['heads']), len(data['bookmarks'])))
|
||||
% (newversion, len(data['heads']), len(data['bookmarks'])))
|
||||
self._save(data)
|
||||
return True, References(data['version'], None, None)
|
||||
return True, References(newversion, None, None, None)
|
||||
|
||||
def get(ui):
|
||||
servicetype = ui.config('commitcloud', 'servicetype')
|
||||
|
@ -1,5 +1,6 @@
|
||||
$ cat >> $HGRCPATH << EOF
|
||||
> [extensions]
|
||||
> fbamend =
|
||||
> infinitepush =
|
||||
> commitcloud =
|
||||
> [ui]
|
||||
@ -10,6 +11,8 @@
|
||||
> hostname = testhost
|
||||
> [alias]
|
||||
> tglog = log -G --template "{node|short} '{desc}' {bookmarks}\n"
|
||||
> [experimental]
|
||||
> evolution = createmarkers, allowunstable
|
||||
> EOF
|
||||
|
||||
$ mkcommit() {
|
||||
@ -142,3 +145,40 @@ Move the bookmark also on the first client, it should be forked in the sync
|
||||
o d20a80d4def3 'base'
|
||||
|
||||
$ cd ..
|
||||
|
||||
Amend a commit
|
||||
$ cd client1
|
||||
$ echo more >> commit1
|
||||
$ hg amend --rebase -m "commit1 amended"
|
||||
rebasing 2:02f6fc2b7154 "commit2" (bookmark1)
|
||||
$ hg pushbackup -q
|
||||
$ hg cloudsync
|
||||
$ hg tglog
|
||||
o 48610b1a7ec0 'commit2' bookmark1
|
||||
|
|
||||
@ a7bb357e7299 'commit1 amended' bookmark1-testhost
|
||||
|
|
||||
o d20a80d4def3 'base'
|
||||
|
||||
$ cd ..
|
||||
|
||||
Sync the amended commit to the other client
|
||||
$ cd client2
|
||||
$ hg cloudsync
|
||||
pulling from ssh://user@dummy/server
|
||||
searching for changes
|
||||
adding changesets
|
||||
adding manifests
|
||||
adding file changes
|
||||
added 2 changesets with 1 changes to 2 files (+1 heads)
|
||||
new changesets a7bb357e7299:48610b1a7ec0
|
||||
(run 'hg heads' to see heads, 'hg merge' to merge)
|
||||
$ hg up -q tip
|
||||
$ hg tglog
|
||||
@ 48610b1a7ec0 'commit2' bookmark1
|
||||
|
|
||||
o a7bb357e7299 'commit1 amended' bookmark1-testhost
|
||||
|
|
||||
o d20a80d4def3 'base'
|
||||
|
||||
$ test ! -f .hg/store/commitcloudpendingobsmarkers
|
||||
|
Loading…
Reference in New Issue
Block a user