hgext/largefiles/lfcommands.py
changeset 43076 2372284d9457
parent 41775 a86e22007b54
child 43077 687b865b95ad
--- a/hgext/largefiles/lfcommands.py	Sat Oct 05 10:29:34 2019 -0400
+++ b/hgext/largefiles/lfcommands.py	Sun Oct 06 09:45:02 2019 -0400
@@ -35,10 +35,7 @@
     filemap,
 )
 
-from . import (
-    lfutil,
-    storefactory
-)
+from . import lfutil, storefactory
 
 release = lock.release
 
@@ -46,15 +43,28 @@
 
 eh = exthelper.exthelper()
 
-@eh.command('lfconvert',
-    [('s', 'size', '',
-      _('minimum size (MB) for files to be converted as largefiles'), 'SIZE'),
-    ('', 'to-normal', False,
-     _('convert from a largefiles repo to a normal repo')),
+
+@eh.command(
+    'lfconvert',
+    [
+        (
+            's',
+            'size',
+            '',
+            _('minimum size (MB) for files to be converted as largefiles'),
+            'SIZE',
+        ),
+        (
+            '',
+            'to-normal',
+            False,
+            _('convert from a largefiles repo to a normal repo'),
+        ),
     ],
     _('hg lfconvert SOURCE DEST [FILE ...]'),
     norepo=True,
-    inferrepo=True)
+    inferrepo=True,
+)
 def lfconvert(ui, src, dest, *pats, **opts):
     '''convert a normal repository to a largefiles repository
 
@@ -97,8 +107,10 @@
         # is to simply walk the changelog, using changelog.nodesbetween().
         # Take a look at mercurial/revlog.py:639 for more details.
         # Use a generator instead of a list to decrease memory usage
-        ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
-            rsrc.heads())[0])
+        ctxs = (
+            rsrc[ctx]
+            for ctx in rsrc.changelog.nodesbetween(None, rsrc.heads())[0]
+        )
         revmap = {node.nullid: node.nullid}
         if tolfile:
             # Lock destination to prevent modification while it is converted to.
@@ -117,13 +129,24 @@
                 matcher = None
 
             lfiletohash = {}
-            with ui.makeprogress(_('converting revisions'),
-                                 unit=_('revisions'),
-                                 total=rsrc['tip'].rev()) as progress:
+            with ui.makeprogress(
+                _('converting revisions'),
+                unit=_('revisions'),
+                total=rsrc['tip'].rev(),
+            ) as progress:
                 for ctx in ctxs:
                     progress.update(ctx.rev())
-                    _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
-                        lfiles, normalfiles, matcher, size, lfiletohash)
+                    _lfconvert_addchangeset(
+                        rsrc,
+                        rdst,
+                        ctx,
+                        revmap,
+                        lfiles,
+                        normalfiles,
+                        matcher,
+                        size,
+                        lfiletohash,
+                    )
 
             if rdst.wvfs.exists(lfutil.shortname):
                 rdst.wvfs.rmtree(lfutil.shortname)
@@ -142,6 +165,7 @@
                 rdst.requirements.add('largefiles')
                 rdst._writerequirements()
         else:
+
             class lfsource(filemap.filemap_source):
                 def __init__(self, ui, source):
                     super(lfsource, self).__init__(ui, source, None)
@@ -151,8 +175,10 @@
                     realname, realrev = rev
                     f = super(lfsource, self).getfile(name, rev)
 
-                    if (not realname.startswith(lfutil.shortnameslash)
-                            or f[0] is None):
+                    if (
+                        not realname.startswith(lfutil.shortnameslash)
+                        or f[0] is None
+                    ):
                         return f
 
                     # Substitute in the largefile data for the hash
@@ -160,16 +186,19 @@
                     path = lfutil.findfile(rsrc, hash)
 
                     if path is None:
-                        raise error.Abort(_("missing largefile for '%s' in %s")
-                                          % (realname, realrev))
+                        raise error.Abort(
+                            _("missing largefile for '%s' in %s")
+                            % (realname, realrev)
+                        )
                     return util.readfile(path), f[1]
 
             class converter(convcmd.converter):
                 def __init__(self, ui, source, dest, revmapfile, opts):
                     src = lfsource(ui, source)
 
-                    super(converter, self).__init__(ui, src, dest, revmapfile,
-                                                    opts)
+                    super(converter, self).__init__(
+                        ui, src, dest, revmapfile, opts
+                    )
 
             found, missing = downloadlfiles(ui, rsrc)
             if missing != 0:
@@ -191,8 +220,10 @@
             # we failed, remove the new directory
             shutil.rmtree(rdst.root)
 
-def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
-        matcher, size, lfiletohash):
+
+def _lfconvert_addchangeset(
+    rsrc, rdst, ctx, revmap, lfiles, normalfiles, matcher, size, lfiletohash
+):
     # Convert src parents to dst parents
     parents = _convertparents(ctx, revmap)
 
@@ -217,8 +248,8 @@
                 if 'l' in fctx.flags():
                     if renamedlfile:
                         raise error.Abort(
-                            _('renamed/copied largefile %s becomes symlink')
-                            % f)
+                            _('renamed/copied largefile %s becomes symlink') % f
+                        )
                     islfile = False
             if islfile:
                 lfiles.add(f)
@@ -243,8 +274,7 @@
                 if f not in lfiletohash or lfiletohash[f] != hash:
                     rdst.wwrite(f, ctx[f].data(), ctx[f].flags())
                     executable = 'x' in ctx[f].flags()
-                    lfutil.writestandin(rdst, fstandin, hash,
-                        executable)
+                    lfutil.writestandin(rdst, fstandin, hash, executable)
                     lfiletohash[f] = hash
         else:
             # normal file
@@ -265,24 +295,39 @@
                 # doesn't change after rename or copy
                 renamed = lfutil.standin(renamed)
 
-            return context.memfilectx(repo, memctx, f,
-                                      lfiletohash[srcfname] + '\n',
-                                      'l' in fctx.flags(), 'x' in fctx.flags(),
-                                      renamed)
+            return context.memfilectx(
+                repo,
+                memctx,
+                f,
+                lfiletohash[srcfname] + '\n',
+                'l' in fctx.flags(),
+                'x' in fctx.flags(),
+                renamed,
+            )
         else:
             return _getnormalcontext(repo, ctx, f, revmap)
 
     # Commit
     _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
 
+
 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
-    mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
-                          getfilectx, ctx.user(), ctx.date(), ctx.extra())
+    mctx = context.memctx(
+        rdst,
+        parents,
+        ctx.description(),
+        dstfiles,
+        getfilectx,
+        ctx.user(),
+        ctx.date(),
+        ctx.extra(),
+    )
     ret = rdst.commitctx(mctx)
     lfutil.copyalltostore(rdst, ret)
     rdst.setparents(ret)
     revmap[ctx.node()] = rdst.changelog.tip()
 
+
 # Generate list of changed files
 def _getchangedfiles(ctx, parents):
     files = set(ctx.files())
@@ -293,6 +338,7 @@
                 files.add(fn)
     return files
 
+
 # Convert src parents to dst parents
 def _convertparents(ctx, revmap):
     parents = []
@@ -302,6 +348,7 @@
         parents.append(node.nullid)
     return parents
 
+
 # Get memfilectx for a normal file
 def _getnormalcontext(repo, ctx, f, revmap):
     try:
@@ -312,9 +359,11 @@
 
     data = fctx.data()
     if f == '.hgtags':
-        data = _converttags (repo.ui, revmap, data)
-    return context.memfilectx(repo, ctx, f, data, 'l' in fctx.flags(),
-                              'x' in fctx.flags(), renamed)
+        data = _converttags(repo.ui, revmap, data)
+    return context.memfilectx(
+        repo, ctx, f, data, 'l' in fctx.flags(), 'x' in fctx.flags(), renamed
+    )
+
 
 # Remap tag data using a revision map
 def _converttags(ui, revmap, data):
@@ -323,23 +372,21 @@
         try:
             id, name = line.split(' ', 1)
         except ValueError:
-            ui.warn(_('skipping incorrectly formatted tag %s\n')
-                % line)
+            ui.warn(_('skipping incorrectly formatted tag %s\n') % line)
             continue
         try:
             newid = node.bin(id)
         except TypeError:
-            ui.warn(_('skipping incorrectly formatted id %s\n')
-                % id)
+            ui.warn(_('skipping incorrectly formatted id %s\n') % id)
             continue
         try:
-            newdata.append('%s %s\n' % (node.hex(revmap[newid]),
-                name))
+            newdata.append('%s %s\n' % (node.hex(revmap[newid]), name))
         except KeyError:
             ui.warn(_('no mapping for id %s\n') % id)
             continue
     return ''.join(newdata)
 
+
 def _islfile(file, ctx, matcher, size):
     '''Return true if file should be considered a largefile, i.e.
     matcher matches it or it is larger than size.'''
@@ -353,6 +400,7 @@
     except error.LookupError:
         return False
 
+
 def uploadlfiles(ui, rsrc, rdst, files):
     '''upload largefiles to the central store'''
 
@@ -367,18 +415,25 @@
     files = [h for h in files if not retval[h]]
     ui.debug("%d largefiles need to be uploaded\n" % len(files))
 
-    with ui.makeprogress(_('uploading largefiles'), unit=_('files'),
-                         total=len(files)) as progress:
+    with ui.makeprogress(
+        _('uploading largefiles'), unit=_('files'), total=len(files)
+    ) as progress:
         for hash in files:
             progress.update(at)
             source = lfutil.findfile(rsrc, hash)
             if not source:
-                raise error.Abort(_('largefile %s missing from store'
-                                   ' (needs to be uploaded)') % hash)
+                raise error.Abort(
+                    _(
+                        'largefile %s missing from store'
+                        ' (needs to be uploaded)'
+                    )
+                    % hash
+                )
             # XXX check for errors here
             store.put(source, hash)
             at += 1
 
+
 def verifylfiles(ui, repo, all=False, contents=False):
     '''Verify that every largefile revision in the current changeset
     exists in the central store.  With --contents, also verify that
@@ -393,6 +448,7 @@
     store = storefactory.openstore(repo)
     return store.verify(revs, contents=contents)
 
+
 def cachelfiles(ui, repo, node, filelist=None):
     '''cachelfiles ensures that all largefiles needed by the specified revision
     are present in the repository's largefile cache.
@@ -411,7 +467,7 @@
             expectedhash = lfutil.readasstandin(ctx[lfutil.standin(lfile)])
         except IOError as err:
             if err.errno == errno.ENOENT:
-                continue # node must be None and standin wasn't found in wctx
+                continue  # node must be None and standin wasn't found in wctx
             raise
         if not lfutil.findfile(repo, expectedhash):
             toget.append((lfile, expectedhash))
@@ -423,15 +479,17 @@
 
     return ([], [])
 
+
 def downloadlfiles(ui, repo, rev=None):
     match = scmutil.match(repo[None], [repo.wjoin(lfutil.shortname)], {})
+
     def prepare(ctx, fns):
         pass
+
     totalsuccess = 0
     totalmissing = 0
-    if rev != []: # walkchangerevs on empty list would return all revs
-        for ctx in cmdutil.walkchangerevs(repo, match, {'rev' : rev},
-                                          prepare):
+    if rev != []:  # walkchangerevs on empty list would return all revs
+        for ctx in cmdutil.walkchangerevs(repo, match, {'rev': rev}, prepare):
             success, missing = cachelfiles(ui, repo, ctx.node())
             totalsuccess += len(success)
             totalmissing += len(missing)
@@ -440,8 +498,10 @@
         ui.status(_("%d largefiles failed to download\n") % totalmissing)
     return totalsuccess, totalmissing
 
-def updatelfiles(ui, repo, filelist=None, printmessage=None,
-                 normallookup=False):
+
+def updatelfiles(
+    ui, repo, filelist=None, printmessage=None, normallookup=False
+):
     '''Update largefiles according to standins in the working directory
 
     If ``printmessage`` is other than ``None``, it means "print (or
@@ -463,21 +523,19 @@
         wctx = repo[None]
         for lfile in lfiles:
             lfileorig = os.path.relpath(
-                scmutil.backuppath(ui, repo, lfile),
-                start=repo.root)
+                scmutil.backuppath(ui, repo, lfile), start=repo.root
+            )
             standin = lfutil.standin(lfile)
             standinorig = os.path.relpath(
-                scmutil.backuppath(ui, repo, standin),
-                start=repo.root)
+                scmutil.backuppath(ui, repo, standin), start=repo.root
+            )
             if wvfs.exists(standin):
