##// END OF EJS Templates
largefile: use the proper "mtime boundary" logic during fixup...
largefile: use the proper "mtime boundary" logic during fixup This will prevent ambiguous cache entry to be used in racy situation. This fix flakiness in test and some real live misbehavior. Differential Revision: https://phab.mercurial-scm.org/D11800

File last commit:

r48676:f5394669 stable
r49219:a96a5d62 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
Valentin Gatien-Baron
store: return just one filename in walk functions...
r48691 yield (t, d, 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):
Valentin Gatien-Baron
store: return just one filename in walk functions...
r48691 for (t, u, 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 ):
Valentin Gatien-Baron
store: return just one filename in walk functions...
r48691 yield (t, u, 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():
Valentin Gatien-Baron
store: return just one filename in walk functions...
r48691 for (t, u, 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):
Valentin Gatien-Baron
store: return just one filename in walk functions...
r48691 yield (t, u, s)
Augie Fackler
remotefilelog: import pruned-down remotefilelog extension from hg-experimental...
r40530
for x in repo.store.topfiles():
Valentin Gatien-Baron
remotefilelog: fix what looks like a wrong refactoring...
r48601 if state.noflatmf and x[1][: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()