Mercurial > hg
diff hgext/largefiles/overrides.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 749ef8c31187 |
children | 687b865b95ad |
line wrap: on
line diff
--- a/hgext/largefiles/overrides.py Sat Oct 05 10:29:34 2019 -0400 +++ b/hgext/largefiles/overrides.py Sun Oct 06 09:45:02 2019 -0400 @@ -14,9 +14,7 @@ from mercurial.i18n import _ -from mercurial.hgweb import ( - webcommands, -) +from mercurial.hgweb import webcommands from mercurial import ( archival, @@ -51,6 +49,7 @@ # -- Utility functions: commonly/repeatedly needed functionality --------------- + def composelargefilematcher(match, manifest): '''create a matcher that matches only the largefiles in the original matcher''' @@ -63,14 +62,16 @@ m.matchfn = lambda f: lfile(f) and origmatchfn(f) return m + def composenormalfilematcher(match, manifest, exclude=None): excluded = set() if exclude is not None: excluded.update(exclude) m = copy.copy(match) - notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in - manifest or f in excluded) + notlfile = lambda f: not ( + lfutil.isstandin(f) or lfutil.standin(f) in manifest or f in excluded + ) m._files = [lf for lf in m._files if notlfile(lf)] m._fileset = set(m._files) m.always = lambda: False @@ -78,10 +79,12 @@ m.matchfn = lambda f: notlfile(f) and origmatchfn(f) return m + def addlargefiles(ui, repo, isaddremove, matcher, uipathfn, **opts): large = opts.get(r'large') lfsize = lfutil.getminsize( - ui, lfutil.islfilesrepo(repo), opts.get(r'lfsize')) + ui, lfutil.islfilesrepo(repo), opts.get(r'lfsize') + ) lfmatcher = None if lfutil.islfilesrepo(repo): @@ -112,8 +115,9 @@ if not repo.wvfs.exists(f): continue - abovemin = (lfsize and - repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024) + abovemin = ( + lfsize and repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024 + ) if large or abovemin or (lfmatcher and lfmatcher(f)): lfnames.append(f) if ui.verbose or not exact: @@ -129,21 +133,28 @@ lfdirstate = lfutil.openlfdirstate(ui, repo) for f in lfnames: standinname = lfutil.standin(f) - lfutil.writestandin(repo, standinname, hash='', - executable=lfutil.getexecutable(repo.wjoin(f))) + lfutil.writestandin( + repo, + standinname, + hash='', + executable=lfutil.getexecutable(repo.wjoin(f)), + ) standins.append(standinname) if lfdirstate[f] == 'r': lfdirstate.normallookup(f) else: lfdirstate.add(f) lfdirstate.write() - bad += [lfutil.splitstandin(f) - for f in repo[None].add(standins) - if f in m.files()] + bad += [ + lfutil.splitstandin(f) + for f in repo[None].add(standins) + if f in m.files() + ] added = [f for f in lfnames if f not in bad] return added, bad + def removelargefiles(ui, repo, isaddremove, matcher, uipathfn, dryrun, **opts): after = opts.get(r'after') m = composelargefilematcher(matcher, repo[None].manifest()) @@ -153,10 +164,10 @@ finally: repo.lfstatus = False manifest = repo[None].manifest() - modified, added, deleted, clean = [[f for f in list - if lfutil.standin(f) in manifest] - for list in (s.modified, s.added, - s.deleted, s.clean)] + modified, added, deleted, clean = [ + [f for f in list if lfutil.standin(f) in manifest] + for list in (s.modified, s.added, s.deleted, s.clean) + ] def warn(files, msg): for f in files: @@ -165,14 +176,28 @@ if after: remove = deleted - result = warn(modified + added + clean, - _('not removing %s: file still exists\n')) + result = warn( + modified + added + clean, _('not removing %s: file still exists\n') + ) else: remove = deleted + clean - result = warn(modified, _('not removing %s: file is modified (use -f' - ' to force removal)\n')) - result = warn(added, _('not removing %s: file has been marked for add' - ' (use forget to undo)\n')) or result + result = warn( + modified, + _( + 'not removing %s: file is modified (use -f' + ' to force removal)\n' + ), + ) + result = ( + warn( + added, + _( + 'not removing %s: file has been marked for add' + ' (use forget to undo)\n' + ), + ) + or result + ) # Need to lock because standin files are deleted then removed from the # repository and we could race in-between. @@ -198,31 +223,47 @@ repo[None].forget(remove) for f in remove: - lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f), - False) + lfutil.synclfdirstate( + repo, lfdirstate, lfutil.splitstandin(f), False + ) lfdirstate.write() return result + # For overriding mercurial.hgweb.webcommands so that largefiles will # appear at their right place in the manifests. @eh.wrapfunction(webcommands, 'decodepath') def decodepath(orig, path): return lfutil.splitstandin(path) or path + # -- Wrappers: modify existing commands -------------------------------- -@eh.wrapcommand('add', - opts=[('', 'large', None, _('add as largefile')), - ('', 'normal', None, _('add as normal file')), - ('', 'lfsize', '', _('add all files above this size (in megabytes) ' - 'as largefiles (default: 10)'))]) + +@eh.wrapcommand( + 'add', + opts=[ + ('', 'large', None, _('add as largefile')), + ('', 'normal', None, _('add as normal file')), + ( + '', + 'lfsize', + '', + _( + 'add all files above this size (in megabytes) ' + 'as largefiles (default: 10)' + ), + ), + ], +) def overrideadd(orig, ui, repo, *pats, **opts): if opts.get(r'normal') and opts.get(r'large'): raise error.Abort(_('--normal cannot be used with --large')) return orig(ui, repo, *pats, **opts) + @eh.wrapfunction(cmdutil, 'add') def cmdutiladd(orig, ui, repo, matcher, prefix, uipathfn, explicitonly, **opts): # The --normal flag short circuits this override @@ -230,21 +271,38 @@ return orig(ui, repo, matcher, prefix, uipathfn, explicitonly, **opts) ladded, lbad = addlargefiles(ui, repo, False, matcher, uipathfn, **opts) - normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(), - ladded) + normalmatcher = composenormalfilematcher( + matcher, repo[None].manifest(), ladded + ) bad = orig(ui, repo, normalmatcher, prefix, uipathfn, explicitonly, **opts) bad.extend(f for f in lbad) return bad + @eh.wrapfunction(cmdutil, 'remove') -def cmdutilremove(orig, ui, repo, matcher, prefix, uipathfn, after, force, - subrepos, dryrun): +def cmdutilremove( + orig, ui, repo, matcher, prefix, uipathfn, after, force, subrepos, dryrun +): normalmatcher = composenormalfilematcher(matcher, repo[None].manifest()) - result = orig(ui, repo, normalmatcher, prefix, uipathfn, after, force, - subrepos, dryrun) - return removelargefiles(ui, repo, False, matcher, uipathfn, dryrun, - after=after, force=force) or result + result = orig( + ui, + repo, + normalmatcher, + prefix, + uipathfn, + after, + force, + subrepos, + dryrun, + ) + return ( + removelargefiles( + ui, repo, False, matcher, uipathfn, dryrun, after=after, force=force + ) + or result + ) + @eh.wrapfunction(subrepo.hgsubrepo, 'status') def overridestatusfn(orig, repo, rev2, **opts): @@ -254,6 +312,7 @@ finally: repo._repo.lfstatus = False + @eh.wrapcommand('status') def overridestatus(orig, ui, repo, *pats, **opts): try: @@ -262,6 +321,7 @@ finally: repo.lfstatus = False + @eh.wrapfunction(subrepo.hgsubrepo, 'dirty') def overridedirty(orig, repo, ignoreupdate=False, missing=False): try: @@ -270,10 +330,18 @@ finally: repo._repo.lfstatus = False + @eh.wrapcommand('log') def overridelog(orig, ui, repo, *pats, **opts): - def overridematchandpats(orig, ctx, pats=(), opts=None, globbed=False, - default='relpath', badfn=None): + def overridematchandpats( + orig, + ctx, + pats=(), + opts=None, + globbed=False, + default='relpath', + badfn=None, + ): """Matcher that merges root directory with .hglf, suitable for log. It is still possible to match .hglf directly. For any listed files run log on the standin too. @@ -304,13 +372,13 @@ cwd = repo.getcwd() if cwd: hglf = lfutil.shortname - back = util.pconvert(repo.pathto(hglf)[:-len(hglf)]) + back = util.pconvert(repo.pathto(hglf)[: -len(hglf)]) def tostandin(f): # The file may already be a standin, so truncate the back # prefix and test before mangling it. This avoids turning # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'. - if f.startswith(back) and lfutil.splitstandin(f[len(back):]): + if f.startswith(back) and lfutil.splitstandin(f[len(back) :]): return f # An absolute path is from outside the repo, so truncate the @@ -318,15 +386,18 @@ # is somewhere in the repo, relative to root, and needs to be # prepended before building the standin. if os.path.isabs(cwd): - f = f[len(back):] + f = f[len(back) :] else: f = cwd + '/' + f return back + lfutil.standin(f) + else: + def tostandin(f): if lfutil.isstandin(f): return f return lfutil.standin(f) + pats.update(fixpats(f, tostandin) for f in p) for i in range(0, len(m._files)): @@ -346,12 +417,14 @@ m._fileset = set(m._files) m.always = lambda: False origmatchfn = m.matchfn + def lfmatchfn(f): lf = lfutil.splitstandin(f) if lf is not None and origmatchfn(lf): return True r = origmatchfn(f) return r + m.matchfn = lfmatchfn ui.debug('updated patterns: %s\n' % ', '.join(sorted(pats))) @@ -363,25 +436,45 @@ # The magic matchandpats override should be used for case (1) but not for # case (2). oldmatchandpats = scmutil.matchandpats + def overridemakefilematcher(orig, repo, pats, opts, badfn=None): wctx = repo[None] match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn) return lambda ctx: match - wrappedmatchandpats = extensions.wrappedfunction(scmutil, 'matchandpats', - overridematchandpats) + wrappedmatchandpats = extensions.wrappedfunction( + scmutil, 'matchandpats', overridematchandpats + ) wrappedmakefilematcher = extensions.wrappedfunction( - logcmdutil, '_makenofollowfilematcher', overridemakefilematcher) + logcmdutil, '_makenofollowfilematcher', overridemakefilematcher + ) with wrappedmatchandpats, wrappedmakefilematcher: return orig(ui, repo, *pats, **opts) -@eh.wrapcommand('verify', - opts=[('', 'large', None, - _('verify that all largefiles in current revision exists')), - ('', 'lfa', None, - _('verify largefiles in all revisions, not just current')), - ('', 'lfc', None, - _('verify local largefile contents, not just existence'))]) + +@eh.wrapcommand( + 'verify', + opts=[ + ( + '', + 'large', + None, + _('verify that all largefiles in current revision exists'), + ), + ( + '', + 'lfa', + None, + _('verify largefiles in all revisions, not just current'), + ), + ( + '', + 'lfc', + None, + _('verify local largefile contents, not just existence'), + ), + ], +) def overrideverify(orig, ui, repo, *pats, **opts): large = opts.pop(r'large', False) all = opts.pop(r'lfa', False) @@ -392,17 +485,22 @@ result = result or lfcommands.verifylfiles(ui, repo, all, contents) return result -@eh.wrapcommand('debugstate', - opts=[('', 'large', None, _('display largefiles dirstate'))]) + +@eh.wrapcommand( + 'debugstate', opts=[('', 'large', None, _('display largefiles dirstate'))] +) def overridedebugstate(orig, ui, repo, *pats, **opts): large = opts.pop(r'large', False) if large: + class fakerepo(object): dirstate = lfutil.openlfdirstate(ui, repo) + orig(ui, fakerepo, *pats, **opts) else: orig(ui, repo, *pats, **opts) + # Before starting the manifest merge, merge.updates will call # _checkunknownfile to check if there are any files in the merged-in # changeset that collide with unknown files in the working copy. @@ -419,6 +517,7 @@ return False return origfn(repo, wctx, mctx, f, f2) + # The manifest merge handles conflicts on the manifest level. We want # to handle changes in largefile-ness of files at this level too. # @@ -446,11 +545,13 @@ # writing the files into the working copy and lfcommands.updatelfiles # will update the largefiles. @eh.wrapfunction(merge, 'calculateupdates') -def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force, - acceptremote, *args, **kwargs): +def overridecalculateupdates( + origfn, repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs +): overwrite = force and not branchmerge actions, diverge, renamedelete = origfn( - repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs) + repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs + ) if overwrite: return actions, diverge, renamedelete @@ -474,13 +575,18 @@ sargs = (p2[f2].flags(), False) # Case 1: normal file in the working copy, largefile in # the second parent - usermsg = _('remote turned local normal file %s into a largefile\n' - 'use (l)argefile or keep (n)ormal file?' - '$$ &Largefile $$ &Normal file') % lfile - if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile + usermsg = ( + _( + 'remote turned local normal file %s into a largefile\n' + 'use (l)argefile or keep (n)ormal file?' + '$$ &Largefile $$ &Normal file' + ) + % lfile + ) + if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile actions[lfile] = ('r', None, 'replaced by standin') actions[standin] = ('g', sargs, 'replaces standin') - else: # keep local normal file + else: # keep local normal file actions[lfile] = ('k', None, 'replaces standin') if branchmerge: actions[standin] = ('k', None, 'replaced by non-standin') @@ -492,10 +598,15 @@ largs = (p2[f2].flags(), False) # Case 2: largefile in the working copy, normal file in # the second parent - usermsg = _('remote turned local largefile %s into a normal file\n' + usermsg = ( + _( + 'remote turned local largefile %s into a normal file\n' 'keep (l)argefile or use (n)ormal file?' - '$$ &Largefile $$ &Normal file') % lfile - if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile + '$$ &Largefile $$ &Normal file' + ) + % lfile + ) + if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile if branchmerge: # largefile can be restored from standin safely actions[lfile] = ('k', None, 'replaced by standin') @@ -503,17 +614,21 @@ else: # "lfile" should be marked as "removed" without # removal of itself - actions[lfile] = ('lfmr', None, - 'forget non-standin largefile') + actions[lfile] = ( + 'lfmr', + None, + 'forget non-standin largefile', + ) # linear-merge should treat this largefile as 're-added' actions[standin] = ('a', None, 'keep standin') - else: # pick remote normal file + else: # pick remote normal file actions[lfile] = ('g', largs, 'replaces standin') actions[standin] = ('r', None, 'replaced by non-standin') return actions, diverge, renamedelete + @eh.wrapfunction(merge, 'recordupdates') def mergerecordupdates(orig, repo, actions, branchmerge, getfiledata): if 'lfmr' in actions: @@ -528,31 +643,43 @@ return orig(repo, actions, branchmerge, getfiledata) + # Override filemerge to prompt the user about how they wish to merge # largefiles. This will handle identical edits without prompting the user. @eh.wrapfunction(filemerge, '_filemerge') -def overridefilemerge(origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, - labels=None): +def overridefilemerge( + origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None +): if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent(): - return origfn(premerge, repo, wctx, mynode, orig, fcd, fco, fca, - labels=labels) + return origfn( + premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=labels + ) ahash = lfutil.readasstandin(fca).lower() dhash = lfutil.readasstandin(fcd).lower() ohash = lfutil.readasstandin(fco).lower() - if (ohash != ahash and - ohash != dhash and - (dhash == ahash or - repo.ui.promptchoice( - _('largefile %s has a merge conflict\nancestor was %s\n' - 'you can keep (l)ocal %s or take (o)ther %s.\n' - 'what do you want to do?' - '$$ &Local $$ &Other') % - (lfutil.splitstandin(orig), ahash, dhash, ohash), - 0) == 1)): + if ( + ohash != ahash + and ohash != dhash + and ( + dhash == ahash + or repo.ui.promptchoice( + _( + 'largefile %s has a merge conflict\nancestor was %s\n' + 'you can keep (l)ocal %s or take (o)ther %s.\n' + 'what do you want to do?' + '$$ &Local $$ &Other' + ) + % (lfutil.splitstandin(orig), ahash, dhash, ohash), + 0, + ) + == 1 + ) + ): repo.wwrite(fcd.path(), fco.data(), fco.flags()) return True, 0, False + @eh.wrapfunction(copiesmod, 'pathcopies') def copiespathcopies(orig, ctx1, ctx2, match=None): copies = orig(ctx1, ctx2, match=match) @@ -563,6 +690,7 @@ return updated + # Copy first changes the matchers to match standins instead of # largefiles. Then it overrides util.copyfile in that function it # checks if the destination largefile already exists. It also keeps a @@ -582,12 +710,21 @@ nonormalfiles = False nolfiles = False manifest = repo[None].manifest() - def normalfilesmatchfn(orig, ctx, pats=(), opts=None, globbed=False, - default='relpath', badfn=None): + + def normalfilesmatchfn( + orig, + ctx, + pats=(), + opts=None, + globbed=False, + default='relpath', + badfn=None, + ): if opts is None: opts = {} match = orig(ctx, pats, opts, globbed, default, badfn=badfn) return composenormalfilematcher(match, manifest) + with extensions.wrappedfunction(scmutil, 'match', normalfilesmatchfn): try: result = orig(ui, repo, pats, opts, rename) @@ -622,8 +759,16 @@ wlock = repo.wlock() manifest = repo[None].manifest() - def overridematch(orig, ctx, pats=(), opts=None, globbed=False, - default='relpath', badfn=None): + + def overridematch( + orig, + ctx, + pats=(), + opts=None, + globbed=False, + default='relpath', + badfn=None, + ): if opts is None: opts = {} newpats = [] @@ -640,14 +785,19 @@ m._files = [lfutil.standin(f) for f in m._files if lfile(f)] m._fileset = set(m._files) origmatchfn = m.matchfn + def matchfn(f): lfile = lfutil.splitstandin(f) - return (lfile is not None and - (f in manifest) and - origmatchfn(lfile) or - None) + return ( + lfile is not None + and (f in manifest) + and origmatchfn(lfile) + or None + ) + m.matchfn = matchfn return m + listpats = [] for pat in pats: if matchmod.patkind(pat) is not None: @@ -656,23 +806,26 @@ listpats.append(makestandin(pat)) copiedfiles = [] + def overridecopyfile(orig, src, dest, *args, **kwargs): - if (lfutil.shortname in src and - dest.startswith(repo.wjoin(lfutil.shortname))): + if lfutil.shortname in src and dest.startswith( + repo.wjoin(lfutil.shortname) + ): destlfile = dest.replace(lfutil.shortname, '') if not opts['force'] and os.path.exists(destlfile): - raise IOError('', - _('destination largefile already exists')) + raise IOError('', _('destination largefile already exists')) copiedfiles.append((src, dest)) orig(src, dest, *args, **kwargs) + with extensions.wrappedfunction(util, 'copyfile', overridecopyfile): with extensions.wrappedfunction(scmutil, 'match', overridematch): result += orig(ui, repo, listpats, opts, rename) lfdirstate = lfutil.openlfdirstate(ui, repo) for (src, dest) in copiedfiles: - if (lfutil.shortname in src and - dest.startswith(repo.wjoin(lfutil.shortname))): + if lfutil.shortname in src and dest.startswith( + repo.wjoin(lfutil.shortname) + ): srclfile = src.replace(repo.wjoin(lfutil.standin('')), '') destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '') destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.' @@ -686,8 +839,7 @@ repo.wvfs.unlinkpath(srclfile, ignoremissing=True) lfdirstate.remove(srclfile) else: - util.copyfile(repo.wjoin(srclfile), - repo.wjoin(destlfile)) + util.copyfile(repo.wjoin(srclfile), repo.wjoin(destlfile)) lfdirstate.add(destlfile) lfdirstate.write() @@ -704,6 +856,7 @@ return result + # When the user calls revert, we have to be careful to not revert any # changes to other largefiles accidentally. This means we have to keep # track of the largefiles that are being reverted so we only pull down @@ -726,13 +879,20 @@ lfutil.updatestandin(repo, lfile, lfutil.standin(lfile)) for lfile in s.deleted: fstandin = lfutil.standin(lfile) - if (repo.wvfs.exists(fstandin)): + if repo.wvfs.exists(fstandin): repo.wvfs.unlink(fstandin) oldstandins = lfutil.getstandinsstate(repo) - def overridematch(orig, mctx, pats=(), opts=None, globbed=False, - default='relpath', badfn=None): + def overridematch( + orig, + mctx, + pats=(), + opts=None, + globbed=False, + default='relpath', + badfn=None, + ): if opts is None: opts = {} match = orig(mctx, pats, opts, globbed, default, badfn=badfn) @@ -742,8 +902,9 @@ # currently doesn't work correctly in that case, this match is # called, so the lfdirstate above may not be the correct one for # this invocation of match. - lfdirstate = lfutil.openlfdirstate(mctx.repo().ui, mctx.repo(), - False) + lfdirstate = lfutil.openlfdirstate( + mctx.repo().ui, mctx.repo(), False + ) wctx = repo[None] matchfiles = [] @@ -758,14 +919,16 @@ m._files = matchfiles m._fileset = set(m._files) origmatchfn = m.matchfn + def matchfn(f): lfile = lfutil.splitstandin(f) if lfile is not None: - return (origmatchfn(lfile) and - (f in ctx or f in mctx)) + return origmatchfn(lfile) and (f in ctx or f in mctx) return origmatchfn(f) + m.matchfn = matchfn return m + with extensions.wrappedfunction(scmutil, 'match', overridematch): orig(ui, repo, ctx, parents, *pats, **opts) @@ -776,16 +939,31 @@ # when target revision is explicitly specified: in such case, # 'n' and valid timestamp in dirstate doesn't ensure 'clean' # of target (standin) file. - lfcommands.updatelfiles(ui, repo, filelist, printmessage=False, - normallookup=True) + lfcommands.updatelfiles( + ui, repo, filelist, printmessage=False, normallookup=True + ) + # after pulling changesets, we need to take some extra care to get # largefiles updated remotely -@eh.wrapcommand('pull', - opts=[('', 'all-largefiles', None, - _('download all pulled versions of largefiles (DEPRECATED)')), - ('', 'lfrev', [], - _('download largefiles for these revisions'), _('REV'))]) +@eh.wrapcommand( + 'pull', + opts=[ + ( + '', + 'all-largefiles', + None, + _('download all pulled versions of largefiles (DEPRECATED)'), + ), + ( + '', + 'lfrev', + [], + _('download largefiles for these revisions'), + _('REV'), + ), + ], +) def overridepull(orig, ui, repo, source=None, **opts): revsprepull = len(repo) if not source: @@ -798,7 +976,7 @@ lfrevs.append('pulled()') if lfrevs and revspostpull > revsprepull: numcached = 0 - repo.firstpulled = revsprepull # for pulled() revset expression + repo.firstpulled = revsprepull # for pulled() revset expression try: for rev in scmutil.revrange(repo, lfrevs): ui.note(_('pulling largefiles for revision %d\n') % rev) @@ -809,9 +987,13 @@ ui.status(_("%d largefiles cached\n") % numcached) return result -@eh.wrapcommand('push', - opts=[('', 'lfrev', [], - _('upload largefiles for these revisions'), _('REV'))]) + +@eh.wrapcommand( + 'push', + opts=[ + ('', 'lfrev', [], _('upload largefiles for these revisions'), _('REV')) + ], +) def overridepush(orig, ui, repo, *args, **kwargs): """Override push command and store --lfrev parameters in opargs""" lfrevs = kwargs.pop(r'lfrev', None) @@ -820,6 +1002,7 @@ opargs['lfrevs'] = scmutil.revrange(repo, lfrevs) return orig(ui, repo, *args, **kwargs) + @eh.wrapfunction(exchange, 'pushoperation') def exchangepushoperation(orig, *args, **kwargs): """Override pushoperation constructor and store lfrevs parameter""" @@ -828,6 +1011,7 @@ pushop.lfrevs = lfrevs return pushop + @eh.revsetpredicate('pulled()') def pulledrevsetsymbol(repo, subset, x): """Changesets that just has been pulled. @@ -854,20 +1038,31 @@ raise error.Abort(_("pulled() only available in --lfrev")) return smartset.baseset([r for r in subset if r >= firstpulled]) -@eh.wrapcommand('clone', - opts=[('', 'all-largefiles', None, - _('download all versions of all largefiles'))]) + +@eh.wrapcommand( + 'clone', + opts=[ + ( + '', + 'all-largefiles', + None, + _('download all versions of all largefiles'), + ) + ], +) def overrideclone(orig, ui, source, dest=None, **opts): d = dest if d is None: d = hg.defaultdest(source) if opts.get(r'all_largefiles') and not hg.islocal(d): - raise error.Abort(_( - '--all-largefiles is incompatible with non-local destination %s') % - d) + raise error.Abort( + _('--all-largefiles is incompatible with non-local destination %s') + % d + ) return orig(ui, source, dest, **opts) + @eh.wrapfunction(hg, 'clone') def hgclone(orig, ui, opts, *args, **kwargs): result = orig(ui, opts, *args, **kwargs) @@ -893,6 +1088,7 @@ return result + @eh.wrapcommand('rebase', extension='rebase') def overriderebase(orig, ui, repo, **opts): if not util.safehasattr(repo, '_largefilesenabled'): @@ -907,6 +1103,7 @@ repo._lfstatuswriters.pop() repo._lfcommithooks.pop() + @eh.wrapcommand('archive') def overridearchivecmd(orig, ui, repo, dest, **opts): repo.unfiltered().lfstatus = True @@ -916,6 +1113,7 @@ finally: repo.unfiltered().lfstatus = False + @eh.wrapfunction(webcommands, 'archive') def hgwebarchive(orig, web): web.repo.lfstatus = True @@ -925,14 +1123,26 @@ finally: web.repo.lfstatus = False + @eh.wrapfunction(archival, 'archive') -def overridearchive(orig, repo, dest, node, kind, decode=True, match=None, - prefix='', mtime=None, subrepos=None): +def overridearchive( + orig, + repo, + dest, + node, + kind, + decode=True, + match=None, + prefix='', + mtime=None, + subrepos=None, +): # For some reason setting repo.lfstatus in hgwebarchive only changes the # unfiltered repo's attr, so check that as well. if not repo.lfstatus and not repo.unfiltered().lfstatus: - return orig(repo, dest, node, kind, decode, match, prefix, mtime, - subrepos) + return orig( + repo, dest, node, kind, decode, match, prefix, mtime, subrepos + ) # No need to lock because we are only reading history and # largefile caches, neither of which are modified. @@ -946,8 +1156,7 @@ if kind == 'files': if prefix: - raise error.Abort( - _('cannot give prefix when archiving to files')) + raise error.Abort(_('cannot give prefix when archiving to files')) else: prefix = archival.tidyprefix(dest, kind, prefix) @@ -962,8 +1171,12 @@ archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) if repo.ui.configbool("ui", "archivemeta"): - write('.hg_archival.txt', 0o644, False, - lambda: archival.buildmetadata(ctx)) + write( + '.hg_archival.txt', + 0o644, + False, + lambda: archival.buildmetadata(ctx), + ) for f in ctx: ff = ctx.flags(f) @@ -975,8 +1188,11 @@ if path is None: raise error.Abort( - _('largefile %s not found in repo store or system cache') - % lfile) + _( + 'largefile %s not found in repo store or system cache' + ) + % lfile + ) else: path = lfile @@ -995,6 +1211,7 @@ archiver.done() + @eh.wrapfunction(subrepo.hgsubrepo, 'archive') def hgsubrepoarchive(orig, repo, archiver, prefix, match=None, decode=True): lfenabled = util.safehasattr(repo._repo, '_largefilesenabled') @@ -1029,8 +1246,11 @@ if path is None: raise error.Abort( - _('largefile %s not found in repo store or system cache') - % lfile) + _( + 'largefile %s not found in repo store or system cache' + ) + % lfile + ) else: path = lfile @@ -1047,6 +1267,7 @@ sub._repo.lfstatus = True sub.archive(archiver, subprefix, submatch, decode) + # If a largefile is modified, the change is not reflected in its # standin until a commit. cmdutil.bailifchanged() raises an exception # if the repo has uncommitted changes. Wrap it to also check if @@ -1060,6 +1281,7 @@ if s.modified or s.added or s.removed or s.deleted: raise error.Abort(_('uncommitted changes')) + @eh.wrapfunction(cmdutil, 'postcommitstatus') def postcommitstatus(orig, repo, *args, **kwargs): repo.lfstatus = True @@ -1068,12 +1290,22 @@ finally: repo.lfstatus = False + @eh.wrapfunction(cmdutil, 'forget') -def cmdutilforget(orig, ui, repo, match, prefix, uipathfn, explicitonly, dryrun, - interactive): +def cmdutilforget( + orig, ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive +): normalmatcher = composenormalfilematcher(match, repo[None].manifest()) - bad, forgot = orig(ui, repo, normalmatcher, prefix, uipathfn, explicitonly, - dryrun, interactive) + bad, forgot = orig( + ui, + repo, + normalmatcher, + prefix, + uipathfn, + explicitonly, + dryrun, + interactive, + ) m = composelargefilematcher(match, repo[None].manifest()) try: @@ -1088,8 +1320,9 @@ for f in forget: fstandin = lfutil.standin(f) if fstandin not in repo.dirstate and not repo.wvfs.isdir(fstandin): - ui.warn(_('not removing %s: file is already untracked\n') - % uipathfn(f)) + ui.warn( + _('not removing %s: file is already untracked\n') % uipathfn(f) + ) bad.append(f) for f in forget: @@ -1115,6 +1348,7 @@ forgot.extend(f for f in forget if f not in rejected) return bad, forgot + def _getoutgoings(repo, other, missing, addfunc): """get pairs of filename and largefile hash in outgoing revisions in 'missing'. @@ -1126,62 +1360,75 @@ """ knowns = set() lfhashes = set() + def dedup(fn, lfhash): k = (fn, lfhash) if k not in knowns: knowns.add(k) lfhashes.add(lfhash) + lfutil.getlfilestoupload(repo, missing, dedup) if lfhashes: lfexists = storefactory.openstore(repo, other).exists(lfhashes) for fn, lfhash in knowns: - if not lfexists[lfhash]: # lfhash doesn't exist on "other" + if not lfexists[lfhash]: # lfhash doesn't exist on "other" addfunc(fn, lfhash) + def outgoinghook(ui, repo, other, opts, missing): if opts.pop('large', None): lfhashes = set() if ui.debugflag: toupload = {} + def addfunc(fn, lfhash): if fn not in toupload: toupload[fn] = [] toupload[fn].append(lfhash) lfhashes.add(lfhash) + def showhashes(fn): for lfhash in sorted(toupload[fn]): - ui.debug(' %s\n' % (lfhash)) + ui.debug(' %s\n' % lfhash) + else: toupload = set() + def addfunc(fn, lfhash): toupload.add(fn) lfhashes.add(lfhash) + def showhashes(fn): pass + _getoutgoings(repo, other, missing, addfunc) if not toupload: ui.status(_('largefiles: no files to upload\n')) else: - ui.status(_('largefiles to upload (%d entities):\n') - % (len(lfhashes))) + ui.status( + _('largefiles to upload (%d entities):\n') % (len(lfhashes)) + ) for file in sorted(toupload): ui.status(lfutil.splitstandin(file) + '\n') showhashes(file) ui.status('\n') -@eh.wrapcommand('outgoing', - opts=[('', 'large', None, _('display outgoing largefiles'))]) + +@eh.wrapcommand( + 'outgoing', opts=[('', 'large', None, _('display outgoing largefiles'))] +) def _outgoingcmd(orig, *args, **kwargs): # Nothing to do here other than add the extra help option- the hook above # processes it. return orig(*args, **kwargs) + def summaryremotehook(ui, repo, opts, changes): largeopt = opts.get('large', False) if changes is None: if largeopt: - return (False, True) # only outgoing check is needed + return (False, True) # only outgoing check is needed else: return (False, False) elif largeopt: @@ -1193,9 +1440,11 @@ toupload = set() lfhashes = set() + def addfunc(fn, lfhash): toupload.add(fn) lfhashes.add(lfhash) + _getoutgoings(repo, peer, outgoing.missing, addfunc) if not toupload: @@ -1203,11 +1452,15 @@ ui.status(_('largefiles: (no files to upload)\n')) else: # i18n: column positioning for "hg summary" - ui.status(_('largefiles: %d entities for %d files to upload\n') - % (len(lfhashes), len(toupload))) + ui.status( + _('largefiles: %d entities for %d files to upload\n') + % (len(lfhashes), len(toupload)) + ) -@eh.wrapcommand('summary', - opts=[('', 'large', None, _('display outgoing largefiles'))]) + +@eh.wrapcommand( + 'summary', opts=[('', 'large', None, _('display outgoing largefiles'))] +) def overridesummary(orig, ui, repo, *pats, **opts): try: repo.lfstatus = True @@ -1215,6 +1468,7 @@ finally: repo.lfstatus = False + @eh.wrapfunction(scmutil, 'addremove') def scmutiladdremove(orig, repo, matcher, prefix, uipathfn, opts=None): if opts is None: @@ -1223,8 +1477,13 @@ return orig(repo, matcher, prefix, uipathfn, opts) # Get the list of missing largefiles so we can remove them lfdirstate = lfutil.openlfdirstate(repo.ui, repo) - unsure, s = lfdirstate.status(matchmod.always(), subrepos=[], - ignored=False, clean=False, unknown=False) + unsure, s = lfdirstate.status( + matchmod.always(), + subrepos=[], + ignored=False, + clean=False, + unknown=False, + ) # Call into the normal remove code, but the removing of the standin, we want # to have handled by original addremove. Monkey patching here makes sure @@ -1240,18 +1499,27 @@ matchfn = m.matchfn m.matchfn = lambda f: f in s.deleted and matchfn(f) - removelargefiles(repo.ui, repo, True, m, uipathfn, opts.get('dry_run'), - **pycompat.strkwargs(opts)) + removelargefiles( + repo.ui, + repo, + True, + m, + uipathfn, + opts.get('dry_run'), + **pycompat.strkwargs(opts) + ) # Call into the normal add code, and any files that *should* be added as # largefiles will be - added, bad = addlargefiles(repo.ui, repo, True, matcher, uipathfn, - **pycompat.strkwargs(opts)) + added, bad = addlargefiles( + repo.ui, repo, True, matcher, uipathfn, **pycompat.strkwargs(opts) + ) # Now that we've handled largefiles, hand off to the original addremove # function to take care of the rest. Make sure it doesn't do anything with # largefiles by passing a matcher that will ignore them. matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) return orig(repo, matcher, prefix, uipathfn, opts) + # Calling purge with --all will cause the largefiles to be deleted. # Override repo.status to prevent this from happening. @eh.wrapcommand('purge', extension='purge') @@ -1267,29 +1535,44 @@ # cleaner instead. repo = repo.unfiltered() oldstatus = repo.status - def overridestatus(node1='.', node2=None, match=None, ignored=False, - clean=False, unknown=False, listsubrepos=False): - r = oldstatus(node1, node2, match, ignored, clean, unknown, - listsubrepos) + + def overridestatus( + node1='.', + node2=None, + match=None, + ignored=False, + clean=False, + unknown=False, + listsubrepos=False, + ): + r = oldstatus( + node1, node2, match, ignored, clean, unknown, listsubrepos + ) lfdirstate = lfutil.openlfdirstate(ui, repo) unknown = [f for f in r.unknown if lfdirstate[f] == '?'] ignored = [f for f in r.ignored if lfdirstate[f] == '?'] - return scmutil.status(r.modified, r.added, r.removed, r.deleted, - unknown, ignored, r.clean) + return scmutil.status( + r.modified, r.added, r.removed, r.deleted, unknown, ignored, r.clean + ) + repo.status = overridestatus orig(ui, repo, *dirs, **opts) repo.status = oldstatus + @eh.wrapcommand('rollback') def overriderollback(orig, ui, repo, **opts): with repo.wlock(): before = repo.dirstate.parents() - orphans = set(f for f in repo.dirstate - if lfutil.isstandin(f) and repo.dirstate[f] != 'r') + orphans = set( + f + for f in repo.dirstate + if lfutil.isstandin(f) and repo.dirstate[f] != 'r' + ) result = orig(ui, repo, **opts) after = repo.dirstate.parents() if before == after: - return result # no need to restore standins + return result # no need to restore standins pctx = repo['.'] for f in repo.dirstate: @@ -1318,6 +1601,7 @@ lfdirstate.write() return result + @eh.wrapcommand('transplant', extension='transplant') def overridetransplant(orig, ui, repo, *revs, **opts): resuming = opts.get(r'continue') @@ -1330,6 +1614,7 @@ repo._lfcommithooks.pop() return result + @eh.wrapcommand('cat') def overridecat(orig, ui, repo, file1, *pats, **opts): opts = pycompat.byteskwargs(opts) @@ -1338,6 +1623,7 @@ notbad = set() m = scmutil.match(ctx, (file1,) + pats, opts) origmatchfn = m.matchfn + def lfmatchfn(f): if origmatchfn(f): return True @@ -1346,14 +1632,18 @@ return False notbad.add(lf) return origmatchfn(lf) + m.matchfn = lfmatchfn origbadfn = m.bad + def lfbadfn(f, msg): if not f in notbad: origbadfn(f, msg) + m.bad = lfbadfn origvisitdirfn = m.visitdir + def lfvisitdirfn(dir): if dir == lfutil.shortname: return True @@ -1364,6 +1654,7 @@ if lf is None: return False return origvisitdirfn(lf) + m.visitdir = lfvisitdirfn for f in ctx.walk(m): @@ -1382,8 +1673,12 @@ success, missing = store.get([(lf, hash)]) if len(success) != 1: raise error.Abort( - _('largefile %s is not in cache and could not be ' - 'downloaded') % lf) + _( + 'largefile %s is not in cache and could not be ' + 'downloaded' + ) + % lf + ) path = lfutil.usercachepath(repo.ui, hash) with open(path, "rb") as fpin: for chunk in util.filechunkiter(fpin): @@ -1391,9 +1686,9 @@ err = 0 return err + @eh.wrapfunction(merge, 'update') -def mergeupdate(orig, repo, node, branchmerge, force, - *args, **kwargs): +def mergeupdate(orig, repo, node, branchmerge, force, *args, **kwargs): matcher = kwargs.get(r'matcher', None) # note if this is a partial update partial = matcher and not matcher.always() @@ -1414,8 +1709,13 @@ # (*1) deprecated, but used internally (e.g: "rebase --collapse") lfdirstate = lfutil.openlfdirstate(repo.ui, repo) - unsure, s = lfdirstate.status(matchmod.always(), subrepos=[], - ignored=False, clean=True, unknown=False) + unsure, s = lfdirstate.status( + matchmod.always(), + subrepos=[], + ignored=False, + clean=True, + unknown=False, + ) oldclean = set(s.clean) pctx = repo['.'] dctx = repo[node] @@ -1425,10 +1725,12 @@ continue lfhash = lfutil.hashfile(lfileabs) standin = lfutil.standin(lfile) - lfutil.writestandin(repo, standin, lfhash, - lfutil.getexecutable(lfileabs)) - if (standin in pctx and - lfhash == lfutil.readasstandin(pctx[standin])): + lfutil.writestandin( + repo, standin, lfhash, lfutil.getexecutable(lfileabs) + ) + if standin in pctx and lfhash == lfutil.readasstandin( + pctx[standin] + ): oldclean.add(lfile) for lfile in s.added: fstandin = lfutil.standin(lfile) @@ -1462,11 +1764,13 @@ if branchmerge or force or partial: filelist.extend(s.deleted + s.removed) - lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, - normallookup=partial) + lfcommands.updatelfiles( + repo.ui, repo, filelist=filelist, normallookup=partial + ) return result + @eh.wrapfunction(scmutil, 'marktouched') def scmutilmarktouched(orig, repo, files, *args, **kwargs): result = orig(repo, files, *args, **kwargs) @@ -1477,11 +1781,17 @@ if lf is not None: filelist.append(lf) if filelist: - lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, - printmessage=False, normallookup=True) + lfcommands.updatelfiles( + repo.ui, + repo, + filelist=filelist, + printmessage=False, + normallookup=True, + ) return result + @eh.wrapfunction(upgrade, 'preservedrequirements') @eh.wrapfunction(upgrade, 'supporteddestrequirements') def upgraderequirements(orig, repo): @@ -1490,15 +1800,17 @@ reqs.add('largefiles') return reqs + _lfscheme = 'largefile://' + @eh.wrapfunction(urlmod, 'open') def openlargefile(orig, ui, url_, data=None): if url_.startswith(_lfscheme): if data: msg = "cannot use data on a 'largefile://' url" raise error.ProgrammingError(msg) - lfid = url_[len(_lfscheme):] + lfid = url_[len(_lfscheme) :] return storefactory.getlfile(ui, lfid) else: return orig(ui, url_, data=data)