-                if (wvfs.exists(standinorig) and
-                    wvfs.exists(lfile)):
-                    shutil.copyfile(wvfs.join(lfile),
-                                    wvfs.join(lfileorig))
+                if wvfs.exists(standinorig) and wvfs.exists(lfile):
+                    shutil.copyfile(wvfs.join(lfile), wvfs.join(lfileorig))
                     wvfs.unlinkpath(standinorig)
                 expecthash = lfutil.readasstandin(wctx[standin])
                 if expecthash != '':
-                    if lfile not in wctx: # not switched to normal file
+                    if lfile not in wctx:  # not switched to normal file
                         if repo.dirstate[standin] != '?':
                             wvfs.unlinkpath(lfile, ignoremissing=True)
                         else:
@@ -493,8 +551,10 @@
                 # lfile is added to the repository again. This happens when a
                 # largefile is converted back to a normal file: the standin
                 # disappears, but a new (normal) file appears as the lfile.
-                if (wvfs.exists(lfile) and
-                    repo.dirstate.normalize(lfile) not in wctx):
+                if (
+                    wvfs.exists(lfile)
+                    and repo.dirstate.normalize(lfile) not in wctx
+                ):
                     wvfs.unlinkpath(lfile)
                     removed += 1
 
@@ -549,13 +609,17 @@
 
         lfdirstate.write()
         if lfiles:
-            statuswriter(_('%d largefiles updated, %d removed\n') % (updated,
-                removed))
+            statuswriter(
+                _('%d largefiles updated, %d removed\n') % (updated, removed)
+            )
+
 
-@eh.command('lfpull',
-    [('r', 'rev', [], _('pull largefiles for these revisions'))
-    ] + cmdutil.remoteopts,
-    _('-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]'))
+@eh.command(
+    'lfpull',
+    [('r', 'rev', [], _('pull largefiles for these revisions'))]
+    + cmdutil.remoteopts,
+    _('-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]'),
+)
 def lfpull(ui, repo, source="default", **opts):
     """pull largefiles for the specified revisions from the specified source
 
@@ -591,9 +655,8 @@
         numcached += len(cached)
     ui.status(_("%d largefiles cached\n") % numcached)
 
-@eh.command('debuglfput',
-    [] + cmdutil.remoteopts,
-    _('FILE'))
+
+@eh.command('debuglfput', [] + cmdutil.remoteopts, _('FILE'))
 def debuglfput(ui, repo, filepath, **kwargs):
     hash = lfutil.hashfile(filepath)
     storefactory.openstore(repo).put(filepath, hash)