##// END OF EJS Templates
tests: use NO_CHECK_EOF for fragments used to test importing via extension...
tests: use NO_CHECK_EOF for fragments used to test importing via extension test-extension.t is excluded in test-check-module-imports.t, because import-checker.py reports that some python code fragments in it does not import modules in recommended style. These code fragments are used to test importing modules relatively and absolutely via extension (e.g. issue4029, issue5208, and so on). Test specific package hierarchy becomes complicated for this purpose, and it seems reasonable to avoid checking these code fragments with import-checker.py. But on the other hand, other code fragments in test-extension.t should be checked by import-checker.py. Therefore, this patch uses NO_CHECK_EOF limit mark only for python code fragments, which are used to test importing via extension in test-extension.t. NO_CHECK_EOF limit mark tells import-checker.py that this code fragment should be ignored, via testparseutil.py.

File last commit:

r39746:7375a9ab default
r40242:37295cee default
Show More
lfcommands.py
609 lines | 21.7 KiB | text/x-python | PythonLexer
various
hgext: add largefiles extension...
r15168 # Copyright 2009-2010 Gregory P. Ward
# Copyright 2009-2010 Intelerad Medical Systems Incorporated
# Copyright 2010-2011 Fog Creek Software
# Copyright 2010-2011 Unity Technologies
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 '''High-level command function for lfconvert, plus the cmdtable.'''
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 from __future__ import absolute_import
various
hgext: add largefiles extension...
r15168
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 import errno
Augie Fackler
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1...
r29341 import hashlib
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 import os
various
hgext: add largefiles extension...
r15168 import shutil
from mercurial.i18n import _
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 from mercurial import (
cmdutil,
context,
error,
hg,
lock,
liscju
largefiles: rename match_ to matchmod import in lfcommands
r29317 match as matchmod,
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 node,
Pulkit Goyal
py3: handle keyword arguments correctly in hgext/largefiles/...
r35349 pycompat,
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 registrar,
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 scmutil,
util,
)
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325
liscju
py3: make largefiles/lfcommands.py use absolute_import
r29308 from ..convert import (
convcmd,
filemap,
)
from . import (
lfutil,
storefactory
)
release = lock.release
various
hgext: add largefiles extension...
r15168
# -- Commands ----------------------------------------------------------
Gregory Szorc
largefiles: declare commands using decorator
r21242 cmdtable = {}
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 command = registrar.command(cmdtable)
Gregory Szorc
largefiles: declare commands using decorator
r21242
@command('lfconvert',
[('s', 'size', '',
_('minimum size (MB) for files to be converted as largefiles'), 'SIZE'),
('', 'to-normal', False,
_('convert from a largefiles repo to a normal repo')),
],
Gregory Szorc
largefiles: define norepo in command decorator
r21770 _('hg lfconvert SOURCE DEST [FILE ...]'),
Gregory Szorc
largefiles: define inferrepo in command decorator
r21785 norepo=True,
inferrepo=True)
various
hgext: add largefiles extension...
r15168 def lfconvert(ui, src, dest, *pats, **opts):
Greg Ward
largefiles: improve help...
r15230 '''convert a normal repository to a largefiles repository
various
hgext: add largefiles extension...
r15168
Greg Ward
largefiles: improve help...
r15230 Convert repository SOURCE to a new repository DEST, identical to
SOURCE except that certain files will be converted as largefiles:
specifically, any file that matches any PATTERN *or* whose size is
above the minimum size threshold is converted as a largefile. The
size used to determine whether or not to track a file as a
largefile is the size of the first version of the file. The
minimum size can be specified either with --size or in
configuration as ``largefiles.size``.
After running this command you will need to make sure that
largefiles is enabled anywhere you intend to push the new
repository.
Greg Ward
largefiles: rename lfconvert --tonormal option to --to-normal
r15332 Use --to-normal to convert largefiles back to normal files; after
Greg Ward
largefiles: improve help...
r15230 this, the DEST repository can be used without largefiles at all.'''
various
hgext: add largefiles extension...
r15168
Pulkit Goyal
py3: handle keyword arguments correctly in hgext/largefiles/...
r35349 opts = pycompat.byteskwargs(opts)
Greg Ward
largefiles: rename lfconvert --tonormal option to --to-normal
r15332 if opts['to_normal']:
various
hgext: add largefiles extension...
r15168 tolfile = False
else:
tolfile = True
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
Greg Ward
largefiles: rearrange how lfconvert detects non-local repos...
r15340
if not hg.islocal(src):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('%s is not a local Mercurial repo') % src)
Greg Ward
largefiles: rearrange how lfconvert detects non-local repos...
r15340 if not hg.islocal(dest):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('%s is not a local Mercurial repo') % dest)
Greg Ward
largefiles: rearrange how lfconvert detects non-local repos...
r15340
Greg Ward
largefiles: test lfconvert error handling; remove redundant code
r15339 rsrc = hg.repository(ui, src)
ui.status(_('initializing destination %s\n') % dest)
rdst = hg.repository(ui, dest, create=True)
various
hgext: add largefiles extension...
r15168
Matt Mackall
largefiles: eliminate naked exceptions
r15171 success = False
Mads Kiilerich
largefiles: use wlock for lfconvert (issue3444)...
r16717 dstwlock = dstlock = None
various
hgext: add largefiles extension...
r15168 try:
# Get a list of all changesets in the source. The easy way to do this
Mads Kiilerich
fix trivial spelling errors
r17424 # is to simply walk the changelog, using changelog.nodesbetween().
various
hgext: add largefiles extension...
r15168 # Take a look at mercurial/revlog.py:639 for more details.
# Use a generator instead of a list to decrease memory usage
ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
rsrc.heads())[0])
revmap = {node.nullid: node.nullid}
if tolfile:
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 # Lock destination to prevent modification while it is converted to.
# Don't need to lock src because we are just reading from its
# history which can't change.
dstwlock = rdst.wlock()
dstlock = rdst.lock()
various
hgext: add largefiles extension...
r15168 lfiles = set()
normalfiles = set()
if not pats:
Boris Feld
configitems: register the 'largefiles.patterns' config
r34757 pats = ui.configlist(lfutil.longname, 'patterns')
various
hgext: add largefiles extension...
r15168 if pats:
liscju
largefiles: rename match_ to matchmod import in lfcommands
r29317 matcher = matchmod.match(rsrc.root, '', list(pats))
various
hgext: add largefiles extension...
r15168 else:
matcher = None
lfiletohash = {}
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 with ui.makeprogress(_('converting revisions'),
unit=_('revisions'),
total=rsrc['tip'].rev()) as progress:
for ctx in ctxs:
progress.update(ctx.rev())
_lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
lfiles, normalfiles, matcher, size, lfiletohash)
various
hgext: add largefiles extension...
r15168
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 if rdst.wvfs.exists(lfutil.shortname):
rdst.wvfs.rmtree(lfutil.shortname)
various
hgext: add largefiles extension...
r15168
for f in lfiletohash.keys():
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 if rdst.wvfs.isfile(f):
rdst.wvfs.unlink(f)
various
hgext: add largefiles extension...
r15168 try:
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 rdst.wvfs.removedirs(rdst.wvfs.dirname(f))
Matt Mackall
largefiles: eliminate naked exceptions
r15171 except OSError:
various
hgext: add largefiles extension...
r15168 pass
Eli Carter
largefiles: include 'largefiles' in converted repository requirements
r15303 # If there were any files converted to largefiles, add largefiles
# to the destination repository's requirements.
if lfiles:
rdst.requirements.add('largefiles')
rdst._writerequirements()
various
hgext: add largefiles extension...
r15168 else:
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 class lfsource(filemap.filemap_source):
def __init__(self, ui, source):
super(lfsource, self).__init__(ui, source, None)
self.filemapper.rename[lfutil.shortname] = '.'
def getfile(self, name, rev):
realname, realrev = rev
f = super(lfsource, self).getfile(name, rev)
if (not realname.startswith(lfutil.shortnameslash)
or f[0] is None):
return f
# Substitute in the largefile data for the hash
hash = f[0].strip()
path = lfutil.findfile(rsrc, hash)
various
hgext: add largefiles extension...
r15168
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 if path is None:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("missing largefile for '%s' in %s")
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 % (realname, realrev))
Bryan O'Sullivan
largefiles: use util.readfile in lfconvert
r27774 return util.readfile(path), f[1]
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325
class converter(convcmd.converter):
def __init__(self, ui, source, dest, revmapfile, opts):
src = lfsource(ui, source)
super(converter, self).__init__(ui, src, dest, revmapfile,
opts)
found, missing = downloadlfiles(ui, rsrc)
if missing != 0:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("all largefiles must be present locally"))
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325
Matt Harbison
largefiles: restore the original converter class after lfconvert --to-normal...
r25560 orig = convcmd.converter
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 convcmd.converter = converter
Matt Harbison
largefiles: restore the original converter class after lfconvert --to-normal...
r25560
try:
Matt Harbison
largefiles: explicitly set the source and sink types to 'hg' for lfconvert...
r35171 convcmd.convert(ui, src, dest, source_type='hg', dest_type='hg')
Matt Harbison
largefiles: restore the original converter class after lfconvert --to-normal...
r25560 finally:
convcmd.converter = orig
Matt Mackall
largefiles: eliminate naked exceptions
r15171 success = True
various
hgext: add largefiles extension...
r15168 finally:
Matt Harbison
largefiles: use the convert extension for 'lfconvert --to-normal'...
r25325 if tolfile:
rdst.dirstate.clear()
release(dstlock, dstwlock)
Matt Mackall
largefiles: eliminate naked exceptions
r15171 if not success:
# we failed, remove the new directory
shutil.rmtree(rdst.root)
various
hgext: add largefiles extension...
r15168
def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
matcher, size, lfiletohash):
# Convert src parents to dst parents
Levi Bard
largefiles: remove pasted code...
r15811 parents = _convertparents(ctx, revmap)
various
hgext: add largefiles extension...
r15168
# Generate list of changed files
Levi Bard
largefiles: remove pasted code...
r15811 files = _getchangedfiles(ctx, parents)
various
hgext: add largefiles extension...
r15168
dstfiles = []
for f in files:
if f not in lfiles and f not in normalfiles:
islfile = _islfile(f, ctx, matcher, size)
# If this file was renamed or copied then copy
Mads Kiilerich
fix trivial spelling errors
r17424 # the largefile-ness of its predecessor
various
hgext: add largefiles extension...
r15168 if f in ctx.manifest():
fctx = ctx.filectx(f)
renamed = fctx.renamed()
Sean Farley
filectx: fix return of renamed...
r39746 if renamed is None:
# the code below assumes renamed to be a boolean or a list
# and won't quite work with the value None
renamed = False
various
hgext: add largefiles extension...
r15168 renamedlfile = renamed and renamed[0] in lfiles
islfile |= renamedlfile
if 'l' in fctx.flags():
if renamedlfile:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Martin Geisler
largefiles: fix uppercase in abort message
r15380 _('renamed/copied largefile %s becomes symlink')
Matt Mackall
largefiles: fix over-long lines
r15170 % f)
various
hgext: add largefiles extension...
r15168 islfile = False
if islfile:
lfiles.add(f)
else:
normalfiles.add(f)
if f in lfiles:
FUJIWARA Katsunori
largefiles: avoid redundant standin() invocations...
r31618 fstandin = lfutil.standin(f)
dstfiles.append(fstandin)
Greg Ward
largefiles: more work on cleaning up comments...
r15254 # largefile in manifest if it has not been removed/renamed
various
hgext: add largefiles extension...
r15168 if f in ctx.manifest():
Levi Bard
largefiles: don't reference uninitialized variable (issue3092)
r15808 fctx = ctx.filectx(f)
if 'l' in fctx.flags():
renamed = fctx.renamed()
various
hgext: add largefiles extension...
r15168 if renamed and renamed[0] in lfiles:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('largefile %s becomes symlink') % f)
various
hgext: add largefiles extension...
r15168
Greg Ward
largefiles: more work on cleaning up comments...
r15254 # largefile was modified, update standins
Augie Fackler
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1...
r29341 m = hashlib.sha1('')
various
hgext: add largefiles extension...
r15168 m.update(ctx[f].data())
hash = m.hexdigest()
if f not in lfiletohash or lfiletohash[f] != hash:
Mads Kiilerich
largefiles: use repo.wwrite for writing standins (issue3909)
r19089 rdst.wwrite(f, ctx[f].data(), ctx[f].flags())
various
hgext: add largefiles extension...
r15168 executable = 'x' in ctx[f].flags()
FUJIWARA Katsunori
largefiles: avoid redundant standin() invocations...
r31618 lfutil.writestandin(rdst, fstandin, hash,
various
hgext: add largefiles extension...
r15168 executable)
lfiletohash[f] = hash
else:
# normal file
dstfiles.append(f)
def getfilectx(repo, memctx, f):
FUJIWARA Katsunori
largefiles: omit redundant isstandin() before splitstandin()...
r31613 srcfname = lfutil.splitstandin(f)
if srcfname is not None:
various
hgext: add largefiles extension...
r15168 # if the file isn't in the manifest then it was removed
FUJIWARA Katsunori
misc: update descriptions about removed file for filectxfn...
r31612 # or renamed, return None to indicate this
various
hgext: add largefiles extension...
r15168 try:
fctx = ctx.filectx(srcfname)
except error.LookupError:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None
various
hgext: add largefiles extension...
r15168 renamed = fctx.renamed()
if renamed:
Greg Ward
largefiles: more work on cleaning up comments...
r15254 # standin is always a largefile because largefile-ness
various
hgext: add largefiles extension...
r15168 # doesn't change after rename or copy
renamed = lfutil.standin(renamed[0])
Martin von Zweigbergk
memfilectx: make changectx argument mandatory in constructor (API)...
r35401 return context.memfilectx(repo, memctx, f,
lfiletohash[srcfname] + '\n',
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 'l' in fctx.flags(), 'x' in fctx.flags(),
renamed)
various
hgext: add largefiles extension...
r15168 else:
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 return _getnormalcontext(repo, ctx, f, revmap)
various
hgext: add largefiles extension...
r15168
# Commit
Levi Bard
largefiles: remove pasted code...
r15811 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
various
hgext: add largefiles extension...
r15168 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
getfilectx, ctx.user(), ctx.date(), ctx.extra())
ret = rdst.commitctx(mctx)
FUJIWARA Katsunori
largefiles: move "copyalltostore" invocation into "markcommitted"...
r23276 lfutil.copyalltostore(rdst, ret)
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 rdst.setparents(ret)
various
hgext: add largefiles extension...
r15168 revmap[ctx.node()] = rdst.changelog.tip()
Levi Bard
largefiles: remove pasted code...
r15811 # Generate list of changed files
def _getchangedfiles(ctx, parents):
files = set(ctx.files())
if node.nullid not in parents:
mc = ctx.manifest()
mp1 = ctx.parents()[0].manifest()
mp2 = ctx.parents()[1].manifest()
files |= (set(mp1) | set(mp2)) - set(mc)
for f in mc:
if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
files.add(f)
return files
# Convert src parents to dst parents
def _convertparents(ctx, revmap):
parents = []
for p in ctx.parents():
parents.append(revmap[p.node()])
while len(parents) < 2:
parents.append(node.nullid)
return parents
# Get memfilectx for a normal file
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 def _getnormalcontext(repo, ctx, f, revmap):
Levi Bard
largefiles: remove pasted code...
r15811 try:
fctx = ctx.filectx(f)
except error.LookupError:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None
Levi Bard
largefiles: remove pasted code...
r15811 renamed = fctx.renamed()
if renamed:
renamed = renamed[0]
data = fctx.data()
if f == '.hgtags':
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 data = _converttags (repo.ui, revmap, data)
Martin von Zweigbergk
memfilectx: make changectx argument mandatory in constructor (API)...
r35401 return context.memfilectx(repo, ctx, f, data, 'l' in fctx.flags(),
Levi Bard
largefiles: remove pasted code...
r15811 'x' in fctx.flags(), renamed)
# Remap tag data using a revision map
def _converttags(ui, revmap, data):
newdata = []
for line in data.splitlines():
try:
id, name = line.split(' ', 1)
except ValueError:
FUJIWARA Katsunori
i18n: fix "% inside _()" problems...
r20868 ui.warn(_('skipping incorrectly formatted tag %s\n')
% line)
Levi Bard
largefiles: remove pasted code...
r15811 continue
try:
newid = node.bin(id)
except TypeError:
FUJIWARA Katsunori
i18n: fix "% inside _()" problems...
r20868 ui.warn(_('skipping incorrectly formatted id %s\n')
% id)
Levi Bard
largefiles: remove pasted code...
r15811 continue
try:
newdata.append('%s %s\n' % (node.hex(revmap[newid]),
name))
except KeyError:
Matt Mackall
i18n: fix all remaining uses of % inside _()
r16231 ui.warn(_('no mapping for id %s\n') % id)
Levi Bard
largefiles: remove pasted code...
r15811 continue
return ''.join(newdata)
various
hgext: add largefiles extension...
r15168 def _islfile(file, ctx, matcher, size):
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 '''Return true if file should be considered a largefile, i.e.
matcher matches it or it is larger than size.'''
# never store special .hg* files as largefiles
various
hgext: add largefiles extension...
r15168 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
return False
if matcher and matcher(file):
return True
try:
return ctx.filectx(file).size() >= size * 1024 * 1024
except error.LookupError:
return False
def uploadlfiles(ui, rsrc, rdst, files):
'''upload largefiles to the central store'''
Benjamin Pollack
largefiles: make the store primary, and the user cache secondary...
r15317 if not files:
various
hgext: add largefiles extension...
r15168 return
liscju
largefiles: make storefactory._openstore public...
r29355 store = storefactory.openstore(rsrc, rdst, put=True)
various
hgext: add largefiles extension...
r15168
at = 0
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 ui.debug("sending statlfile command for %d largefiles\n" % len(files))
retval = store.exists(files)
Augie Fackler
largfiles: replace filter() with listcomp when result needs to be a list...
r36329 files = [h for h in files if not retval[h]]
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 ui.debug("%d largefiles need to be uploaded\n" % len(files))
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 with ui.makeprogress(_('uploading largefiles'), unit=_('files'),
total=len(files)) as progress:
for hash in files:
progress.update(at)
source = lfutil.findfile(rsrc, hash)
if not source:
raise error.Abort(_('largefile %s missing from store'
' (needs to be uploaded)') % hash)
# XXX check for errors here
store.put(source, hash)
at += 1
various
hgext: add largefiles extension...
r15168
def verifylfiles(ui, repo, all=False, contents=False):
Mads Kiilerich
largefiles: docstrings for verify methods
r18574 '''Verify that every largefile revision in the current changeset
various
hgext: add largefiles extension...
r15168 exists in the central store. With --contents, also verify that
Mads Kiilerich
largefiles: docstrings for verify methods
r18574 the contents of each local largefile file revision are correct (SHA-1 hash
various
hgext: add largefiles extension...
r15168 matches the revision ID). With --all, check every changeset in
this repository.'''
if all:
Matt Harbison
largefiles: ignore hidden changesets with 'verify --large --lfa'...
r25508 revs = repo.revs('all()')
various
hgext: add largefiles extension...
r15168 else:
revs = ['.']
liscju
largefiles: make storefactory._openstore public...
r29355 store = storefactory.openstore(repo)
various
hgext: add largefiles extension...
r15168 return store.verify(revs, contents=contents)
Na'Tosha Bard
largefiles: optimize performance when updating (issue3440)...
r16700 def cachelfiles(ui, repo, node, filelist=None):
various
hgext: add largefiles extension...
r15168 '''cachelfiles ensures that all largefiles needed by the specified revision
are present in the repository's largefile cache.
returns a tuple (cached, missing). cached is the list of files downloaded
by this operation; missing is the list of files that were needed but could
not be found.'''
lfiles = lfutil.listlfiles(repo, node)
Na'Tosha Bard
largefiles: optimize performance when updating (issue3440)...
r16700 if filelist:
lfiles = set(lfiles) & set(filelist)
various
hgext: add largefiles extension...
r15168 toget = []
FUJIWARA Katsunori
largefiles: avoid redundant changectx looking up at each repetitions...
r31654 ctx = repo[node]
various
hgext: add largefiles extension...
r15168 for lfile in lfiles:
Mads Kiilerich
largefiles: simplify cachelfiles - don't spend a lot of time checking hashes...
r18728 try:
FUJIWARA Katsunori
largefiles: use readasstandin() to read hex hash directly from filectx...
r31740 expectedhash = lfutil.readasstandin(ctx[lfutil.standin(lfile)])
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as err:
Mads Kiilerich
largefiles: simplify cachelfiles - don't spend a lot of time checking hashes...
r18728 if err.errno == errno.ENOENT:
continue # node must be None and standin wasn't found in wctx
raise
if not lfutil.findfile(repo, expectedhash):
various
hgext: add largefiles extension...
r15168 toget.append((lfile, expectedhash))
if toget:
liscju
largefiles: make storefactory._openstore public...
r29355 store = storefactory.openstore(repo)
various
hgext: add largefiles extension...
r15168 ret = store.get(toget)
return ret
return ([], [])
Na'Tosha Bard
largefiles: refactor downloading of all largefiles to generic function
r16691 def downloadlfiles(ui, repo, rev=None):
Martin von Zweigbergk
cleanup: rename "matchfn" to "match" where obviously a matcher...
r34085 match = scmutil.match(repo[None], [repo.wjoin(lfutil.shortname)], {})
Na'Tosha Bard
largefiles: refactor downloading of all largefiles to generic function
r16691 def prepare(ctx, fns):
pass
totalsuccess = 0
totalmissing = 0
Mads Kiilerich
largefiles: fix download of largefiles from an empty list of changesets...
r18722 if rev != []: # walkchangerevs on empty list would return all revs
Martin von Zweigbergk
cleanup: rename "matchfn" to "match" where obviously a matcher...
r34085 for ctx in cmdutil.walkchangerevs(repo, match, {'rev' : rev},
Mads Kiilerich
largefiles: fix download of largefiles from an empty list of changesets...
r18722 prepare):
success, missing = cachelfiles(ui, repo, ctx.node())
totalsuccess += len(success)
totalmissing += len(missing)
Na'Tosha Bard
largefiles: refactor downloading of all largefiles to generic function
r16691 ui.status(_("%d additional largefiles cached\n") % totalsuccess)
if totalmissing > 0:
ui.status(_("%d largefiles failed to download\n") % totalmissing)
return totalsuccess, totalmissing
FUJIWARA Katsunori
largefiles: get function to write status messages via "getstatuswriter()"...
r23189 def updatelfiles(ui, repo, filelist=None, printmessage=None,
Mads Kiilerich
largefiles: always consider updatelfiles 'checked' parameter set...
r24788 normallookup=False):
FUJIWARA Katsunori
largefiles: get function to write status messages via "getstatuswriter()"...
r23189 '''Update largefiles according to standins in the working directory
If ``printmessage`` is other than ``None``, it means "print (or
ignore, for false) message forcibly".
'''
statuswriter = lfutil.getstatuswriter(ui, repo, printmessage)
Bryan O'Sullivan
with: use context manager for wlock in updatelfiles
r27820 with repo.wlock():
various
hgext: add largefiles extension...
r15168 lfdirstate = lfutil.openlfdirstate(ui, repo)
lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
if filelist is not None:
FUJIWARA Katsunori
largefiles: update lfdirstate for unchanged largefiles during linear merging...
r22197 filelist = set(filelist)
various
hgext: add largefiles extension...
r15168 lfiles = [f for f in lfiles if f in filelist]
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063 update = {}
Matt Harbison
largefiles: pay attention to dropped standin files when updating largefiles...
r35175 dropped = set()
various
hgext: add largefiles extension...
r15168 updated, removed = 0, 0
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 wvfs = repo.wvfs
FUJIWARA Katsunori
largefiles: avoid redundant changectx looking up at each repetitions...
r31654 wctx = repo[None]
Mads Kiilerich
largefiles: inline _updatelfile, prepare for further refactorings
r20062 for lfile in lfiles:
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 rellfile = lfile
rellfileorig = os.path.relpath(
scmutil.origpath(ui, repo, wvfs.join(rellfile)),
start=repo.root)
relstandin = lfutil.standin(lfile)
relstandinorig = os.path.relpath(
scmutil.origpath(ui, repo, wvfs.join(relstandin)),
start=repo.root)
if wvfs.exists(relstandin):
if (wvfs.exists(relstandinorig) and
wvfs.exists(rellfile)):
shutil.copyfile(wvfs.join(rellfile),
wvfs.join(rellfileorig))
wvfs.unlinkpath(relstandinorig)
FUJIWARA Katsunori
largefiles: replace readstandin() by readasstandin()...
r31735 expecthash = lfutil.readasstandin(wctx[relstandin])
Mads Kiilerich
largefiles: always consider updatelfiles 'checked' parameter set...
r24788 if expecthash != '':
FUJIWARA Katsunori
largefiles: avoid redundant changectx looking up at each repetitions...
r31654 if lfile not in wctx: # not switched to normal file
Matt Harbison
largefiles: pay attention to dropped standin files when updating largefiles...
r35175 if repo.dirstate[relstandin] != '?':
wvfs.unlinkpath(rellfile, ignoremissing=True)
else:
dropped.add(rellfile)
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 # use normallookup() to allocate an entry in largefiles
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 # dirstate to prevent lfilesrepo.status() from reporting
# missing files as removed.
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063 lfdirstate.normallookup(lfile)
update[lfile] = expecthash
Mads Kiilerich
largefiles: inline _updatelfile, prepare for further refactorings
r20062 else:
# Remove lfiles for which the standin is deleted, unless the
# lfile is added to the repository again. This happens when a
# largefile is converted back to a normal file: the standin
# disappears, but a new (normal) file appears as the lfile.
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 if (wvfs.exists(rellfile) and
FUJIWARA Katsunori
largefiles: avoid redundant changectx looking up at each repetitions...
r31654 repo.dirstate.normalize(lfile) not in wctx):
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 wvfs.unlinkpath(rellfile)
Mads Kiilerich
largefiles: inline _updatelfile, prepare for further refactorings
r20062 removed += 1
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063
# largefile processing might be slow and be interrupted - be prepared
lfdirstate.write()
if lfiles:
Matt Harbison
largefiles: pay attention to dropped standin files when updating largefiles...
r35175 lfiles = [f for f in lfiles if f not in dropped]
for f in dropped:
repo.wvfs.unlinkpath(lfutil.standin(f))
# This needs to happen for dropped files, otherwise they stay in
# the M state.
lfutil.synclfdirstate(repo, lfdirstate, f, normallookup)
FUJIWARA Katsunori
largefiles: get function to write status messages via "getstatuswriter()"...
r23189 statuswriter(_('getting changed largefiles\n'))
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063 cachelfiles(ui, repo, None, lfiles)
for lfile in lfiles:
update1 = 0
expecthash = update.get(lfile)
if expecthash:
if not lfutil.copyfromcache(repo, expecthash, lfile):
# failed ... but already removed and set to normallookup
continue
# Synchronize largefile dirstate to the last modified
# time of the file
lfdirstate.normal(lfile)
update1 = 1
Mads Kiilerich
largefiles: clarify variable name holding file mode...
r30269 # copy the exec mode of largefile standin from the repository's
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063 # dirstate to its state in the lfdirstate.
liscju
largefiles: replace invocation of os.path module by vfs in lfcommands.py
r28559 rellfile = lfile
relstandin = lfutil.standin(lfile)
if wvfs.exists(relstandin):
Mads Kiilerich
largefiles: clarify variable name holding file mode...
r30269 # exec is decided by the users permissions using mask 0o100
Mads Kiilerich
largefiles: when setting/clearing x bit on largefiles, don't change other bits...
r30141 standinexec = wvfs.stat(relstandin).st_mode & 0o100
Mads Kiilerich
largefiles: clarify variable name holding file mode...
r30269 st = wvfs.stat(rellfile)
mode = st.st_mode
if standinexec != mode & 0o100:
# first remove all X bits, then shift all R bits to X
mode &= ~0o111
Mads Kiilerich
largefiles: when setting/clearing x bit on largefiles, don't change other bits...
r30141 if standinexec:
Mads Kiilerich
largefiles: clarify variable name holding file mode...
r30269 mode |= (mode >> 2) & 0o111 & ~util.umask
wvfs.chmod(rellfile, mode)
Mads Kiilerich
largefiles: update in two steps, handle interrupted updates better...
r20063 update1 = 1
updated += update1
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 lfutil.synclfdirstate(repo, lfdirstate, lfile, normallookup)
various
hgext: add largefiles extension...
r15168
lfdirstate.write()
FUJIWARA Katsunori
largefiles: get function to write status messages via "getstatuswriter()"...
r23189 if lfiles:
statuswriter(_('%d largefiles updated, %d removed\n') % (updated,
various
hgext: add largefiles extension...
r15168 removed))
Gregory Szorc
largefiles: declare commands using decorator
r21242 @command('lfpull',
[('r', 'rev', [], _('pull largefiles for these revisions'))
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.remoteopts,
Gregory Szorc
largefiles: declare commands using decorator
r21242 _('-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]'))
Mads Kiilerich
largefiles: introduce lfpull command for pulling missing largefiles
r18976 def lfpull(ui, repo, source="default", **opts):
"""pull largefiles for the specified revisions from the specified source
Pull largefiles that are referenced from local changesets but missing
locally, pulling from a remote repository to the local cache.
If SOURCE is omitted, the 'default' path will be used.
See :hg:`help urls` for more information.
.. container:: verbose
Some examples:
- pull largefiles for all branch heads::
hg lfpull -r "head() and not closed()"
- pull largefiles on the default branch::
hg lfpull -r "branch(default)"
"""
repo.lfpullsource = source
Pulkit Goyal
py3: handle keyword arguments correctly in hgext/largefiles/...
r35349 revs = opts.get(r'rev', [])
Mads Kiilerich
largefiles: introduce lfpull command for pulling missing largefiles
r18976 if not revs:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no revisions specified'))
Mads Kiilerich
largefiles: introduce lfpull command for pulling missing largefiles
r18976 revs = scmutil.revrange(repo, revs)
numcached = 0
for rev in revs:
Augie Fackler
lfcommands: use %d on known-int in format string...
r37761 ui.note(_('pulling largefiles for revision %d\n') % rev)
Mads Kiilerich
largefiles: introduce lfpull command for pulling missing largefiles
r18976 (cached, missing) = cachelfiles(ui, repo, rev)
numcached += len(cached)
ui.status(_("%d largefiles cached\n") % numcached)
Boris Feld
largefiles: add a 'debuglfput' command to put largefile into the store...
r35579
@command('debuglfput',
[] + cmdutil.remoteopts,
_('FILE'))
def debuglfput(ui, repo, filepath, **kwargs):
hash = lfutil.hashfile(filepath)
storefactory.openstore(repo).put(filepath, hash)
ui.write('%s\n' % hash)
return 0