sapling/edenscm/hgext/commitcloud/localservice.py
Liubov Dmitrieva 5e7afa31ff commit cloud / pushbackup - use the same way to check what is backedup with Mononoke and Mercurial
Summary:
Use the same way to check if the commits have been backed up in Mononoke and Mercurial.

The only common way to check is 'lookup' command because Mercurial doesn't support discovery for commit cloud commits, the command 'known' is also not supported.

Also we have to go one by one because lookup doesn't got any better API.
It is still much faster than backup commits that are already there.

Introduce such check for pushbackup as well.

Remove hacky way to check it from cloud sync.

For commit cloud in Mononoke we will have backfill, so the server side check  will be heavily used when you go to Mononoke at the first time.

Unfortunately connection pool module in mercurial is not good enough in detecting closed connections and can easily return a broken connection on the next call.

Reviewed By: markbt

Differential Revision: D14085849

fbshipit-source-id: d76d9a71f9efdbdfec4de3198cd428b6b693418d
2019-02-19 05:49:07 -08:00

138 lines
4.5 KiB
Python

# Copyright 2018 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
# Standard Library
import json
import os
from edenscm.mercurial import error
from . import baseservice, commitcloudcommon
class LocalService(baseservice.BaseService):
"""Local commit-cloud service implemented using files on disk.
There is no locking, so this is suitable only for use in unit tests.
"""
def __init__(self, ui):
self._ui = ui
self.path = ui.config("commitcloud", "servicelocation")
if not self.path or not os.path.isdir(self.path):
msg = "Invalid commitcloud.servicelocation: %s" % self.path
raise error.Abort(msg)
def _load(self):
filename = os.path.join(self.path, "commitcloudservicedb")
if os.path.exists(filename):
with open(filename) as f:
data = json.load(f)
return data
else:
return {"version": 0, "heads": [], "bookmarks": {}, "obsmarkers": {}}
def _save(self, data):
filename = os.path.join(self.path, "commitcloudservicedb")
with open(filename, "w") as f:
json.dump(data, f)
def _filteredobsmarkers(self, data, baseversion):
"""filter the obmarkers since the baseversion
This includes (baseversion, data[version]] obsmarkers
"""
versions = range(baseversion, data["version"])
data["new_obsmarkers_data"] = sum(
(data["obsmarkers"][str(n + 1)] for n in versions), []
)
del data["obsmarkers"]
return data
def _injectheaddates(self, data):
"""inject a head_dates field into the data"""
data["head_dates"] = {}
heads = set(data["heads"])
filename = os.path.join(self.path, "nodedata")
if os.path.exists(filename):
with open(filename) as f:
nodes = json.load(f)
for node in nodes:
if node["node"] in heads:
data["head_dates"][node["node"]] = node["date"][0]
return data
def requiresauthentication(self):
return False
def check(self):
return True
def getreferences(self, reponame, workspace, baseversion):
data = self._load()
version = data["version"]
if version == baseversion:
self._ui.debug(
"commitcloud local service: "
"get_references for current version %s\n" % version
)
return baseservice.References(version, None, None, None, None)
else:
self._ui.debug(
"commitcloud local service: "
"get_references for versions from %s to %s\n" % (baseversion, version)
)
data = self._filteredobsmarkers(data, baseversion)
data = self._injectheaddates(data)
return self._makereferences(data)
def updatereferences(
self,
reponame,
workspace,
version,
oldheads,
newheads,
oldbookmarks,
newbookmarks,
newobsmarkers,
):
data = self._load()
if version != data["version"]:
return False, self._makereferences(self._filteredobsmarkers(data, version))
newversion = data["version"] + 1
data["version"] = newversion
data["heads"] = newheads
data["bookmarks"] = newbookmarks
data["obsmarkers"][str(newversion)] = self._encodedmarkers(newobsmarkers)
self._ui.debug(
"commitcloud local service: "
"update_references to %s (%s heads, %s bookmarks)\n"
% (newversion, len(data["heads"]), len(data["bookmarks"]))
)
self._save(data)
return True, baseservice.References(newversion, None, None, None, None)
def getsmartlog(self, reponame, workspace, repo):
filename = os.path.join(self.path, "usersmartlogdata")
if not os.path.exists(filename):
nodes = {}
else:
with open(filename) as f:
data = json.load(f)
nodes = self._makenodes(data["smartlog"])
try:
return self._makefakedag(nodes, repo)
except Exception as e:
raise commitcloudcommon.UnexpectedError(self._ui, e)
def getbundles(self, reponame, heads):
"""Fetch bundles directly
"""
raise NotImplementedError