Beispiel #1
0
def autodiff(ui, repo, *pats, **opts):
    diffopts = patch.difffeatureopts(ui, opts)
    git = opts.get("git", "no")
    brokenfiles = set()
    losedatafn = None
    if git in ("yes", "no"):
        diffopts.git = git == "yes"
        diffopts.upgrade = False
    elif git == "auto":
        diffopts.git = False
        diffopts.upgrade = True
    elif git == "warn":
        diffopts.git = False
        diffopts.upgrade = True

        def losedatafn(fn=None, **kwargs):
            brokenfiles.add(fn)
            return True

    elif git == "abort":
        diffopts.git = False
        diffopts.upgrade = True

        def losedatafn(fn=None, **kwargs):
            raise error.Abort("losing data for %s" % fn)

    else:
        raise error.Abort("--git must be yes, no or auto")

    node1, node2 = scmutil.revpair(repo, [])
    m = scmutil.match(repo[node2], pats, opts)
    it = patch.diff(repo,
                    repo[node1],
                    repo[node2],
                    match=m,
                    opts=diffopts,
                    losedatafn=losedatafn)
    for chunk in it:
        ui.writebytes(chunk)
    for fn in sorted(brokenfiles):
        ui.write(("data lost for: %s\n" % fn))
Beispiel #2
0
def fastannotate(ui, repo, *pats, **opts):
    """show changeset information by line for each file

    List changes in files, showing the revision id responsible for each line.

    This command is useful for discovering when a change was made and by whom.

    By default this command prints revision numbers. If you include --file,
    --user, or --date, the revision number is suppressed unless you also
    include --number. The default format can also be customized by setting
    fastannotate.defaultformat.

    Returns 0 on success.

    .. container:: verbose

        This command uses an implementation different from the vanilla annotate
        command, which may produce slightly different (while still reasonable)
        outputs for some cases.

        Unlike the vanilla anootate, fastannotate follows rename regardless of
        the existence of --file.

        For the best performance when running on a full repo, use -c, -l,
        avoid -u, -d, -n. Use --linear and --no-content to make it even faster.

        For the best performance when running on a shallow (remotefilelog)
        repo, avoid --linear, --no-follow, or any diff options. As the server
        won't be able to populate annotate cache when non-default options
        affecting results are used.
    """
    if not pats:
        raise error.Abort(_("at least one filename or pattern is required"))

    # performance hack: filtered repo can be slow. unfilter by default.
    if ui.configbool("fastannotate", "unfilteredrepo", True):
        repo = repo.unfiltered()

    rev = opts.get("rev", ".")
    rebuild = opts.get("rebuild", False)

    diffopts = patch.difffeatureopts(ui, opts, section="annotate", whitespace=True)
    aopts = facontext.annotateopts(
        diffopts=diffopts,
        followmerge=not opts.get("linear", False),
        followrename=not opts.get("no_follow", False),
    )

    if not any(opts.get(s) for s in ["user", "date", "file", "number", "changeset"]):
        # default 'number' for compatibility. but fastannotate is more
        # efficient with "changeset", "line-number" and "no-content".
        for name in ui.configlist("fastannotate", "defaultformat", ["number"]):
            opts[name] = True

    ui.pager("fastannotate")
    template = opts.get("template")
    if template == "json":
        formatter = faformatter.jsonformatter(ui, repo, opts)
    else:
        formatter = faformatter.defaultformatter(ui, repo, opts)
    showdeleted = opts.get("deleted", False)
    showlines = not bool(opts.get("no_content"))
    showpath = opts.get("file", False)

    # find the head of the main (master) branch
    master = ui.config("fastannotate", "mainbranch") or rev

    # paths will be used for prefetching and the real annotating
    paths = list(_matchpaths(repo, rev, pats, opts, aopts))

    # for client, prefetch from the server
    if util.safehasattr(repo, "prefetchfastannotate"):
        repo.prefetchfastannotate(paths)

    for path in paths:
        result = lines = existinglines = None
        while True:
            try:
                with facontext.annotatecontext(repo, path, aopts, rebuild) as a:
                    result = a.annotate(
                        rev,
                        master=master,
                        showpath=showpath,
                        showlines=(showlines and not showdeleted),
                    )
                    if showdeleted:
                        existinglines = set((l[0], l[1]) for l in result)
                        result = a.annotatealllines(
                            rev, showpath=showpath, showlines=showlines
                        )
                break
            except (faerror.CannotReuseError, faerror.CorruptedFileError):
                # happens if master moves backwards, or the file was deleted
                # and readded, or renamed to an existing name, or corrupted.
                if rebuild:  # give up since we have tried rebuild already
                    raise
                else:  # try a second time rebuilding the cache (slow)
                    rebuild = True
                    continue

        if showlines:
            result, lines = result

        formatter.write(result, lines, existinglines=existinglines)
    formatter.end()
Beispiel #3
0
def _hgwebannotate(orig, fctx, ui):
    diffopts = patch.difffeatureopts(ui,
                                     untrusted=True,
                                     section="annotate",
                                     whitespace=True)
    return _doannotate(fctx, diffopts=diffopts)