##// END OF EJS Templates
remotefilelog: stop using RuntimeError for control flow...
remotefilelog: stop using RuntimeError for control flow We introduce a new exception to handle the various failure categories, rather than relying on RuntimeError. Differential Revision: https://phab.mercurial-scm.org/D11006

File last commit:

r47758:07b9ebea default
r48344:e9720776 default
Show More
remotefilelogserver.py
441 lines | 14.2 KiB | text/x-python | PythonLexer
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 # remotefilelogserver.py - server logic for a remotefilelog server
#
# Copyright 2013 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
import errno
import os
import stat
import time
Augie Fackler
remotefilelog: rip out lz4 support...
r40542 import zlib
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
from mercurial.i18n import _
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 from mercurial.node import bin, hex
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from mercurial.pycompat import open
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 from mercurial import (
changegroup,
changelog,
context,
error,
extensions,
match,
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 pycompat,
Pulkit Goyal
scmutil: introduce function to check whether repo uses treemanifest or not...
r46129 scmutil,
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 store,
streamclone,
util,
wireprotoserver,
wireprototypes,
wireprotov1server,
)
Augie Fackler
formatting: blacken the codebase...
r43346 from . import (
Augie Fackler
remotefilelog: rename capability for legacy ssh file fetching method...
r40543 constants,
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 shallowutil,
)
_sshv1server = wireprotoserver.sshv1protocolhandler
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def setupserver(ui, repo):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Sets up a normal Mercurial repo so it can serve files to shallow repos."""
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 onetimesetup(ui)
# don't send files to shallow clients during pulls
Augie Fackler
formatting: blacken the codebase...
r43346 def generatefiles(
orig, self, changedfiles, linknodes, commonrevs, source, *args, **kwargs
):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 caps = self._bundlecaps or []
Augie Fackler
remotefilelog: consolidate and rename bundle2 capability...
r40544 if constants.BUNDLE2_CAPABLITY in caps:
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 # only send files that don't match the specified patterns
includepattern = None
excludepattern = None
Augie Fackler
formatting: blacken the codebase...
r43346 for cap in self._bundlecaps or []:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cap.startswith(b"includepattern="):
includepattern = cap[len(b"includepattern=") :].split(b'\0')
elif cap.startswith(b"excludepattern="):
excludepattern = cap[len(b"excludepattern=") :].split(b'\0')
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 m = match.always()
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if includepattern or excludepattern:
Augie Fackler
formatting: blacken the codebase...
r43346 m = match.match(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.root, b'', None, includepattern, excludepattern
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
changedfiles = list([f for f in changedfiles if not m(f)])
Augie Fackler
formatting: blacken the codebase...
r43346 return orig(
self, changedfiles, linknodes, commonrevs, source, *args, **kwargs
)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
extensions.wrapfunction(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changegroup.cgpacker, b'generatefiles', generatefiles
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
onetime = False
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def onetimesetup(ui):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Configures the wireprotocol for both clients and servers."""
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 global onetime
if onetime:
return
onetime = True
# support file content requests
wireprotov1server.wireprotocommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'x_rfl_getflogheads', b'path', permission=b'pull'
Augie Fackler
formatting: blacken the codebase...
r43346 )(getflogheads)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 wireprotov1server.wireprotocommand(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'x_rfl_getfiles', b'', permission=b'pull'
)(getfiles)
wireprotov1server.wireprotocommand(
b'x_rfl_getfile', b'file node', permission=b'pull'
Augie Fackler
formatting: blacken the codebase...
r43346 )(getfile)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
class streamstate(object):
match = None
shallowremote = False
noflatmf = False
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 state = streamstate()
def stream_out_shallow(repo, proto, other):
includepattern = None
excludepattern = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raw = other.get(b'includepattern')
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if raw:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 includepattern = raw.split(b'\0')
raw = other.get(b'excludepattern')
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if raw:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 excludepattern = raw.split(b'\0')
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
oldshallow = state.shallowremote
oldmatch = state.match
oldnoflatmf = state.noflatmf
try:
state.shallowremote = True
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 state.match = match.always()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state.noflatmf = other.get(b'noflatmanifest') == b'True'
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if includepattern or excludepattern:
Augie Fackler
formatting: blacken the codebase...
r43346 state.match = match.match(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.root, b'', None, includepattern, excludepattern
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 streamres = wireprotov1server.stream(repo, proto)
# Force the first value to execute, so the file list is computed
# within the try/finally scope
first = next(streamres.gen)
second = next(streamres.gen)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def gen():
yield first
yield second
for value in streamres.gen:
yield value
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return wireprototypes.streamres(gen())
finally:
state.shallowremote = oldshallow
state.match = oldmatch
state.noflatmf = oldnoflatmf
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 wireprotov1server.commands[b'stream_out_shallow'] = (
stream_out_shallow,
b'*',
)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
# don't clone filelogs to shallow clients
Pulkit Goyal
remotefilelogserver: add a matcher argument to _walkstreamfiles()...
r40550 def _walkstreamfiles(orig, repo, matcher=None):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if state.shallowremote:
# if we are shallow ourselves, stream our local commits
Pulkit Goyal
shallowutil: introduce a helper function isenabled()...
r40549 if shallowutil.isenabled(repo):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 striplen = len(repo.store.path) + 1
readdir = repo.store.rawvfs.readdir
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 visit = [os.path.join(repo.store.path, b'data')]
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 while visit:
p = visit.pop()
for f, kind, st in readdir(p, stat=True):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fp = p + b'/' + f
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if kind == stat.S_IFREG:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not fp.endswith(b'.i') and not fp.endswith(
b'.d'
):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 n = util.pconvert(fp[striplen:])
store: also return some information about the type of file `walk` found...
r47657 d = store.decodedir(n)
t = store.FILETYPE_OTHER
yield (t, d, n, st.st_size)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if kind == stat.S_IFDIR:
visit.append(fp)
Pulkit Goyal
scmutil: introduce function to check whether repo uses treemanifest or not...
r46129 if scmutil.istreemanifest(repo):
store: also return some information about the type of file `walk` found...
r47657 for (t, u, e, s) in repo.store.datafiles():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if u.startswith(b'meta/') and (
u.endswith(b'.i') or u.endswith(b'.d')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
store: also return some information about the type of file `walk` found...
r47657 yield (t, u, e, s)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
# Return .d and .i files that do not match the shallow pattern
match = state.match
if match and not match.always():
store: also return some information about the type of file `walk` found...
r47657 for (t, u, e, s) in repo.store.datafiles():
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 f = u[5:-2] # trim data/... and .i/.d
if not state.match(f):
store: also return some information about the type of file `walk` found...
r47657 yield (t, u, e, s)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
for x in repo.store.topfiles():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if state.noflatmf and x[0][:11] == b'00manifest.':
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 continue
yield x
Pulkit Goyal
shallowutil: introduce a helper function isenabled()...
r40549 elif shallowutil.isenabled(repo):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 # don't allow cloning from a shallow repo to a full repo
# since it would require fetching every version of every
# file in order to create the revlogs.
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"Cannot clone from a shallow repo to a full repo.")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 else:
Pulkit Goyal
remotefilelogserver: add a matcher argument to _walkstreamfiles()...
r40550 for x in orig(repo, matcher):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 yield x
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.wrapfunction(streamclone, b'_walkstreamfiles', _walkstreamfiles)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
# expose remotefilelog capabilities
def _capabilities(orig, repo, proto):
caps = orig(repo, proto)
Augie Fackler
formatting: blacken the codebase...
r43346 if shallowutil.isenabled(repo) or ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'remotefilelog', b'server'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if isinstance(proto, _sshv1server):
# legacy getfiles method which only works over ssh
Augie Fackler
remotefilelog: rename capability for legacy ssh file fetching method...
r40543 caps.append(constants.NETWORK_CAP_LEGACY_SSH_GETFILES)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 caps.append(b'x_rfl_getflogheads')
caps.append(b'x_rfl_getfile')
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return caps
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.wrapfunction(wireprotov1server, b'_capabilities', _capabilities)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
def _adjustlinkrev(orig, self, *args, **kwargs):
# When generating file blobs, taking the real path is too slow on large
# repos, so force it to just return the linkrev directly.
repo = self._repo
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(repo, b'forcelinkrev') and repo.forcelinkrev:
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return self._filelog.linkrev(self._filelog.rev(self._filenode))
return orig(self, *args, **kwargs)
extensions.wrapfunction(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 context.basefilectx, b'_adjustlinkrev', _adjustlinkrev
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
def _iscmd(orig, cmd):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmd == b'x_rfl_getfiles':
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return False
return orig(cmd)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.wrapfunction(wireprotoserver, b'iscmd', _iscmd)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def _loadfileblob(repo, cachepath, path, node):
filecachepath = os.path.join(cachepath, path, hex(node))
if not os.path.exists(filecachepath) or os.path.getsize(filecachepath) == 0:
filectx = repo.filectx(path, fileid=node)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if filectx.node() == repo.nullid:
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 repo.changelog = changelog.changelog(repo.svfs)
filectx = repo.filectx(path, fileid=node)
text = createfileblob(filectx)
Augie Fackler
remotefilelog: rip out lz4 support...
r40542 # TODO configurable compression engines
text = zlib.compress(text)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
# everything should be user & group read/writable
oldumask = os.umask(0o002)
try:
dirname = os.path.dirname(filecachepath)
if not os.path.exists(dirname):
try:
os.makedirs(dirname)
except OSError as ex:
if ex.errno != errno.EEXIST:
raise
f = None
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = util.atomictempfile(filecachepath, b"wb")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 f.write(text)
except (IOError, OSError):
# Don't abort if the user only has permission to read,
# and not write.
pass
finally:
if f:
f.close()
finally:
os.umask(oldumask)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(filecachepath, b"rb") as f:
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 text = f.read()
return text
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def getflogheads(repo, proto, path):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """A server api for requesting a filelog's heads"""
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 flog = repo.file(path)
heads = flog.heads()
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 return b'\n'.join((hex(head) for head in heads if head != repo.nullid))
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def getfile(repo, proto, file, node):
"""A server api for requesting a particular version of a file. Can be used
in batches to request many files at once. The return protocol is:
<errorcode>\0<data/errormsg> where <errorcode> is 0 for success or
non-zero for an error.
data is a compressed blob with revlog flag and ancestors information. See
createfileblob for its content.
"""
Pulkit Goyal
shallowutil: introduce a helper function isenabled()...
r40549 if shallowutil.isenabled(repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'1\0' + _(b'cannot fetch remote files from shallow repo')
cachepath = repo.ui.config(b"remotefilelog", b"servercachepath")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if not cachepath:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachepath = os.path.join(repo.path, b"remotefilelogcache")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 node = bin(node.strip())
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if node == repo.nullid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'0\0'
return b'0\0' + _loadfileblob(repo, cachepath, file, node)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def getfiles(repo, proto):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """A server api for requesting particular versions of particular files."""
Pulkit Goyal
shallowutil: introduce a helper function isenabled()...
r40549 if shallowutil.isenabled(repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot fetch remote files from shallow repo'))
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if not isinstance(proto, _sshv1server):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot fetch remote files over non-ssh protocol'))
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
def streamer():
fin = proto._fin
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachepath = repo.ui.config(b"remotefilelog", b"servercachepath")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if not cachepath:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachepath = os.path.join(repo.path, b"remotefilelogcache")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
while True:
request = fin.readline()[:-1]
if not request:
break
node = bin(request[:40])
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if node == repo.nullid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'0\n'
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 continue
path = request[40:]
text = _loadfileblob(repo, cachepath, path, node)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'%d\n%s' % (len(text), text)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
# it would be better to only flush after processing a whole batch
# but currently we don't know if there are more requests coming
proto._fout.flush()
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return wireprototypes.streamres(streamer())
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def createfileblob(filectx):
"""
format:
v0:
str(len(rawtext)) + '\0' + rawtext + ancestortext
v1:
'v1' + '\n' + metalist + '\0' + rawtext + ancestortext
metalist := metalist + '\n' + meta | meta
meta := sizemeta | flagmeta
sizemeta := METAKEYSIZE + str(len(rawtext))
flagmeta := METAKEYFLAG + str(flag)
note: sizemeta must exist. METAKEYFLAG and METAKEYSIZE must have a
length of 1.
"""
flog = filectx.filelog()
frev = filectx.filerev()
revlogflags = flog._revlog.flags(frev)
if revlogflags == 0:
# normal files
text = filectx.data()
else:
# lfs, read raw revision data
rawdata: update caller in remotefilelog...
r43039 text = flog.rawdata(frev)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
repo = filectx._repo
ancestors = [filectx]
try:
repo.forcelinkrev = True
ancestors.extend([f for f in filectx.ancestors()])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ancestortext = b""
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 for ancestorctx in ancestors:
parents = ancestorctx.parents()
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 p1 = repo.nullid
p2 = repo.nullid
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if len(parents) > 0:
p1 = parents[0].filenode()
if len(parents) > 1:
p2 = parents[1].filenode()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 copyname = b""
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 rename = ancestorctx.renamed()
if rename:
copyname = rename[0]
linknode = ancestorctx.node()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ancestortext += b"%s%s%s%s%s\0" % (
Augie Fackler
formatting: blacken the codebase...
r43346 ancestorctx.filenode(),
p1,
p2,
linknode,
copyname,
)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 finally:
repo.forcelinkrev = False
header = shallowutil.buildfileblobheader(len(text), revlogflags)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"%s\0%s%s" % (header, text, ancestortext)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 def gcserver(ui, repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.ui.configbool(b"remotefilelog", b"server"):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 return
neededfiles = set()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 heads = repo.revs(b"heads(tip~25000:) - null")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachepath = repo.vfs.join(b"remotefilelogcache")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 for head in heads:
mf = repo[head].manifest()
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for filename, filenode in pycompat.iteritems(mf):
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 filecachepath = os.path.join(cachepath, filename, hex(filenode))
neededfiles.add(filecachepath)
# delete unneeded older files
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 days = repo.ui.configint(b"remotefilelog", b"serverexpiration")
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 expiration = time.time() - (days * 24 * 60 * 60)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 progress = ui.makeprogress(_(b"removing old server cache"), unit=b"files")
Martin von Zweigbergk
remotefilelog: use progress helper in remotefilelogserver...
r40877 progress.update(0)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 for root, dirs, files in os.walk(cachepath):
for file in files:
filepath = os.path.join(root, file)
Martin von Zweigbergk
remotefilelog: use progress helper in remotefilelogserver...
r40877 progress.increment()
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530 if filepath in neededfiles:
continue
stat = os.stat(filepath)
if stat.st_mtime < expiration:
os.remove(filepath)
Martin von Zweigbergk
remotefilelog: use progress helper in remotefilelogserver...
r40877 progress.complete()