##// END OF EJS Templates
showstack: add an extension docstring...
showstack: add an extension docstring Now, running `hg help showstack` will give details on how to use the extension.

File last commit:

r35636:c780e064 default
r35674:c9eb92fb default
Show More
__init__.py
233 lines | 7.5 KiB | text/x-python | PythonLexer
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 # lfs - hash-preserving large file support using Git-LFS protocol
#
# Copyright 2017 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.
"""lfs - large file support (EXPERIMENTAL)
Configs::
[lfs]
# Remote endpoint. Multiple protocols are supported:
# - http(s)://user:pass@example.com/path
# git-lfs endpoint
# - file:///tmp/path
# local filesystem, usually for testing
# if unset, lfs will prompt setting this when it must use this value.
# (default: unset)
url = https://example.com/lfs
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 # Which files to track in LFS. Path tests are "**.extname" for file
# extensions, and "path:under/some/directory" for path prefix. Both
# are relative to the repository root, and the latter must be quoted.
# File size can be tested with the "size()" fileset, and tests can be
# joined with fileset operators. (See "hg help filesets.operators".)
#
# Some examples:
# - all() # everything
# - none() # nothing
# - size(">20MB") # larger than 20MB
# - !**.txt # anything not a *.txt file
# - **.zip | **.tar.gz | **.7z # some types of compressed files
# - "path:bin" # files under "bin" in the project root
# - (**.php & size(">2MB")) | (**.js & size(">5MB")) | **.tar.gz
# | ("path:bin" & !"path:/bin/README") | size(">1GB")
# (default: none())
track = size(">10M")
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097
# how many times to retry before giving up on transferring an object
retry = 5
Matt Harbison
lfs: introduce a user level cache for lfs files...
r35281
# the local directory to store lfs files for sharing across local clones.
# If not set, the cache is located in an OS specific cache location.
usercache = /path/to/global/cache
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 """
from __future__ import absolute_import
Matt Harbison
lfs: quiesce check-module-import warnings...
r35098 from mercurial.i18n import _
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 from mercurial import (
bundle2,
changegroup,
context,
exchange,
extensions,
filelog,
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 fileset,
Matt Harbison
lfs: enable the extension locally after cloning a repo with 'lfs' requirement...
r35214 hg,
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167 localrepo,
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 minifileset,
Matt Harbison
lfs: add the 'lfs' requirement in the changegroup transaction introducing lfs...
r35520 node,
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 registrar,
revlog,
scmutil,
Boris Feld
lfs: allow to run 'debugupgraderepo' on repo with largefiles...
r35347 upgrade,
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 vfs as vfsmod,
Matt Harbison
lfs: show a friendly message when pushing lfs to a server without lfs enabled...
r35522 wireproto,
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 )
from . import (
blobstore,
wrapper,
)
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
testedwith = 'ships-with-hg-core'
Matt Harbison
lfs: register config options...
r35099 configtable = {}
configitem = registrar.configitem(configtable)
Matt Harbison
lfs: add an experimental config to override User-Agent for the blob transfer...
r35456 configitem('experimental', 'lfs.user-agent',
default=None,
)
Matt Harbison
lfs: register config options...
r35099 configitem('lfs', 'url',
Matt Harbison
lfs: drop deprecated remote store config options...
r35632 default=None,
Matt Harbison
lfs: register config options...
r35099 )
Matt Harbison
lfs: introduce a user level cache for lfs files...
r35281 configitem('lfs', 'usercache',
default=None,
)
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 # Deprecated
Matt Harbison
lfs: register config options...
r35099 configitem('lfs', 'threshold',
default=None,
)
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 configitem('lfs', 'track',
default='none()',
)
Matt Harbison
lfs: register config options...
r35099 configitem('lfs', 'retry',
default=5,
)
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 cmdtable = {}
command = registrar.command(cmdtable)
templatekeyword = registrar.templatekeyword()
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167 def featuresetup(ui, supported):
# don't die on seeing a repo with the lfs requirement
supported |= {'lfs'}
def uisetup(ui):
localrepo.localrepository.featuresetupfuncs.add(featuresetup)
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 def reposetup(ui, repo):
# Nothing to do with a remote repo
if not repo.local():
return
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 trackspec = repo.ui.config('lfs', 'track')
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097
Matt Harbison
lfs: migrate most file filtering from threshold to custom filter...
r35636 # deprecated config: lfs.threshold
threshold = repo.ui.configbytes('lfs', 'threshold')
if threshold:
fileset.parse(trackspec) # make sure syntax errors are confined
trackspec = "(%s) | size('>%d')" % (trackspec, threshold)
repo.svfs.options['lfstrack'] = minifileset.compile(trackspec)
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 repo.svfs.lfslocalblobstore = blobstore.local(repo)
repo.svfs.lfsremoteblobstore = blobstore.remote(repo)
# Push hook
repo.prepushoutgoinghooks.add('lfs', wrapper.prepush)
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167 if 'lfs' not in repo.requirements:
def checkrequireslfs(ui, repo, **kwargs):
if 'lfs' not in repo.requirements:
Matt Harbison
lfs: add the 'lfs' requirement in the changegroup transaction introducing lfs...
r35520 last = kwargs.get('node_last')
_bin = node.bin
if last:
s = repo.set('%n:%n', _bin(kwargs['node']), _bin(last))
else:
s = repo.set('%n', _bin(kwargs['node']))
for ctx in s:
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167 # TODO: is there a way to just walk the files in the commit?
Jun Wu
lfs: fix committing deleted files caused by e0a1b9ee93cd...
r35468 if any(ctx[f].islfs() for f in ctx.files() if f in ctx):
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167 repo.requirements.add('lfs')
repo._writerequirements()
Matt Harbison
lfs: add the 'lfs' requirement in the changegroup transaction introducing lfs...
r35520 break
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167
ui.setconfig('hooks', 'commit.lfs', checkrequireslfs, 'lfs')
Matt Harbison
lfs: add the 'lfs' requirement in the changegroup transaction introducing lfs...
r35520 ui.setconfig('hooks', 'pretxnchangegroup.lfs', checkrequireslfs, 'lfs')
Matt Harbison
lfs: add a repo requirement for this extension once an lfs file is committed...
r35167
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 def wrapfilelog(filelog):
wrapfunction = extensions.wrapfunction
wrapfunction(filelog, 'addrevision', wrapper.filelogaddrevision)
wrapfunction(filelog, 'renamed', wrapper.filelogrenamed)
wrapfunction(filelog, 'size', wrapper.filelogsize)
def extsetup(ui):
wrapfilelog(filelog.filelog)
wrapfunction = extensions.wrapfunction
Matt Harbison
lfs: add a repo requirement for this extension when converting to lfs...
r35170
wrapfunction(scmutil, 'wrapconvertsink', wrapper.convertsink)
Matt Harbison
lfs: restore the local blob store after a repo upgrade...
r35364 wrapfunction(upgrade, '_finishdatamigration',
wrapper.upgradefinishdatamigration)
Boris Feld
lfs: allow to run 'debugupgraderepo' on repo with largefiles...
r35347 wrapfunction(upgrade, 'preservedrequirements',
wrapper.upgraderequirements)
wrapfunction(upgrade, 'supporteddestrequirements',
wrapper.upgraderequirements)
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 wrapfunction(changegroup,
'supportedoutgoingversions',
wrapper.supportedoutgoingversions)
wrapfunction(changegroup,
'allsupportedversions',
wrapper.allsupportedversions)
Matt Harbison
lfs: show a friendly message when pushing lfs to a server without lfs enabled...
r35522 wrapfunction(exchange, 'push', wrapper.push)
wrapfunction(wireproto, '_capabilities', wrapper._capabilities)
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 wrapfunction(context.basefilectx, 'cmp', wrapper.filectxcmp)
wrapfunction(context.basefilectx, 'isbinary', wrapper.filectxisbinary)
context.basefilectx.islfs = wrapper.filectxislfs
revlog.addflagprocessor(
revlog.REVIDX_EXTSTORED,
(
wrapper.readfromstore,
wrapper.writetostore,
wrapper.bypasscheckhash,
),
)
Matt Harbison
lfs: enable the extension locally after cloning a repo with 'lfs' requirement...
r35214 wrapfunction(hg, 'clone', wrapper.hgclone)
Matt Harbison
lfs: enable the extension locally after sharing a repo with 'lfs' requirement...
r35215 wrapfunction(hg, 'postshare', wrapper.hgpostshare)
Matt Harbison
lfs: enable the extension locally after cloning a repo with 'lfs' requirement...
r35214
Matt Harbison
lfs: import the Facebook git-lfs client extension...
r35097 # Make bundle choose changegroup3 instead of changegroup2. This affects
# "hg bundle" command. Note: it does not cover all bundle formats like
# "packed1". Using "packed1" with lfs will likely cause trouble.
names = [k for k, v in exchange._bundlespeccgversions.items() if v == '02']
for k in names:
exchange._bundlespeccgversions[k] = '03'
# bundlerepo uses "vfsmod.readonlyvfs(othervfs)", we need to make sure lfs
# options and blob stores are passed from othervfs to the new readonlyvfs.
wrapfunction(vfsmod.readonlyvfs, '__init__', wrapper.vfsinit)
# when writing a bundle via "hg bundle" command, upload related LFS blobs
wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
@templatekeyword('lfs_files')
def lfsfiles(repo, ctx, **args):
"""List of strings. LFS files added or modified by the changeset."""
pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
return sorted(pointers.keys())
@command('debuglfsupload',
[('r', 'rev', [], _('upload large files introduced by REV'))])
def debuglfsupload(ui, repo, **opts):
"""upload lfs blobs added by the working copy parent or given revisions"""
revs = opts.get('rev', [])
pointers = wrapper.extractpointers(repo, scmutil.revrange(repo, revs))
wrapper.uploadblobs(repo, pointers)