##// END OF EJS Templates
dirstate-v2: Change the on-disk format when the requirement is enabled...
dirstate-v2: Change the on-disk format when the requirement is enabled For now, the format is the same except with an additional marker at the start. This marker is redundant: for existing repositories it is `.hg/requires` that determines which format to use. For new repositories, it is the new `format.exp-dirstate-v2` config. There is no upgrade or downgrade so far. Most of the changes are about plumbing a boolean through layers of APIs to indicate which format should be used. Differential Revision: https://phab.mercurial-scm.org/D10719

File last commit:

r48055:1766130f default
r48055:1766130f default
Show More
lfutil.py
784 lines | 24.6 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.
'''largefiles utility code: must not import other modules in this package.'''
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 from __future__ import absolute_import
various
hgext: add largefiles extension...
r15168
Martin von Zweigbergk
largefiles: move lfstatus context manager to lfutil...
r43982 import contextlib
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 import copy
various
hgext: add largefiles extension...
r15168 import os
import stat
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309
from mercurial.i18n import _
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 from mercurial.node import hex
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from mercurial.pycompat import open
various
hgext: add largefiles extension...
r15168
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 from mercurial import (
dirstate,
Pulkit Goyal
py3: replace pycompat.getenv with encoding.environ.get...
r30820 encoding,
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 error,
httpconnection,
liscju
largefiles: rename match_ to matchmod import in lfutil
r29320 match as matchmod,
Pulkit Goyal
py3: replace os.name with pycompat.osname (part 2 of 2)
r30640 pycompat,
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 requirements,
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 scmutil,
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 sparse,
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 util,
Pierre-Yves David
vfs: use 'vfs' module directly in 'hgext.largefile'...
r31247 vfs as vfsmod,
liscju
py3: make largefiles/lfutil.py use absolute_import
r29309 )
Augie Fackler
hgext: replace references to hashlib.sha1 with hashutil.sha1...
r44519 from mercurial.utils import hashutil
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shortname = b'.hglf'
shortnameslash = shortname + b'/'
longname = b'largefiles'
various
hgext: add largefiles extension...
r15168
# -- Private worker functions ------------------------------------------
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
largefiles: move lfstatus context manager to lfutil...
r43982 @contextlib.contextmanager
Martin von Zweigbergk
largefiles: allow "lfstatus" context manager to set value to False...
r43983 def lfstatus(repo, value=True):
Martin von Zweigbergk
largefiles: move lfstatus context manager to lfutil...
r43982 oldvalue = getattr(repo, 'lfstatus', False)
Martin von Zweigbergk
largefiles: allow "lfstatus" context manager to set value to False...
r43983 repo.lfstatus = value
Martin von Zweigbergk
largefiles: move lfstatus context manager to lfutil...
r43982 try:
yield
finally:
repo.lfstatus = oldvalue
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 def getminsize(ui, assumelfiles, opt, default=10):
lfsize = opt
if not lfsize and assumelfiles:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lfsize = ui.config(longname, b'minsize', default=default)
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 if lfsize:
try:
Greg Ward
largefiles: allow minimum size to be a float...
r15228 lfsize = float(lfsize)
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'largefiles: size must be number (not %s)\n') % lfsize
Augie Fackler
formatting: blacken the codebase...
r43346 )
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 if lfsize is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'minimum size for largefiles must be specified'))
Greg Ward
largefiles: factor out lfutil.getminsize()
r15227 return lfsize
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def link(src, dest):
Mads Kiilerich
largefiles: add some docstrings
r28576 """Try to create hardlink - if that fails, efficiently make a copy."""
Mads Kiilerich
largefiles: refactoring - create destination dir in lfutil.link
r18998 util.makedirs(os.path.dirname(dest))
various
hgext: add largefiles extension...
r15168 try:
Na'Tosha Bard
largefiles: fix commit of specified file on non-windows
r15206 util.oslink(src, dest)
various
hgext: add largefiles extension...
r15168 except OSError:
Martin Geisler
largefiles: copy files into .hg/largefiles atomically...
r15572 # if hardlinks fail, fallback on atomic copy
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(src, b'rb') as srcf, util.atomictempfile(dest) as dstf:
Jun Wu
codemod: simplify nested withs...
r33438 for chunk in util.filechunkiter(srcf):
dstf.write(chunk)
various
hgext: add largefiles extension...
r15168 os.chmod(dest, os.stat(src).st_mode)
Augie Fackler
formatting: blacken the codebase...
r43346
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 def usercachepath(ui, hash):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return the correct location in the "global" largefiles cache for a file
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 with the given hash.
This cache is used for sharing of largefiles across repositories - both
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 to preserve download bandwidth and storage space."""
Mads Kiilerich
largefiles: drop partial support for not having a user cache...
r28575 return os.path.join(_usercachedir(ui), hash)
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
largefiles: refactor _usercachedir() to allow reuse with lfs...
r35280 def _usercachedir(ui, name=longname):
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 '''Return the location of the "global" largefiles cache.'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = ui.configpath(name, b'usercache')
various
hgext: add largefiles extension...
r15168 if path:
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 return path
Matt Harbison
lfutil: provide a hint if the largefiles/lfs cache path cannot be determined...
r44863
hint = None
Jun Wu
codemod: use pycompat.iswindows...
r34646 if pycompat.iswindows:
Augie Fackler
formatting: blacken the codebase...
r43346 appdata = encoding.environ.get(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'LOCALAPPDATA', encoding.environ.get(b'APPDATA')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 if appdata:
Matt Harbison
largefiles: refactor _usercachedir() to allow reuse with lfs...
r35280 return os.path.join(appdata, name)
Matt Harbison
lfutil: provide a hint if the largefiles/lfs cache path cannot be determined...
r44863
hint = _(b"define %s or %s in the environment, or set %s.usercache") % (
b"LOCALAPPDATA",
b"APPDATA",
name,
)
Jun Wu
codemod: use pycompat.isdarwin...
r34648 elif pycompat.isdarwin:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 home = encoding.environ.get(b'HOME')
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 if home:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return os.path.join(home, b'Library', b'Caches', name)
Matt Harbison
lfutil: provide a hint if the largefiles/lfs cache path cannot be determined...
r44863
hint = _(b"define %s in the environment, or set %s.usercache") % (
b"HOME",
name,
)
Jun Wu
codemod: use pycompat.isposix...
r34647 elif pycompat.isposix:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = encoding.environ.get(b'XDG_CACHE_HOME')
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 if path:
Matt Harbison
largefiles: refactor _usercachedir() to allow reuse with lfs...
r35280 return os.path.join(path, name)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 home = encoding.environ.get(b'HOME')
Mads Kiilerich
largefiles: refactor usercachepath - extract user cache path function...
r28574 if home:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return os.path.join(home, b'.cache', name)
Matt Harbison
lfutil: provide a hint if the largefiles/lfs cache path cannot be determined...
r44863
hint = _(b"define %s or %s in the environment, or set %s.usercache") % (
b"XDG_CACHE_HOME",
b"HOME",
name,
)
various
hgext: add largefiles extension...
r15168 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(
_(b'unknown operating system: %s\n') % pycompat.osname
)
Matt Harbison
lfutil: provide a hint if the largefiles/lfs cache path cannot be determined...
r44863
raise error.Abort(_(b'unknown %s usercache location') % name, hint=hint)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 def inusercache(ui, hash):
Kevin Gessner
largefiles: don't require a user cache (issue3088) (issue3155)...
r15658 path = usercachepath(ui, hash)
Mads Kiilerich
largefiles: drop partial support for not having a user cache...
r28575 return os.path.exists(path)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def findfile(repo, hash):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return store path of the largefile with the specified hash.
Mads Kiilerich
largefiles: add some docstrings
r28576 As a side effect, the file might be linked from user cache.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 Return None if the file can't be found locally."""
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 path, exists = findstorepath(repo, hash)
if exists:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'found %s in store\n') % hash)
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 return path
Benjamin Pollack
largefiles: make the store primary, and the user cache secondary...
r15317 elif inusercache(repo.ui, hash):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.note(_(b'found %s in system cache\n') % hash)
Hao Lian
largefiles: ensure destination directory exists before findfile links to there...
r15408 path = storepath(repo, hash)
link(usercachepath(repo.ui, hash), path)
Na'Tosha Bard
largefiles: refactor lfutil.findfiles to be more logical
r15913 return path
return None
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 class largefilesdirstate(dirstate.dirstate):
various
hgext: add largefiles extension...
r15168 def __getitem__(self, key):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).__getitem__(unixpath(key))
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def normal(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).normal(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def remove(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).remove(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def add(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).add(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def drop(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).drop(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def forget(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).forget(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: correctly handle dirstate status when rebasing...
r15793 def normallookup(self, f):
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return super(largefilesdirstate, self).normallookup(unixpath(f))
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
largefiles: fix profile of unused largefilesdirstate._ignore
r21085 def _ignore(self, f):
Mads Kiilerich
largefiles: simplify lfdirstate ignore handling - it is only for tracking .hglf
r18148 return False
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
dirstate: show develwarn for write() invocation without transaction...
r26749 def write(self, tr=False):
# (1) disable PENDING mode always
# (lfdirstate isn't yet managed as a part of the transaction)
# (2) avoid develwarn 'use dirstate.write with ....'
super(largefilesdirstate, self).write(None)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
largefiles: enable islfilesrepo() prior to a commit (issue3541)...
r17659 def openlfdirstate(ui, repo, create=True):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 Return a dirstate object that tracks largefiles: i.e. its root is
the repo root, but it is saved in .hg/largefiles/dirstate.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 vfs = repo.vfs
lfstoredir = longname
Pierre-Yves David
vfs: use 'vfs' module directly in 'hgext.largefile'...
r31247 opener = vfsmod.vfs(vfs.join(lfstoredir))
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 use_dirstate_v2 = requirements.DIRSTATE_V2_REQUIREMENT in repo.requirements
Augie Fackler
formatting: blacken the codebase...
r43346 lfdirstate = largefilesdirstate(
opener,
ui,
repo.root,
repo.dirstate._validate,
lambda: sparse.matcher(repo),
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 repo.nodeconstants,
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 use_dirstate_v2,
Augie Fackler
formatting: blacken the codebase...
r43346 )
various
hgext: add largefiles extension...
r15168
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 # If the largefiles dirstate does not exist, populate and create
# it. This ensures that we create it on the first meaningful
Levi Bard
largefiles: fix inappropriate locking (issue3182)...
r15794 # largefiles operation in a new clone.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if create and not vfs.exists(vfs.join(lfstoredir, b'dirstate')):
various
hgext: add largefiles extension...
r15168 matcher = getstandinmatcher(repo)
Augie Fackler
formatting: blacken the codebase...
r43346 standins = repo.dirstate.walk(
matcher, subrepos=[], unknown=False, ignored=False
)
Matt Harbison
largefiles: avoid unnecessary creation of .hg/largefiles when opening lfdirstate...
r21917
if len(standins) > 0:
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 vfs.makedirs(lfstoredir)
Matt Harbison
largefiles: avoid unnecessary creation of .hg/largefiles when opening lfdirstate...
r21917
for standin in standins:
various
hgext: add largefiles extension...
r15168 lfile = splitstandin(standin)
lfdirstate.normallookup(lfile)
return lfdirstate
Augie Fackler
formatting: blacken the codebase...
r43346
Mads Kiilerich
largefiles: remove confusing rev parameter for lfdirstatestatus...
r23039 def lfdirstatestatus(lfdirstate, repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pctx = repo[b'.']
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 match = matchmod.always()
Augie Fackler
formatting: blacken the codebase...
r43346 unsure, s = lfdirstate.status(
match, subrepos=[], ignored=False, clean=False, unknown=False
)
Martin von Zweigbergk
largefiles: access status fields by name rather than index
r22919 modified, clean = s.modified, s.clean
Levi Bard
largefiles: fix inappropriate locking (issue3182)...
r15794 for lfile in unsure:
Mads Kiilerich
largefiles: fix revert removing a largefile from a merge...
r18299 try:
FUJIWARA Katsunori
largefiles: rename local variable appropriately...
r31657 fctx = pctx[standin(lfile)]
Mads Kiilerich
largefiles: fix revert removing a largefile from a merge...
r18299 except LookupError:
fctx = None
FUJIWARA Katsunori
largefiles: use readasstandin() to read hex hash directly from filectx...
r31740 if not fctx or readasstandin(fctx) != hashfile(repo.wjoin(lfile)):
Levi Bard
largefiles: fix inappropriate locking (issue3182)...
r15794 modified.append(lfile)
else:
clean.append(lfile)
lfdirstate.normal(lfile)
Martin von Zweigbergk
lfutil: avoid creating unnecessary copy of status tuple...
r22912 return s
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def listlfiles(repo, rev=None, matcher=None):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """return a list of largefiles in the working copy or the
specified changeset"""
various
hgext: add largefiles extension...
r15168
if matcher is None:
matcher = getstandinmatcher(repo)
# ignore unknown files in working directory
Augie Fackler
formatting: blacken the codebase...
r43346 return [
splitstandin(f)
for f in repo[rev].walk(matcher)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if rev is not None or repo.dirstate[f] != b'?'
Augie Fackler
formatting: blacken the codebase...
r43346 ]
various
hgext: add largefiles extension...
r15168
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 def instore(repo, hash, forcelocal=False):
liscju
largefiles: fix misleading comments in lfutil instore and storepath...
r29419 '''Return true if a largefile with the given hash exists in the store'''
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 return os.path.exists(storepath(repo, hash, forcelocal))
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 def storepath(repo, hash, forcelocal=False):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return the correct location in the repository largefiles store for a
file with the given hash."""
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 if not forcelocal and repo.shared():
return repo.vfs.reljoin(repo.sharedpath, longname, hash)
Pierre-Yves David
largefiles: directly use repo.vfs.join...
r31332 return repo.vfs.join(longname, hash)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
largefiles: introduce lfutil.findstorepath()...
r24629 def findstorepath(repo, hash):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Search through the local store path(s) to find the file for the given
Matt Harbison
largefiles: introduce lfutil.findstorepath()...
r24629 hash. If the file is not found, its path in the primary store is returned.
The return value is a tuple of (path, exists(path)).
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631 # For shared repos, the primary store is in the share source. But for
# backward compatibility, force a lookup in the local store if it wasn't
# found in the share source.
path = storepath(repo, hash, False)
if instore(repo, hash):
return (path, True)
elif repo.shared() and instore(repo, hash, True):
Henrik Stuart
largefiles: fix support for local largefiles while using share extension...
r29329 return storepath(repo, hash, True), True
Matt Harbison
largefiles: use the share source as the primary local store (issue4471)...
r24631
return (path, False)
Matt Harbison
largefiles: introduce lfutil.findstorepath()...
r24629
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def copyfromcache(repo, hash, filename):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Copy the specified largefile from the repo or system cache to
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 filename in the repository. Return true on success or false if the
file was not found in either cache (which should not happened:
this is meant to be called only after ensuring that the needed
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 largefile exists in the cache)."""
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 wvfs = repo.wvfs
various
hgext: add largefiles extension...
r15168 path = findfile(repo, hash)
if path is None:
return False
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 wvfs.makedirs(wvfs.dirname(wvfs.join(filename)))
Martin Geisler
largefiles: add comment about non-atomic working directory...
r15570 # The write may fail before the file is fully written, but we
# don't use atomic writes in the working copy.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(path, b'rb') as srcfd, wvfs(filename, b'wb') as destfd:
Augie Fackler
formatting: blacken the codebase...
r43346 gothash = copyandhash(util.filechunkiter(srcfd), destfd)
Mads Kiilerich
largefiles: check hash of files in the store before copying to working dir...
r26823 if gothash != hash:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'%s: data corruption in %s with hash %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (filename, path, gothash)
)
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 wvfs.unlink(filename)
Mads Kiilerich
largefiles: check hash of files in the store before copying to working dir...
r26823 return False
various
hgext: add largefiles extension...
r15168 return True
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: make copytostore() accept only changectx as the 2nd argument (API)...
r31738 def copytostore(repo, ctx, file, fstandin):
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 wvfs = repo.wvfs
FUJIWARA Katsunori
largefiles: make copytostore() accept only changectx as the 2nd argument (API)...
r31738 hash = readasstandin(ctx[fstandin])
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 if instore(repo, hash):
various
hgext: add largefiles extension...
r15168 return
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 if wvfs.exists(file):
copytostoreabsolute(repo, wvfs.join(file), hash)
Mads Kiilerich
largefiles: fix commit of missing largefiles...
r27903 else:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"%s: largefile %s not available from local store\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (file, hash)
)
various
hgext: add largefiles extension...
r15168
Dan Villiom Podlaski Christiansen
largefiles: factor out a copyalltostore() function
r15796 def copyalltostore(repo, node):
'''Copy all largefiles in a given revision to the store'''
ctx = repo[node]
for filename in ctx.files():
FUJIWARA Katsunori
largefiles: omit redundant isstandin() before splitstandin()...
r31613 realfile = splitstandin(filename)
if realfile is not None and filename in ctx.manifest():
FUJIWARA Katsunori
largefiles: add copytostore() fstandin argument to replace readstandin() (API)...
r31736 copytostore(repo, ctx, realfile, filename)
Dan Villiom Podlaski Christiansen
largefiles: factor out a copyalltostore() function
r15796
Augie Fackler
formatting: blacken the codebase...
r43346
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 def copytostoreabsolute(repo, file, hash):
if inusercache(repo.ui, hash):
link(usercachepath(repo.ui, hash), storepath(repo, hash))
FUJIWARA Katsunori
largefiles: move "copyalltostore" invocation into "markcommitted"...
r23276 else:
Mads Kiilerich
largefiles: refactoring - create destination dir in lfutil.link
r18998 util.makedirs(os.path.dirname(storepath(repo, hash)))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(file, b'rb') as srcf:
Augie Fackler
formatting: blacken the codebase...
r43346 with util.atomictempfile(
storepath(repo, hash), createmode=repo.store.createmode
) as dstf:
Mads Kiilerich
largefiles: use context for file closing...
r30142 for chunk in util.filechunkiter(srcf):
dstf.write(chunk)
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 linktousercache(repo, hash)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Benjamin Pollack
largefiles: rename functions and methods to match desired behavior...
r15316 def linktousercache(repo, hash):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Link / copy the largefile with the specified hash from the store
to the cache."""
Kevin Gessner
largefiles: don't require a user cache (issue3088) (issue3155)...
r15658 path = usercachepath(repo.ui, hash)
Mads Kiilerich
largefiles: drop partial support for not having a user cache...
r28575 link(storepath(repo, hash), path)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
largefiles: pass in whole matcher to getstandinmatcher()...
r25292 def getstandinmatcher(repo, rmatcher=None):
'''Return a match object that applies rmatcher to the standin directory'''
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 wvfs = repo.wvfs
standindir = shortname
Matt Harbison
largefiles: use the optional badfn argument when building a matcher...
r25470
# no warnings about missing files or directories
badfn = lambda f, msg: None
Martin von Zweigbergk
largefiles: avoid match.files() in conditions...
r25293 if rmatcher and not rmatcher.always():
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 pats = [wvfs.join(standindir, pat) for pat in rmatcher.files()]
Matt Harbison
largefiles: ensure lfutil.getstandinmatcher() only matches standins...
r26025 if not pats:
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 pats = [wvfs.join(standindir)]
Matt Harbison
largefiles: use the optional badfn argument when building a matcher...
r25470 match = scmutil.match(repo[None], pats, badfn=badfn)
Mads Kiilerich
largefiles: getstandinmatcher should not depend on existence of directories...
r18724 else:
various
hgext: add largefiles extension...
r15168 # no patterns: relative to repo root
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 match = scmutil.match(repo[None], [wvfs.join(standindir)], badfn=badfn)
various
hgext: add largefiles extension...
r15168 return match
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def composestandinmatcher(repo, rmatcher):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return a matcher that accepts standins corresponding to the
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 files accepted by rmatcher. Pass the list of files in the matcher
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 as the paths specified by the user."""
Martin von Zweigbergk
largefiles: pass in whole matcher to getstandinmatcher()...
r25292 smatcher = getstandinmatcher(repo, rmatcher)
various
hgext: add largefiles extension...
r15168 isstandin = smatcher.matchfn
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 def composedmatchfn(f):
various
hgext: add largefiles extension...
r15168 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 smatcher.matchfn = composedmatchfn
various
hgext: add largefiles extension...
r15168
return smatcher
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def standin(filename):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return the repo-relative path to the standin for the specified big
file."""
various
hgext: add largefiles extension...
r15168 # Notes:
Mads Kiilerich
fix wording and not-completely-trivial spelling errors and bad docstrings
r17425 # 1) Some callers want an absolute path, but for instance addlargefiles
Mads Kiilerich
largefiles: remove trivial portability wrappers
r18154 # needs it repo-relative so it can be passed to repo[None].add(). So
# leave it up to the caller to use repo.wjoin() to get an absolute path.
various
hgext: add largefiles extension...
r15168 # 2) Join with '/' because that's what dirstate always uses, even on
# Windows. Change existing separator to '/' first in case we are
# passed filenames from an external source (like the command line).
Mads Kiilerich
largefiles: use constant for '.hglf/'...
r18151 return shortnameslash + util.pconvert(filename)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def isstandin(filename):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return true if filename is a big file standin. filename must be
in Mercurial's internal form (slash-separated)."""
Mads Kiilerich
largefiles: use constant for '.hglf/'...
r18151 return filename.startswith(shortnameslash)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def splitstandin(filename):
# Split on / because that's what dirstate always uses, even on Windows.
# Change local separator to / first just in case we are passed filenames
# from an external source (like the command line).
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bits = util.pconvert(filename).split(b'/', 1)
various
hgext: add largefiles extension...
r15168 if len(bits) == 2 and bits[0] == shortname:
return bits[1]
else:
return None
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: add lfile argument to updatestandin() for efficiency (API)...
r31659 def updatestandin(repo, lfile, standin):
"""Re-calculate hash value of lfile and write it into standin
This assumes that "lfutil.standin(lfile) == standin", for efficiency.
"""
FUJIWARA Katsunori
largefiles: omit redundant splitstandin() invocations...
r31615 file = repo.wjoin(lfile)
if repo.wvfs.exists(lfile):
various
hgext: add largefiles extension...
r15168 hash = hashfile(file)
executable = getexecutable(file)
writestandin(repo, standin, hash, executable)
Matt Harbison
largefiles: prevent committing a missing largefile...
r27947 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'%s: file not found!') % lfile)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: introduce readasstandin() to read hex hash from given filectx...
r31734 def readasstandin(fctx):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """read hex hash from given filectx of standin file
FUJIWARA Katsunori
largefiles: introduce readasstandin() to read hex hash from given filectx...
r31734
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 This encapsulates how "standin" data is stored into storage layer."""
FUJIWARA Katsunori
largefiles: introduce readasstandin() to read hex hash from given filectx...
r31734 return fctx.data().strip()
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def writestandin(repo, standin, hash, executable):
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 '''write hash to <repo.root>/<standin>'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.wwrite(standin, hash + b'\n', executable and b'x' or b'')
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def copyandhash(instream, outfile):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Read bytes from instream (iterable) and write them to outfile,
computing the SHA-1 hash of the data along the way. Return the hash."""
Augie Fackler
hgext: replace references to hashlib.sha1 with hashutil.sha1...
r44519 hasher = hashutil.sha1(b'')
various
hgext: add largefiles extension...
r15168 for data in instream:
hasher.update(data)
outfile.write(data)
Gregory Szorc
py3: use hex(hasher.digest())...
r36129 return hex(hasher.digest())
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def hashfile(file):
if not os.path.exists(file):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
with open(file, b'rb') as fd:
FUJIWARA Katsunori
largefiles: reuse hexsha1() to centralize hash calculation logic into it...
r31652 return hexsha1(fd)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def getexecutable(filename):
mode = os.stat(filename).st_mode
Augie Fackler
formatting: blacken the codebase...
r43346 return (
(mode & stat.S_IXUSR)
and (mode & stat.S_IXGRP)
and (mode & stat.S_IXOTH)
)
various
hgext: add largefiles extension...
r15168
def urljoin(first, second, *arg):
def join(left, right):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not left.endswith(b'/'):
left += b'/'
if right.startswith(b'/'):
various
hgext: add largefiles extension...
r15168 right = right[1:]
return left + right
url = join(first, second)
for a in arg:
url = join(url, a)
return url
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: reuse hexsha1() to centralize hash calculation logic into it...
r31652 def hexsha1(fileobj):
various
hgext: add largefiles extension...
r15168 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
object data"""
Augie Fackler
hgext: replace references to hashlib.sha1 with hashutil.sha1...
r44519 h = hashutil.sha1()
FUJIWARA Katsunori
largefiles: reuse hexsha1() to centralize hash calculation logic into it...
r31652 for chunk in util.filechunkiter(fileobj):
various
hgext: add largefiles extension...
r15168 h.update(chunk)
Gregory Szorc
py3: use hex(hasher.digest())...
r36129 return hex(h.digest())
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def httpsendfile(ui, filename):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return httpconnection.httpsendfile(ui, filename, b'rb')
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def unixpath(path):
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 '''Return a version of path normalized for use with the lfdirstate.'''
FUJIWARA Katsunori
i18n: use util.pconvert() instead of 'str.replace()' for problematic encoding...
r16066 return util.pconvert(os.path.normpath(path))
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def islfilesrepo(repo):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Return true if the repo is a largefile repo.'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'largefiles' in repo.requirements and any(
store: also return some information about the type of file `walk` found...
r47657 shortnameslash in f[1] for f in repo.store.datafiles()
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Matt Harbison
largefiles: enable islfilesrepo() prior to a commit (issue3541)...
r17659 return True
Augie Fackler
cleanup: use __builtins__.any instead of util.any...
r25149 return any(openlfdirstate(repo.ui, repo, False))
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
largefiles: py2.4 doesn't have BaseException...
r15333 class storeprotonotcapable(Exception):
various
hgext: add largefiles extension...
r15168 def __init__(self, storetypes):
self.storetypes = storetypes
Na'Tosha Bard
largefiles: only cache largefiles in new heads...
r16103
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: optimize update speed by only updating changed largefiles...
r16120 def getstandinsstate(repo):
standins = []
matcher = getstandinmatcher(repo)
FUJIWARA Katsunori
largefiles: replace readstandin() by readasstandin()...
r31735 wctx = repo[None]
Augie Fackler
formatting: blacken the codebase...
r43346 for standin in repo.dirstate.walk(
matcher, subrepos=[], unknown=False, ignored=False
):
Na'Tosha Bard
largefiles: optimize update speed by only updating changed largefiles...
r16120 lfile = splitstandin(standin)
Mads Kiilerich
largefiles: fix update from a merge with removed files...
r18300 try:
FUJIWARA Katsunori
largefiles: replace readstandin() by readasstandin()...
r31735 hash = readasstandin(wctx[standin])
Mads Kiilerich
largefiles: fix update from a merge with removed files...
r18300 except IOError:
hash = None
standins.append((lfile, hash))
Na'Tosha Bard
largefiles: optimize update speed by only updating changed largefiles...
r16120 return standins
Na'Tosha Bard
largefiles: move calculation of largefiles for updating to utility function
r16245
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 def synclfdirstate(repo, lfdirstate, lfile, normallookup):
lfstandin = standin(lfile)
if lfstandin in repo.dirstate:
stat = repo.dirstate._map[lfstandin]
state, mtime = stat[0], stat[3]
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state, mtime = b'?', -1
if state == b'n':
Augie Fackler
formatting: blacken the codebase...
r43346 if normallookup or mtime < 0 or not repo.wvfs.exists(lfile):
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 # state 'n' doesn't ensure 'clean' in this case
lfdirstate.normallookup(lfile)
else:
lfdirstate.normal(lfile)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'm':
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 lfdirstate.normallookup(lfile)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'r':
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 lfdirstate.remove(lfile)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'a':
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 lfdirstate.add(lfile)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'?':
FUJIWARA Katsunori
largefiles: factor out synchronization of lfdirstate for future use
r22095 lfdirstate.drop(lfile)
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: factor out procedures to update lfdirstate for post-committing...
r23184 def markcommitted(orig, ctx, node):
Matt Harbison
largefiles: replace 'ctx._repo' with 'ctx.repo()'
r24336 repo = ctx.repo()
FUJIWARA Katsunori
largefiles: factor out procedures to update lfdirstate for post-committing...
r23184
orig(node)
FUJIWARA Katsunori
largefiles: avoid redundant "updatelfiles" invocation in "overridetransplant"...
r23273 # ATTENTION: "ctx.files()" may differ from "repo[node].files()"
# because files coming from the 2nd parent are omitted in the latter.
#
# The former should be used to get targets of "synclfdirstate",
# because such files:
# - are marked as "a" by "patch.patch()" (e.g. via transplant), and
# - have to be marked as "n" after commit, but
# - aren't listed in "repo[node].files()"
FUJIWARA Katsunori
largefiles: factor out procedures to update lfdirstate for post-committing...
r23184 lfdirstate = openlfdirstate(repo.ui, repo)
for f in ctx.files():
FUJIWARA Katsunori
largefiles: omit redundant isstandin() before splitstandin()...
r31613 lfile = splitstandin(f)
if lfile is not None:
FUJIWARA Katsunori
largefiles: factor out procedures to update lfdirstate for post-committing...
r23184 synclfdirstate(repo, lfdirstate, lfile, False)
lfdirstate.write()
FUJIWARA Katsunori
largefiles: move "copyalltostore" invocation into "markcommitted"...
r23276 # As part of committing, copy all of the largefiles into the cache.
FUJIWARA Katsunori
largefiles: call readstandin() with changectx itself instead of rev or node...
r31616 #
# Using "node" instead of "ctx" implies additional "repo[node]"
# lookup while copyalltostore(), but can omit redundant check for
# files comming from the 2nd parent, which should exist in store
# at merging.
FUJIWARA Katsunori
largefiles: move "copyalltostore" invocation into "markcommitted"...
r23276 copyalltostore(repo, node)
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: move calculation of largefiles for updating to utility function
r16245 def getlfilestoupdate(oldstandins, newstandins):
changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
filelist = []
for f in changedstandins:
if f[0] not in filelist:
filelist.append(f[0])
return filelist
FUJIWARA Katsunori
largefiles: centralize the logic to get outgoing largefiles...
r21042
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: centralize the logic to get outgoing largefiles...
r21042 def getlfilestoupload(repo, missing, addfunc):
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 makeprogress = repo.ui.makeprogress
Augie Fackler
formatting: blacken the codebase...
r43346 with makeprogress(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'finding outgoing largefiles'),
unit=_(b'revisions'),
Augie Fackler
formatting: blacken the codebase...
r43346 total=len(missing),
) as progress:
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 for i, n in enumerate(missing):
progress.update(i)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 parents = [p for p in repo[n].parents() if p != repo.nullid]
Matt Harbison
largefiles: ensure that the standin files are available in getlfilestoupload()...
r23657
Martin von Zweigbergk
largefiles: allow "lfstatus" context manager to set value to False...
r43983 with lfstatus(repo, value=False):
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 ctx = repo[n]
Matt Harbison
largefiles: ensure that the standin files are available in getlfilestoupload()...
r23657
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 files = set(ctx.files())
if len(parents) == 2:
mc = ctx.manifest()
Martin von Zweigbergk
cleanup: use p1() and p2() instead of parents()[0] and parents()[1]...
r41442 mp1 = ctx.p1().manifest()
mp2 = ctx.p2().manifest()
Matt Harbison
largefiles: use a context manager to control the progress bar lifetime
r39427 for f in mp1:
if f not in mc:
files.add(f)
for f in mp2:
if f not in mc:
files.add(f)
for f in mc:
if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
files.add(f)
for fn in files:
if isstandin(fn) and fn in ctx:
addfunc(fn, readasstandin(ctx[fn]))
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185 def updatestandinsbymatch(repo, match):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Update standins in the working directory according to specified match
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
This returns (possibly modified) ``match`` object to be used for
subsequent commit process.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
ui = repo.ui
# Case 1: user calls commit with no specific files or
# include/exclude patterns: refresh and commit all files that
# are "dirty".
if match is None or match.always():
# Spend a bit of time here to get a list of files we know
# are modified so we can compare only against those.
# It can cost a lot of time (several seconds)
# otherwise to update all standins if the largefiles are
# large.
lfdirstate = openlfdirstate(ui, repo)
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 dirtymatch = matchmod.always()
Augie Fackler
formatting: blacken the codebase...
r43346 unsure, s = lfdirstate.status(
dirtymatch, subrepos=[], ignored=False, clean=False, unknown=False
)
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185 modifiedfiles = unsure + s.modified + s.added + s.removed
lfiles = listlfiles(repo)
# this only loops through largefiles that exist (not
# removed/renamed)
for lfile in lfiles:
if lfile in modifiedfiles:
FUJIWARA Katsunori
largefiles: avoid redundant standin() invocations...
r31618 fstandin = standin(lfile)
if repo.wvfs.exists(fstandin):
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185 # this handles the case where a rebase is being
# performed and the working copy is not updated
# yet.
liscju
largefiles: replace invocation of os.path module by vfs in lfutil.py...
r28560 if repo.wvfs.exists(lfile):
FUJIWARA Katsunori
largefiles: add lfile argument to updatestandin() for efficiency (API)...
r31659 updatestandin(repo, lfile, fstandin)
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
return match
lfiles = listlfiles(repo)
match._files = repo._subdirlfs(match.files(), lfiles)
# Case 2: user calls commit with specified patterns: refresh
# any matching big files.
smatcher = composestandinmatcher(repo, match)
Augie Fackler
formatting: blacken the codebase...
r43346 standins = repo.dirstate.walk(
smatcher, subrepos=[], unknown=False, ignored=False
)
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
# No matching big files: get out of the way and pass control to
# the usual commit() method.
if not standins:
return match
# Refresh all matching big files. It's possible that the
# commit will end up failing, in which case the big files will
# stay refreshed. No harm done: the user modified them and
# asked to commit them, so sooner or later we're going to
# refresh the standins. Might as well leave them refreshed.
lfdirstate = openlfdirstate(ui, repo)
for fstandin in standins:
lfile = splitstandin(fstandin)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if lfdirstate[lfile] != b'r':
FUJIWARA Katsunori
largefiles: add lfile argument to updatestandin() for efficiency (API)...
r31659 updatestandin(repo, lfile, fstandin)
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
# Cook up a new matcher that only matches regular files or
# standins corresponding to the big files requested by the
# user. Have to modify _files to prevent commit() from
# complaining "not tracked" for big files.
match = copy.copy(match)
origmatchfn = match.matchfn
# Check both the list of largefiles and the list of
# standins because if a largefile was removed, it
# won't be in the list of largefiles at this point
match._files += sorted(standins)
actualfiles = []
for f in match._files:
fstandin = standin(f)
Mads Kiilerich
largefiles: fix explicit commit of normal/largefile switch...
r26817 # For largefiles, only one of the normal and standin should be
Matt Harbison
largefiles: fix an explicit largefile commit after a remove (issue4969)...
r27942 # committed (except if one of them is a remove). In the case of a
# standin removal, drop the normal file if it is unknown to dirstate.
Mads Kiilerich
largefiles: fix explicit commit of normal/largefile switch...
r26817 # Thus, skip plain largefile names but keep the standin.
Matt Harbison
largefiles: fix an explicit largefile commit after a remove (issue4969)...
r27942 if f in lfiles or fstandin in standins:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo.dirstate[fstandin] != b'r':
if repo.dirstate[f] != b'r':
Matt Harbison
largefiles: fix an explicit largefile commit after a remove (issue4969)...
r27942 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif repo.dirstate[f] == b'?':
Matt Harbison
largefiles: fix an explicit largefile commit after a remove (issue4969)...
r27942 continue
FUJIWARA Katsunori
largefiles: factor out procedures to update standins for pre-committing...
r23185
actualfiles.append(f)
match._files = actualfiles
def matchfn(f):
if origmatchfn(f):
return f not in lfiles
else:
return f in standins
match.matchfn = matchfn
return match
FUJIWARA Katsunori
largefiles: update standins only at the 1st commit of "hg rebase --continue"...
r23187
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: update standins only at the 1st commit of "hg rebase --continue"...
r23187 class automatedcommithook(object):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Stateful hook to update standins at the 1st commit of resuming
FUJIWARA Katsunori
largefiles: update standins only at the 1st commit of "hg rebase --continue"...
r23187
For efficiency, updating standins in the working directory should
be avoided while automated committing (like rebase, transplant and
so on), because they should be updated before committing.
But the 1st commit of resuming automated committing (e.g. ``rebase
--continue``) should update them, because largefiles may be
modified manually.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: update standins only at the 1st commit of "hg rebase --continue"...
r23187 def __init__(self, resuming):
self.resuming = resuming
def __call__(self, repo, match):
if self.resuming:
Augie Fackler
formatting: blacken the codebase...
r43346 self.resuming = False # avoids updating at subsequent commits
FUJIWARA Katsunori
largefiles: update standins only at the 1st commit of "hg rebase --continue"...
r23187 return updatestandinsbymatch(repo, match)
else:
return match
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188 def getstatuswriter(ui, repo, forcibly=None):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return the function to write largefiles specific status out
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188
If ``forcibly`` is ``None``, this returns the last element of
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23543 ``repo._lfstatuswriters`` as "default" writer function.
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188
Otherwise, this returns the function to always write out (or
ignore if ``not forcibly``) status.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if forcibly is None and util.safehasattr(repo, b'_largefilesenabled'):
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188 return repo._lfstatuswriters[-1]
else:
if forcibly:
Augie Fackler
formatting: blacken the codebase...
r43346 return ui.status # forcibly WRITE OUT
FUJIWARA Katsunori
largefiles: introduce "_lfstatuswriters" to customize status reporting...
r23188 else:
Augie Fackler
formatting: blacken the codebase...
r43346 return lambda *msg, **opts: None # forcibly IGNORE