def extdiff(ui, repo, *pats, **opts): """use external program to diff repository (or selected files) Show differences between revisions for the specified files, using an external program. The default program used is diff, with default options "-Npru". To select a different program, use the -p/--program option. The program will be passed the names of two directories to compare. To pass additional options to the program, use -o/--option. These will be passed before the names of the directories to compare. When two revision arguments are given, then changes are shown between those revisions. If only one revision is specified then that revision is compared to the working directory, and, when no revisions are specified, the working directory files are compared to its parent.""" opts = pycompat.byteskwargs(opts) program = opts.get("program") option = opts.get("option") if not program: program = "diff" option = option or ["-Npru"] cmdline = " ".join(map(util.shellquote, [program] + option)) return dodiff(ui, repo, cmdline, pats, opts)
def countrate(ui, repo, amap, *pats, **opts): """Calculate stats""" opts = pycompat.byteskwargs(opts) if opts.get("dateformat"): def getkey(ctx): t, tz = ctx.date() date = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) return date.strftime(opts["dateformat"]) else: tmpl = opts.get("oldtemplate") or opts.get("template") tmpl = cmdutil.makelogtemplater(ui, repo, tmpl) def getkey(ctx): ui.pushbuffer() tmpl.show(ctx) return ui.popbuffer() rate = {} df = False if opts.get("date"): df = util.matchdate(opts["date"]) prog = progress.bar(ui, _("analyzing"), _("revisions"), len(repo)) m = scmutil.match(repo[None], pats, opts) def prep(ctx, fns): rev = ctx.rev() if df and not df(ctx.date()[0]): # doesn't match date format return key = getkey(ctx).strip() key = amap.get(key, key) # alias remap if opts.get("changesets"): rate[key] = (rate.get(key, (0, ))[0] + 1, 0) else: parents = ctx.parents() if len(parents) > 1: ui.note(_("revision %d is a merge, ignoring...\n") % (rev, )) return ctx1 = parents[0] lines = changedlines(ui, repo, ctx1, ctx, fns) rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)] prog.value += 1 with prog: for ctx in cmdutil.walkchangerevs(repo, m, opts, prep): continue return rate
def snapshotshow(ui, repo, *args, **opts): """show the snapshot contents, given its revision id """ opts = pycompat.byteskwargs(opts) cctx = getsnapshotctx(ui, repo, args) rev = cctx.hex() opts["rev"] = [rev] opts["patch"] = True revs, expr, filematcher = cmdutil.getlogrevs(repo.unfiltered(), [], opts) revmatchfn = filematcher(rev) if filematcher else None ui.pager("snapshotshow") displayer = cmdutil.show_changeset(ui, repo.unfiltered(), opts, buffered=True) with extensions.wrappedfunction(patch, "diff", _diff), extensions.wrappedfunction( cmdutil.changeset_printer, "_show", _show ), extensions.wrappedfunction(cmdutil.changeset_templater, "_show", _show): displayer.show(cctx, matchfn=revmatchfn) displayer.flush(cctx) displayer.close()
def mvcheck(orig, ui, repo, *pats, **opts): """Hook to check for moves at commit time""" opts = pycompat.byteskwargs(opts) renames = None disabled = opts.pop("no_automv", False) or opts.pop( "no-move-detection", False) if not disabled: threshold = ui.configint("automv", "similarity") if not 0 <= threshold <= 100: raise error.Abort(_("automv.similarity must be between 0 and 100")) if threshold > 0: match = scmutil.match(repo[None], pats, opts) added, removed = _interestingfiles(repo, match) renames = _findrenames(repo, match, added, removed, threshold / 100.0) with repo.wlock(): if renames is not None: scmutil._markchanges(repo, (), (), renames) return orig(ui, repo, *pats, **pycompat.strkwargs(opts))
def printsnapshots(self, ui, repo, **opts): opts = pycompat.byteskwargs(opts) fm = ui.formatter("snapshots", opts) if len(self.snapshots) == 0: ui.status(_("no snapshots created\n")) unfi = repo.unfiltered() for snapshotnode in self.snapshots: ctx = unfi[snapshotnode] message = ctx.description().split("\n")[0] metadataid = ctx.extra()["snapshotmetadataid"] if metadataid: metadataid = metadataid[:12] else: metadataid = "None" fm.startitem() # TODO(alexeyqu): print list of related files if --verbose fm.write("revision", "%s", str(ctx)) fm.condwrite(ui.verbose, "snapshotmetadataid", "% 15s", metadataid) fm.write("message", " %s", message) fm.plain("\n") fm.end()
def __call__(self, ui, repo, *pats, **opts): opts = pycompat.byteskwargs(opts) options = " ".join(map(util.shellquote, opts["option"])) if options: options = " " + options return dodiff(ui, repo, self._cmdline + options, pats, opts)
def _dosign(ui, repo, *revs, **opts): mygpg = newgpg(ui, **opts) opts = pycompat.byteskwargs(opts) sigver = "0" sigmessage = "" date = opts.get("date") if date: opts["date"] = util.parsedate(date) if revs: nodes = [repo.lookup(n) for n in revs] else: nodes = [ node for node in repo.dirstate.parents() if node != hgnode.nullid ] if len(nodes) > 1: raise error.Abort( _("uncommitted merge - please provide a " "specific revision")) if not nodes: nodes = [repo.changelog.tip()] for n in nodes: hexnode = hgnode.hex(n) ui.write( _("signing %d:%s\n") % (repo.changelog.rev(n), hgnode.short(n))) # build data data = node2txt(repo, n, sigver) sig = mygpg.sign(data) if not sig: raise error.Abort(_("error while signing")) sig = binascii.b2a_base64(sig) sig = sig.replace("\n", "") sigmessage += "%s %s %s\n" % (hexnode, sigver, sig) # write it if opts["local"]: repo.localvfs.append("localsigs", sigmessage) return if not opts["force"]: msigs = match.exact(repo.root, "", [".hgsigs"]) if any(repo.status(match=msigs, unknown=True, ignored=True)): raise error.Abort( _("working copy of .hgsigs is changed "), hint=_("please commit .hgsigs manually"), ) sigsfile = repo.wvfs(".hgsigs", "ab") sigsfile.write(sigmessage) sigsfile.close() if ".hgsigs" not in repo.dirstate: with repo.lock(), repo.transaction("add-signatures"): repo[None].add([".hgsigs"]) if opts["no_commit"]: return message = opts["message"] if not message: # we don't translate commit messages message = "\n".join([ "Added signature for changeset %s" % hgnode.short(n) for n in nodes ]) try: editor = cmdutil.getcommiteditor(editform="gpg.sign", **pycompat.strkwargs(opts)) repo.commit(message, opts["user"], opts["date"], match=msigs, editor=editor) except ValueError as inst: raise error.Abort(str(inst))
def journal(ui, repo, *args, **opts): """show history of the checked out commit or a bookmark Show the history of all the commits that were once the current commit. In other words, shows a list of your previously checked out commits. :hg:`journal` can be used to find older versions of commits (for example, when you want to revert to a previous state). It can also be used to discover commits that were previously hidden. By default, :hg:`journal` displays the history of the current commit. To display a list of commits pointed to by a bookmark, specify a bookmark name. Specify --all to show the history of both the current commit and all bookmarks. In the output for --all, bookmarks are listed by name, and '.' indicates the current commit. Specify -Tjson to produce machine-readable output. .. container:: verbose By default, :hg:`journal` only shows the commit hash and the corresponding command. Specify --verbose to also include the previous commit hash, user, and timestamp. Use -c/--commits to output log information about each commit hash. To customize the log output, you can also specify switches like '--patch', '--git', '--stat', and '--template'. If a bookmark name starts with 're:', the remainder of the name is treated as a regular expression. To match a name that actually starts with 're:', use the prefix 'literal:'. """ opts = pycompat.byteskwargs(opts) name = "." if opts.get("all"): if args: raise error.Abort( _("You can't combine --all and filtering on a name")) name = None if args: name = args[0] fm = ui.formatter("journal", opts) ui.pager("journal") if not opts.get("template"): if name is None: displayname = _("the working copy and bookmarks") else: displayname = "'%s'" % name ui.status(_("previous locations of %s:\n") % displayname) limit = cmdutil.loglimit(opts) entry = None for count, entry in enumerate(repo.journal.filtered(name=name)): if count == limit: break newhashesstr = fm.formatlist(list(map(fm.hexfunc, entry.newhashes)), name="node", sep=",") oldhashesstr = fm.formatlist(list(map(fm.hexfunc, entry.oldhashes)), name="node", sep=",") fm.startitem() fm.condwrite(ui.verbose, "oldhashes", "%s -> ", oldhashesstr) fm.write("newhashes", "%s", newhashesstr) fm.condwrite(ui.verbose, "user", " %-8s", entry.user) fm.condwrite( opts.get("all") or name.startswith("re:"), "name", " %-8s", entry.name) timestring = fm.formatdate(entry.timestamp, "%Y-%m-%d %H:%M %1%2") fm.condwrite(ui.verbose, "date", " %s", timestring) fm.write("command", " %s\n", entry.command) if opts.get("commits"): displayer = cmdutil.show_changeset(ui, repo, opts, buffered=False) for hash in entry.newhashes: try: ctx = repo[hash] displayer.show(ctx) except error.RepoLookupError as e: fm.write("repolookuperror", "%s\n\n", str(e)) displayer.close() fm.end() if entry is None and not opts.get("template"): ui.status(_("no recorded locations\n"))