view hgext/infinitepush/infinitepushcommands.py @ 37189:b377b7dfe682

infinitepush: drop the logic related to inhibit extension The inhibit extension lives in hg-experimental and is not a core extension. Differential Revision: https://phab.mercurial-scm.org/D2098
author Pulkit Goyal <7895pulkit@gmail.com>
date Sat, 03 Feb 2018 17:59:49 +0530
parents de4c2f3af97f
children
line wrap: on
line source

# Copyright 2016 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""
config::

    [infinitepush]
    # limit number of files in the node metadata. This is to make sure we don't
    # waste too much space on huge codemod commits.
    metadatafilelimit = 100
"""

from __future__ import absolute_import

import json

from mercurial.node import bin
from mercurial.i18n import _

from mercurial import (
    copies as copiesmod,
    encoding,
    error,
    hg,
    patch,
    registrar,
    scmutil,
    util,
)

from . import (
    common,
)

downloadbundle = common.downloadbundle

cmdtable = {}
command = registrar.command(cmdtable)

@command('debugfillinfinitepushmetadata',
         [('', 'node', [], 'node to fill metadata for')])
def debugfillinfinitepushmetadata(ui, repo, **opts):
    '''Special command that fills infinitepush metadata for a node
    '''

    nodes = opts['node']
    if not nodes:
        raise error.Abort(_('nodes are not specified'))

    filelimit = ui.configint('infinitepush', 'metadatafilelimit', 100)
    nodesmetadata = {}
    for node in nodes:
        index = repo.bundlestore.index
        if not bool(index.getbundle(node)):
            raise error.Abort(_('node %s is not found') % node)

        if node not in repo:
            newbundlefile = downloadbundle(repo, bin(node))
            bundlepath = "bundle:%s+%s" % (repo.root, newbundlefile)
            bundlerepo = hg.repository(ui, bundlepath)
            repo = bundlerepo

        p1 = repo[node].p1().node()
        diffopts = patch.diffallopts(ui, {})
        match = scmutil.matchall(repo)
        chunks = patch.diff(repo, p1, node, match, None, diffopts, relroot='')
        difflines = util.iterlines(chunks)

        states = 'modified added removed deleted unknown ignored clean'.split()
        status = repo.status(p1, node)
        status = zip(states, status)

        filestatus = {}
        for state, files in status:
            for f in files:
                filestatus[f] = state

        diffstat = patch.diffstatdata(difflines)
        changed_files = {}
        copies = copiesmod.pathcopies(repo[p1], repo[node])
        for filename, adds, removes, isbinary in diffstat[:filelimit]:
            # use special encoding that allows non-utf8 filenames
            filename = encoding.jsonescape(filename, paranoid=True)
            changed_files[filename] = {
                'adds': adds, 'removes': removes, 'isbinary': isbinary,
                'status': filestatus.get(filename, 'unknown')
            }
            if filename in copies:
                changed_files[filename]['copies'] = copies[filename]

        output = {}
        output['changed_files'] = changed_files
        if len(diffstat) > filelimit:
            output['changed_files_truncated'] = True
        nodesmetadata[node] = output

    with index:
        for node, metadata in nodesmetadata.iteritems():
            dumped = json.dumps(metadata, sort_keys=True)
            index.saveoptionaljsonmetadata(node, dumped)