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))
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()
def _hgwebannotate(orig, fctx, ui): diffopts = patch.difffeatureopts(ui, untrusted=True, section="annotate", whitespace=True) return _doannotate(fctx, diffopts=diffopts)