diff --git a/hgext/absorb.py b/hgext/absorb.py --- a/hgext/absorb.py +++ b/hgext/absorb.py @@ -59,7 +59,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @@ -67,14 +67,14 @@ configtable = {} configitem = registrar.configitem(configtable) -configitem("absorb", "add-noise", default=True) -configitem("absorb", "amend-flag", default=None) -configitem("absorb", "max-stack-size", default=50) +configitem(b"absorb", b"add-noise", default=True) +configitem(b"absorb", b"amend-flag", default=None) +configitem(b"absorb", b"max-stack-size", default=50) colortable = { - "absorb.description": "yellow", - "absorb.node": "blue bold", - "absorb.path": "bold", + b"absorb.description": b"yellow", + b"absorb.node": b"blue bold", + b"absorb.path": b"bold", } defaultdict = collections.defaultdict @@ -98,7 +98,7 @@ """minimal filecontext representing an empty file""" def data(self): - return "" + return b"" def node(self): return node.nullid @@ -364,11 +364,11 @@ if self.ui.debugflag: idx = (max(rev - 1, 0)) // 2 self.ui.write( - _("%s: chunk %d:%d -> %d lines\n") + _(b"%s: chunk %d:%d -> %d lines\n") % (node.short(self.fctxs[idx].node()), a1, a2, len(blines)) ) self.linelog.replacelines(rev, a1, a2, b1, b2) - if self.opts.get("edit_lines", False): + if self.opts.get(b"edit_lines", False): self.finalcontents = self._checkoutlinelogwithedits() else: self.finalcontents = self._checkoutlinelog() @@ -434,7 +434,7 @@ """like mdiff.allblocks, but only care about differences""" blocks = mdiff.allblocks(a, b, lines1=alines, lines2=blines) for chunk, btype in blocks: - if btype != "!": + if btype != b"!": continue yield chunk @@ -443,7 +443,7 @@ this is similar to running a partial "annotate". """ llog = linelog.linelog() - a, alines = "", [] + a, alines = b"", [] for i in pycompat.xrange(len(self.contents)): b, blines = self.contents[i], self.contentlines[i] llrev = i * 2 + 1 @@ -459,7 +459,7 @@ for i in pycompat.xrange(len(self.contents)): rev = (i + 1) * 2 self.linelog.annotate(rev) - content = "".join(map(self._getline, self.linelog.annotateresult)) + content = b"".join(map(self._getline, self.linelog.annotateresult)) contents.append(content) return contents @@ -469,8 +469,8 @@ # header editortext = ( _( - 'HG: editing %s\nHG: "y" means the line to the right ' - "exists in the changeset to the top\nHG:\n" + b'HG: editing %s\nHG: "y" means the line to the right ' + b"exists in the changeset to the top\nHG:\n" ) % self.fctxs[-1].path() ) @@ -481,13 +481,13 @@ if not isinstance(f, emptyfilecontext) ] for i, (j, f) in enumerate(visiblefctxs): - editortext += _("HG: %s/%s %s %s\n") % ( - "|" * i, - "-" * (len(visiblefctxs) - i + 1), + editortext += _(b"HG: %s/%s %s %s\n") % ( + b"|" * i, + b"-" * (len(visiblefctxs) - i + 1), node.short(f.node()), - f.description().split("\n", 1)[0], + f.description().split(b"\n", 1)[0], ) - editortext += _("HG: %s\n") % ("|" * len(visiblefctxs)) + editortext += _(b"HG: %s\n") % (b"|" * len(visiblefctxs)) # figure out the lifetime of a line, this is relatively inefficient, # but probably fine lineset = defaultdict(lambda: set()) # {(llrev, linenum): {llrev}} @@ -497,33 +497,33 @@ lineset[l].add(i) # append lines for l in alllines: - editortext += " %s : %s" % ( - "".join( + editortext += b" %s : %s" % ( + b"".join( [ - ("y" if i in lineset[l] else " ") + (b"y" if i in lineset[l] else b" ") for i, _f in visiblefctxs ] ), self._getline(l), ) # run editor - editedtext = self.ui.edit(editortext, "", action="absorb") + editedtext = self.ui.edit(editortext, b"", action=b"absorb") if not editedtext: - raise error.Abort(_("empty editor text")) + raise error.Abort(_(b"empty editor text")) # parse edited result - contents = ["" for i in self.fctxs] + contents = [b"" for i in self.fctxs] leftpadpos = 4 colonpos = leftpadpos + len(visiblefctxs) + 1 for l in mdiff.splitnewlines(editedtext): - if l.startswith("HG:"): + if l.startswith(b"HG:"): continue - if l[colonpos - 1 : colonpos + 2] != " : ": - raise error.Abort(_("malformed line: %s") % l) + if l[colonpos - 1 : colonpos + 2] != b" : ": + raise error.Abort(_(b"malformed line: %s") % l) linecontent = l[colonpos + 2 :] for i, ch in enumerate( pycompat.bytestr(l[leftpadpos : colonpos - 1]) ): - if ch == "y": + if ch == b"y": contents[visiblefctxs[i][0]] += linecontent # chunkstats is hard to calculate if anything changes, therefore # set them to just a simple value (1, 1). @@ -589,7 +589,7 @@ def _showchanges(self, fm, alines, blines, chunk, fixups): def trim(line): - if line.endswith("\n"): + if line.endswith(b"\n"): line = line[:-1] return line @@ -605,25 +605,25 @@ fm.startitem() fm.write( - "hunk", - " %s\n", - "@@ -%d,%d +%d,%d @@" % (a1, a2 - a1, b1, b2 - b1), - label="diff.hunk", + b"hunk", + b" %s\n", + b"@@ -%d,%d +%d,%d @@" % (a1, a2 - a1, b1, b2 - b1), + label=b"diff.hunk", ) - fm.data(path=self.path, linetype="hunk") + fm.data(path=self.path, linetype=b"hunk") def writeline(idx, diffchar, line, linetype, linelabel): fm.startitem() - node = "" + node = b"" if idx: ctx = self.fctxs[idx] fm.context(fctx=ctx) node = ctx.hex() self.ctxaffected.add(ctx.changectx()) - fm.write("node", "%-7.7s ", node, label="absorb.node") + fm.write(b"node", b"%-7.7s ", node, label=b"absorb.node") fm.write( - "diffchar " + linetype, - "%s%s\n", + b"diffchar " + linetype, + b"%s%s\n", diffchar, line, label=linelabel, @@ -632,11 +632,19 @@ for i in pycompat.xrange(a1, a2): writeline( - aidxs[i - a1], "-", trim(alines[i]), "deleted", "diff.deleted" + aidxs[i - a1], + b"-", + trim(alines[i]), + b"deleted", + b"diff.deleted", ) for i in pycompat.xrange(b1, b2): writeline( - bidxs[i - b1], "+", trim(blines[i]), "inserted", "diff.inserted" + bidxs[i - b1], + b"+", + trim(blines[i]), + b"inserted", + b"diff.inserted", ) @@ -681,7 +689,7 @@ self.paths = [] # but if --edit-lines is used, the user may want to edit files # even if they are not modified - editopt = self.opts.get("edit_lines") + editopt = self.opts.get(b"edit_lines") if not self.status.modified and editopt and match: interestingpaths = match.files() else: @@ -691,7 +699,7 @@ # sorting is necessary to eliminate ambiguity for the "double move" # case: "hg cp A B; hg cp A C; hg rm A", then only "B" can affect "A". for path in sorted(interestingpaths): - self.ui.debug("calculating fixups for %s\n" % path) + self.ui.debug(b"calculating fixups for %s\n" % path) targetfctx = targetctx[path] fctxs, ctx2fctx = getfilestack(self.stack, path, seenfctxs) # ignore symbolic links or binary, or unchanged files @@ -708,9 +716,9 @@ fstate = filefixupstate(fctxs, path, ui=self.ui, opts=self.opts) if fm is not None: fm.startitem() - fm.plain("showing changes for ") - fm.write("path", "%s\n", path, label="absorb.path") - fm.data(linetype="path") + fm.plain(b"showing changes for ") + fm.write(b"path", b"%s\n", path, label=b"absorb.path") + fm.data(linetype=b"path") fstate.diffwith(targetfctx, fm) self.fixupmap[path] = fstate self.paths.append(path) @@ -720,7 +728,7 @@ """apply fixups to individual filefixupstates""" for path, state in self.fixupmap.iteritems(): if self.ui.debugflag: - self.ui.write(_("applying fixups to %s\n") % path) + self.ui.write(_(b"applying fixups to %s\n") % path) state.apply() @property @@ -733,10 +741,10 @@ def commit(self): """commit changes. update self.finalnode, self.replacemap""" - with self.repo.transaction("absorb") as tr: + with self.repo.transaction(b"absorb") as tr: self._commitstack() self._movebookmarks(tr) - if self.repo["."].node() in self.replacemap: + if self.repo[b"."].node() in self.replacemap: self._moveworkingdirectoryparent() self._cleanupoldcommits() return self.finalnode @@ -750,14 +758,14 @@ for path, stat in chunkstats.iteritems(): if stat[0]: ui.write( - _("%s: %d of %d chunk(s) applied\n") + _(b"%s: %d of %d chunk(s) applied\n") % (path, stat[0], stat[1]) ) elif not ui.quiet: # a summary for all files stats = chunkstats.values() applied, total = (sum(s[i] for s in stats) for i in (0, 1)) - ui.write(_("%d of %d chunk(s) applied\n") % (applied, total)) + ui.write(_(b"%d of %d chunk(s) applied\n") % (applied, total)) def _commitstack(self): """make new commits. update self.finalnode, self.replacemap. @@ -777,7 +785,7 @@ if self._willbecomenoop(memworkingcopy, ctx, nextp1): # changeset is no longer necessary self.replacemap[ctx.node()] = None - msg = _("became empty and was dropped") + msg = _(b"became empty and was dropped") else: # changeset needs re-commit nodestr = self._commitsingle(memworkingcopy, ctx, p1=nextp1) @@ -785,21 +793,21 @@ nextp1 = lastcommitted self.replacemap[ctx.node()] = lastcommitted.node() if memworkingcopy: - msg = _("%d file(s) changed, became %s") % ( + msg = _(b"%d file(s) changed, became %s") % ( len(memworkingcopy), self._ctx2str(lastcommitted), ) else: - msg = _("became %s") % self._ctx2str(lastcommitted) + msg = _(b"became %s") % self._ctx2str(lastcommitted) if self.ui.verbose and msg: - self.ui.write(_("%s: %s\n") % (self._ctx2str(ctx), msg)) + self.ui.write(_(b"%s: %s\n") % (self._ctx2str(ctx), msg)) self.finalnode = lastcommitted and lastcommitted.node() def _ctx2str(self, ctx): if self.ui.debugflag: - return "%d:%s" % (ctx.rev(), ctx.hex()) + return b"%d:%s" % (ctx.rev(), ctx.hex()) else: - return "%d:%s" % (ctx.rev(), node.short(ctx.node())) + return b"%d:%s" % (ctx.rev(), node.short(ctx.node())) def _getnewfilecontents(self, ctx): """(ctx) -> {path: str} @@ -832,18 +840,18 @@ changes.append((name, hsh)) if self.ui.verbose: self.ui.write( - _("moving bookmark %s to %s\n") % (name, node.hex(hsh)) + _(b"moving bookmark %s to %s\n") % (name, node.hex(hsh)) ) else: changes.append((name, None)) if self.ui.verbose: - self.ui.write(_("deleting bookmark %s\n") % name) + self.ui.write(_(b"deleting bookmark %s\n") % name) repo._bookmarks.applychanges(repo, tr, changes) def _moveworkingdirectoryparent(self): if not self.finalnode: # Find the latest not-{obsoleted,stripped} parent. - revs = self.repo.revs("max(::. - %ln)", self.replacemap.keys()) + revs = self.repo.revs(b"max(::. - %ln)", self.replacemap.keys()) ctx = self.repo[revs.first()] self.finalnode = ctx.node() else: @@ -854,7 +862,7 @@ # be slow. in absorb's case, no need to invalidate fsmonitorstate. noop = lambda: 0 restore = noop - if util.safehasattr(dirstate, "_fsmonitorstate"): + if util.safehasattr(dirstate, b"_fsmonitorstate"): bak = dirstate._fsmonitorstate.invalidate def restore(): @@ -901,8 +909,8 @@ """ parents = p1 and (p1, node.nullid) extra = ctx.extra() - if self._useobsolete and self.ui.configbool("absorb", "add-noise"): - extra["absorb_source"] = ctx.hex() + if self._useobsolete and self.ui.configbool(b"absorb", b"add-noise"): + extra[b"absorb_source"] = ctx.hex() mctx = overlaycontext(memworkingcopy, ctx, parents, extra=extra) return mctx.commit() @@ -918,7 +926,7 @@ } if replacements: scmutil.cleanupnodes( - self.repo, replacements, operation="absorb", fixphase=True + self.repo, replacements, operation=b"absorb", fixphase=True ) @@ -935,7 +943,7 @@ patchlines = mdiff.splitnewlines(buf.getvalue()) # hunk.prettystr() will update hunk.removed a2 = a1 + hunk.removed - blines = [l[1:] for l in patchlines[1:] if not l.startswith("-")] + blines = [l[1:] for l in patchlines[1:] if not l.startswith(b"-")] return path, (a1, a2, blines) @@ -967,7 +975,7 @@ lines = mdiff.splitnewlines(ctx[path].data()) for a1, a2, blines in patches: lines[a1:a2] = blines - memworkingcopy[path] = "".join(lines) + memworkingcopy[path] = b"".join(lines) return overlaycontext(memworkingcopy, ctx) @@ -979,18 +987,21 @@ return fixupstate. """ if stack is None: - limit = ui.configint("absorb", "max-stack-size") - headctx = repo["."] + limit = ui.configint(b"absorb", b"max-stack-size") + headctx = repo[b"."] if len(headctx.parents()) > 1: - raise error.Abort(_("cannot absorb into a merge")) + raise error.Abort(_(b"cannot absorb into a merge")) stack = getdraftstack(headctx, limit) if limit and len(stack) >= limit: ui.warn( - _("absorb: only the recent %d changesets will " "be analysed\n") + _( + b"absorb: only the recent %d changesets will " + b"be analysed\n" + ) % limit ) if not stack: - raise error.Abort(_("no mutable changeset to change")) + raise error.Abort(_(b"no mutable changeset to change")) if targetctx is None: # default to working copy targetctx = repo[None] if pats is None: @@ -999,85 +1010,89 @@ opts = {} state = fixupstate(stack, ui=ui, opts=opts) matcher = scmutil.match(targetctx, pats, opts) - if opts.get("interactive"): + if opts.get(b"interactive"): diff = patch.diff(repo, stack[-1].node(), targetctx.node(), matcher) origchunks = patch.parsepatch(diff) chunks = cmdutil.recordfilter(ui, origchunks, matcher)[0] targetctx = overlaydiffcontext(stack[-1], chunks) fm = None - if opts.get("print_changes") or not opts.get("apply_changes"): - fm = ui.formatter("absorb", opts) + if opts.get(b"print_changes") or not opts.get(b"apply_changes"): + fm = ui.formatter(b"absorb", opts) state.diffwith(targetctx, matcher, fm) if fm is not None: fm.startitem() - fm.write("count", "\n%d changesets affected\n", len(state.ctxaffected)) - fm.data(linetype="summary") + fm.write( + b"count", b"\n%d changesets affected\n", len(state.ctxaffected) + ) + fm.data(linetype=b"summary") for ctx in reversed(stack): if ctx not in state.ctxaffected: continue fm.startitem() fm.context(ctx=ctx) - fm.data(linetype="changeset") - fm.write("node", "%-7.7s ", ctx.hex(), label="absorb.node") + fm.data(linetype=b"changeset") + fm.write(b"node", b"%-7.7s ", ctx.hex(), label=b"absorb.node") descfirstline = ctx.description().splitlines()[0] fm.write( - "descfirstline", - "%s\n", + b"descfirstline", + b"%s\n", descfirstline, - label="absorb.description", + label=b"absorb.description", ) fm.end() - if not opts.get("dry_run"): + if not opts.get(b"dry_run"): if ( - not opts.get("apply_changes") + not opts.get(b"apply_changes") and state.ctxaffected - and ui.promptchoice("apply changes (yn)? $$ &Yes $$ &No", default=1) + and ui.promptchoice( + b"apply changes (yn)? $$ &Yes $$ &No", default=1 + ) ): - raise error.Abort(_("absorb cancelled\n")) + raise error.Abort(_(b"absorb cancelled\n")) state.apply() if state.commit(): state.printchunkstats() elif not ui.quiet: - ui.write(_("nothing applied\n")) + ui.write(_(b"nothing applied\n")) return state @command( - "absorb", + b"absorb", [ ( - "a", - "apply-changes", + b"a", + b"apply-changes", None, - _("apply changes without prompting for confirmation"), + _(b"apply changes without prompting for confirmation"), ), ( - "p", - "print-changes", + b"p", + b"print-changes", None, - _("always print which changesets are modified by which changes"), + _(b"always print which changesets are modified by which changes"), ), ( - "i", - "interactive", + b"i", + b"interactive", None, - _("interactively select which chunks to apply (EXPERIMENTAL)"), + _(b"interactively select which chunks to apply (EXPERIMENTAL)"), ), ( - "e", - "edit-lines", + b"e", + b"edit-lines", None, _( - "edit what lines belong to which changesets before commit " - "(EXPERIMENTAL)" + b"edit what lines belong to which changesets before commit " + b"(EXPERIMENTAL)" ), ), ] + commands.dryrunopts + commands.templateopts + commands.walkopts, - _("hg absorb [OPTION] [FILE]..."), + _(b"hg absorb [OPTION] [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, ) @@ -1108,7 +1123,7 @@ opts = pycompat.byteskwargs(opts) with repo.wlock(), repo.lock(): - if not opts["dry_run"]: + if not opts[b"dry_run"]: cmdutil.checkunfinished(repo) state = absorb(ui, repo, pats=pats, opts=opts) diff --git a/hgext/acl.py b/hgext/acl.py --- a/hgext/acl.py +++ b/hgext/acl.py @@ -232,66 +232,66 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) # deprecated config: acl.config configitem( - "acl", "config", default=None, + b"acl", b"config", default=None, ) configitem( - "acl.groups", ".*", default=None, generic=True, + b"acl.groups", b".*", default=None, generic=True, ) configitem( - "acl.deny.branches", ".*", default=None, generic=True, + b"acl.deny.branches", b".*", default=None, generic=True, ) configitem( - "acl.allow.branches", ".*", default=None, generic=True, + b"acl.allow.branches", b".*", default=None, generic=True, ) configitem( - "acl.deny", ".*", default=None, generic=True, + b"acl.deny", b".*", default=None, generic=True, ) configitem( - "acl.allow", ".*", default=None, generic=True, + b"acl.allow", b".*", default=None, generic=True, ) configitem( - "acl", "sources", default=lambda: ["serve"], + b"acl", b"sources", default=lambda: [b"serve"], ) def _getusers(ui, group): # First, try to use group definition from section [acl.groups] - hgrcusers = ui.configlist("acl.groups", group) + hgrcusers = ui.configlist(b"acl.groups", group) if hgrcusers: return hgrcusers - ui.debug('acl: "%s" not defined in [acl.groups]\n' % group) + ui.debug(b'acl: "%s" not defined in [acl.groups]\n' % group) # If no users found in group definition, get users from OS-level group try: return util.groupmembers(group) except KeyError: - raise error.Abort(_("group '%s' is undefined") % group) + raise error.Abort(_(b"group '%s' is undefined") % group) def _usermatch(ui, user, usersorgroups): - if usersorgroups == "*": + if usersorgroups == b"*": return True - for ug in usersorgroups.replace(",", " ").split(): + for ug in usersorgroups.replace(b",", b" ").split(): - if ug.startswith("!"): + if ug.startswith(b"!"): # Test for excluded user or group. Format: # if ug is a user name: !username # if ug is a group name: !@groupname ug = ug[1:] if ( - not ug.startswith("@") + not ug.startswith(b"@") and user != ug - or ug.startswith("@") + or ug.startswith(b"@") and user not in _getusers(ui, ug[1:]) ): return True @@ -299,7 +299,9 @@ # Test for user or group. Format: # if ug is a user name: username # if ug is a group name: @groupname - elif user == ug or ug.startswith("@") and user in _getusers(ui, ug[1:]): + elif ( + user == ug or ug.startswith(b"@") and user in _getusers(ui, ug[1:]) + ): return True return False @@ -308,14 +310,14 @@ def buildmatch(ui, repo, user, key): """return tuple of (match function, list enabled).""" if not ui.has_section(key): - ui.debug("acl: %s not enabled\n" % key) + ui.debug(b"acl: %s not enabled\n" % key) return None pats = [ pat for pat, users in ui.configitems(key) if _usermatch(ui, user, users) ] ui.debug( - "acl: %s enabled, %d entries for user %s\n" % (key, len(pats), user) + b"acl: %s enabled, %d entries for user %s\n" % (key, len(pats), user) ) # Branch-based ACL @@ -323,14 +325,14 @@ if pats: # If there's an asterisk (meaning "any branch"), always return True; # Otherwise, test if b is in pats - if "*" in pats: + if b"*" in pats: return util.always return lambda b: b in pats return util.never # Path-based ACL if pats: - return match.match(repo.root, "", pats) + return match.match(repo.root, b"", pats) return util.never @@ -342,122 +344,128 @@ never loaded. This function ensure the extension is enabled when running hooks. """ - if "acl" in ui._knownconfig: + if b"acl" in ui._knownconfig: return - ui.setconfig("extensions", "acl", "", source="internal") - extensions.loadall(ui, ["acl"]) + ui.setconfig(b"extensions", b"acl", b"", source=b"internal") + extensions.loadall(ui, [b"acl"]) def hook(ui, repo, hooktype, node=None, source=None, **kwargs): ensureenabled(ui) - if hooktype not in ["pretxnchangegroup", "pretxncommit", "prepushkey"]: + if hooktype not in [b"pretxnchangegroup", b"pretxncommit", b"prepushkey"]: raise error.Abort( _( - 'config error - hook type "%s" cannot stop ' - "incoming changesets, commits, nor bookmarks" + b'config error - hook type "%s" cannot stop ' + b"incoming changesets, commits, nor bookmarks" ) % hooktype ) - if hooktype == "pretxnchangegroup" and source not in ui.configlist( - "acl", "sources" + if hooktype == b"pretxnchangegroup" and source not in ui.configlist( + b"acl", b"sources" ): - ui.debug('acl: changes have source "%s" - skipping\n' % source) + ui.debug(b'acl: changes have source "%s" - skipping\n' % source) return user = None - if source == "serve" and r"url" in kwargs: - url = kwargs[r"url"].split(":") - if url[0] == "remote" and url[1].startswith("http"): + if source == b"serve" and r"url" in kwargs: + url = kwargs[r"url"].split(b":") + if url[0] == b"remote" and url[1].startswith(b"http"): user = urlreq.unquote(url[3]) if user is None: user = procutil.getuser() - ui.debug('acl: checking access for user "%s"\n' % user) + ui.debug(b'acl: checking access for user "%s"\n' % user) - if hooktype == "prepushkey": + if hooktype == b"prepushkey": _pkhook(ui, repo, hooktype, node, source, user, **kwargs) else: _txnhook(ui, repo, hooktype, node, source, user, **kwargs) def _pkhook(ui, repo, hooktype, node, source, user, **kwargs): - if kwargs[r"namespace"] == "bookmarks": + if kwargs[r"namespace"] == b"bookmarks": bookmark = kwargs[r"key"] ctx = kwargs[r"new"] - allowbookmarks = buildmatch(ui, None, user, "acl.allow.bookmarks") - denybookmarks = buildmatch(ui, None, user, "acl.deny.bookmarks") + allowbookmarks = buildmatch(ui, None, user, b"acl.allow.bookmarks") + denybookmarks = buildmatch(ui, None, user, b"acl.deny.bookmarks") if denybookmarks and denybookmarks(bookmark): raise error.Abort( - _('acl: user "%s" denied on bookmark "%s"' ' (changeset "%s")') + _( + b'acl: user "%s" denied on bookmark "%s"' + b' (changeset "%s")' + ) % (user, bookmark, ctx) ) if allowbookmarks and not allowbookmarks(bookmark): raise error.Abort( _( - 'acl: user "%s" not allowed on bookmark "%s"' - ' (changeset "%s")' + b'acl: user "%s" not allowed on bookmark "%s"' + b' (changeset "%s")' ) % (user, bookmark, ctx) ) ui.debug( - 'acl: bookmark access granted: "%s" on bookmark "%s"\n' + b'acl: bookmark access granted: "%s" on bookmark "%s"\n' % (ctx, bookmark) ) def _txnhook(ui, repo, hooktype, node, source, user, **kwargs): # deprecated config: acl.config - cfg = ui.config("acl", "config") + cfg = ui.config(b"acl", b"config") if cfg: ui.readconfig( cfg, sections=[ - "acl.groups", - "acl.allow.branches", - "acl.deny.branches", - "acl.allow", - "acl.deny", + b"acl.groups", + b"acl.allow.branches", + b"acl.deny.branches", + b"acl.allow", + b"acl.deny", ], ) - allowbranches = buildmatch(ui, None, user, "acl.allow.branches") - denybranches = buildmatch(ui, None, user, "acl.deny.branches") - allow = buildmatch(ui, repo, user, "acl.allow") - deny = buildmatch(ui, repo, user, "acl.deny") + allowbranches = buildmatch(ui, None, user, b"acl.allow.branches") + denybranches = buildmatch(ui, None, user, b"acl.deny.branches") + allow = buildmatch(ui, repo, user, b"acl.allow") + deny = buildmatch(ui, repo, user, b"acl.deny") for rev in pycompat.xrange(repo[node].rev(), len(repo)): ctx = repo[rev] branch = ctx.branch() if denybranches and denybranches(branch): raise error.Abort( - _('acl: user "%s" denied on branch "%s"' ' (changeset "%s")') + _(b'acl: user "%s" denied on branch "%s"' b' (changeset "%s")') % (user, branch, ctx) ) if allowbranches and not allowbranches(branch): raise error.Abort( _( - 'acl: user "%s" not allowed on branch "%s"' - ' (changeset "%s")' + b'acl: user "%s" not allowed on branch "%s"' + b' (changeset "%s")' ) % (user, branch, ctx) ) ui.debug( - 'acl: branch access granted: "%s" on branch "%s"\n' % (ctx, branch) + b'acl: branch access granted: "%s" on branch "%s"\n' % (ctx, branch) ) for f in ctx.files(): if deny and deny(f): raise error.Abort( - _('acl: user "%s" denied on "%s"' ' (changeset "%s")') + _(b'acl: user "%s" denied on "%s"' b' (changeset "%s")') % (user, f, ctx) ) if allow and not allow(f): raise error.Abort( - _('acl: user "%s" not allowed on "%s"' ' (changeset "%s")') + _( + b'acl: user "%s" not allowed on "%s"' + b' (changeset "%s")' + ) % (user, f, ctx) ) - ui.debug('acl: path access granted: "%s"\n' % ctx) + ui.debug(b'acl: path access granted: "%s"\n' % ctx) diff --git a/hgext/amend.py b/hgext/amend.py --- a/hgext/amend.py +++ b/hgext/amend.py @@ -24,23 +24,23 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @command( - "amend", + b"amend", [ ( - "A", - "addremove", + b"A", + b"addremove", None, - _("mark new/missing files as added/removed before committing"), + _(b"mark new/missing files as added/removed before committing"), ), - ("e", "edit", None, _("invoke editor on commit messages")), - ("i", "interactive", None, _("use interactive mode")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), + (b"i", b"interactive", None, _(b"use interactive mode")), ( b"", b"close-branch", @@ -48,13 +48,13 @@ _(b"mark a branch as closed, hiding it from the branch list"), ), (b"s", b"secret", None, _(b"use the secret phase for committing")), - ("n", "note", "", _("store a note on the amend")), + (b"n", b"note", b"", _(b"store a note on the amend")), ] + cmdutil.walkopts + cmdutil.commitopts + cmdutil.commitopts2 + cmdutil.commitopts3, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, inferrepo=True, ) @@ -70,7 +70,7 @@ cmdutil.checknotesize(ui, opts) with repo.wlock(), repo.lock(): - if not opts.get("logfile"): - opts["message"] = opts.get("message") or repo["."].description() - opts["amend"] = True + if not opts.get(b"logfile"): + opts[b"message"] = opts.get(b"message") or repo[b"."].description() + opts[b"amend"] = True return commands._docommit(ui, repo, *pats, **pycompat.strkwargs(opts)) diff --git a/hgext/automv.py b/hgext/automv.py --- a/hgext/automv.py +++ b/hgext/automv.py @@ -42,14 +42,14 @@ configitem = registrar.configitem(configtable) configitem( - "automv", "similarity", default=95, + b"automv", b"similarity", default=95, ) def extsetup(ui): - entry = extensions.wrapcommand(commands.table, "commit", mvcheck) + entry = extensions.wrapcommand(commands.table, b"commit", mvcheck) entry[1].append( - ("", "no-automv", None, _("disable automatic file move detection")) + (b"", b"no-automv", None, _(b"disable automatic file move detection")) ) @@ -57,11 +57,11 @@ """Hook to check for moves at commit time""" opts = pycompat.byteskwargs(opts) renames = None - disabled = opts.pop("no_automv", False) + disabled = opts.pop(b"no_automv", False) if not disabled: - threshold = ui.configint("automv", "similarity") + threshold = ui.configint(b"automv", b"similarity") if not 0 <= threshold <= 100: - raise error.Abort(_("automv.similarity must be between 0 and 100")) + raise error.Abort(_(b"automv.similarity must be between 0 and 100")) if threshold > 0: match = scmutil.match(repo[None], pats, opts) added, removed = _interestingfiles(repo, match) @@ -87,7 +87,7 @@ added = stat.added removed = stat.removed - copy = copies.pathcopies(repo["."], repo[None], matcher) + copy = copies.pathcopies(repo[b"."], repo[None], matcher) # remove the copy files for which we already have copy info added = [f for f in added if f not in copy] @@ -108,10 +108,10 @@ ): if repo.ui.verbose: repo.ui.status( - _("detected move of %s as %s (%d%% similar)\n") + _(b"detected move of %s as %s (%d%% similar)\n") % (uipathfn(src), uipathfn(dst), score * 100) ) renames[dst] = src if renames: - repo.ui.status(_("detected move of %d files\n") % len(renames)) + repo.ui.status(_(b"detected move of %d files\n") % len(renames)) return renames diff --git a/hgext/beautifygraph.py b/hgext/beautifygraph.py --- a/hgext/beautifygraph.py +++ b/hgext/beautifygraph.py @@ -26,33 +26,33 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def prettyedge(before, edge, after): - if edge == "~": - return "\xE2\x95\xA7" # U+2567 ╧ - if edge == "/": - return "\xE2\x95\xB1" # U+2571 ╱ - if edge == "-": - return "\xE2\x94\x80" # U+2500 ─ - if edge == "|": - return "\xE2\x94\x82" # U+2502 │ - if edge == ":": - return "\xE2\x94\x86" # U+2506 ┆ - if edge == "\\": - return "\xE2\x95\xB2" # U+2572 ╲ - if edge == "+": - if before == " " and not after == " ": - return "\xE2\x94\x9C" # U+251C ├ - if after == " " and not before == " ": - return "\xE2\x94\xA4" # U+2524 ┤ - return "\xE2\x94\xBC" # U+253C ┼ + if edge == b"~": + return b"\xE2\x95\xA7" # U+2567 ╧ + if edge == b"/": + return b"\xE2\x95\xB1" # U+2571 ╱ + if edge == b"-": + return b"\xE2\x94\x80" # U+2500 ─ + if edge == b"|": + return b"\xE2\x94\x82" # U+2502 │ + if edge == b":": + return b"\xE2\x94\x86" # U+2506 ┆ + if edge == b"\\": + return b"\xE2\x95\xB2" # U+2572 ╲ + if edge == b"+": + if before == b" " and not after == b" ": + return b"\xE2\x94\x9C" # U+251C ├ + if after == b" " and not before == b" ": + return b"\xE2\x94\xA4" # U+2524 ┤ + return b"\xE2\x94\xBC" # U+253C ┼ return edge def convertedges(line): - line = " %s " % line + line = b" %s " % line pretty = [] for idx in pycompat.xrange(len(line) - 2): pretty.append( @@ -62,21 +62,21 @@ line[idx + 2 : idx + 3], ) ) - return "".join(pretty) + return b"".join(pretty) def getprettygraphnode(orig, *args, **kwargs): node = orig(*args, **kwargs) - if node == "o": - return "\xE2\x97\x8B" # U+25CB ○ - if node == "@": - return "\xE2\x97\x8D" # U+25CD ◍ - if node == "*": - return "\xE2\x88\x97" # U+2217 ∗ - if node == "x": - return "\xE2\x97\x8C" # U+25CC ◌ - if node == "_": - return "\xE2\x95\xA4" # U+2564 ╤ + if node == b"o": + return b"\xE2\x97\x8B" # U+25CB ○ + if node == b"@": + return b"\xE2\x97\x8D" # U+25CD ◍ + if node == b"*": + return b"\xE2\x88\x97" # U+2217 ∗ + if node == b"x": + return b"\xE2\x97\x8C" # U+25CC ◌ + if node == b"_": + return b"\xE2\x95\xA4" # U+2564 ╤ return node @@ -87,21 +87,21 @@ def extsetup(ui): - if ui.plain("graph"): + if ui.plain(b"graph"): return - if encoding.encoding != "UTF-8": - ui.warn(_("beautifygraph: unsupported encoding, UTF-8 required\n")) + if encoding.encoding != b"UTF-8": + ui.warn(_(b"beautifygraph: unsupported encoding, UTF-8 required\n")) return if r"A" in encoding._wide: ui.warn( _( - "beautifygraph: unsupported terminal settings, " - "monospace narrow text required\n" + b"beautifygraph: unsupported terminal settings, " + b"monospace narrow text required\n" ) ) return - extensions.wrapfunction(graphmod, "outputgraph", outputprettygraph) - extensions.wrapfunction(templatekw, "getgraphnode", getprettygraphnode) + extensions.wrapfunction(graphmod, b"outputgraph", outputprettygraph) + extensions.wrapfunction(templatekw, b"getgraphnode", getprettygraphnode) diff --git a/hgext/blackbox.py b/hgext/blackbox.py --- a/hgext/blackbox.py +++ b/hgext/blackbox.py @@ -63,7 +63,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @@ -72,27 +72,27 @@ configitem = registrar.configitem(configtable) configitem( - "blackbox", "dirty", default=False, + b"blackbox", b"dirty", default=False, ) configitem( - "blackbox", "maxsize", default="1 MB", + b"blackbox", b"maxsize", default=b"1 MB", ) configitem( - "blackbox", "logsource", default=False, + b"blackbox", b"logsource", default=False, ) configitem( - "blackbox", "maxfiles", default=7, + b"blackbox", b"maxfiles", default=7, ) configitem( - "blackbox", "track", default=lambda: ["*"], + b"blackbox", b"track", default=lambda: [b"*"], ) configitem( - "blackbox", - "ignore", - default=lambda: ["chgserver", "cmdserver", "extension"], + b"blackbox", + b"ignore", + default=lambda: [b"chgserver", b"cmdserver", b"extension"], ) configitem( - "blackbox", "date-format", default="%Y/%m/%d %H:%M:%S", + b"blackbox", b"date-format", default=b"%Y/%m/%d %H:%M:%S", ) _lastlogger = loggingutil.proxylogger() @@ -101,10 +101,10 @@ class blackboxlogger(object): def __init__(self, ui, repo): self._repo = repo - self._trackedevents = set(ui.configlist("blackbox", "track")) - self._ignoredevents = set(ui.configlist("blackbox", "ignore")) - self._maxfiles = ui.configint("blackbox", "maxfiles") - self._maxsize = ui.configbytes("blackbox", "maxsize") + self._trackedevents = set(ui.configlist(b"blackbox", b"track")) + self._ignoredevents = set(ui.configlist(b"blackbox", b"ignore")) + self._maxfiles = ui.configint(b"blackbox", b"maxfiles") + self._maxsize = ui.configbytes(b"blackbox", b"maxsize") self._inlog = False def tracked(self, event): @@ -125,29 +125,29 @@ self._inlog = False def _log(self, ui, event, msg, opts): - default = ui.configdate("devel", "default-date") - date = dateutil.datestr(default, ui.config("blackbox", "date-format")) + default = ui.configdate(b"devel", b"default-date") + date = dateutil.datestr(default, ui.config(b"blackbox", b"date-format")) user = procutil.getuser() - pid = "%d" % procutil.getpid() - changed = "" + pid = b"%d" % procutil.getpid() + changed = b"" ctx = self._repo[None] parents = ctx.parents() - rev = "+".join([hex(p.node()) for p in parents]) - if ui.configbool("blackbox", "dirty") and ctx.dirty( + rev = b"+".join([hex(p.node()) for p in parents]) + if ui.configbool(b"blackbox", b"dirty") and ctx.dirty( missing=True, merge=False, branch=False ): - changed = "+" - if ui.configbool("blackbox", "logsource"): - src = " [%s]" % event + changed = b"+" + if ui.configbool(b"blackbox", b"logsource"): + src = b" [%s]" % event else: - src = "" + src = b"" try: - fmt = "%s %s @%s%s (%s)%s> %s" + fmt = b"%s %s @%s%s (%s)%s> %s" args = (date, user, rev, changed, pid, src, msg) with loggingutil.openlogfile( ui, self._repo.vfs, - name="blackbox.log", + name=b"blackbox.log", maxfiles=self._maxfiles, maxsize=self._maxsize, ) as fp: @@ -156,7 +156,7 @@ # deactivate this to avoid failed logging again self._trackedevents.clear() ui.debug( - "warning: cannot write to blackbox.log: %s\n" + b"warning: cannot write to blackbox.log: %s\n" % encoding.strtolocal(err.strerror) ) return @@ -184,13 +184,13 @@ if _lastlogger.logger is None: _lastlogger.logger = logger - repo._wlockfreeprefix.add("blackbox.log") + repo._wlockfreeprefix.add(b"blackbox.log") @command( - "blackbox", - [("l", "limit", 10, _("the number of events to show")),], - _("hg blackbox [OPTION]..."), + b"blackbox", + [(b"l", b"limit", 10, _(b"the number of events to show")),], + _(b"hg blackbox [OPTION]..."), helpcategory=command.CATEGORY_MAINTENANCE, helpbasic=True, ) @@ -198,12 +198,12 @@ """view the recent repository events """ - if not repo.vfs.exists("blackbox.log"): + if not repo.vfs.exists(b"blackbox.log"): return limit = opts.get(r"limit") - fp = repo.vfs("blackbox.log", "r") - lines = fp.read().split("\n") + fp = repo.vfs(b"blackbox.log", b"r") + lines = fp.read().split(b"\n") count = 0 output = [] @@ -216,4 +216,4 @@ count += 1 output.append(line) - ui.status("\n".join(reversed(output))) + ui.status(b"\n".join(reversed(output))) diff --git a/hgext/bookflow.py b/hgext/bookflow.py --- a/hgext/bookflow.py +++ b/hgext/bookflow.py @@ -24,14 +24,14 @@ registrar, ) -MY_NAME = "bookflow" +MY_NAME = b"bookflow" configtable = {} configitem = registrar.configitem(configtable) -configitem(MY_NAME, "protect", ["@"]) -configitem(MY_NAME, "require-bookmark", True) -configitem(MY_NAME, "enable-branches", False) +configitem(MY_NAME, b"protect", [b"@"]) +configitem(MY_NAME, b"require-bookmark", True) +configitem(MY_NAME, b"enable-branches", False) cmdtable = {} command = registrar.command(cmdtable) @@ -40,19 +40,19 @@ def commit_hook(ui, repo, **kwargs): active = repo._bookmarks.active if active: - if active in ui.configlist(MY_NAME, "protect"): + if active in ui.configlist(MY_NAME, b"protect"): raise error.Abort( - _("cannot commit, bookmark %s is protected") % active + _(b"cannot commit, bookmark %s is protected") % active ) if not cwd_at_bookmark(repo, active): raise error.Abort( _( - "cannot commit, working directory out of sync with active bookmark" + b"cannot commit, working directory out of sync with active bookmark" ), - hint=_("run 'hg up %s'") % active, + hint=_(b"run 'hg up %s'") % active, ) - elif ui.configbool(MY_NAME, "require-bookmark", True): - raise error.Abort(_("cannot commit without an active bookmark")) + elif ui.configbool(MY_NAME, b"require-bookmark", True): + raise error.Abort(_(b"cannot commit without an active bookmark")) return 0 @@ -74,7 +74,7 @@ if name in marks: raise error.Abort( _( - "bookmark %s already exists, to move use the --rev option" + b"bookmark %s already exists, to move use the --rev option" ) % name ) @@ -92,8 +92,8 @@ if active and not cwd_at_bookmark(repo, active): ui.warn( _( - "working directory out of sync with active bookmark, run " - "'hg up %s'" + b"working directory out of sync with active bookmark, run " + b"'hg up %s'" ) % active ) @@ -104,23 +104,23 @@ if label and not opts.get(r"clean") and not opts.get(r"rev"): raise error.Abort( _( - "creating named branches is disabled and you should use bookmarks" + b"creating named branches is disabled and you should use bookmarks" ), - hint="see 'hg help bookflow'", + hint=b"see 'hg help bookflow'", ) return orig(ui, repo, label, **opts) def cwd_at_bookmark(repo, mark): mark_id = repo._bookmarks[mark] - cur_id = repo.lookup(".") + cur_id = repo.lookup(b".") return cur_id == mark_id def uisetup(ui): - extensions.wrapfunction(bookmarks, "update", bookmarks_update) - extensions.wrapfunction(bookmarks, "addbookmarks", bookmarks_addbookmarks) - extensions.wrapcommand(commands.table, "commit", commands_commit) - extensions.wrapcommand(commands.table, "pull", commands_pull) - if not ui.configbool(MY_NAME, "enable-branches"): - extensions.wrapcommand(commands.table, "branch", commands_branch) + extensions.wrapfunction(bookmarks, b"update", bookmarks_update) + extensions.wrapfunction(bookmarks, b"addbookmarks", bookmarks_addbookmarks) + extensions.wrapcommand(commands.table, b"commit", commands_commit) + extensions.wrapcommand(commands.table, b"pull", commands_pull) + if not ui.configbool(MY_NAME, b"enable-branches"): + extensions.wrapcommand(commands.table, b"branch", commands_branch) diff --git a/hgext/bugzilla.py b/hgext/bugzilla.py --- a/hgext/bugzilla.py +++ b/hgext/bugzilla.py @@ -319,32 +319,32 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "bugzilla", "apikey", default="", + b"bugzilla", b"apikey", default=b"", ) configitem( - "bugzilla", "bzdir", default="/var/www/html/bugzilla", + b"bugzilla", b"bzdir", default=b"/var/www/html/bugzilla", ) configitem( - "bugzilla", "bzemail", default=None, + b"bugzilla", b"bzemail", default=None, ) configitem( - "bugzilla", "bzurl", default="http://localhost/bugzilla/", + b"bugzilla", b"bzurl", default=b"http://localhost/bugzilla/", ) configitem( - "bugzilla", "bzuser", default=None, + b"bugzilla", b"bzuser", default=None, ) configitem( - "bugzilla", "db", default="bugs", + b"bugzilla", b"db", default=b"bugs", ) configitem( - "bugzilla", - "fixregexp", + b"bugzilla", + b"fixregexp", default=( br"fix(?:es)?\s*(?:bugs?\s*)?,?\s*" br"(?:nos?\.?|num(?:ber)?s?)?\s*" @@ -353,23 +353,23 @@ ), ) configitem( - "bugzilla", "fixresolution", default="FIXED", + b"bugzilla", b"fixresolution", default=b"FIXED", ) configitem( - "bugzilla", "fixstatus", default="RESOLVED", + b"bugzilla", b"fixstatus", default=b"RESOLVED", ) configitem( - "bugzilla", "host", default="localhost", + b"bugzilla", b"host", default=b"localhost", ) configitem( - "bugzilla", "notify", default=configitem.dynamicdefault, + b"bugzilla", b"notify", default=configitem.dynamicdefault, ) configitem( - "bugzilla", "password", default=None, + b"bugzilla", b"password", default=None, ) configitem( - "bugzilla", - "regexp", + b"bugzilla", + b"regexp", default=( br"bugs?\s*,?\s*(?:#|nos?\.?|num(?:ber)?s?)?\s*" br"(?P(?:\d+\s*(?:,?\s*(?:and)?)?\s*)+)" @@ -377,25 +377,25 @@ ), ) configitem( - "bugzilla", "strip", default=0, + b"bugzilla", b"strip", default=0, ) configitem( - "bugzilla", "style", default=None, + b"bugzilla", b"style", default=None, ) configitem( - "bugzilla", "template", default=None, + b"bugzilla", b"template", default=None, ) configitem( - "bugzilla", "timeout", default=5, + b"bugzilla", b"timeout", default=5, ) configitem( - "bugzilla", "user", default="bugs", + b"bugzilla", b"user", default=b"bugs", ) configitem( - "bugzilla", "usermap", default=None, + b"bugzilla", b"usermap", default=None, ) configitem( - "bugzilla", "version", default=None, + b"bugzilla", b"version", default=None, ) @@ -404,13 +404,13 @@ def __init__(self, ui): self.ui = ui - usermap = self.ui.config("bugzilla", "usermap") + usermap = self.ui.config(b"bugzilla", b"usermap") if usermap: - self.ui.readconfig(usermap, sections=["usermap"]) + self.ui.readconfig(usermap, sections=[b"usermap"]) def map_committer(self, user): """map name of committer to Bugzilla user name.""" - for committer, bzuser in self.ui.configitems("usermap"): + for committer, bzuser in self.ui.configitems(b"usermap"): if committer.lower() == user.lower(): return bzuser return user @@ -457,7 +457,7 @@ @staticmethod def sql_buglist(ids): """return SQL-friendly list of bug ids""" - return "(" + ",".join(map(str, ids)) + ")" + return b"(" + b",".join(map(str, ids)) + b")" _MySQLdb = None @@ -467,18 +467,20 @@ bzmysql._MySQLdb = mysql except ImportError as err: - raise error.Abort(_("python mysql support not available: %s") % err) + raise error.Abort( + _(b"python mysql support not available: %s") % err + ) bzaccess.__init__(self, ui) - host = self.ui.config("bugzilla", "host") - user = self.ui.config("bugzilla", "user") - passwd = self.ui.config("bugzilla", "password") - db = self.ui.config("bugzilla", "db") - timeout = int(self.ui.config("bugzilla", "timeout")) + host = self.ui.config(b"bugzilla", b"host") + user = self.ui.config(b"bugzilla", b"user") + passwd = self.ui.config(b"bugzilla", b"password") + db = self.ui.config(b"bugzilla", b"db") + timeout = int(self.ui.config(b"bugzilla", b"timeout")) self.ui.note( - _("connecting to %s:%s as %s, password %s\n") - % (host, db, user, "*" * len(passwd)) + _(b"connecting to %s:%s as %s, password %s\n") + % (host, db, user, b"*" * len(passwd)) ) self.conn = bzmysql._MySQLdb.connect( host=host, user=user, passwd=passwd, db=db, connect_timeout=timeout @@ -486,35 +488,35 @@ self.cursor = self.conn.cursor() self.longdesc_id = self.get_longdesc_id() self.user_ids = {} - self.default_notify = "cd %(bzdir)s && ./processmail %(id)s %(user)s" + self.default_notify = b"cd %(bzdir)s && ./processmail %(id)s %(user)s" def run(self, *args, **kwargs): """run a query.""" - self.ui.note(_("query: %s %s\n") % (args, kwargs)) + self.ui.note(_(b"query: %s %s\n") % (args, kwargs)) try: self.cursor.execute(*args, **kwargs) except bzmysql._MySQLdb.MySQLError: - self.ui.note(_("failed query: %s %s\n") % (args, kwargs)) + self.ui.note(_(b"failed query: %s %s\n") % (args, kwargs)) raise def get_longdesc_id(self): """get identity of longdesc field""" - self.run('select fieldid from fielddefs where name = "longdesc"') + self.run(b'select fieldid from fielddefs where name = "longdesc"') ids = self.cursor.fetchall() if len(ids) != 1: - raise error.Abort(_("unknown database schema")) + raise error.Abort(_(b"unknown database schema")) return ids[0][0] def filter_real_bug_ids(self, bugs): """filter not-existing bugs from set.""" self.run( - "select bug_id from bugs where bug_id in %s" + b"select bug_id from bugs where bug_id in %s" % bzmysql.sql_buglist(bugs.keys()) ) existing = [id for (id,) in self.cursor.fetchall()] for id in bugs.keys(): if id not in existing: - self.ui.status(_("bug %d does not exist\n") % id) + self.ui.status(_(b"bug %d does not exist\n") % id) del bugs[id] def filter_cset_known_bug_ids(self, node, bugs): @@ -526,36 +528,36 @@ ) for (id,) in self.cursor.fetchall(): self.ui.status( - _("bug %d already knows about changeset %s\n") + _(b"bug %d already knows about changeset %s\n") % (id, short(node)) ) del bugs[id] def notify(self, bugs, committer): """tell bugzilla to send mail.""" - self.ui.status(_("telling bugzilla to send mail:\n")) + self.ui.status(_(b"telling bugzilla to send mail:\n")) (user, userid) = self.get_bugzilla_user(committer) for id in bugs.keys(): - self.ui.status(_(" bug %s\n") % id) - cmdfmt = self.ui.config("bugzilla", "notify", self.default_notify) - bzdir = self.ui.config("bugzilla", "bzdir") + self.ui.status(_(b" bug %s\n") % id) + cmdfmt = self.ui.config(b"bugzilla", b"notify", self.default_notify) + bzdir = self.ui.config(b"bugzilla", b"bzdir") try: # Backwards-compatible with old notify string, which # took one string. This will throw with a new format # string. cmd = cmdfmt % id except TypeError: - cmd = cmdfmt % {"bzdir": bzdir, "id": id, "user": user} - self.ui.note(_("running notify command %s\n") % cmd) - fp = procutil.popen("(%s) 2>&1" % cmd, "rb") + cmd = cmdfmt % {b"bzdir": bzdir, b"id": id, b"user": user} + self.ui.note(_(b"running notify command %s\n") % cmd) + fp = procutil.popen(b"(%s) 2>&1" % cmd, b"rb") out = util.fromnativeeol(fp.read()) ret = fp.close() if ret: self.ui.warn(out) raise error.Abort( - _("bugzilla notify command %s") % procutil.explainexit(ret) + _(b"bugzilla notify command %s") % procutil.explainexit(ret) ) - self.ui.status(_("done\n")) + self.ui.status(_(b"done\n")) def get_user_id(self, user): """look up numeric bugzilla user id.""" @@ -565,7 +567,7 @@ try: userid = int(user) except ValueError: - self.ui.note(_("looking up user %s\n") % user) + self.ui.note(_(b"looking up user %s\n") % user) self.run( """select userid from profiles where login_name like %s""", @@ -587,16 +589,16 @@ userid = self.get_user_id(user) except KeyError: try: - defaultuser = self.ui.config("bugzilla", "bzuser") + defaultuser = self.ui.config(b"bugzilla", b"bzuser") if not defaultuser: raise error.Abort( - _("cannot find bugzilla user id for %s") % user + _(b"cannot find bugzilla user id for %s") % user ) userid = self.get_user_id(defaultuser) user = defaultuser except KeyError: raise error.Abort( - _("cannot find bugzilla user id for %s or %s") + _(b"cannot find bugzilla user id for %s or %s") % (user, defaultuser) ) return (user, userid) @@ -607,7 +609,7 @@ Try adding comment as committer of changeset, otherwise as default bugzilla user.""" if len(newstate) > 0: - self.ui.warn(_("Bugzilla/MySQL cannot update bug state\n")) + self.ui.warn(_(b"Bugzilla/MySQL cannot update bug state\n")) (user, userid) = self.get_bugzilla_user(committer) now = time.strftime(r"%Y-%m-%d %H:%M:%S") @@ -631,7 +633,7 @@ def __init__(self, ui): bzmysql.__init__(self, ui) self.default_notify = ( - "cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s" + b"cd %(bzdir)s && perl -T contrib/sendbugmail.pl %(id)s %(user)s" ) @@ -643,10 +645,10 @@ def get_longdesc_id(self): """get identity of longdesc field""" - self.run('select id from fielddefs where name = "longdesc"') + self.run(b'select id from fielddefs where name = "longdesc"') ids = self.cursor.fetchall() if len(ids) != 1: - raise error.Abort(_("unknown database schema")) + raise error.Abort(_(b"unknown database schema")) return ids[0][0] @@ -674,7 +676,7 @@ def send_cookies(self, connection): if self.cookies: for cookie in self.cookies: - connection.putheader("Cookie", cookie) + connection.putheader(b"Cookie", cookie) def request(self, host, handler, request_body, verbose=0): self.verbose = verbose @@ -702,9 +704,9 @@ response = h._conn.getresponse() # Add any cookie definitions to our list. - for header in response.msg.getallmatchingheaders("Set-Cookie"): - val = header.split(": ", 1)[1] - cookie = val.split(";", 1)[0] + for header in response.msg.getallmatchingheaders(b"Set-Cookie"): + val = header.split(b": ", 1)[1] + cookie = val.split(b";", 1)[0] self.cookies.append(cookie) if response.status != 200: @@ -729,13 +731,13 @@ # inheritance with a new-style class. class cookietransport(cookietransportrequest, xmlrpclib.Transport): def __init__(self, use_datetime=0): - if util.safehasattr(xmlrpclib.Transport, "__init__"): + if util.safehasattr(xmlrpclib.Transport, b"__init__"): xmlrpclib.Transport.__init__(self, use_datetime) class cookiesafetransport(cookietransportrequest, xmlrpclib.SafeTransport): def __init__(self, use_datetime=0): - if util.safehasattr(xmlrpclib.Transport, "__init__"): + if util.safehasattr(xmlrpclib.Transport, b"__init__"): xmlrpclib.SafeTransport.__init__(self, use_datetime) @@ -748,26 +750,26 @@ def __init__(self, ui): bzaccess.__init__(self, ui) - bzweb = self.ui.config("bugzilla", "bzurl") - bzweb = bzweb.rstrip("/") + "/xmlrpc.cgi" + bzweb = self.ui.config(b"bugzilla", b"bzurl") + bzweb = bzweb.rstrip(b"/") + b"/xmlrpc.cgi" - user = self.ui.config("bugzilla", "user") - passwd = self.ui.config("bugzilla", "password") + user = self.ui.config(b"bugzilla", b"user") + passwd = self.ui.config(b"bugzilla", b"password") - self.fixstatus = self.ui.config("bugzilla", "fixstatus") - self.fixresolution = self.ui.config("bugzilla", "fixresolution") + self.fixstatus = self.ui.config(b"bugzilla", b"fixstatus") + self.fixresolution = self.ui.config(b"bugzilla", b"fixresolution") self.bzproxy = xmlrpclib.ServerProxy(bzweb, self.transport(bzweb)) - ver = self.bzproxy.Bugzilla.version()["version"].split(".") + ver = self.bzproxy.Bugzilla.version()[b"version"].split(b".") self.bzvermajor = int(ver[0]) self.bzverminor = int(ver[1]) login = self.bzproxy.User.login( - {"login": user, "password": passwd, "restrict_login": True} + {b"login": user, b"password": passwd, b"restrict_login": True} ) - self.bztoken = login.get("token", "") + self.bztoken = login.get(b"token", b"") def transport(self, uri): - if util.urlreq.urlparse(uri, "http")[0] == "https": + if util.urlreq.urlparse(uri, b"http")[0] == b"https": return cookiesafetransport() else: return cookietransport() @@ -775,56 +777,58 @@ def get_bug_comments(self, id): """Return a string with all comment text for a bug.""" c = self.bzproxy.Bug.comments( - {"ids": [id], "include_fields": ["text"], "token": self.bztoken} + {b"ids": [id], b"include_fields": [b"text"], b"token": self.bztoken} ) - return "".join([t["text"] for t in c["bugs"]["%d" % id]["comments"]]) + return b"".join( + [t[b"text"] for t in c[b"bugs"][b"%d" % id][b"comments"]] + ) def filter_real_bug_ids(self, bugs): probe = self.bzproxy.Bug.get( { - "ids": sorted(bugs.keys()), - "include_fields": [], - "permissive": True, - "token": self.bztoken, + b"ids": sorted(bugs.keys()), + b"include_fields": [], + b"permissive": True, + b"token": self.bztoken, } ) - for badbug in probe["faults"]: - id = badbug["id"] - self.ui.status(_("bug %d does not exist\n") % id) + for badbug in probe[b"faults"]: + id = badbug[b"id"] + self.ui.status(_(b"bug %d does not exist\n") % id) del bugs[id] def filter_cset_known_bug_ids(self, node, bugs): for id in sorted(bugs.keys()): if self.get_bug_comments(id).find(short(node)) != -1: self.ui.status( - _("bug %d already knows about changeset %s\n") + _(b"bug %d already knows about changeset %s\n") % (id, short(node)) ) del bugs[id] def updatebug(self, bugid, newstate, text, committer): args = {} - if "hours" in newstate: - args["work_time"] = newstate["hours"] + if b"hours" in newstate: + args[b"work_time"] = newstate[b"hours"] if self.bzvermajor >= 4: - args["ids"] = [bugid] - args["comment"] = {"body": text} - if "fix" in newstate: - args["status"] = self.fixstatus - args["resolution"] = self.fixresolution - args["token"] = self.bztoken + args[b"ids"] = [bugid] + args[b"comment"] = {b"body": text} + if b"fix" in newstate: + args[b"status"] = self.fixstatus + args[b"resolution"] = self.fixresolution + args[b"token"] = self.bztoken self.bzproxy.Bug.update(args) else: - if "fix" in newstate: + if b"fix" in newstate: self.ui.warn( _( - "Bugzilla/XMLRPC needs Bugzilla 4.0 or later " - "to mark bugs fixed\n" + b"Bugzilla/XMLRPC needs Bugzilla 4.0 or later " + b"to mark bugs fixed\n" ) ) - args["id"] = bugid - args["comment"] = text + args[b"id"] = bugid + args[b"comment"] = text self.bzproxy.Bug.add_comment(args) @@ -851,18 +855,18 @@ def __init__(self, ui): bzxmlrpc.__init__(self, ui) - self.bzemail = self.ui.config("bugzilla", "bzemail") + self.bzemail = self.ui.config(b"bugzilla", b"bzemail") if not self.bzemail: - raise error.Abort(_("configuration 'bzemail' missing")) + raise error.Abort(_(b"configuration 'bzemail' missing")) mail.validateconfig(self.ui) def makecommandline(self, fieldname, value): if self.bzvermajor >= 4: - return "@%s %s" % (fieldname, pycompat.bytestr(value)) + return b"@%s %s" % (fieldname, pycompat.bytestr(value)) else: - if fieldname == "id": - fieldname = "bug_id" - return "@%s = %s" % (fieldname, pycompat.bytestr(value)) + if fieldname == b"id": + fieldname = b"bug_id" + return b"@%s = %s" % (fieldname, pycompat.bytestr(value)) def send_bug_modify_email(self, bugid, commands, comment, committer): """send modification message to Bugzilla bug via email. @@ -877,39 +881,41 @@ """ user = self.map_committer(committer) matches = self.bzproxy.User.get( - {"match": [user], "token": self.bztoken} + {b"match": [user], b"token": self.bztoken} ) - if not matches["users"]: - user = self.ui.config("bugzilla", "user") + if not matches[b"users"]: + user = self.ui.config(b"bugzilla", b"user") matches = self.bzproxy.User.get( - {"match": [user], "token": self.bztoken} + {b"match": [user], b"token": self.bztoken} ) - if not matches["users"]: + if not matches[b"users"]: raise error.Abort( - _("default bugzilla user %s email not found") % user + _(b"default bugzilla user %s email not found") % user ) - user = matches["users"][0]["email"] - commands.append(self.makecommandline("id", bugid)) + user = matches[b"users"][0][b"email"] + commands.append(self.makecommandline(b"id", bugid)) - text = "\n".join(commands) + "\n\n" + comment + text = b"\n".join(commands) + b"\n\n" + comment _charsets = mail._charsets(self.ui) user = mail.addressencode(self.ui, user, _charsets) bzemail = mail.addressencode(self.ui, self.bzemail, _charsets) msg = mail.mimeencode(self.ui, text, _charsets) - msg["From"] = user - msg["To"] = bzemail - msg["Subject"] = mail.headencode(self.ui, "Bug modification", _charsets) + msg[b"From"] = user + msg[b"To"] = bzemail + msg[b"Subject"] = mail.headencode( + self.ui, b"Bug modification", _charsets + ) sendmail = mail.connect(self.ui) sendmail(user, bzemail, msg.as_string()) def updatebug(self, bugid, newstate, text, committer): cmds = [] - if "hours" in newstate: - cmds.append(self.makecommandline("work_time", newstate["hours"])) - if "fix" in newstate: - cmds.append(self.makecommandline("bug_status", self.fixstatus)) - cmds.append(self.makecommandline("resolution", self.fixresolution)) + if b"hours" in newstate: + cmds.append(self.makecommandline(b"work_time", newstate[b"hours"])) + if b"fix" in newstate: + cmds.append(self.makecommandline(b"bug_status", self.fixstatus)) + cmds.append(self.makecommandline(b"resolution", self.fixresolution)) self.send_bug_modify_email(bugid, cmds, text, committer) @@ -924,26 +930,26 @@ def __init__(self, ui): bzaccess.__init__(self, ui) - bz = self.ui.config("bugzilla", "bzurl") - self.bzroot = "/".join([bz, "rest"]) - self.apikey = self.ui.config("bugzilla", "apikey") - self.user = self.ui.config("bugzilla", "user") - self.passwd = self.ui.config("bugzilla", "password") - self.fixstatus = self.ui.config("bugzilla", "fixstatus") - self.fixresolution = self.ui.config("bugzilla", "fixresolution") + bz = self.ui.config(b"bugzilla", b"bzurl") + self.bzroot = b"/".join([bz, b"rest"]) + self.apikey = self.ui.config(b"bugzilla", b"apikey") + self.user = self.ui.config(b"bugzilla", b"user") + self.passwd = self.ui.config(b"bugzilla", b"password") + self.fixstatus = self.ui.config(b"bugzilla", b"fixstatus") + self.fixresolution = self.ui.config(b"bugzilla", b"fixresolution") def apiurl(self, targets, include_fields=None): - url = "/".join([self.bzroot] + [pycompat.bytestr(t) for t in targets]) + url = b"/".join([self.bzroot] + [pycompat.bytestr(t) for t in targets]) qv = {} if self.apikey: - qv["api_key"] = self.apikey + qv[b"api_key"] = self.apikey elif self.user and self.passwd: - qv["login"] = self.user - qv["password"] = self.passwd + qv[b"login"] = self.user + qv[b"password"] = self.passwd if include_fields: - qv["include_fields"] = include_fields + qv[b"include_fields"] = include_fields if qv: - url = "%s?%s" % (url, util.urlreq.urlencode(qv)) + url = b"%s?%s" % (url, util.urlreq.urlencode(qv)) return url def _fetch(self, burl): @@ -952,30 +958,30 @@ return json.loads(resp.read()) except util.urlerr.httperror as inst: if inst.code == 401: - raise error.Abort(_("authorization failed")) + raise error.Abort(_(b"authorization failed")) if inst.code == 404: raise NotFound() else: raise - def _submit(self, burl, data, method="POST"): + def _submit(self, burl, data, method=b"POST"): data = json.dumps(data) - if method == "PUT": + if method == b"PUT": class putrequest(util.urlreq.request): def get_method(self): - return "PUT" + return b"PUT" request_type = putrequest else: request_type = util.urlreq.request - req = request_type(burl, data, {"Content-Type": "application/json"}) + req = request_type(burl, data, {b"Content-Type": b"application/json"}) try: resp = url.opener(self.ui).open(req) return json.loads(resp.read()) except util.urlerr.httperror as inst: if inst.code == 401: - raise error.Abort(_("authorization failed")) + raise error.Abort(_(b"authorization failed")) if inst.code == 404: raise NotFound() else: @@ -985,7 +991,7 @@ """remove bug IDs that do not exist in Bugzilla from bugs.""" badbugs = set() for bugid in bugs: - burl = self.apiurl(("bug", bugid), include_fields="status") + burl = self.apiurl((b"bug", bugid), include_fields=b"status") try: self._fetch(burl) except NotFound: @@ -997,12 +1003,15 @@ """remove bug IDs where node occurs in comment text from bugs.""" sn = short(node) for bugid in bugs.keys(): - burl = self.apiurl(("bug", bugid, "comment"), include_fields="text") + burl = self.apiurl( + (b"bug", bugid, b"comment"), include_fields=b"text" + ) result = self._fetch(burl) - comments = result["bugs"][pycompat.bytestr(bugid)]["comments"] - if any(sn in c["text"] for c in comments): + comments = result[b"bugs"][pycompat.bytestr(bugid)][b"comments"] + if any(sn in c[b"text"] for c in comments): self.ui.status( - _("bug %d already knows about changeset %s\n") % (bugid, sn) + _(b"bug %d already knows about changeset %s\n") + % (bugid, sn) ) del bugs[bugid] @@ -1013,28 +1022,32 @@ the changeset. Otherwise use the default Bugzilla user. """ bugmod = {} - if "hours" in newstate: - bugmod["work_time"] = newstate["hours"] - if "fix" in newstate: - bugmod["status"] = self.fixstatus - bugmod["resolution"] = self.fixresolution + if b"hours" in newstate: + bugmod[b"work_time"] = newstate[b"hours"] + if b"fix" in newstate: + bugmod[b"status"] = self.fixstatus + bugmod[b"resolution"] = self.fixresolution if bugmod: # if we have to change the bugs state do it here - bugmod["comment"] = { - "comment": text, - "is_private": False, - "is_markdown": False, + bugmod[b"comment"] = { + b"comment": text, + b"is_private": False, + b"is_markdown": False, } - burl = self.apiurl(("bug", bugid)) - self._submit(burl, bugmod, method="PUT") - self.ui.debug("updated bug %s\n" % bugid) + burl = self.apiurl((b"bug", bugid)) + self._submit(burl, bugmod, method=b"PUT") + self.ui.debug(b"updated bug %s\n" % bugid) else: - burl = self.apiurl(("bug", bugid, "comment")) + burl = self.apiurl((b"bug", bugid, b"comment")) self._submit( burl, - {"comment": text, "is_private": False, "is_markdown": False,}, + { + b"comment": text, + b"is_private": False, + b"is_markdown": False, + }, ) - self.ui.debug("added comment to bug %s\n" % bugid) + self.ui.debug(b"added comment to bug %s\n" % bugid) def notify(self, bugs, committer): """Force sending of Bugzilla notification emails. @@ -1049,32 +1062,32 @@ # supported versions of bugzilla. different versions have # different schemas. _versions = { - "2.16": bzmysql, - "2.18": bzmysql_2_18, - "3.0": bzmysql_3_0, - "xmlrpc": bzxmlrpc, - "xmlrpc+email": bzxmlrpcemail, - "restapi": bzrestapi, + b"2.16": bzmysql, + b"2.18": bzmysql_2_18, + b"3.0": bzmysql_3_0, + b"xmlrpc": bzxmlrpc, + b"xmlrpc+email": bzxmlrpcemail, + b"restapi": bzrestapi, } def __init__(self, ui, repo): self.ui = ui self.repo = repo - bzversion = self.ui.config("bugzilla", "version") + bzversion = self.ui.config(b"bugzilla", b"version") try: bzclass = bugzilla._versions[bzversion] except KeyError: raise error.Abort( - _("bugzilla version %s not supported") % bzversion + _(b"bugzilla version %s not supported") % bzversion ) self.bzdriver = bzclass(self.ui) self.bug_re = re.compile( - self.ui.config("bugzilla", "regexp"), re.IGNORECASE + self.ui.config(b"bugzilla", b"regexp"), re.IGNORECASE ) self.fix_re = re.compile( - self.ui.config("bugzilla", "fixregexp"), re.IGNORECASE + self.ui.config(b"bugzilla", b"fixregexp"), re.IGNORECASE ) self.split_re = re.compile(br"\D+") @@ -1106,25 +1119,25 @@ start = m.end() if m is bugmatch: bugmatch = self.bug_re.search(ctx.description(), start) - if "fix" in bugattribs: - del bugattribs["fix"] + if b"fix" in bugattribs: + del bugattribs[b"fix"] else: fixmatch = self.fix_re.search(ctx.description(), start) - bugattribs["fix"] = None + bugattribs[b"fix"] = None try: - ids = m.group("ids") + ids = m.group(b"ids") except IndexError: ids = m.group(1) try: - hours = float(m.group("hours")) - bugattribs["hours"] = hours + hours = float(m.group(b"hours")) + bugattribs[b"hours"] = hours except IndexError: pass except TypeError: pass except ValueError: - self.ui.status(_("%s: invalid hours\n") % m.group("hours")) + self.ui.status(_(b"%s: invalid hours\n") % m.group(b"hours")) for id in self.split_re.split(ids): if not id: @@ -1142,10 +1155,10 @@ def webroot(root): """strip leading prefix of repo root and turn into url-safe path.""" - count = int(self.ui.config("bugzilla", "strip")) + count = int(self.ui.config(b"bugzilla", b"strip")) root = util.pconvert(root) while count > 0: - c = root.find("/") + c = root.find(b"/") if c == -1: break root = root[c + 1 :] @@ -1153,13 +1166,13 @@ return root mapfile = None - tmpl = self.ui.config("bugzilla", "template") + tmpl = self.ui.config(b"bugzilla", b"template") if not tmpl: - mapfile = self.ui.config("bugzilla", "style") + mapfile = self.ui.config(b"bugzilla", b"style") if not mapfile and not tmpl: tmpl = _( - "changeset {node|short} in repo {root} refers " - "to bug {bug}.\ndetails:\n\t{desc|tabindent}" + b"changeset {node|short} in repo {root} refers " + b"to bug {bug}.\ndetails:\n\t{desc|tabindent}" ) spec = logcmdutil.templatespec(tmpl, mapfile) t = logcmdutil.changesettemplater(self.ui, self.repo, spec) @@ -1168,7 +1181,7 @@ ctx, changes=ctx.changeset(), bug=pycompat.bytestr(bugid), - hgweb=self.ui.config("web", "baseurl"), + hgweb=self.ui.config(b"web", b"baseurl"), root=self.repo.root, webroot=webroot(self.repo.root), ) @@ -1188,7 +1201,7 @@ seen multiple times does not fill bug with duplicate data.""" if node is None: raise error.Abort( - _("hook type %s does not pass a changeset id") % hooktype + _(b"hook type %s does not pass a changeset id") % hooktype ) try: bz = bugzilla(ui, repo) @@ -1199,4 +1212,4 @@ bz.update(bug, bugs[bug], ctx) bz.notify(bugs, stringutil.email(ctx.user())) except Exception as e: - raise error.Abort(_("Bugzilla error: %s") % e) + raise error.Abort(_(b"Bugzilla error: %s") % e) diff --git a/hgext/censor.py b/hgext/censor.py --- a/hgext/censor.py +++ b/hgext/censor.py @@ -42,49 +42,55 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "censor", + b"censor", [ - ("r", "rev", "", _("censor file from specified revision"), _("REV")), - ("t", "tombstone", "", _("replacement tombstone data"), _("TEXT")), + ( + b"r", + b"rev", + b"", + _(b"censor file from specified revision"), + _(b"REV"), + ), + (b"t", b"tombstone", b"", _(b"replacement tombstone data"), _(b"TEXT")), ], - _("-r REV [-t TEXT] [FILE]"), + _(b"-r REV [-t TEXT] [FILE]"), helpcategory=command.CATEGORY_MAINTENANCE, ) -def censor(ui, repo, path, rev="", tombstone="", **opts): +def censor(ui, repo, path, rev=b"", tombstone=b"", **opts): with repo.wlock(), repo.lock(): return _docensor(ui, repo, path, rev, tombstone, **opts) -def _docensor(ui, repo, path, rev="", tombstone="", **opts): +def _docensor(ui, repo, path, rev=b"", tombstone=b"", **opts): if not path: - raise error.Abort(_("must specify file path to censor")) + raise error.Abort(_(b"must specify file path to censor")) if not rev: - raise error.Abort(_("must specify revision to censor")) + raise error.Abort(_(b"must specify revision to censor")) wctx = repo[None] m = scmutil.match(wctx, (path,)) if m.anypats() or len(m.files()) != 1: - raise error.Abort(_("can only specify an explicit filename")) + raise error.Abort(_(b"can only specify an explicit filename")) path = m.files()[0] flog = repo.file(path) if not len(flog): - raise error.Abort(_("cannot censor file with no history")) + raise error.Abort(_(b"cannot censor file with no history")) rev = scmutil.revsingle(repo, rev, rev).rev() try: ctx = repo[rev] except KeyError: - raise error.Abort(_("invalid revision identifier %s") % rev) + raise error.Abort(_(b"invalid revision identifier %s") % rev) try: fctx = ctx.filectx(path) except error.LookupError: - raise error.Abort(_("file does not exist at revision %s") % rev) + raise error.Abort(_(b"file does not exist at revision %s") % rev) fnode = fctx.filenode() heads = [] @@ -93,17 +99,17 @@ if path in hc and hc.filenode(path) == fnode: heads.append(hc) if heads: - headlist = ", ".join([short(c.node()) for c in heads]) + headlist = b", ".join([short(c.node()) for c in heads]) raise error.Abort( - _("cannot censor file in heads (%s)") % headlist, - hint=_("clean/delete and commit first"), + _(b"cannot censor file in heads (%s)") % headlist, + hint=_(b"clean/delete and commit first"), ) wp = wctx.parents() if ctx.node() in [p.node() for p in wp]: raise error.Abort( - _("cannot censor working directory"), - hint=_("clean/delete/update first"), + _(b"cannot censor working directory"), + hint=_(b"clean/delete/update first"), ) with repo.transaction(b"censor") as tr: diff --git a/hgext/children.py b/hgext/children.py --- a/hgext/children.py +++ b/hgext/children.py @@ -33,14 +33,22 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "children", - [("r", "rev", ".", _("show children of the specified revision"), _("REV")),] + b"children", + [ + ( + b"r", + b"rev", + b".", + _(b"show children of the specified revision"), + _(b"REV"), + ), + ] + templateopts, - _("hg children [-r REV] [FILE]"), + _(b"hg children [-r REV] [FILE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, inferrepo=True, ) @@ -62,7 +70,7 @@ """ opts = pycompat.byteskwargs(opts) - rev = opts.get("rev") + rev = opts.get(b"rev") ctx = scmutil.revsingle(repo, rev) if file_: fctx = repo.filectx(file_, changeid=ctx.rev()) diff --git a/hgext/churn.py b/hgext/churn.py --- a/hgext/churn.py +++ b/hgext/churn.py @@ -32,17 +32,17 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def changedlines(ui, repo, ctx1, ctx2, fns): added, removed = 0, 0 fmatch = scmutil.matchfiles(repo, fns) - diff = "".join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch)) - for l in diff.split("\n"): - if l.startswith("+") and not l.startswith("+++ "): + diff = b"".join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch)) + for l in diff.split(b"\n"): + if l.startswith(b"+") and not l.startswith(b"+++ "): added += 1 - elif l.startswith("-") and not l.startswith("--- "): + elif l.startswith(b"-") and not l.startswith(b"--- "): removed += 1 return (added, removed) @@ -50,17 +50,17 @@ def countrate(ui, repo, amap, *pats, **opts): """Calculate stats""" opts = pycompat.byteskwargs(opts) - if opts.get("dateformat"): + if opts.get(b"dateformat"): def getkey(ctx): t, tz = ctx.date() date = datetime.datetime(*time.gmtime(float(t) - tz)[:6]) return encoding.strtolocal( - date.strftime(encoding.strfromlocal(opts["dateformat"])) + date.strftime(encoding.strfromlocal(opts[b"dateformat"])) ) else: - tmpl = opts.get("oldtemplate") or opts.get("template") + tmpl = opts.get(b"oldtemplate") or opts.get(b"template") tmpl = logcmdutil.maketemplater(ui, repo, tmpl) def getkey(ctx): @@ -69,12 +69,12 @@ return ui.popbuffer() progress = ui.makeprogress( - _("analyzing"), unit=_("revisions"), total=len(repo) + _(b"analyzing"), unit=_(b"revisions"), total=len(repo) ) rate = {} df = False - if opts.get("date"): - df = dateutil.matchdate(opts["date"]) + if opts.get(b"date"): + df = dateutil.matchdate(opts[b"date"]) m = scmutil.match(repo[None], pats, opts) @@ -85,12 +85,12 @@ key = getkey(ctx).strip() key = amap.get(key, key) # alias remap - if opts.get("changesets"): + if opts.get(b"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,)) + ui.note(_(b"revision %d is a merge, ignoring...\n") % (rev,)) return ctx1 = parents[0] @@ -108,50 +108,50 @@ @command( - "churn", + b"churn", [ ( - "r", - "rev", + b"r", + b"rev", [], - _("count rate for the specified revision or revset"), - _("REV"), + _(b"count rate for the specified revision or revset"), + _(b"REV"), ), ( - "d", - "date", - "", - _("count rate for revisions matching date spec"), - _("DATE"), + b"d", + b"date", + b"", + _(b"count rate for revisions matching date spec"), + _(b"DATE"), ), ( - "t", - "oldtemplate", - "", - _("template to group changesets (DEPRECATED)"), - _("TEMPLATE"), + b"t", + b"oldtemplate", + b"", + _(b"template to group changesets (DEPRECATED)"), + _(b"TEMPLATE"), ), ( - "T", - "template", - "{author|email}", - _("template to group changesets"), - _("TEMPLATE"), + b"T", + b"template", + b"{author|email}", + _(b"template to group changesets"), + _(b"TEMPLATE"), ), ( - "f", - "dateformat", - "", - _("strftime-compatible format for grouping by date"), - _("FORMAT"), + b"f", + b"dateformat", + b"", + _(b"strftime-compatible format for grouping by date"), + _(b"FORMAT"), ), - ("c", "changesets", False, _("count rate by number of changesets")), - ("s", "sort", False, _("sort by key (default: sort by count)")), - ("", "diffstat", False, _("display added/removed lines separately")), - ("", "aliases", "", _("file with email aliases"), _("FILE")), + (b"c", b"changesets", False, _(b"count rate by number of changesets")), + (b"s", b"sort", False, _(b"sort by key (default: sort by count)")), + (b"", b"diffstat", False, _(b"display added/removed lines separately")), + (b"", b"aliases", b"", _(b"file with email aliases"), _(b"FILE")), ] + cmdutil.walkopts, - _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"), + _(b"hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"), helpcategory=command.CATEGORY_MAINTENANCE, inferrepo=True, ) @@ -193,21 +193,21 @@ """ def pad(s, l): - return s + " " * (l - encoding.colwidth(s)) + return s + b" " * (l - encoding.colwidth(s)) amap = {} aliases = opts.get(r"aliases") - if not aliases and os.path.exists(repo.wjoin(".hgchurn")): - aliases = repo.wjoin(".hgchurn") + if not aliases and os.path.exists(repo.wjoin(b".hgchurn")): + aliases = repo.wjoin(b".hgchurn") if aliases: - for l in open(aliases, "rb"): + for l in open(aliases, b"rb"): try: - alias, actual = l.rsplit("=" in l and "=" or None, 1) + alias, actual = l.rsplit(b"=" in l and b"=" or None, 1) amap[alias.strip()] = actual.strip() except ValueError: l = l.strip() if l: - ui.warn(_("skipping malformed alias: %s\n") % l) + ui.warn(_(b"skipping malformed alias: %s\n") % l) continue rate = list(countrate(ui, repo, amap, *pats, **opts).items()) @@ -224,7 +224,7 @@ maxname = max(len(k) for k, v in rate) ttywidth = ui.termwidth() - ui.debug("assuming %i character terminal\n" % ttywidth) + ui.debug(b"assuming %i character terminal\n" % ttywidth) width = ttywidth - maxname - 2 - 2 - 2 if opts.get(r"diffstat"): @@ -232,21 +232,21 @@ def format(name, diffstat): added, removed = diffstat - return "%s %15s %s%s\n" % ( + return b"%s %15s %s%s\n" % ( pad(name, maxname), - "+%d/-%d" % (added, removed), - ui.label("+" * charnum(added), "diffstat.inserted"), - ui.label("-" * charnum(removed), "diffstat.deleted"), + b"+%d/-%d" % (added, removed), + ui.label(b"+" * charnum(added), b"diffstat.inserted"), + ui.label(b"-" * charnum(removed), b"diffstat.deleted"), ) else: width -= 6 def format(name, count): - return "%s %6d %s\n" % ( + return b"%s %6d %s\n" % ( pad(name, maxname), sum(count), - "*" * charnum(sum(count)), + b"*" * charnum(sum(count)), ) def charnum(count): diff --git a/hgext/clonebundles.py b/hgext/clonebundles.py --- a/hgext/clonebundles.py +++ b/hgext/clonebundles.py @@ -201,7 +201,7 @@ wireprotov1server, ) -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def capabilities(orig, repo, proto): @@ -210,11 +210,11 @@ # Only advertise if a manifest exists. This does add some I/O to requests. # But this should be cheaper than a wasted network round trip due to # missing file. - if repo.vfs.exists("clonebundles.manifest"): - caps.append("clonebundles") + if repo.vfs.exists(b"clonebundles.manifest"): + caps.append(b"clonebundles") return caps def extsetup(ui): - extensions.wrapfunction(wireprotov1server, "_capabilities", capabilities) + extensions.wrapfunction(wireprotov1server, b"_capabilities", capabilities) diff --git a/hgext/closehead.py b/hgext/closehead.py --- a/hgext/closehead.py +++ b/hgext/closehead.py @@ -24,17 +24,17 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" commitopts = cmdutil.commitopts commitopts2 = cmdutil.commitopts2 -commitopts3 = [("r", "rev", [], _("revision to check"), _("REV"))] +commitopts3 = [(b"r", b"rev", [], _(b"revision to check"), _(b"REV"))] @command( - "close-head|close-heads", + b"close-head|close-heads", commitopts + commitopts2 + commitopts3, - _("[OPTION]... [REV]..."), + _(b"[OPTION]... [REV]..."), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, inferrepo=True, ) @@ -55,11 +55,11 @@ text=message, files=[], filectxfn=None, - user=opts.get("user"), - date=opts.get("date"), + user=opts.get(b"user"), + date=opts.get(b"date"), extra=extra, ) - tr = repo.transaction("commit") + tr = repo.transaction(b"commit") ret = repo.commitctx(cctx, True) bookmarks.update(repo, [rev, None], ret) cctx.markcommitted(ret) @@ -67,11 +67,11 @@ opts = pycompat.byteskwargs(opts) - revs += tuple(opts.get("rev", [])) + revs += tuple(opts.get(b"rev", [])) revs = scmutil.revrange(repo, revs) if not revs: - raise error.Abort(_("no revisions specified")) + raise error.Abort(_(b"no revisions specified")) heads = [] for branch in repo.branchmap(): @@ -79,17 +79,17 @@ heads = set(repo[h].rev() for h in heads) for rev in revs: if rev not in heads: - raise error.Abort(_("revision is not an open head: %d") % rev) + raise error.Abort(_(b"revision is not an open head: %d") % rev) message = cmdutil.logmessage(ui, opts) if not message: - raise error.Abort(_("no commit message specified with -l or -m")) - extra = {"close": "1"} + raise error.Abort(_(b"no commit message specified with -l or -m")) + extra = {b"close": b"1"} with repo.wlock(), repo.lock(): for rev in revs: r = repo[rev] branch = r.branch() - extra["branch"] = branch + extra[b"branch"] = branch docommit(r) return 0 diff --git a/hgext/commitextras.py b/hgext/commitextras.py --- a/hgext/commitextras.py +++ b/hgext/commitextras.py @@ -22,57 +22,64 @@ cmdtable = {} command = registrar.command(cmdtable) -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" usedinternally = { - "amend_source", - "branch", - "close", - "histedit_source", - "topic", - "rebase_source", - "intermediate-source", - "__touch-noise__", - "source", - "transplant_source", + b"amend_source", + b"branch", + b"close", + b"histedit_source", + b"topic", + b"rebase_source", + b"intermediate-source", + b"__touch-noise__", + b"source", + b"transplant_source", } def extsetup(ui): - entry = extensions.wrapcommand(commands.table, "commit", _commit) + entry = extensions.wrapcommand(commands.table, b"commit", _commit) options = entry[1] options.append( - ("", "extra", [], _("set a changeset's extra values"), _("KEY=VALUE")) + ( + b"", + b"extra", + [], + _(b"set a changeset's extra values"), + _(b"KEY=VALUE"), + ) ) def _commit(orig, ui, repo, *pats, **opts): - if util.safehasattr(repo, "unfiltered"): + if util.safehasattr(repo, b"unfiltered"): repo = repo.unfiltered() class repoextra(repo.__class__): def commit(self, *innerpats, **inneropts): extras = opts.get(r"extra") for raw in extras: - if "=" not in raw: + if b"=" not in raw: msg = _( - "unable to parse '%s', should follow " - "KEY=VALUE format" + b"unable to parse '%s', should follow " + b"KEY=VALUE format" ) raise error.Abort(msg % raw) - k, v = raw.split("=", 1) + k, v = raw.split(b"=", 1) if not k: - msg = _("unable to parse '%s', keys can't be empty") + msg = _(b"unable to parse '%s', keys can't be empty") raise error.Abort(msg % raw) if re.search(br"[^\w-]", k): msg = _( - "keys can only contain ascii letters, digits," - " '_' and '-'" + b"keys can only contain ascii letters, digits," + b" '_' and '-'" ) raise error.Abort(msg) if k in usedinternally: msg = _( - "key '%s' is used internally, can't be set " "manually" + b"key '%s' is used internally, can't be set " + b"manually" ) raise error.Abort(msg % k) inneropts[r"extra"][k] = v diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py --- a/hgext/convert/__init__.py +++ b/hgext/convert/__init__.py @@ -24,60 +24,72 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" # Commands definition was moved elsewhere to ease demandload job. @command( - "convert", + b"convert", [ ( - "", - "authors", - "", + b"", + b"authors", + b"", _( - "username mapping filename (DEPRECATED) (use --authormap instead)" + b"username mapping filename (DEPRECATED) (use --authormap instead)" ), - _("FILE"), + _(b"FILE"), ), - ("s", "source-type", "", _("source repository type"), _("TYPE")), - ("d", "dest-type", "", _("destination repository type"), _("TYPE")), - ("r", "rev", [], _("import up to source revision REV"), _("REV")), - ("A", "authormap", "", _("remap usernames using this file"), _("FILE")), + (b"s", b"source-type", b"", _(b"source repository type"), _(b"TYPE")), ( - "", - "filemap", - "", - _("remap file names using contents of file"), - _("FILE"), + b"d", + b"dest-type", + b"", + _(b"destination repository type"), + _(b"TYPE"), + ), + (b"r", b"rev", [], _(b"import up to source revision REV"), _(b"REV")), + ( + b"A", + b"authormap", + b"", + _(b"remap usernames using this file"), + _(b"FILE"), ), ( - "", - "full", - None, - _("apply filemap changes by converting all files again"), + b"", + b"filemap", + b"", + _(b"remap file names using contents of file"), + _(b"FILE"), ), ( - "", - "splicemap", - "", - _("splice synthesized history into place"), - _("FILE"), + b"", + b"full", + None, + _(b"apply filemap changes by converting all files again"), ), ( - "", - "branchmap", - "", - _("change branch names while converting"), - _("FILE"), + b"", + b"splicemap", + b"", + _(b"splice synthesized history into place"), + _(b"FILE"), ), - ("", "branchsort", None, _("try to sort changesets by branches")), - ("", "datesort", None, _("try to sort changesets by date")), - ("", "sourcesort", None, _("preserve source changesets order")), - ("", "closesort", None, _("try to reorder closed revisions")), + ( + b"", + b"branchmap", + b"", + _(b"change branch names while converting"), + _(b"FILE"), + ), + (b"", b"branchsort", None, _(b"try to sort changesets by branches")), + (b"", b"datesort", None, _(b"try to sort changesets by date")), + (b"", b"sourcesort", None, _(b"preserve source changesets order")), + (b"", b"closesort", None, _(b"try to reorder closed revisions")), ], - _("hg convert [OPTION]... SOURCE [DEST [REVMAP]]"), + _(b"hg convert [OPTION]... SOURCE [DEST [REVMAP]]"), norepo=True, ) def convert(ui, src, dest=None, revmapfile=None, **opts): @@ -483,34 +495,44 @@ return convcmd.convert(ui, src, dest, revmapfile, **opts) -@command("debugsvnlog", [], "hg debugsvnlog", norepo=True) +@command(b"debugsvnlog", [], b"hg debugsvnlog", norepo=True) def debugsvnlog(ui, **opts): return subversion.debugsvnlog(ui, **opts) @command( - "debugcvsps", + b"debugcvsps", [ # Main options shared with cvsps-2.1 - ("b", "branches", [], _("only return changes on specified branches")), - ("p", "prefix", "", _("prefix to remove from file names")), ( - "r", - "revisions", + b"b", + b"branches", [], - _("only return changes after or between specified tags"), + _(b"only return changes on specified branches"), + ), + (b"p", b"prefix", b"", _(b"prefix to remove from file names")), + ( + b"r", + b"revisions", + [], + _(b"only return changes after or between specified tags"), ), - ("u", "update-cache", None, _("update cvs log cache")), - ("x", "new-cache", None, _("create new cvs log cache")), - ("z", "fuzz", 60, _("set commit time fuzz in seconds")), - ("", "root", "", _("specify cvsroot")), + (b"u", b"update-cache", None, _(b"update cvs log cache")), + (b"x", b"new-cache", None, _(b"create new cvs log cache")), + (b"z", b"fuzz", 60, _(b"set commit time fuzz in seconds")), + (b"", b"root", b"", _(b"specify cvsroot")), # Options specific to builtin cvsps - ("", "parents", "", _("show parent changesets")), - ("", "ancestors", "", _("show current changeset in ancestor branches")), + (b"", b"parents", b"", _(b"show parent changesets")), + ( + b"", + b"ancestors", + b"", + _(b"show current changeset in ancestor branches"), + ), # Options that are ignored for compatibility with cvsps-2.1 - ("A", "cvs-direct", None, _("ignored for compatibility")), + (b"A", b"cvs-direct", None, _(b"ignored for compatibility")), ], - _("hg debugcvsps [OPTION]... [PATH]..."), + _(b"hg debugcvsps [OPTION]... [PATH]..."), norepo=True, ) def debugcvsps(ui, *args, **opts): @@ -528,14 +550,14 @@ def kwconverted(context, mapping, name): - ctx = context.resource(mapping, "ctx") - rev = ctx.extra().get("convert_revision", "") - if rev.startswith("svn:"): - if name == "svnrev": + ctx = context.resource(mapping, b"ctx") + rev = ctx.extra().get(b"convert_revision", b"") + if rev.startswith(b"svn:"): + if name == b"svnrev": return b"%d" % subversion.revsplit(rev)[2] - elif name == "svnpath": + elif name == b"svnpath": return subversion.revsplit(rev)[1] - elif name == "svnuuid": + elif name == b"svnuuid": return subversion.revsplit(rev)[0] return rev @@ -543,22 +565,22 @@ templatekeyword = registrar.templatekeyword() -@templatekeyword("svnrev", requires={"ctx"}) +@templatekeyword(b"svnrev", requires={b"ctx"}) def kwsvnrev(context, mapping): """String. Converted subversion revision number.""" - return kwconverted(context, mapping, "svnrev") + return kwconverted(context, mapping, b"svnrev") -@templatekeyword("svnpath", requires={"ctx"}) +@templatekeyword(b"svnpath", requires={b"ctx"}) def kwsvnpath(context, mapping): """String. Converted subversion revision project path.""" - return kwconverted(context, mapping, "svnpath") + return kwconverted(context, mapping, b"svnpath") -@templatekeyword("svnuuid", requires={"ctx"}) +@templatekeyword(b"svnuuid", requires={b"ctx"}) def kwsvnuuid(context, mapping): """String. Converted subversion revision repository identifier.""" - return kwconverted(context, mapping, "svnuuid") + return kwconverted(context, mapping, b"svnuuid") # tell hggettext to extract docstrings from these functions: diff --git a/hgext/convert/bzr.py b/hgext/convert/bzr.py --- a/hgext/convert/bzr.py +++ b/hgext/convert/bzr.py @@ -17,7 +17,7 @@ # these do not work with demandimport, blacklist demandimport.IGNORES.update( - ["bzrlib.transactions", "bzrlib.urlutils", "ElementPath",] + [b"bzrlib.transactions", b"bzrlib.urlutils", b"ElementPath",] ) try: @@ -35,7 +35,7 @@ except ImportError: pass -supportedkinds = ("file", "symlink") +supportedkinds = (b"file", b"symlink") class bzr_source(common.converter_source): @@ -44,16 +44,16 @@ def __init__(self, ui, repotype, path, revs=None): super(bzr_source, self).__init__(ui, repotype, path, revs=revs) - if not os.path.exists(os.path.join(path, ".bzr")): + if not os.path.exists(os.path.join(path, b".bzr")): raise common.NoRepo( - _("%s does not look like a Bazaar repository") % path + _(b"%s does not look like a Bazaar repository") % path ) try: # access bzrlib stuff bzrdir except NameError: - raise common.NoRepo(_("Bazaar modules could not be loaded")) + raise common.NoRepo(_(b"Bazaar modules could not be loaded")) path = os.path.abspath(path) self._checkrepotype(path) @@ -61,10 +61,10 @@ self.sourcerepo = bzrdir.BzrDir.open(path).open_repository() except errors.NoRepositoryPresent: raise common.NoRepo( - _("%s does not look like a Bazaar repository") % path + _(b"%s does not look like a Bazaar repository") % path ) self._parentids = {} - self._saverev = ui.configbool("convert", "bzr.saverev") + self._saverev = ui.configbool(b"convert", b"bzr.saverev") def _checkrepotype(self, path): # Lightweight checkouts detection is informational but probably @@ -84,13 +84,13 @@ ): self.ui.warn( _( - "warning: lightweight checkouts may cause " - "conversion failures, try with a regular " - "branch instead.\n" + b"warning: lightweight checkouts may cause " + b"conversion failures, try with a regular " + b"branch instead.\n" ) ) except Exception: - self.ui.note(_("bzr source type could not be determined\n")) + self.ui.note(_(b"bzr source type could not be determined\n")) def before(self): """Before the conversion begins, acquire a read lock @@ -126,16 +126,16 @@ revid = info.rev_id if revid is None: raise error.Abort( - _("%s is not a valid revision") % self.revs[0] + _(b"%s is not a valid revision") % self.revs[0] ) heads = [revid] # Empty repositories return 'null:', which cannot be retrieved - heads = [h for h in heads if h != "null:"] + heads = [h for h in heads if h != b"null:"] return heads def getfile(self, name, rev): revtree = self.sourcerepo.revision_tree(rev) - fileid = revtree.path2id(name.decode(self.encoding or "utf-8")) + fileid = revtree.path2id(name.decode(self.encoding or b"utf-8")) kind = None if fileid is not None: kind = revtree.kind(fileid) @@ -143,11 +143,11 @@ # the file is not available anymore - was deleted return None, None mode = self._modecache[(name, rev)] - if kind == "symlink": + if kind == b"symlink": target = revtree.get_symlink_target(fileid) if target is None: raise error.Abort( - _("%s.%s symlink has no target") % (name, rev) + _(b"%s.%s symlink has no target") % (name, rev) ) return target, mode else: @@ -156,7 +156,7 @@ def getchanges(self, version, full): if full: - raise error.Abort(_("convert from cvs does not support --full")) + raise error.Abort(_(b"convert from cvs does not support --full")) self._modecache = {} self._revtree = self.sourcerepo.revision_tree(version) # get the parentids from the cache @@ -176,12 +176,12 @@ parents = self._filterghosts(rev.parent_ids) self._parentids[version] = parents - branch = self.recode(rev.properties.get("branch-nick", u"default")) - if branch == "trunk": - branch = "default" + branch = self.recode(rev.properties.get(b"branch-nick", u"default")) + if branch == b"trunk": + branch = b"default" return common.commit( parents=parents, - date="%d %d" % (rev.timestamp, -rev.timezone), + date=b"%d %d" % (rev.timestamp, -rev.timezone), author=self.recode(rev.committer), desc=self.recode(rev.message), branch=branch, @@ -248,13 +248,13 @@ # bazaar tracks directories, mercurial does not, so # we have to rename the directory contents - if kind[1] == "directory": - if kind[0] not in (None, "directory"): + if kind[1] == b"directory": + if kind[0] not in (None, b"directory"): # Replacing 'something' with a directory, record it # so it can be removed. changes.append((self.recode(paths[0]), revid)) - if kind[0] == "directory" and None not in paths: + if kind[0] == b"directory" and None not in paths: renaming = paths[0] != paths[1] # neither an add nor an delete - a move # rename all directory contents manually @@ -262,9 +262,9 @@ # get all child-entries of the directory for name, entry in inventory.iter_entries(subdir): # hg does not track directory renames - if entry.kind == "directory": + if entry.kind == b"directory": continue - frompath = self.recode(paths[0] + "/" + name) + frompath = self.recode(paths[0] + b"/" + name) if frompath in seen: # Already handled by a more specific change entry # This is important when you have: @@ -275,15 +275,15 @@ seen.add(frompath) if not renaming: continue - topath = self.recode(paths[1] + "/" + name) + topath = self.recode(paths[1] + b"/" + name) # register the files as changed changes.append((frompath, revid)) changes.append((topath, revid)) # add to mode cache mode = ( - (entry.executable and "x") - or (entry.kind == "symlink" and "s") - or "" + (entry.executable and b"x") + or (entry.kind == b"symlink" and b"s") + or b"" ) self._modecache[(topath, revid)] = mode # register the change as move @@ -312,7 +312,7 @@ # populate the mode cache kind, executable = [e[1] for e in (kind, executable)] - mode = (executable and "x") or (kind == "symlink" and "l") or "" + mode = (executable and b"x") or (kind == b"symlink" and b"l") or b"" self._modecache[(topath, revid)] = mode changes.append((topath, revid)) diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -46,7 +46,7 @@ @property def infile(self): - return self._l.infile or "" + return self._l.infile or b"" @property def lineno(self): @@ -56,13 +56,13 @@ def shlexer(data=None, filepath=None, wordchars=None, whitespace=None): if data is None: if pycompat.ispy3: - data = open(filepath, "r", encoding=r"latin1") + data = open(filepath, b"r", encoding=r"latin1") else: - data = open(filepath, "r") + data = open(filepath, b"r") else: if filepath is not None: raise error.ProgrammingError( - "shlexer only accepts data or filepath, not both" + b"shlexer only accepts data or filepath, not both" ) if pycompat.ispy3: data = data.decode("latin1") @@ -87,7 +87,7 @@ def encodearg(s): lines = base64.encodestring(s) lines = [l.splitlines()[0] for l in lines] - return "".join(lines) + return b"".join(lines) s = pickle.dumps(args) return encodearg(s) @@ -109,14 +109,14 @@ exc = error.Abort else: exc = MissingTool - raise exc(_('cannot find required "%s" tool') % name) + raise exc(_(b'cannot find required "%s" tool') % name) class NoRepo(Exception): pass -SKIPREV = "SKIP" +SKIPREV = b"SKIP" class commit(object): @@ -135,8 +135,8 @@ optparents=None, ctx=None, ): - self.author = author or "unknown" - self.date = date or "0 0" + self.author = author or b"unknown" + self.date = date or b"0 0" self.desc = desc self.parents = parents # will be converted and used as parents self.optparents = optparents or [] # will be used if already converted @@ -160,15 +160,15 @@ self.revs = revs self.repotype = repotype - self.encoding = "utf-8" + self.encoding = b"utf-8" - def checkhexformat(self, revstr, mapname="splicemap"): + def checkhexformat(self, revstr, mapname=b"splicemap"): """ fails if revstr is not a 40 byte hex. mercurial and git both uses such format for their revision numbering """ if not re.match(br"[0-9a-fA-F]{40,40}$", revstr): raise error.Abort( - _("%s entry %s is not a valid revision" " identifier") + _(b"%s entry %s is not a valid revision" b" identifier") % (mapname, revstr) ) @@ -236,7 +236,7 @@ def recode(self, s, encoding=None): if not encoding: - encoding = self.encoding or "utf-8" + encoding = self.encoding or b"utf-8" if isinstance(s, pycompat.unicode): return s.encode("utf-8") @@ -292,7 +292,7 @@ """ return {} - def checkrevformat(self, revstr, mapname="splicemap"): + def checkrevformat(self, revstr, mapname=b"splicemap"): """revstr is a string that describes a revision in the given source control system. Return true if revstr has correct format. @@ -412,20 +412,20 @@ cmdline = [self.command, cmd] + list(args) for k, v in kwargs.iteritems(): if len(k) == 1: - cmdline.append("-" + k) + cmdline.append(b"-" + k) else: - cmdline.append("--" + k.replace("_", "-")) + cmdline.append(b"--" + k.replace(b"_", b"-")) try: if len(k) == 1: - cmdline.append("" + v) + cmdline.append(b"" + v) else: - cmdline[-1] += "=" + v + cmdline[-1] += b"=" + v except TypeError: pass cmdline = [procutil.shellquote(arg) for arg in cmdline] if not self.ui.debugflag: - cmdline += ["2>", pycompat.bytestr(os.devnull)] - cmdline = " ".join(cmdline) + cmdline += [b"2>", pycompat.bytestr(os.devnull)] + cmdline = b" ".join(cmdline) return cmdline def _run(self, cmd, *args, **kwargs): @@ -449,7 +449,7 @@ def _dorun(self, openfunc, cmd, *args, **kwargs): cmdline = self._cmdline(cmd, *args, **kwargs) - self.ui.debug("running: %s\n" % (cmdline,)) + self.ui.debug(b"running: %s\n" % (cmdline,)) self.prerun() try: return openfunc(cmdline) @@ -466,16 +466,16 @@ p = self._run(cmd, *args, **kwargs) output = p.stdout.readlines() p.wait() - self.ui.debug("".join(output)) + self.ui.debug(b"".join(output)) return output, p.returncode - def checkexit(self, status, output=""): + def checkexit(self, status, output=b""): if status: if output: - self.ui.warn(_("%s error:\n") % self.command) + self.ui.warn(_(b"%s error:\n") % self.command) self.ui.warn(output) msg = procutil.explainexit(status) - raise error.Abort("%s %s" % (self.command, msg)) + raise error.Abort(b"%s %s" % (self.command, msg)) def run0(self, cmd, *args, **kwargs): output, status = self.run(cmd, *args, **kwargs) @@ -484,7 +484,7 @@ def runlines0(self, cmd, *args, **kwargs): output, status = self.runlines(cmd, *args, **kwargs) - self.checkexit(status, "".join(output)) + self.checkexit(status, b"".join(output)) return output @propertycache @@ -540,7 +540,7 @@ if not self.path: return try: - fp = open(self.path, "rb") + fp = open(self.path, b"rb") except IOError as err: if err.errno != errno.ENOENT: raise @@ -551,10 +551,10 @@ # Ignore blank lines continue try: - key, value = line.rsplit(" ", 1) + key, value = line.rsplit(b" ", 1) except ValueError: raise error.Abort( - _("syntax error in %s(%d): key/value pair expected") + _(b"syntax error in %s(%d): key/value pair expected") % (self.path, i + 1) ) if key not in self: @@ -565,13 +565,13 @@ def __setitem__(self, key, value): if self.fp is None: try: - self.fp = open(self.path, "ab") + self.fp = open(self.path, b"ab") except IOError as err: raise error.Abort( - _("could not open map file %r: %s") + _(b"could not open map file %r: %s") % (self.path, encoding.strtolocal(err.strerror)) ) - self.fp.write(util.tonativeeol("%s %s\n" % (key, value))) + self.fp.write(util.tonativeeol(b"%s %s\n" % (key, value))) self.fp.flush() super(mapfile, self).__setitem__(key, value) diff --git a/hgext/convert/convcmd.py b/hgext/convert/convcmd.py --- a/hgext/convert/convcmd.py +++ b/hgext/convert/convcmd.py @@ -52,7 +52,7 @@ svn_sink = subversion.svn_sink svn_source = subversion.svn_source -orig_encoding = "ascii" +orig_encoding = b"ascii" def recode(s): @@ -90,36 +90,36 @@ # destination repository. For such commits, using a literal "default" # in branchmap below allows the user to map "default" to an alternate # default branch in the destination repository. - branch = branchmap.get(branch or "default", branch) + branch = branchmap.get(branch or b"default", branch) # At some point we used "None" literal to denote the default branch, # attempt to use that for backward compatibility. if not branch: - branch = branchmap.get("None", branch) + branch = branchmap.get(b"None", branch) return branch source_converters = [ - ("cvs", convert_cvs, "branchsort"), - ("git", convert_git, "branchsort"), - ("svn", svn_source, "branchsort"), - ("hg", mercurial_source, "sourcesort"), - ("darcs", darcs_source, "branchsort"), - ("mtn", monotone_source, "branchsort"), - ("gnuarch", gnuarch_source, "branchsort"), - ("bzr", bzr_source, "branchsort"), - ("p4", p4_source, "branchsort"), + (b"cvs", convert_cvs, b"branchsort"), + (b"git", convert_git, b"branchsort"), + (b"svn", svn_source, b"branchsort"), + (b"hg", mercurial_source, b"sourcesort"), + (b"darcs", darcs_source, b"branchsort"), + (b"mtn", monotone_source, b"branchsort"), + (b"gnuarch", gnuarch_source, b"branchsort"), + (b"bzr", bzr_source, b"branchsort"), + (b"p4", p4_source, b"branchsort"), ] sink_converters = [ - ("hg", mercurial_sink), - ("svn", svn_sink), + (b"hg", mercurial_sink), + (b"svn", svn_sink), ] def convertsource(ui, path, type, revs): exceptions = [] if type and type not in [s[0] for s in source_converters]: - raise error.Abort(_("%s: invalid source repository type") % type) + raise error.Abort(_(b"%s: invalid source repository type") % type) for name, source, sortmode in source_converters: try: if not type or name == type: @@ -128,22 +128,22 @@ exceptions.append(inst) if not ui.quiet: for inst in exceptions: - ui.write("%s\n" % pycompat.bytestr(inst.args[0])) - raise error.Abort(_("%s: missing or unsupported repository") % path) + ui.write(b"%s\n" % pycompat.bytestr(inst.args[0])) + raise error.Abort(_(b"%s: missing or unsupported repository") % path) def convertsink(ui, path, type): if type and type not in [s[0] for s in sink_converters]: - raise error.Abort(_("%s: invalid destination repository type") % type) + raise error.Abort(_(b"%s: invalid destination repository type") % type) for name, sink in sink_converters: try: if not type or name == type: return sink(ui, name, path) except NoRepo as inst: - ui.note(_("convert: %s\n") % inst) + ui.note(_(b"convert: %s\n") % inst) except MissingTool as inst: - raise error.Abort("%s\n" % inst) - raise error.Abort(_("%s: unknown repository type") % path) + raise error.Abort(b"%s\n" % inst) + raise error.Abort(_(b"%s: unknown repository type") % path) class progresssource(object): @@ -151,7 +151,7 @@ self.ui = ui self.source = source self.progress = ui.makeprogress( - _("getting files"), unit=_("files"), total=filecount + _(b"getting files"), unit=_(b"files"), total=filecount ) def getfile(self, file, rev): @@ -189,12 +189,12 @@ if authorfile and os.path.exists(authorfile): self.readauthormap(authorfile) # Extend/Override with new author map if necessary - if opts.get("authormap"): - self.readauthormap(opts.get("authormap")) + if opts.get(b"authormap"): + self.readauthormap(opts.get(b"authormap")) self.authorfile = self.dest.authorfile() - self.splicemap = self.parsesplicemap(opts.get("splicemap")) - self.branchmap = mapfile(ui, opts.get("branchmap")) + self.splicemap = self.parsesplicemap(opts.get(b"splicemap")) + self.branchmap = mapfile(ui, opts.get(b"branchmap")) def parsesplicemap(self, path): """ check and validate the splicemap format and @@ -211,21 +211,21 @@ return {} m = {} try: - fp = open(path, "rb") + fp = open(path, b"rb") for i, line in enumerate(util.iterfile(fp)): line = line.splitlines()[0].rstrip() if not line: # Ignore blank lines continue # split line - lex = common.shlexer(data=line, whitespace=",") + lex = common.shlexer(data=line, whitespace=b",") line = list(lex) # check number of parents if not (2 <= len(line) <= 3): raise error.Abort( _( - "syntax error in %s(%d): child parent1" - "[,parent2] expected" + b"syntax error in %s(%d): child parent1" + b"[,parent2] expected" ) % (path, i + 1) ) @@ -239,7 +239,7 @@ # if file does not exist or error reading, exit except IOError: raise error.Abort( - _("splicemap file not found or error reading %s:") % path + _(b"splicemap file not found or error reading %s:") % path ) return m @@ -251,7 +251,7 @@ parents = {} numcommits = self.source.numcommits() progress = self.ui.makeprogress( - _("scanning"), unit=_("revisions"), total=numcommits + _(b"scanning"), unit=_(b"revisions"), total=numcommits ) while visit: n = visit.pop(0) @@ -283,8 +283,8 @@ # Could be in source but not converted during this run self.ui.warn( _( - "splice map revision %s is not being " - "converted, ignoring\n" + b"splice map revision %s is not being " + b"converted, ignoring\n" ) % c ) @@ -296,7 +296,7 @@ continue # Parent is not in dest and not being converted, not good if p not in parents: - raise error.Abort(_("unknown splice map parent: %s") % p) + raise error.Abort(_(b"unknown splice map parent: %s") % p) pc.append(p) parents[c] = pc @@ -369,7 +369,7 @@ def makeclosesorter(): """Close order sort.""" keyfn = lambda n: ( - "close" not in self.commitcache[n].extra, + b"close" not in self.commitcache[n].extra, self.commitcache[n].sortkey, ) @@ -392,16 +392,16 @@ return picknext - if sortmode == "branchsort": + if sortmode == b"branchsort": picknext = makebranchsorter() - elif sortmode == "datesort": + elif sortmode == b"datesort": picknext = makedatesorter() - elif sortmode == "sourcesort": + elif sortmode == b"sourcesort": picknext = makesourcesorter() - elif sortmode == "closesort": + elif sortmode == b"closesort": picknext = makeclosesorter() else: - raise error.Abort(_("unknown sort mode: %s") % sortmode) + raise error.Abort(_(b"unknown sort mode: %s") % sortmode) children, actives = mapchildren(parents) @@ -420,7 +420,7 @@ pendings[c].remove(n) except ValueError: raise error.Abort( - _("cycle detected between %s and %s") + _(b"cycle detected between %s and %s") % (recode(c), recode(n)) ) if not pendings[c]: @@ -429,45 +429,47 @@ pendings[c] = None if len(s) != len(parents): - raise error.Abort(_("not all revisions were sorted")) + raise error.Abort(_(b"not all revisions were sorted")) return s def writeauthormap(self): authorfile = self.authorfile if authorfile: - self.ui.status(_("writing author map file %s\n") % authorfile) - ofile = open(authorfile, "wb+") + self.ui.status(_(b"writing author map file %s\n") % authorfile) + ofile = open(authorfile, b"wb+") for author in self.authors: ofile.write( - util.tonativeeol("%s=%s\n" % (author, self.authors[author])) + util.tonativeeol( + b"%s=%s\n" % (author, self.authors[author]) + ) ) ofile.close() def readauthormap(self, authorfile): - afile = open(authorfile, "rb") + afile = open(authorfile, b"rb") for line in afile: line = line.strip() - if not line or line.startswith("#"): + if not line or line.startswith(b"#"): continue try: - srcauthor, dstauthor = line.split("=", 1) + srcauthor, dstauthor = line.split(b"=", 1) except ValueError: - msg = _("ignoring bad line in author map file %s: %s\n") + msg = _(b"ignoring bad line in author map file %s: %s\n") self.ui.warn(msg % (authorfile, line.rstrip())) continue srcauthor = srcauthor.strip() dstauthor = dstauthor.strip() if self.authors.get(srcauthor) in (None, dstauthor): - msg = _("mapping author %s to %s\n") + msg = _(b"mapping author %s to %s\n") self.ui.debug(msg % (srcauthor, dstauthor)) self.authors[srcauthor] = dstauthor continue - m = _("overriding mapping for author %s, was %s, will be %s\n") + m = _(b"overriding mapping for author %s, was %s, will be %s\n") self.ui.status(m % (srcauthor, self.authors[srcauthor], dstauthor)) afile.close() @@ -481,7 +483,7 @@ def copy(self, rev): commit = self.commitcache[rev] - full = self.opts.get("full") + full = self.opts.get(b"full") changes = self.source.getchanges(rev, full) if isinstance(changes, bytes): if changes == SKIPREV: @@ -503,8 +505,8 @@ try: parents = self.splicemap[rev] self.ui.status( - _("spliced in %s as parents of %s\n") - % (_(" and ").join(parents), rev) + _(b"spliced in %s as parents of %s\n") + % (_(b" and ").join(parents), rev) ) parents = [self.map.get(p, p) for p in parents] except KeyError: @@ -536,34 +538,34 @@ self.source.before() self.dest.before() self.source.setrevmap(self.map) - self.ui.status(_("scanning source...\n")) + self.ui.status(_(b"scanning source...\n")) heads = self.source.getheads() parents = self.walktree(heads) self.mergesplicemap(parents, self.splicemap) - self.ui.status(_("sorting...\n")) + self.ui.status(_(b"sorting...\n")) t = self.toposort(parents, sortmode) num = len(t) c = None - self.ui.status(_("converting...\n")) + self.ui.status(_(b"converting...\n")) progress = self.ui.makeprogress( - _("converting"), unit=_("revisions"), total=len(t) + _(b"converting"), unit=_(b"revisions"), total=len(t) ) for i, c in enumerate(t): num -= 1 desc = self.commitcache[c].desc - if "\n" in desc: + if b"\n" in desc: desc = desc.splitlines()[0] # convert log message to local encoding without using # tolocal() because the encoding.encoding convert() # uses is 'utf-8' - self.ui.status("%d %s\n" % (num, recode(desc))) - self.ui.note(_("source: %s\n") % recode(c)) + self.ui.status(b"%d %s\n" % (num, recode(desc))) + self.ui.note(_(b"source: %s\n") % recode(c)) progress.update(i) self.copy(c) progress.complete() - if not self.ui.configbool("convert", "skiptags"): + if not self.ui.configbool(b"convert", b"skiptags"): tags = self.source.gettags() ctags = {} for k in tags: @@ -610,45 +612,47 @@ opts = pycompat.byteskwargs(opts) global orig_encoding orig_encoding = encoding.encoding - encoding.encoding = "UTF-8" + encoding.encoding = b"UTF-8" # support --authors as an alias for --authormap - if not opts.get("authormap"): - opts["authormap"] = opts.get("authors") + if not opts.get(b"authormap"): + opts[b"authormap"] = opts.get(b"authors") if not dest: - dest = hg.defaultdest(src) + "-hg" - ui.status(_("assuming destination %s\n") % dest) + dest = hg.defaultdest(src) + b"-hg" + ui.status(_(b"assuming destination %s\n") % dest) - destc = convertsink(ui, dest, opts.get("dest_type")) + destc = convertsink(ui, dest, opts.get(b"dest_type")) destc = scmutil.wrapconvertsink(destc) try: srcc, defaultsort = convertsource( - ui, src, opts.get("source_type"), opts.get("rev") + ui, src, opts.get(b"source_type"), opts.get(b"rev") ) except Exception: for path in destc.created: shutil.rmtree(path, True) raise - sortmodes = ("branchsort", "datesort", "sourcesort", "closesort") + sortmodes = (b"branchsort", b"datesort", b"sourcesort", b"closesort") sortmode = [m for m in sortmodes if opts.get(m)] if len(sortmode) > 1: - raise error.Abort(_("more than one sort mode specified")) + raise error.Abort(_(b"more than one sort mode specified")) if sortmode: sortmode = sortmode[0] else: sortmode = defaultsort - if sortmode == "sourcesort" and not srcc.hasnativeorder(): + if sortmode == b"sourcesort" and not srcc.hasnativeorder(): raise error.Abort( - _("--sourcesort is not supported by this data source") + _(b"--sourcesort is not supported by this data source") ) - if sortmode == "closesort" and not srcc.hasnativeclose(): - raise error.Abort(_("--closesort is not supported by this data source")) + if sortmode == b"closesort" and not srcc.hasnativeclose(): + raise error.Abort( + _(b"--closesort is not supported by this data source") + ) - fmap = opts.get("filemap") + fmap = opts.get(b"filemap") if fmap: srcc = filemap.filemap_source(ui, srcc, fmap) destc.setfilemapmode(True) diff --git a/hgext/convert/cvs.py b/hgext/convert/cvs.py --- a/hgext/convert/cvs.py +++ b/hgext/convert/cvs.py @@ -39,19 +39,19 @@ def __init__(self, ui, repotype, path, revs=None): super(convert_cvs, self).__init__(ui, repotype, path, revs=revs) - cvs = os.path.join(path, "CVS") + cvs = os.path.join(path, b"CVS") if not os.path.exists(cvs): - raise NoRepo(_("%s does not look like a CVS checkout") % path) + raise NoRepo(_(b"%s does not look like a CVS checkout") % path) - checktool("cvs") + checktool(b"cvs") self.changeset = None self.files = {} self.tags = {} self.lastbranch = {} self.socket = None - self.cvsroot = open(os.path.join(cvs, "Root"), "rb").read()[:-1] - self.cvsrepo = open(os.path.join(cvs, "Repository"), "rb").read()[:-1] + self.cvsroot = open(os.path.join(cvs, b"Root"), b"rb").read()[:-1] + self.cvsrepo = open(os.path.join(cvs, b"Repository"), b"rb").read()[:-1] self.encoding = encoding.encoding self._connect() @@ -65,7 +65,10 @@ if self.revs: if len(self.revs) > 1: raise error.Abort( - _("cvs source does not support specifying " "multiple revs") + _( + b"cvs source does not support specifying " + b"multiple revs" + ) ) # TODO: handle tags try: @@ -73,23 +76,23 @@ maxrev = int(self.revs[0]) except ValueError: raise error.Abort( - _("revision %s is not a patchset number") % self.revs[0] + _(b"revision %s is not a patchset number") % self.revs[0] ) d = encoding.getcwd() try: os.chdir(self.path) - cache = "update" - if not self.ui.configbool("convert", "cvsps.cache"): + cache = b"update" + if not self.ui.configbool(b"convert", b"cvsps.cache"): cache = None db = cvsps.createlog(self.ui, cache=cache) db = cvsps.createchangeset( self.ui, db, - fuzz=int(self.ui.config("convert", "cvsps.fuzz")), - mergeto=self.ui.config("convert", "cvsps.mergeto"), - mergefrom=self.ui.config("convert", "cvsps.mergefrom"), + fuzz=int(self.ui.config(b"convert", b"cvsps.fuzz")), + mergeto=self.ui.config(b"convert", b"cvsps.mergeto"), + mergefrom=self.ui.config(b"convert", b"cvsps.mergefrom"), ) for cs in db: @@ -99,16 +102,16 @@ cs.author = self.recode(cs.author) self.lastbranch[cs.branch] = id cs.comment = self.recode(cs.comment) - if self.ui.configbool("convert", "localtimezone"): + if self.ui.configbool(b"convert", b"localtimezone"): cs.date = makedatetimestamp(cs.date[0]) - date = dateutil.datestr(cs.date, "%Y-%m-%d %H:%M:%S %1%2") + date = dateutil.datestr(cs.date, b"%Y-%m-%d %H:%M:%S %1%2") self.tags.update(dict.fromkeys(cs.tags, id)) files = {} for f in cs.entries: - files[f.file] = "%s%s" % ( - ".".join([(b"%d" % x) for x in f.revision]), - ["", "(DEAD)"][f.dead], + files[f.file] = b"%s%s" % ( + b".".join([(b"%d" % x) for x in f.revision]), + [b"", b"(DEAD)"][f.dead], ) # add current commit to set @@ -117,7 +120,7 @@ date=date, parents=[(b"%d" % p.id) for p in cs.parents], desc=cs.comment, - branch=cs.branch or "", + branch=cs.branch or b"", ) self.changeset[id] = c self.files[id] = files @@ -130,38 +133,38 @@ root = self.cvsroot conntype = None user, host = None, None - cmd = ["cvs", "server"] + cmd = [b"cvs", b"server"] - self.ui.status(_("connecting to %s\n") % root) + self.ui.status(_(b"connecting to %s\n") % root) - if root.startswith(":pserver:"): + if root.startswith(b":pserver:"): root = root[9:] m = re.match( r"(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)", root ) if m: - conntype = "pserver" + conntype = b"pserver" user, passw, serv, port, root = m.groups() if not user: - user = "anonymous" + user = b"anonymous" if not port: port = 2401 else: port = int(port) - format0 = ":pserver:%s@%s:%s" % (user, serv, root) - format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root) + format0 = b":pserver:%s@%s:%s" % (user, serv, root) + format1 = b":pserver:%s@%s:%d%s" % (user, serv, port, root) if not passw: - passw = "A" - cvspass = os.path.expanduser("~/.cvspass") + passw = b"A" + cvspass = os.path.expanduser(b"~/.cvspass") try: - pf = open(cvspass, "rb") + pf = open(cvspass, b"rb") for line in pf.read().splitlines(): - part1, part2 = line.split(" ", 1) + part1, part2 = line.split(b" ", 1) # /1 :pserver:user@example.com:2401/cvsroot/foo # Ah%s" % date) + cmd.append(b"-d>%s" % date) cmd.append(directory) # state machine begins here @@ -244,17 +244,17 @@ store = False # set when a new record can be appended cmd = [procutil.shellquote(arg) for arg in cmd] - ui.note(_("running %s\n") % (" ".join(cmd))) - ui.debug("prefix=%r directory=%r root=%r\n" % (prefix, directory, root)) + ui.note(_(b"running %s\n") % (b" ".join(cmd))) + ui.debug(b"prefix=%r directory=%r root=%r\n" % (prefix, directory, root)) - pfp = procutil.popen(" ".join(cmd), "rb") + pfp = procutil.popen(b" ".join(cmd), b"rb") peek = util.fromnativeeol(pfp.readline()) while True: line = peek - if line == "": + if line == b"": break peek = util.fromnativeeol(pfp.readline()) - if line.endswith("\n"): + if line.endswith(b"\n"): line = line[:-1] # ui.debug('state=%d line=%r\n' % (state, line)) @@ -268,12 +268,12 @@ filename = util.normpath(rcs[:-2]) if filename.startswith(prefix): filename = filename[len(prefix) :] - if filename.startswith("/"): + if filename.startswith(b"/"): filename = filename[1:] - if filename.startswith("Attic/"): + if filename.startswith(b"Attic/"): filename = filename[6:] else: - filename = filename.replace("/Attic/", "/") + filename = filename.replace(b"/Attic/", b"/") state = 2 continue state = 1 @@ -290,7 +290,7 @@ elif state == 1: # expect 'Working file' (only when using log instead of rlog) match = re_10.match(line) - assert match, _("RCS file must be followed by working file") + assert match, _(b"RCS file must be followed by working file") filename = util.normpath(match.group(1)) state = 2 @@ -304,7 +304,7 @@ # read the symbolic names and store as tags match = re_30.match(line) if match: - rev = [int(x) for x in match.group(2).split(".")] + rev = [int(x) for x in match.group(2).split(b".")] # Convert magic branch number to an odd-numbered one revn = len(rev) @@ -328,7 +328,7 @@ state = 5 else: assert not re_32.match(line), _( - "must have at least " "some revisions" + b"must have at least " b"some revisions" ) elif state == 5: @@ -336,11 +336,11 @@ # we create the logentry here from values stored in states 0 to 4, # as this state is re-entered for subsequent revisions of a file. match = re_50.match(line) - assert match, _("expected revision number") + assert match, _(b"expected revision number") e = logentry( rcs=scache(rcs), file=scache(filename), - revision=tuple([int(x) for x in match.group(1).split(".")]), + revision=tuple([int(x) for x in match.group(1).split(b".")]), branches=[], parent=None, commitid=None, @@ -353,21 +353,25 @@ elif state == 6: # expecting date, author, state, lines changed match = re_60.match(line) - assert match, _("revision must be followed by date line") + assert match, _(b"revision must be followed by date line") d = match.group(1) - if d[2] == "/": + if d[2] == b"/": # Y2K - d = "19" + d + d = b"19" + d if len(d.split()) != 3: # cvs log dates always in GMT - d = d + " UTC" + d = d + b" UTC" e.date = dateutil.parsedate( d, - ["%y/%m/%d %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%Y-%m-%d %H:%M:%S"], + [ + b"%y/%m/%d %H:%M:%S", + b"%Y/%m/%d %H:%M:%S", + b"%Y-%m-%d %H:%M:%S", + ], ) e.author = scache(match.group(2)) - e.dead = match.group(3).lower() == "dead" + e.dead = match.group(3).lower() == b"dead" if match.group(5): if match.group(6): @@ -383,14 +387,14 @@ e.commitid = match.group(8) if match.group(9): # cvsnt mergepoint - myrev = match.group(10).split(".") + myrev = match.group(10).split(b".") if len(myrev) == 2: # head - e.mergepoint = "HEAD" + e.mergepoint = b"HEAD" else: - myrev = ".".join(myrev[:-2] + ["0", myrev[-2]]) + myrev = b".".join(myrev[:-2] + [b"0", myrev[-2]]) branches = [b for b in branchmap if branchmap[b] == myrev] assert len(branches) == 1, ( - "unknown branch: %s" % e.mergepoint + b"unknown branch: %s" % e.mergepoint ) e.mergepoint = branches[0] @@ -403,8 +407,8 @@ m = re_70.match(line) if m: e.branches = [ - tuple([int(y) for y in x.strip().split(".")]) - for x in m.group(1).split(";") + tuple([int(y) for y in x.strip().split(b".")]) + for x in m.group(1).split(b";") ] state = 8 elif re_31.match(line) and re_50.match(peek): @@ -420,7 +424,7 @@ # store commit log message if re_31.match(line): cpeek = peek - if cpeek.endswith("\n"): + if cpeek.endswith(b"\n"): cpeek = cpeek[:-1] if re_50.match(cpeek): state = 5 @@ -448,7 +452,7 @@ and file_added_re.match(e.comment[0]) ): ui.debug( - "found synthetic revision in %s: %r\n" % (e.rcs, e.comment[0]) + b"found synthetic revision in %s: %r\n" % (e.rcs, e.comment[0]) ) e.synthetic = True @@ -456,7 +460,7 @@ # clean up the results and save in the log. store = False e.tags = sorted([scache(x) for x in tags.get(e.revision, [])]) - e.comment = scache("\n".join(e.comment)) + e.comment = scache(b"\n".join(e.comment)) revn = len(e.revision) if revn > 3 and (revn % 2) == 0: @@ -467,7 +471,7 @@ # find the branches starting from this revision branchpoints = set() for branch, revision in branchmap.iteritems(): - revparts = tuple([int(i) for i in revision.split(".")]) + revparts = tuple([int(i) for i in revision.split(b".")]) if len(revparts) < 2: # bad tags continue if revparts[-2] == 0 and revparts[-1] % 2 == 0: @@ -481,11 +485,12 @@ log.append(e) - rcsmap[e.rcs.replace("/Attic/", "/")] = e.rcs + rcsmap[e.rcs.replace(b"/Attic/", b"/")] = e.rcs if len(log) % 100 == 0: ui.status( - stringutil.ellipsis("%d %s" % (len(log), e.file), 80) + "\n" + stringutil.ellipsis(b"%d %s" % (len(log), e.file), 80) + + b"\n" ) log.sort(key=lambda x: (x.rcs, x.revision)) @@ -493,7 +498,7 @@ # find parent revisions of individual files versions = {} for e in sorted(oldlog, key=lambda x: (x.rcs, x.revision)): - rcs = e.rcs.replace("/Attic/", "/") + rcs = e.rcs.replace(b"/Attic/", b"/") if rcs in rcsmap: e.rcs = rcsmap[rcs] branch = e.revision[:-1] @@ -516,28 +521,28 @@ if oldlog and oldlog[-1].date >= log[0].date: raise logerror( _( - "log cache overlaps with new log entries," - " re-run without cache." + b"log cache overlaps with new log entries," + b" re-run without cache." ) ) log = oldlog + log # write the new cachefile - ui.note(_("writing cvs log cache %s\n") % cachefile) - pickle.dump(log, open(cachefile, "wb")) + ui.note(_(b"writing cvs log cache %s\n") % cachefile) + pickle.dump(log, open(cachefile, b"wb")) else: log = oldlog - ui.status(_("%d log entries\n") % len(log)) + ui.status(_(b"%d log entries\n") % len(log)) - encodings = ui.configlist("convert", "cvsps.logencoding") + encodings = ui.configlist(b"convert", b"cvsps.logencoding") if encodings: def revstr(r): # this is needed, because logentry.revision is a tuple of "int" # (e.g. (1, 2) for "1.2") - return ".".join(pycompat.maplist(pycompat.bytestr, r)) + return b".".join(pycompat.maplist(pycompat.bytestr, r)) for entry in log: comment = entry.comment @@ -548,7 +553,7 @@ ) if ui.debugflag: ui.debug( - "transcoding by %s: %s of %s\n" + b"transcoding by %s: %s of %s\n" % (e, revstr(entry.revision), entry.file) ) break @@ -558,20 +563,22 @@ raise error.Abort( inst, hint=_( - "check convert.cvsps.logencoding" " configuration" + b"check convert.cvsps.logencoding" b" configuration" ), ) else: raise error.Abort( _( - "no encoding can transcode" - " CVS log message for %s of %s" + b"no encoding can transcode" + b" CVS log message for %s of %s" ) % (revstr(entry.revision), entry.file), - hint=_("check convert.cvsps.logencoding" " configuration"), + hint=_( + b"check convert.cvsps.logencoding" b" configuration" + ), ) - hook.hook(ui, None, "cvslog", True, log=log) + hook.hook(ui, None, b"cvslog", True, log=log) return log @@ -598,14 +605,16 @@ self.__dict__.update(entries) def __repr__(self): - items = ("%s=%r" % (k, self.__dict__[k]) for k in sorted(self.__dict__)) - return "%s(%s)" % (type(self).__name__, ", ".join(items)) + items = ( + b"%s=%r" % (k, self.__dict__[k]) for k in sorted(self.__dict__) + ) + return b"%s(%s)" % (type(self).__name__, b", ".join(items)) def createchangeset(ui, log, fuzz=60, mergefrom=None, mergeto=None): """Convert log into changesets.""" - ui.status(_("creating changesets\n")) + ui.status(_(b"creating changesets\n")) # try to order commitids by date mindate = {} @@ -620,10 +629,10 @@ log.sort( key=lambda x: ( mindate.get(x.commitid, (-1, 0)), - x.commitid or "", + x.commitid or b"", x.comment, x.author, - x.branch or "", + x.branch or b"", x.date, x.branchpoints, ) @@ -683,8 +692,8 @@ files = set() if len(changesets) % 100 == 0: - t = "%d %s" % (len(changesets), repr(e.comment)[1:-1]) - ui.status(stringutil.ellipsis(t, 80) + "\n") + t = b"%d %s" % (len(changesets), repr(e.comment)[1:-1]) + ui.status(stringutil.ellipsis(t, 80) + b"\n") c.entries.append(e) files.add(e.file) @@ -706,9 +715,9 @@ # Sort files in each changeset def entitycompare(l, r): - "Mimic cvsps sorting order" - l = l.file.split("/") - r = r.file.split("/") + b"Mimic cvsps sorting order" + l = l.file.split(b"/") + r = r.file.split(b"/") nl = len(l) nr = len(r) n = min(nl, nr) @@ -843,7 +852,7 @@ # Ensure no changeset has a synthetic changeset as a parent. while p.synthetic: assert len(p.parents) <= 1, _( - "synthetic changeset cannot have multiple parents" + b"synthetic changeset cannot have multiple parents" ) if p.parents: p = p.parents[0] @@ -855,7 +864,7 @@ c.parents.append(p) if c.mergepoint: - if c.mergepoint == "HEAD": + if c.mergepoint == b"HEAD": c.mergepoint = None c.parents.append(changesets[branches[c.mergepoint]]) @@ -863,15 +872,15 @@ m = mergefrom.search(c.comment) if m: m = m.group(1) - if m == "HEAD": + if m == b"HEAD": m = None try: candidate = changesets[branches[m]] except KeyError: ui.warn( _( - "warning: CVS commit message references " - "non-existent branch %r:\n%s\n" + b"warning: CVS commit message references " + b"non-existent branch %r:\n%s\n" ) % (pycompat.bytestr(m), c.comment) ) @@ -883,7 +892,7 @@ if m: if m.groups(): m = m.group(1) - if m == "HEAD": + if m == b"HEAD": m = None else: m = None # if no group found then merge to HEAD @@ -893,7 +902,7 @@ author=c.author, branch=m, date=c.date, - comment="convert-repo: CVS merge from branch %s" + comment=b"convert-repo: CVS merge from branch %s" % c.branch, entries=[], tags=[], @@ -928,13 +937,13 @@ for l, r in odd: if l.id is not None and r.id is not None: ui.warn( - _("changeset %d is both before and after %d\n") + _(b"changeset %d is both before and after %d\n") % (l.id, r.id) ) - ui.status(_("%d changeset entries\n") % len(changesets)) + ui.status(_(b"%d changeset entries\n") % len(changesets)) - hook.hook(ui, None, "cvschangesets", True, changesets=changesets) + hook.hook(ui, None, b"cvschangesets", True, changesets=changesets) return changesets @@ -945,27 +954,27 @@ commit log entries and dates. """ opts = pycompat.byteskwargs(opts) - if opts["new_cache"]: - cache = "write" - elif opts["update_cache"]: - cache = "update" + if opts[b"new_cache"]: + cache = b"write" + elif opts[b"update_cache"]: + cache = b"update" else: cache = None - revisions = opts["revisions"] + revisions = opts[b"revisions"] try: if args: log = [] for d in args: - log += createlog(ui, d, root=opts["root"], cache=cache) + log += createlog(ui, d, root=opts[b"root"], cache=cache) else: - log = createlog(ui, root=opts["root"], cache=cache) + log = createlog(ui, root=opts[b"root"], cache=cache) except logerror as e: - ui.write("%r\n" % e) + ui.write(b"%r\n" % e) return - changesets = createchangeset(ui, log, opts["fuzz"]) + changesets = createchangeset(ui, log, opts[b"fuzz"]) del log # Print changesets (optionally filtered) @@ -975,7 +984,7 @@ ancestors = {} # parent branch for cs in changesets: - if opts["ancestors"]: + if opts[b"ancestors"]: if cs.branch not in branches and cs.parents and cs.parents[0].id: ancestors[cs.branch] = ( changesets[cs.parents[0].id - 1].branch, @@ -984,72 +993,75 @@ branches[cs.branch] = cs.id # limit by branches - if opts["branches"] and (cs.branch or "HEAD") not in opts["branches"]: + if ( + opts[b"branches"] + and (cs.branch or b"HEAD") not in opts[b"branches"] + ): continue if not off: # Note: trailing spaces on several lines here are needed to have # bug-for-bug compatibility with cvsps. - ui.write("---------------------\n") - ui.write(("PatchSet %d \n" % cs.id)) + ui.write(b"---------------------\n") + ui.write((b"PatchSet %d \n" % cs.id)) ui.write( ( - "Date: %s\n" - % dateutil.datestr(cs.date, "%Y/%m/%d %H:%M:%S %1%2") + b"Date: %s\n" + % dateutil.datestr(cs.date, b"%Y/%m/%d %H:%M:%S %1%2") ) ) - ui.write(("Author: %s\n" % cs.author)) - ui.write(("Branch: %s\n" % (cs.branch or "HEAD"))) + ui.write((b"Author: %s\n" % cs.author)) + ui.write((b"Branch: %s\n" % (cs.branch or b"HEAD"))) ui.write( ( - "Tag%s: %s \n" + b"Tag%s: %s \n" % ( - ["", "s"][len(cs.tags) > 1], - ",".join(cs.tags) or "(none)", + [b"", b"s"][len(cs.tags) > 1], + b",".join(cs.tags) or b"(none)", ) ) ) if cs.branchpoints: ui.write( - "Branchpoints: %s \n" % ", ".join(sorted(cs.branchpoints)) + b"Branchpoints: %s \n" % b", ".join(sorted(cs.branchpoints)) ) - if opts["parents"] and cs.parents: + if opts[b"parents"] and cs.parents: if len(cs.parents) > 1: ui.write( ( - "Parents: %s\n" - % (",".join([(b"%d" % p.id) for p in cs.parents])) + b"Parents: %s\n" + % (b",".join([(b"%d" % p.id) for p in cs.parents])) ) ) else: - ui.write(("Parent: %d\n" % cs.parents[0].id)) + ui.write((b"Parent: %d\n" % cs.parents[0].id)) - if opts["ancestors"]: + if opts[b"ancestors"]: b = cs.branch r = [] while b: b, c = ancestors[b] - r.append("%s:%d:%d" % (b or "HEAD", c, branches[b])) + r.append(b"%s:%d:%d" % (b or b"HEAD", c, branches[b])) if r: - ui.write(("Ancestors: %s\n" % (",".join(r)))) + ui.write((b"Ancestors: %s\n" % (b",".join(r)))) - ui.write("Log:\n") - ui.write("%s\n\n" % cs.comment) - ui.write("Members: \n") + ui.write(b"Log:\n") + ui.write(b"%s\n\n" % cs.comment) + ui.write(b"Members: \n") for f in cs.entries: fn = f.file - if fn.startswith(opts["prefix"]): - fn = fn[len(opts["prefix"]) :] + if fn.startswith(opts[b"prefix"]): + fn = fn[len(opts[b"prefix"]) :] ui.write( - "\t%s:%s->%s%s \n" + b"\t%s:%s->%s%s \n" % ( fn, - ".".join([b"%d" % x for x in f.parent]) or "INITIAL", - ".".join([(b"%d" % x) for x in f.revision]), - ["", "(DEAD)"][f.dead], + b".".join([b"%d" % x for x in f.parent]) or b"INITIAL", + b".".join([(b"%d" % x) for x in f.revision]), + [b"", b"(DEAD)"][f.dead], ) ) - ui.write("\n") + ui.write(b"\n") # have we seen the start tag? if revisions and off: diff --git a/hgext/convert/darcs.py b/hgext/convert/darcs.py --- a/hgext/convert/darcs.py +++ b/hgext/convert/darcs.py @@ -46,22 +46,22 @@ class darcs_source(common.converter_source, common.commandline): def __init__(self, ui, repotype, path, revs=None): common.converter_source.__init__(self, ui, repotype, path, revs=revs) - common.commandline.__init__(self, ui, "darcs") + common.commandline.__init__(self, ui, b"darcs") # check for _darcs, ElementTree so that we can easily skip # test-convert-darcs if ElementTree is not around - if not os.path.exists(os.path.join(path, "_darcs")): - raise NoRepo(_("%s does not look like a darcs repository") % path) + if not os.path.exists(os.path.join(path, b"_darcs")): + raise NoRepo(_(b"%s does not look like a darcs repository") % path) - common.checktool("darcs") - version = self.run0("--version").splitlines()[0].strip() - if version < "2.1": + common.checktool(b"darcs") + version = self.run0(b"--version").splitlines()[0].strip() + if version < b"2.1": raise error.Abort( - _("darcs version 2.1 or newer needed (found %r)") % version + _(b"darcs version 2.1 or newer needed (found %r)") % version ) - if "ElementTree" not in globals(): - raise error.Abort(_("Python ElementTree module is not available")) + if b"ElementTree" not in globals(): + raise error.Abort(_(b"Python ElementTree module is not available")) self.path = os.path.realpath(path) @@ -73,30 +73,33 @@ # Check darcs repository format format = self.format() if format: - if format in ("darcs-1.0", "hashed"): + if format in (b"darcs-1.0", b"hashed"): raise NoRepo( - _("%s repository format is unsupported, " "please upgrade") + _( + b"%s repository format is unsupported, " + b"please upgrade" + ) % format ) else: - self.ui.warn(_("failed to detect repository format!")) + self.ui.warn(_(b"failed to detect repository format!")) def before(self): self.tmppath = pycompat.mkdtemp( - prefix="convert-" + os.path.basename(self.path) + "-" + prefix=b"convert-" + os.path.basename(self.path) + b"-" ) - output, status = self.run("init", repodir=self.tmppath) + output, status = self.run(b"init", repodir=self.tmppath) self.checkexit(status) tree = self.xml( - "changes", xml_output=True, summary=True, repodir=self.path + b"changes", xml_output=True, summary=True, repodir=self.path ) tagname = None child = None - for elt in tree.findall("patch"): - node = elt.get("hash") - name = elt.findtext("name", "") - if name.startswith("TAG "): + for elt in tree.findall(b"patch"): + node = elt.get(b"hash") + name = elt.findtext(b"name", b"") + if name.startswith(b"TAG "): tagname = name[4:].strip() elif tagname is not None: self.tags[tagname] = node @@ -107,7 +110,7 @@ self.parents[child] = [] def after(self): - self.ui.debug("cleaning up %s\n" % self.tmppath) + self.ui.debug(b"cleaning up %s\n" % self.tmppath) shutil.rmtree(self.tmppath, ignore_errors=True) def recode(self, s, encoding=None): @@ -125,7 +128,7 @@ # While we are decoding the XML as latin-1 to be as liberal as # possible, etree will still raise an exception if any # non-printable characters are in the XML changelog. - parser = XMLParser(encoding="latin-1") + parser = XMLParser(encoding=b"latin-1") p = self._run(cmd, **kwargs) etree.parse(p.stdout, parser=parser) p.wait() @@ -133,20 +136,20 @@ return etree.getroot() def format(self): - output, status = self.run("show", "repo", repodir=self.path) + output, status = self.run(b"show", b"repo", repodir=self.path) self.checkexit(status) m = re.search(r"^\s*Format:\s*(.*)$", output, re.MULTILINE) if not m: return None - return ",".join(sorted(f.strip() for f in m.group(1).split(","))) + return b",".join(sorted(f.strip() for f in m.group(1).split(b","))) def manifest(self): man = [] output, status = self.run( - "show", "files", no_directories=True, repodir=self.tmppath + b"show", b"files", no_directories=True, repodir=self.tmppath ) self.checkexit(status) - for line in output.split("\n"): + for line in output.split(b"\n"): path = line[2:] if path: man.append(path) @@ -157,14 +160,14 @@ def getcommit(self, rev): elt = self.changes[rev] - dateformat = "%a %b %d %H:%M:%S %Z %Y" - date = dateutil.strdate(elt.get("local_date"), dateformat) - desc = elt.findtext("name") + "\n" + elt.findtext("comment", "") + dateformat = b"%a %b %d %H:%M:%S %Z %Y" + date = dateutil.strdate(elt.get(b"local_date"), dateformat) + desc = elt.findtext(b"name") + b"\n" + elt.findtext(b"comment", b"") # etree can return unicode objects for name, comment, and author, # so recode() is used to ensure str objects are emitted. - newdateformat = "%Y-%m-%d %H:%M:%S %1%2" + newdateformat = b"%Y-%m-%d %H:%M:%S %1%2" return common.commit( - author=self.recode(elt.get("author")), + author=self.recode(elt.get(b"author")), date=dateutil.datestr(date, newdateformat), desc=self.recode(desc).strip(), parents=self.parents[rev], @@ -172,34 +175,34 @@ def pull(self, rev): output, status = self.run( - "pull", + b"pull", self.path, all=True, - match="hash %s" % rev, + match=b"hash %s" % rev, no_test=True, no_posthook=True, - external_merge="/bin/false", + external_merge=b"/bin/false", repodir=self.tmppath, ) if status: - if output.find("We have conflicts in") == -1: + if output.find(b"We have conflicts in") == -1: self.checkexit(status, output) - output, status = self.run("revert", all=True, repodir=self.tmppath) + output, status = self.run(b"revert", all=True, repodir=self.tmppath) self.checkexit(status, output) def getchanges(self, rev, full): if full: - raise error.Abort(_("convert from darcs does not support --full")) + raise error.Abort(_(b"convert from darcs does not support --full")) copies = {} changes = [] man = None - for elt in self.changes[rev].find("summary").getchildren(): - if elt.tag in ("add_directory", "remove_directory"): + for elt in self.changes[rev].find(b"summary").getchildren(): + if elt.tag in (b"add_directory", b"remove_directory"): continue - if elt.tag == "move": + if elt.tag == b"move": if man is None: man = self.manifest() - source, dest = elt.get("from"), elt.get("to") + source, dest = elt.get(b"from"), elt.get(b"to") if source in man: # File move changes.append((source, rev)) @@ -207,11 +210,11 @@ copies[dest] = source else: # Directory move, deduce file moves from manifest - source = source + "/" + source = source + b"/" for f in man: if not f.startswith(source): continue - fdest = dest + "/" + f[len(source) :] + fdest = dest + b"/" + f[len(source) :] changes.append((f, rev)) changes.append((fdest, rev)) copies[fdest] = f @@ -223,7 +226,7 @@ def getfile(self, name, rev): if rev != self.lastrev: - raise error.Abort(_("internal calling inconsistency")) + raise error.Abort(_(b"internal calling inconsistency")) path = os.path.join(self.tmppath, name) try: data = util.readfile(path) @@ -232,7 +235,7 @@ if inst.errno == errno.ENOENT: return None, None raise - mode = (mode & 0o111) and "x" or "" + mode = (mode & 0o111) and b"x" or b"" return data, mode def gettags(self): diff --git a/hgext/convert/filemap.py b/hgext/convert/filemap.py --- a/hgext/convert/filemap.py +++ b/hgext/convert/filemap.py @@ -30,8 +30,8 @@ i = len(path) while i != -1: yield path[:i], path[i + 1 :] - i = path.rfind("/", 0, i) - yield ".", path + i = path.rfind(b"/", 0, i) + yield b".", path def normalize(path): @@ -55,7 +55,7 @@ self.targetprefixes = None if path: if self.parse(path): - raise error.Abort(_("errors in filemap")) + raise error.Abort(_(b"errors in filemap")) def parse(self, path): errs = 0 @@ -63,48 +63,48 @@ def check(name, mapping, listname): if not name: self.ui.warn( - _("%s:%d: path to %s is missing\n") + _(b"%s:%d: path to %s is missing\n") % (lex.infile, lex.lineno, listname) ) return 1 if name in mapping: self.ui.warn( - _("%s:%d: %r already in %s list\n") + _(b"%s:%d: %r already in %s list\n") % (lex.infile, lex.lineno, name, listname) ) return 1 - if name.startswith("/") or name.endswith("/") or "//" in name: + if name.startswith(b"/") or name.endswith(b"/") or b"//" in name: self.ui.warn( - _("%s:%d: superfluous / in %s %r\n") + _(b"%s:%d: superfluous / in %s %r\n") % (lex.infile, lex.lineno, listname, pycompat.bytestr(name)) ) return 1 return 0 lex = common.shlexer( - filepath=path, wordchars="!@#$%^&*()-=+[]{}|;:,./<>?" + filepath=path, wordchars=b"!@#$%^&*()-=+[]{}|;:,./<>?" ) cmd = lex.get_token() while cmd: - if cmd == "include": + if cmd == b"include": name = normalize(lex.get_token()) - errs += check(name, self.exclude, "exclude") + errs += check(name, self.exclude, b"exclude") self.include[name] = name - elif cmd == "exclude": + elif cmd == b"exclude": name = normalize(lex.get_token()) - errs += check(name, self.include, "include") - errs += check(name, self.rename, "rename") + errs += check(name, self.include, b"include") + errs += check(name, self.rename, b"rename") self.exclude[name] = name - elif cmd == "rename": + elif cmd == b"rename": src = normalize(lex.get_token()) dest = normalize(lex.get_token()) - errs += check(src, self.exclude, "exclude") + errs += check(src, self.exclude, b"exclude") self.rename[src] = dest - elif cmd == "source": + elif cmd == b"source": errs += self.parse(normalize(lex.get_token())) else: self.ui.warn( - _("%s:%d: unknown directive %r\n") + _(b"%s:%d: unknown directive %r\n") % (lex.infile, lex.lineno, pycompat.bytestr(cmd)) ) errs += 1 @@ -118,7 +118,7 @@ return mapping[pre], pre, suf except KeyError: pass - return "", name, "" + return b"", name, b"" def istargetfile(self, filename): """Return true if the given target filename is covered as a destination @@ -131,7 +131,7 @@ # If "." is a target, then all target files are considered from the # source. - if not self.targetprefixes or "." in self.targetprefixes: + if not self.targetprefixes or b"." in self.targetprefixes: return True filename = normalize(filename) @@ -152,17 +152,17 @@ if self.exclude: exc = self.lookup(name, self.exclude)[0] else: - exc = "" + exc = b"" if (not self.include and exc) or (len(inc) <= len(exc)): return None newpre, pre, suf = self.lookup(name, self.rename) if newpre: - if newpre == ".": + if newpre == b".": return suf if suf: - if newpre.endswith("/"): + if newpre.endswith(b"/"): return newpre + suf - return newpre + "/" + suf + return newpre + b"/" + suf return newpre return name @@ -204,7 +204,7 @@ self.seenchildren = {} # experimental config: convert.ignoreancestorcheck self.ignoreancestorcheck = self.ui.configbool( - "convert", "ignoreancestorcheck" + b"convert", b"ignoreancestorcheck" ) def before(self): @@ -256,7 +256,7 @@ try: self.origparents[rev] = self.getcommit(rev).parents except error.RepoLookupError: - self.ui.debug("unknown revmap source: %s\n" % rev) + self.ui.debug(b"unknown revmap source: %s\n" % rev) continue if arg is not None: self.children[arg] = self.children.get(arg, 0) + 1 @@ -316,7 +316,7 @@ try: files = self.base.getchangedfiles(rev, i) except NotImplementedError: - raise error.Abort(_("source repository doesn't support --filemap")) + raise error.Abort(_(b"source repository doesn't support --filemap")) for f in files: if self.filemapper(f): return True @@ -331,7 +331,7 @@ # close marker is significant (i.e. all of the branch ancestors weren't # eliminated). Therefore if there *is* a close marker, getchanges() # doesn't consider it significant, and this revision should be dropped. - return not files and "close" not in self.commits[rev].extra + return not files and b"close" not in self.commits[rev].extra def mark_not_wanted(self, rev, p): # Mark rev as not interesting and update data structures. @@ -363,7 +363,9 @@ if p in self.wantedancestors: wrev.update(self.wantedancestors[p]) else: - self.ui.warn(_("warning: %s parent %s is missing\n") % (rev, p)) + self.ui.warn( + _(b"warning: %s parent %s is missing\n") % (rev, p) + ) wrev.add(rev) self.wantedancestors[rev] = wrev @@ -423,7 +425,7 @@ self.origparents[rev] = parents closed = False - if "close" in self.commits[rev].extra: + if b"close" in self.commits[rev].extra: # A branch closing revision is only useful if one of its # parents belong to the branch being closed pbranches = [self._cachedcommit(p).branch for p in mparents] diff --git a/hgext/convert/git.py b/hgext/convert/git.py --- a/hgext/convert/git.py +++ b/hgext/convert/git.py @@ -26,22 +26,22 @@ self.url = url def hgsub(self): - return "%s = [git]%s" % (self.path, self.url) + return b"%s = [git]%s" % (self.path, self.url) def hgsubstate(self): - return "%s %s" % (self.node, self.path) + return b"%s %s" % (self.node, self.path) # Keys in extra fields that should not be copied if the user requests. bannedextrakeys = { # Git commit object built-ins. - "tree", - "parent", - "author", - "committer", + b"tree", + b"parent", + b"author", + b"committer", # Mercurial built-ins. - "branch", - "close", + b"branch", + b"close", } @@ -51,7 +51,7 @@ # both issues. def _gitcmd(self, cmd, *args, **kwargs): - return cmd("--git-dir=%s" % self.path, *args, **kwargs) + return cmd(b"--git-dir=%s" % self.path, *args, **kwargs) def gitrun0(self, *args, **kwargs): return self._gitcmd(self.run0, *args, **kwargs) @@ -70,100 +70,104 @@ def __init__(self, ui, repotype, path, revs=None): super(convert_git, self).__init__(ui, repotype, path, revs=revs) - common.commandline.__init__(self, ui, "git") + common.commandline.__init__(self, ui, b"git") # Pass an absolute path to git to prevent from ever being interpreted # as a URL path = os.path.abspath(path) - if os.path.isdir(path + "/.git"): - path += "/.git" - if not os.path.exists(path + "/objects"): + if os.path.isdir(path + b"/.git"): + path += b"/.git" + if not os.path.exists(path + b"/objects"): raise common.NoRepo( - _("%s does not look like a Git repository") % path + _(b"%s does not look like a Git repository") % path ) # The default value (50) is based on the default for 'git diff'. - similarity = ui.configint("convert", "git.similarity") + similarity = ui.configint(b"convert", b"git.similarity") if similarity < 0 or similarity > 100: - raise error.Abort(_("similarity must be between 0 and 100")) + raise error.Abort(_(b"similarity must be between 0 and 100")) if similarity > 0: - self.simopt = ["-C%d%%" % similarity] - findcopiesharder = ui.configbool("convert", "git.findcopiesharder") + self.simopt = [b"-C%d%%" % similarity] + findcopiesharder = ui.configbool( + b"convert", b"git.findcopiesharder" + ) if findcopiesharder: - self.simopt.append("--find-copies-harder") + self.simopt.append(b"--find-copies-harder") - renamelimit = ui.configint("convert", "git.renamelimit") - self.simopt.append("-l%d" % renamelimit) + renamelimit = ui.configint(b"convert", b"git.renamelimit") + self.simopt.append(b"-l%d" % renamelimit) else: self.simopt = [] - common.checktool("git", "git") + common.checktool(b"git", b"git") self.path = path self.submodules = [] - self.catfilepipe = self.gitpipe("cat-file", "--batch") + self.catfilepipe = self.gitpipe(b"cat-file", b"--batch") - self.copyextrakeys = self.ui.configlist("convert", "git.extrakeys") + self.copyextrakeys = self.ui.configlist(b"convert", b"git.extrakeys") banned = set(self.copyextrakeys) & bannedextrakeys if banned: raise error.Abort( - _("copying of extra key is forbidden: %s") - % _(", ").join(sorted(banned)) + _(b"copying of extra key is forbidden: %s") + % _(b", ").join(sorted(banned)) ) - committeractions = self.ui.configlist("convert", "git.committeractions") + committeractions = self.ui.configlist( + b"convert", b"git.committeractions" + ) messagedifferent = None messagealways = None for a in committeractions: - if a.startswith(("messagedifferent", "messagealways")): + if a.startswith((b"messagedifferent", b"messagealways")): k = a v = None - if "=" in a: - k, v = a.split("=", 1) + if b"=" in a: + k, v = a.split(b"=", 1) - if k == "messagedifferent": - messagedifferent = v or "committer:" - elif k == "messagealways": - messagealways = v or "committer:" + if k == b"messagedifferent": + messagedifferent = v or b"committer:" + elif k == b"messagealways": + messagealways = v or b"committer:" if messagedifferent and messagealways: raise error.Abort( _( - "committeractions cannot define both " - "messagedifferent and messagealways" + b"committeractions cannot define both " + b"messagedifferent and messagealways" ) ) - dropcommitter = "dropcommitter" in committeractions - replaceauthor = "replaceauthor" in committeractions + dropcommitter = b"dropcommitter" in committeractions + replaceauthor = b"replaceauthor" in committeractions if dropcommitter and replaceauthor: raise error.Abort( _( - "committeractions cannot define both " - "dropcommitter and replaceauthor" + b"committeractions cannot define both " + b"dropcommitter and replaceauthor" ) ) if dropcommitter and messagealways: raise error.Abort( _( - "committeractions cannot define both " - "dropcommitter and messagealways" + b"committeractions cannot define both " + b"dropcommitter and messagealways" ) ) if not messagedifferent and not messagealways: - messagedifferent = "committer:" + messagedifferent = b"committer:" self.committeractions = { - "dropcommitter": dropcommitter, - "replaceauthor": replaceauthor, - "messagedifferent": messagedifferent, - "messagealways": messagealways, + b"dropcommitter": dropcommitter, + b"replaceauthor": replaceauthor, + b"messagedifferent": messagedifferent, + b"messagealways": messagealways, } def after(self): @@ -172,35 +176,38 @@ def getheads(self): if not self.revs: - output, status = self.gitrun("rev-parse", "--branches", "--remotes") + output, status = self.gitrun( + b"rev-parse", b"--branches", b"--remotes" + ) heads = output.splitlines() if status: - raise error.Abort(_("cannot retrieve git heads")) + raise error.Abort(_(b"cannot retrieve git heads")) else: heads = [] for rev in self.revs: - rawhead, ret = self.gitrun("rev-parse", "--verify", rev) + rawhead, ret = self.gitrun(b"rev-parse", b"--verify", rev) heads.append(rawhead[:-1]) if ret: - raise error.Abort(_('cannot retrieve git head "%s"') % rev) + raise error.Abort(_(b'cannot retrieve git head "%s"') % rev) return heads def catfile(self, rev, ftype): if rev == nodemod.nullhex: raise IOError - self.catfilepipe[0].write(rev + "\n") + self.catfilepipe[0].write(rev + b"\n") self.catfilepipe[0].flush() info = self.catfilepipe[1].readline().split() if info[1] != ftype: raise error.Abort( - _("cannot read %r object at %s") + _(b"cannot read %r object at %s") % (pycompat.bytestr(ftype), rev) ) size = int(info[2]) data = self.catfilepipe[1].read(size) if len(data) < size: raise error.Abort( - _("cannot read %r object at %s: unexpected size") % (ftype, rev) + _(b"cannot read %r object at %s: unexpected size") + % (ftype, rev) ) # read the trailing newline self.catfilepipe[1].read(1) @@ -209,14 +216,14 @@ def getfile(self, name, rev): if rev == nodemod.nullhex: return None, None - if name == ".hgsub": - data = "\n".join([m.hgsub() for m in self.submoditer()]) - mode = "" - elif name == ".hgsubstate": - data = "\n".join([m.hgsubstate() for m in self.submoditer()]) - mode = "" + if name == b".hgsub": + data = b"\n".join([m.hgsub() for m in self.submoditer()]) + mode = b"" + elif name == b".hgsubstate": + data = b"\n".join([m.hgsubstate() for m in self.submoditer()]) + mode = b"" else: - data = self.catfile(rev, "blob") + data = self.catfile(rev, b"blob") mode = self.modecache[(name, rev)] return data, mode @@ -236,21 +243,23 @@ c = config.config() # Each item in .gitmodules starts with whitespace that cant be parsed c.parse( - ".gitmodules", - "\n".join(line.strip() for line in content.split("\n")), + b".gitmodules", + b"\n".join(line.strip() for line in content.split(b"\n")), ) for sec in c.sections(): s = c[sec] - if "url" in s and "path" in s: - self.submodules.append(submodule(s["path"], "", s["url"])) + if b"url" in s and b"path" in s: + self.submodules.append(submodule(s[b"path"], b"", s[b"url"])) def retrievegitmodules(self, version): - modules, ret = self.gitrun("show", "%s:%s" % (version, ".gitmodules")) + modules, ret = self.gitrun( + b"show", b"%s:%s" % (version, b".gitmodules") + ) if ret: # This can happen if a file is in the repo that has permissions # 160000, but there is no .gitmodules file. self.ui.warn( - _("warning: cannot read submodules config file in " "%s\n") + _(b"warning: cannot read submodules config file in " b"%s\n") % version ) return @@ -259,74 +268,76 @@ self.parsegitmodules(modules) except error.ParseError: self.ui.warn( - _("warning: unable to parse .gitmodules in %s\n") % version + _(b"warning: unable to parse .gitmodules in %s\n") % version ) return for m in self.submodules: - node, ret = self.gitrun("rev-parse", "%s:%s" % (version, m.path)) + node, ret = self.gitrun(b"rev-parse", b"%s:%s" % (version, m.path)) if ret: continue m.node = node.strip() def getchanges(self, version, full): if full: - raise error.Abort(_("convert from git does not support --full")) + raise error.Abort(_(b"convert from git does not support --full")) self.modecache = {} cmd = ( - ["diff-tree", "-z", "--root", "-m", "-r"] + self.simopt + [version] + [b"diff-tree", b"-z", b"--root", b"-m", b"-r"] + + self.simopt + + [version] ) output, status = self.gitrun(*cmd) if status: - raise error.Abort(_("cannot read changes in %s") % version) + raise error.Abort(_(b"cannot read changes in %s") % version) changes = [] copies = {} seen = set() entry = None subexists = [False] subdeleted = [False] - difftree = output.split("\x00") + difftree = output.split(b"\x00") lcount = len(difftree) i = 0 - skipsubmodules = self.ui.configbool("convert", "git.skipsubmodules") + skipsubmodules = self.ui.configbool(b"convert", b"git.skipsubmodules") def add(entry, f, isdest): seen.add(f) h = entry[3] - p = entry[1] == "100755" - s = entry[1] == "120000" - renamesource = not isdest and entry[4][0] == "R" + p = entry[1] == b"100755" + s = entry[1] == b"120000" + renamesource = not isdest and entry[4][0] == b"R" - if f == ".gitmodules": + if f == b".gitmodules": if skipsubmodules: return subexists[0] = True - if entry[4] == "D" or renamesource: + if entry[4] == b"D" or renamesource: subdeleted[0] = True - changes.append((".hgsub", nodemod.nullhex)) + changes.append((b".hgsub", nodemod.nullhex)) else: - changes.append((".hgsub", "")) - elif entry[1] == "160000" or entry[0] == ":160000": + changes.append((b".hgsub", b"")) + elif entry[1] == b"160000" or entry[0] == b":160000": if not skipsubmodules: subexists[0] = True else: if renamesource: h = nodemod.nullhex - self.modecache[(f, h)] = (p and "x") or (s and "l") or "" + self.modecache[(f, h)] = (p and b"x") or (s and b"l") or b"" changes.append((f, h)) while i < lcount: l = difftree[i] i += 1 if not entry: - if not l.startswith(":"): + if not l.startswith(b":"): continue entry = tuple(pycompat.bytestr(p) for p in l.split()) continue f = l - if entry[4][0] == "C": + if entry[4][0] == b"C": copysrc = f copydest = difftree[i] i += 1 @@ -336,7 +347,7 @@ add(entry, f, False) # A file can be copied multiple times, or modified and copied # simultaneously. So f can be repeated even if fdest isn't. - if entry[4][0] == "R": + if entry[4][0] == b"R": # rename: next line is the destination fdest = difftree[i] i += 1 @@ -344,21 +355,21 @@ add(entry, fdest, True) # .gitmodules isn't imported at all, so it being copied to # and fro doesn't really make sense - if f != ".gitmodules" and fdest != ".gitmodules": + if f != b".gitmodules" and fdest != b".gitmodules": copies[fdest] = f entry = None if subexists[0]: if subdeleted[0]: - changes.append((".hgsubstate", nodemod.nullhex)) + changes.append((b".hgsubstate", nodemod.nullhex)) else: self.retrievegitmodules(version) - changes.append((".hgsubstate", "")) + changes.append((b".hgsubstate", b"")) return (changes, copies, set()) def getcommit(self, version): - c = self.catfile(version, "commit") # read the commit hash - end = c.find("\n\n") + c = self.catfile(version, b"commit") # read the commit hash + end = c.find(b"\n\n") message = c[end + 2 :] message = self.recode(message) l = c[:end].splitlines() @@ -366,43 +377,43 @@ author = committer = None extra = {} for e in l[1:]: - n, v = e.split(" ", 1) - if n == "author": + n, v = e.split(b" ", 1) + if n == b"author": p = v.split() tm, tz = p[-2:] - author = " ".join(p[:-2]) - if author[0] == "<": + author = b" ".join(p[:-2]) + if author[0] == b"<": author = author[1:-1] author = self.recode(author) - if n == "committer": + if n == b"committer": p = v.split() tm, tz = p[-2:] - committer = " ".join(p[:-2]) - if committer[0] == "<": + committer = b" ".join(p[:-2]) + if committer[0] == b"<": committer = committer[1:-1] committer = self.recode(committer) - if n == "parent": + if n == b"parent": parents.append(v) if n in self.copyextrakeys: extra[n] = v - if self.committeractions["dropcommitter"]: + if self.committeractions[b"dropcommitter"]: committer = None - elif self.committeractions["replaceauthor"]: + elif self.committeractions[b"replaceauthor"]: author = committer if committer: - messagealways = self.committeractions["messagealways"] - messagedifferent = self.committeractions["messagedifferent"] + messagealways = self.committeractions[b"messagealways"] + messagedifferent = self.committeractions[b"messagedifferent"] if messagealways: - message += "\n%s %s\n" % (messagealways, committer) + message += b"\n%s %s\n" % (messagealways, committer) elif messagedifferent and author != committer: - message += "\n%s %s\n" % (messagedifferent, committer) + message += b"\n%s %s\n" % (messagedifferent, committer) - tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] + tzs, tzh, tzm = tz[-5:-4] + b"1", tz[-4:-2], tz[-2:] tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) - date = tm + " " + (b"%d" % tz) - saverev = self.ui.configbool("convert", "git.saverev") + date = tm + b" " + (b"%d" % tz) + saverev = self.ui.configbool(b"convert", b"git.saverev") c = common.commit( parents=parents, @@ -416,27 +427,27 @@ return c def numcommits(self): - output, ret = self.gitrunlines("rev-list", "--all") + output, ret = self.gitrunlines(b"rev-list", b"--all") if ret: raise error.Abort( - _("cannot retrieve number of commits in %s") % self.path + _(b"cannot retrieve number of commits in %s") % self.path ) return len(output) def gettags(self): tags = {} alltags = {} - output, status = self.gitrunlines("ls-remote", "--tags", self.path) + output, status = self.gitrunlines(b"ls-remote", b"--tags", self.path) if status: - raise error.Abort(_("cannot read tags from %s") % self.path) - prefix = "refs/tags/" + raise error.Abort(_(b"cannot read tags from %s") % self.path) + prefix = b"refs/tags/" # Build complete list of tags, both annotated and bare ones for line in output: line = line.strip() - if line.startswith("error:") or line.startswith("fatal:"): - raise error.Abort(_("cannot read tags from %s") % self.path) + if line.startswith(b"error:") or line.startswith(b"fatal:"): + raise error.Abort(_(b"cannot read tags from %s") % self.path) node, tag = line.split(None, 1) if not tag.startswith(prefix): continue @@ -444,10 +455,10 @@ # Filter out tag objects for annotated tag refs for tag in alltags: - if tag.endswith("^{}"): + if tag.endswith(b"^{}"): tags[tag[:-3]] = alltags[tag] else: - if tag + "^{}" in alltags: + if tag + b"^{}" in alltags: continue else: tags[tag] = alltags[tag] @@ -458,28 +469,28 @@ changes = [] if i is None: output, status = self.gitrunlines( - "diff-tree", "--root", "-m", "-r", version + b"diff-tree", b"--root", b"-m", b"-r", version ) if status: - raise error.Abort(_("cannot read changes in %s") % version) + raise error.Abort(_(b"cannot read changes in %s") % version) for l in output: - if "\t" not in l: + if b"\t" not in l: continue - m, f = l[:-1].split("\t") + m, f = l[:-1].split(b"\t") changes.append(f) else: output, status = self.gitrunlines( - "diff-tree", - "--name-only", - "--root", - "-r", + b"diff-tree", + b"--name-only", + b"--root", + b"-r", version, - "%s^%d" % (version, i + 1), - "--", + b"%s^%d" % (version, i + 1), + b"--", ) if status: - raise error.Abort(_("cannot read changes in %s") % version) - changes = [f.rstrip("\n") for f in output] + raise error.Abort(_(b"cannot read changes in %s") % version) + changes = [f.rstrip(b"\n") for f in output] return changes @@ -487,19 +498,19 @@ bookmarks = {} # Handle local and remote branches - remoteprefix = self.ui.config("convert", "git.remoteprefix") + remoteprefix = self.ui.config(b"convert", b"git.remoteprefix") reftypes = [ # (git prefix, hg prefix) - ("refs/remotes/origin/", remoteprefix + "/"), - ("refs/heads/", ""), + (b"refs/remotes/origin/", remoteprefix + b"/"), + (b"refs/heads/", b""), ] exclude = { - "refs/remotes/origin/HEAD", + b"refs/remotes/origin/HEAD", } try: - output, status = self.gitrunlines("show-ref") + output, status = self.gitrunlines(b"show-ref") for line in output: line = line.strip() rev, name = line.split(None, 1) @@ -507,13 +518,13 @@ for gitprefix, hgprefix in reftypes: if not name.startswith(gitprefix) or name in exclude: continue - name = "%s%s" % (hgprefix, name[len(gitprefix) :]) + name = b"%s%s" % (hgprefix, name[len(gitprefix) :]) bookmarks[name] = rev except Exception: pass return bookmarks - def checkrevformat(self, revstr, mapname="splicemap"): + def checkrevformat(self, revstr, mapname=b"splicemap"): """ git revision string is a 40 byte hex """ self.checkhexformat(revstr, mapname) diff --git a/hgext/convert/gnuarch.py b/hgext/convert/gnuarch.py --- a/hgext/convert/gnuarch.py +++ b/hgext/convert/gnuarch.py @@ -31,9 +31,9 @@ class gnuarch_rev(object): def __init__(self, rev): self.rev = rev - self.summary = "" + self.summary = b"" self.date = None - self.author = "" + self.author = b"" self.continuationof = None self.add_files = [] self.mod_files = [] @@ -44,20 +44,20 @@ def __init__(self, ui, repotype, path, revs=None): super(gnuarch_source, self).__init__(ui, repotype, path, revs=revs) - if not os.path.exists(os.path.join(path, "{arch}")): + if not os.path.exists(os.path.join(path, b"{arch}")): raise common.NoRepo( - _("%s does not look like a GNU Arch repository") % path + _(b"%s does not look like a GNU Arch repository") % path ) # Could use checktool, but we want to check for baz or tla. self.execmd = None - if procutil.findexe("baz"): - self.execmd = "baz" + if procutil.findexe(b"baz"): + self.execmd = b"baz" else: - if procutil.findexe("tla"): - self.execmd = "tla" + if procutil.findexe(b"tla"): + self.execmd = b"tla" else: - raise error.Abort(_("cannot find a GNU Arch tool")) + raise error.Abort(_(b"cannot find a GNU Arch tool")) common.commandline.__init__(self, ui, self.execmd) @@ -76,41 +76,45 @@ def before(self): # Get registered archives self.archives = [ - i.rstrip("\n") for i in self.runlines0("archives", "-n") + i.rstrip(b"\n") for i in self.runlines0(b"archives", b"-n") ] - if self.execmd == "tla": - output = self.run0("tree-version", self.path) + if self.execmd == b"tla": + output = self.run0(b"tree-version", self.path) else: - output = self.run0("tree-version", "-d", self.path) + output = self.run0(b"tree-version", b"-d", self.path) self.treeversion = output.strip() # Get name of temporary directory - version = self.treeversion.split("/") - self.tmppath = os.path.join(tempfile.gettempdir(), "hg-%s" % version[1]) + version = self.treeversion.split(b"/") + self.tmppath = os.path.join( + tempfile.gettempdir(), b"hg-%s" % version[1] + ) # Generate parents dictionary self.parents[None] = [] treeversion = self.treeversion child = None while treeversion: - self.ui.status(_("analyzing tree version %s...\n") % treeversion) + self.ui.status(_(b"analyzing tree version %s...\n") % treeversion) - archive = treeversion.split("/")[0] + archive = treeversion.split(b"/")[0] if archive not in self.archives: self.ui.status( _( - "tree analysis stopped because it points to " - "an unregistered archive %s...\n" + b"tree analysis stopped because it points to " + b"an unregistered archive %s...\n" ) % archive ) break # Get the complete list of revisions for that tree version - output, status = self.runlines("revisions", "-r", "-f", treeversion) + output, status = self.runlines( + b"revisions", b"-r", b"-f", treeversion + ) self.checkexit( - status, "failed retrieving revisions for %s" % treeversion + status, b"failed retrieving revisions for %s" % treeversion ) # No new iteration unless a revision has a continuation-of header @@ -122,9 +126,9 @@ self.parents[rev] = [] # Read author, date and summary - catlog, status = self.run("cat-log", "-d", self.path, rev) + catlog, status = self.run(b"cat-log", b"-d", self.path, rev) if status: - catlog = self.run0("cat-archive-log", rev) + catlog = self.run0(b"cat-archive-log", rev) self._parsecatlog(catlog, rev) # Populate the parents map @@ -138,18 +142,18 @@ # or if we have to 'jump' to a different treeversion given # by the continuation-of header. if self.changes[rev].continuationof: - treeversion = "--".join( - self.changes[rev].continuationof.split("--")[:-1] + treeversion = b"--".join( + self.changes[rev].continuationof.split(b"--")[:-1] ) break # If we reached a base-0 revision w/o any continuation-of # header, it means the tree history ends here. - if rev[-6:] == "base-0": + if rev[-6:] == b"base-0": break def after(self): - self.ui.debug("cleaning up %s\n" % self.tmppath) + self.ui.debug(b"cleaning up %s\n" % self.tmppath) shutil.rmtree(self.tmppath, ignore_errors=True) def getheads(self): @@ -157,7 +161,7 @@ def getfile(self, name, rev): if rev != self.lastrev: - raise error.Abort(_("internal calling inconsistency")) + raise error.Abort(_(b"internal calling inconsistency")) if not os.path.lexists(os.path.join(self.tmppath, name)): return None, None @@ -166,7 +170,7 @@ def getchanges(self, rev, full): if full: - raise error.Abort(_("convert from arch does not support --full")) + raise error.Abort(_(b"convert from arch does not support --full")) self._update(rev) changes = [] copies = {} @@ -212,14 +216,14 @@ cmdline = [self.execmd, cmd] cmdline += args cmdline = [procutil.shellquote(arg) for arg in cmdline] - cmdline += [">", os.devnull, "2>", os.devnull] - cmdline = procutil.quotecommand(" ".join(cmdline)) - self.ui.debug(cmdline, "\n") + cmdline += [b">", os.devnull, b"2>", os.devnull] + cmdline = procutil.quotecommand(b" ".join(cmdline)) + self.ui.debug(cmdline, b"\n") return os.system(pycompat.rapply(procutil.tonativestr, cmdline)) def _update(self, rev): - self.ui.debug("applying revision %s...\n" % rev) - changeset, status = self.runlines("replay", "-d", self.tmppath, rev) + self.ui.debug(b"applying revision %s...\n" % rev) + changeset, status = self.runlines(b"replay", b"-d", self.tmppath, rev) if status: # Something went wrong while merging (baz or tla # issue?), get latest revision and try from there @@ -228,7 +232,7 @@ else: old_rev = self.parents[rev][0] self.ui.debug( - "computing changeset between %s and %s...\n" % (old_rev, rev) + b"computing changeset between %s and %s...\n" % (old_rev, rev) ) self._parsechangeset(changeset, rev) @@ -237,16 +241,16 @@ if stat.S_ISLNK(mode): data = util.readlink(os.path.join(self.tmppath, name)) if mode: - mode = "l" + mode = b"l" else: - mode = "" + mode = b"" else: data = util.readfile(os.path.join(self.tmppath, name)) - mode = (mode & 0o111) and "x" or "" + mode = (mode & 0o111) and b"x" or b"" return data, mode def _exclude(self, name): - exclude = ["{arch}", ".arch-ids", ".arch-inventory"] + exclude = [b"{arch}", b".arch-ids", b".arch-inventory"] for exc in exclude: if name.find(exc) != -1: return True @@ -280,15 +284,15 @@ return changes, copies def _obtainrevision(self, rev): - self.ui.debug("obtaining revision %s...\n" % rev) - output = self._execute("get", rev, self.tmppath) + self.ui.debug(b"obtaining revision %s...\n" % rev) + output = self._execute(b"get", rev, self.tmppath) self.checkexit(output) - self.ui.debug("analyzing revision %s...\n" % rev) + self.ui.debug(b"analyzing revision %s...\n" % rev) files = self._readcontents(self.tmppath) self.changes[rev].add_files += files def _stripbasepath(self, path): - if path.startswith("./"): + if path.startswith(b"./"): return path[2:] return path @@ -298,73 +302,73 @@ # Commit date self.changes[rev].date = dateutil.datestr( - dateutil.strdate(catlog["Standard-date"], "%Y-%m-%d %H:%M:%S") + dateutil.strdate(catlog[b"Standard-date"], b"%Y-%m-%d %H:%M:%S") ) # Commit author - self.changes[rev].author = self.recode(catlog["Creator"]) + self.changes[rev].author = self.recode(catlog[b"Creator"]) # Commit description - self.changes[rev].summary = "\n\n".join( - (catlog["Summary"], catlog.get_payload()) + self.changes[rev].summary = b"\n\n".join( + (catlog[b"Summary"], catlog.get_payload()) ) self.changes[rev].summary = self.recode(self.changes[rev].summary) # Commit revision origin when dealing with a branch or tag - if "Continuation-of" in catlog: + if b"Continuation-of" in catlog: self.changes[rev].continuationof = self.recode( - catlog["Continuation-of"] + catlog[b"Continuation-of"] ) except Exception: - raise error.Abort(_("could not parse cat-log of %s") % rev) + raise error.Abort(_(b"could not parse cat-log of %s") % rev) def _parsechangeset(self, data, rev): for l in data: l = l.strip() # Added file (ignore added directory) - if l.startswith("A") and not l.startswith("A/"): + if l.startswith(b"A") and not l.startswith(b"A/"): file = self._stripbasepath(l[1:].strip()) if not self._exclude(file): self.changes[rev].add_files.append(file) # Deleted file (ignore deleted directory) - elif l.startswith("D") and not l.startswith("D/"): + elif l.startswith(b"D") and not l.startswith(b"D/"): file = self._stripbasepath(l[1:].strip()) if not self._exclude(file): self.changes[rev].del_files.append(file) # Modified binary file - elif l.startswith("Mb"): + elif l.startswith(b"Mb"): file = self._stripbasepath(l[2:].strip()) if not self._exclude(file): self.changes[rev].mod_files.append(file) # Modified link - elif l.startswith("M->"): + elif l.startswith(b"M->"): file = self._stripbasepath(l[3:].strip()) if not self._exclude(file): self.changes[rev].mod_files.append(file) # Modified file - elif l.startswith("M"): + elif l.startswith(b"M"): file = self._stripbasepath(l[1:].strip()) if not self._exclude(file): self.changes[rev].mod_files.append(file) # Renamed file (or link) - elif l.startswith("=>"): - files = l[2:].strip().split(" ") + elif l.startswith(b"=>"): + files = l[2:].strip().split(b" ") if len(files) == 1: - files = l[2:].strip().split("\t") + files = l[2:].strip().split(b"\t") src = self._stripbasepath(files[0]) dst = self._stripbasepath(files[1]) if not self._exclude(src) and not self._exclude(dst): self.changes[rev].ren_files[src] = dst # Conversion from file to link or from link to file (modified) - elif l.startswith("ch"): + elif l.startswith(b"ch"): file = self._stripbasepath(l[2:].strip()) if not self._exclude(file): self.changes[rev].mod_files.append(file) # Renamed directory - elif l.startswith("/>"): - dirs = l[2:].strip().split(" ") + elif l.startswith(b"/>"): + dirs = l[2:].strip().split(b" ") if len(dirs) == 1: - dirs = l[2:].strip().split("\t") + dirs = l[2:].strip().split(b"\t") src = self._stripbasepath(dirs[0]) dst = self._stripbasepath(dirs[1]) if not self._exclude(src) and not self._exclude(dst): diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -51,33 +51,33 @@ class mercurial_sink(common.converter_sink): def __init__(self, ui, repotype, path): common.converter_sink.__init__(self, ui, repotype, path) - self.branchnames = ui.configbool("convert", "hg.usebranchnames") - self.clonebranches = ui.configbool("convert", "hg.clonebranches") - self.tagsbranch = ui.config("convert", "hg.tagsbranch") + self.branchnames = ui.configbool(b"convert", b"hg.usebranchnames") + self.clonebranches = ui.configbool(b"convert", b"hg.clonebranches") + self.tagsbranch = ui.config(b"convert", b"hg.tagsbranch") self.lastbranch = None if os.path.isdir(path) and len(os.listdir(path)) > 0: try: self.repo = hg.repository(self.ui, path) if not self.repo.local(): raise NoRepo( - _("%s is not a local Mercurial repository") % path + _(b"%s is not a local Mercurial repository") % path ) except error.RepoError as err: ui.traceback() raise NoRepo(err.args[0]) else: try: - ui.status(_("initializing destination %s repository\n") % path) + ui.status(_(b"initializing destination %s repository\n") % path) self.repo = hg.repository(self.ui, path, create=True) if not self.repo.local(): raise NoRepo( - _("%s is not a local Mercurial repository") % path + _(b"%s is not a local Mercurial repository") % path ) self.created.append(path) except error.RepoError: ui.traceback() raise NoRepo( - _("could not create hg repository %s as sink") % path + _(b"could not create hg repository %s as sink") % path ) self.lock = None self.wlock = None @@ -85,22 +85,22 @@ self.subrevmaps = {} def before(self): - self.ui.debug("run hg sink pre-conversion action\n") + self.ui.debug(b"run hg sink pre-conversion action\n") self.wlock = self.repo.wlock() self.lock = self.repo.lock() def after(self): - self.ui.debug("run hg sink post-conversion action\n") + self.ui.debug(b"run hg sink post-conversion action\n") if self.lock: self.lock.release() if self.wlock: self.wlock.release() def revmapfile(self): - return self.repo.vfs.join("shamap") + return self.repo.vfs.join(b"shamap") def authorfile(self): - return self.repo.vfs.join("authormap") + return self.repo.vfs.join(b"authormap") def setbranch(self, branch, pbranches): if not self.clonebranches: @@ -109,8 +109,8 @@ setbranch = branch != self.lastbranch self.lastbranch = branch if not branch: - branch = "default" - pbranches = [(b[0], b[1] and b[1] or "default") for b in pbranches] + branch = b"default" + pbranches = [(b[0], b[1] and b[1] or b"default") for b in pbranches] branchpath = os.path.join(self.path, branch) if setbranch: @@ -135,7 +135,9 @@ for pbranch, heads in sorted(missings.iteritems()): pbranchpath = os.path.join(self.path, pbranch) prepo = hg.peer(self.ui, {}, pbranchpath) - self.ui.note(_("pulling from %s into %s\n") % (pbranch, branch)) + self.ui.note( + _(b"pulling from %s into %s\n") % (pbranch, branch) + ) exchange.pull( self.repo, prepo, [prepo.lookup(h) for h in heads] ) @@ -144,10 +146,10 @@ def _rewritetags(self, source, revmap, data): fp = stringio() for line in data.splitlines(): - s = line.split(" ", 1) + s = line.split(b" ", 1) if len(s) != 2: - self.ui.warn(_('invalid tag entry: "%s"\n') % line) - fp.write("%s\n" % line) # Bogus, but keep for hash stability + self.ui.warn(_(b'invalid tag entry: "%s"\n') % line) + fp.write(b"%s\n" % line) # Bogus, but keep for hash stability continue revid = revmap.get(source.lookuprev(s[0])) if not revid: @@ -155,16 +157,16 @@ revid = s[0] else: # missing, but keep for hash stability - self.ui.warn(_('missing tag entry: "%s"\n') % line) - fp.write("%s\n" % line) + self.ui.warn(_(b'missing tag entry: "%s"\n') % line) + fp.write(b"%s\n" % line) continue - fp.write("%s %s\n" % (revid, s[1])) + fp.write(b"%s %s\n" % (revid, s[1])) return fp.getvalue() def _rewritesubstate(self, source, data): fp = stringio() for line in data.splitlines(): - s = line.split(" ", 1) + s = line.split(b" ", 1) if len(s) != 2: continue @@ -174,7 +176,7 @@ revmap = self.subrevmaps.get(subpath) if revmap is None: revmap = mapfile( - self.ui, self.repo.wjoin(subpath, ".hg/shamap") + self.ui, self.repo.wjoin(subpath, b".hg/shamap") ) self.subrevmaps[subpath] = revmap @@ -182,9 +184,9 @@ # need to be converted, in which case they can be cloned # into place instead of converted. Therefore, only warn # once. - msg = _('no ".hgsubstate" updates will be made for "%s"\n') + msg = _(b'no ".hgsubstate" updates will be made for "%s"\n') if len(revmap) == 0: - sub = self.repo.wvfs.reljoin(subpath, ".hg") + sub = self.repo.wvfs.reljoin(subpath, b".hg") if self.repo.wvfs.exists(sub): self.ui.warn(msg % subpath) @@ -193,13 +195,13 @@ if not newid: if len(revmap) > 0: self.ui.warn( - _("%s is missing from %s/.hg/shamap\n") + _(b"%s is missing from %s/.hg/shamap\n") % (revid, subpath) ) else: revid = newid - fp.write("%s %s\n" % (revid, subpath)) + fp.write(b"%s %s\n" % (revid, subpath)) return fp.getvalue() @@ -232,16 +234,16 @@ # If the file requires actual merging, abort. We don't have enough # context to resolve merges correctly. - if action in ["m", "dm", "cd", "dc"]: + if action in [b"m", b"dm", b"cd", b"dc"]: raise error.Abort( _( - "unable to convert merge commit " - "since target parents do not merge cleanly (file " - "%s, parents %s and %s)" + b"unable to convert merge commit " + b"since target parents do not merge cleanly (file " + b"%s, parents %s and %s)" ) % (file, p1ctx, p2ctx) ) - elif action == "k": + elif action == b"k": # 'keep' means nothing changed from p1 continue else: @@ -255,7 +257,7 @@ def getfilectx(repo, memctx, f): if p2ctx and f in p2files and f not in copies: - self.ui.debug("reusing %s from p2\n" % f) + self.ui.debug(b"reusing %s from p2\n" % f) try: return p2ctx[f] except error.ManifestLookupError: @@ -269,17 +271,17 @@ data, mode = source.getfile(f, v) if data is None: return None - if f == ".hgtags": + if f == b".hgtags": data = self._rewritetags(source, revmap, data) - if f == ".hgsubstate": + if f == b".hgsubstate": data = self._rewritesubstate(source, data) return context.memfilectx( self.repo, memctx, f, data, - "l" in mode, - "x" in mode, + b"l" in mode, + b"x" in mode, copies.get(f), ) @@ -310,15 +312,15 @@ extra = commit.extra.copy() - sourcename = self.repo.ui.config("convert", "hg.sourcename") + sourcename = self.repo.ui.config(b"convert", b"hg.sourcename") if sourcename: - extra["convert_source"] = sourcename + extra[b"convert_source"] = sourcename for label in ( - "source", - "transplant_source", - "rebase_source", - "intermediate-source", + b"source", + b"transplant_source", + b"rebase_source", + b"intermediate-source", ): node = extra.get(label) @@ -326,20 +328,20 @@ continue # Only transplant stores its reference in binary - if label == "transplant_source": + if label == b"transplant_source": node = nodemod.hex(node) newrev = revmap.get(node) if newrev is not None: - if label == "transplant_source": + if label == b"transplant_source": newrev = nodemod.bin(newrev) extra[label] = newrev if self.branchnames and commit.branch: - extra["branch"] = commit.branch + extra[b"branch"] = commit.branch if commit.rev and commit.saverev: - extra["convert_revision"] = commit.rev + extra[b"convert_revision"] = commit.rev while parents: p1 = p2 @@ -373,14 +375,14 @@ # We won't know if the conversion changes the node until after the # commit, so copy the source's phase for now. self.repo.ui.setconfig( - "phases", - "new-commit", + b"phases", + b"new-commit", phases.phasenames[commit.phase], - "convert", + b"convert", ) - with self.repo.transaction("convert") as tr: - if self.repo.ui.config("convert", "hg.preserve-hash"): + with self.repo.transaction(b"convert") as tr: + if self.repo.ui.config(b"convert", b"hg.preserve-hash"): origctx = commit.ctx else: origctx = None @@ -396,15 +398,15 @@ self.repo, tr, phases.draft, [ctx.node()] ) - text = "(octopus merge fixup)\n" + text = b"(octopus merge fixup)\n" p2 = node if self.filemapmode and nparents == 1: man = self.repo.manifestlog.getstorage(b"") mnode = self.repo.changelog.read(nodemod.bin(p2))[0] - closed = "close" in commit.extra + closed = b"close" in commit.extra if not closed and not man.cmp(m1node, man.revision(mnode)): - self.ui.status(_("filtering out empty revision\n")) + self.ui.status(_(b"filtering out empty revision\n")) self.repo.rollback(force=True) return parent return p2 @@ -416,13 +418,13 @@ oldlines = set() for branch, heads in self.repo.branchmap().iteritems(): for h in heads: - if ".hgtags" in self.repo[h]: + if b".hgtags" in self.repo[h]: oldlines.update( - set(self.repo[h][".hgtags"].data().splitlines(True)) + set(self.repo[h][b".hgtags"].data().splitlines(True)) ) oldlines = sorted(list(oldlines)) - newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags]) + newlines = sorted([(b"%s %s\n" % (tags[tag], tag)) for tag in tags]) if newlines == oldlines: return None, None @@ -430,12 +432,12 @@ oldtags = set() newtags = set() for line in oldlines: - s = line.strip().split(" ", 1) + s = line.strip().split(b" ", 1) if len(s) != 2: continue oldtags.add(s[1]) for line in newlines: - s = line.strip().split(" ", 1) + s = line.strip().split(b" ", 1) if len(s) != 2: continue if s[1] not in oldtags: @@ -444,21 +446,21 @@ if not newtags: return None, None - data = "".join(newlines) + data = b"".join(newlines) def getfilectx(repo, memctx, f): return context.memfilectx(repo, memctx, f, data, False, False, None) - self.ui.status(_("updating tags\n")) - date = "%d 0" % int(time.mktime(time.gmtime())) - extra = {"branch": self.tagsbranch} + self.ui.status(_(b"updating tags\n")) + date = b"%d 0" % int(time.mktime(time.gmtime())) + extra = {b"branch": self.tagsbranch} ctx = context.memctx( self.repo, (tagparent, None), - "update tags", - [".hgtags"], + b"update tags", + [b".hgtags"], getfilectx, - "convert-repo", + b"convert-repo", date, extra, ) @@ -475,8 +477,8 @@ try: wlock = self.repo.wlock() lock = self.repo.lock() - tr = self.repo.transaction("bookmark") - self.ui.status(_("updating bookmarks\n")) + tr = self.repo.transaction(b"bookmark") + self.ui.status(_(b"updating bookmarks\n")) destmarks = self.repo._bookmarks changes = [ (bookmark, nodemod.bin(updatedbookmark[bookmark])) @@ -495,9 +497,9 @@ if rev not in self.repo and self.clonebranches: raise error.Abort( _( - "revision %s not found in destination " - "repository (lookups with clonebranches=true " - "are not implemented)" + b"revision %s not found in destination " + b"repository (lookups with clonebranches=true " + b"are not implemented)" ) % rev ) @@ -507,9 +509,9 @@ class mercurial_source(common.converter_source): def __init__(self, ui, repotype, path, revs=None): common.converter_source.__init__(self, ui, repotype, path, revs) - self.ignoreerrors = ui.configbool("convert", "hg.ignoreerrors") + self.ignoreerrors = ui.configbool(b"convert", b"hg.ignoreerrors") self.ignored = set() - self.saverev = ui.configbool("convert", "hg.saverev") + self.saverev = ui.configbool(b"convert", b"hg.saverev") try: self.repo = hg.repository(self.ui, path) # try to provoke an exception if this isn't really a hg @@ -518,21 +520,21 @@ raise error.RepoError except error.RepoError: ui.traceback() - raise NoRepo(_("%s is not a local Mercurial repository") % path) + raise NoRepo(_(b"%s is not a local Mercurial repository") % path) self.lastrev = None self.lastctx = None self._changescache = None, None self.convertfp = None # Restrict converted revisions to startrev descendants - startnode = ui.config("convert", "hg.startrev") - hgrevs = ui.config("convert", "hg.revs") + startnode = ui.config(b"convert", b"hg.startrev") + hgrevs = ui.config(b"convert", b"hg.revs") if hgrevs is None: if startnode is not None: try: startnode = self.repo.lookup(startnode) except error.RepoError: raise error.Abort( - _("%s is not a valid start revision") % startnode + _(b"%s is not a valid start revision") % startnode ) startrev = self.repo.changelog.rev(startnode) children = {startnode: 1} @@ -548,7 +550,10 @@ else: if revs or startnode is not None: raise error.Abort( - _("hg.revs cannot be combined with " "hg.startrev or --rev") + _( + b"hg.revs cannot be combined with " + b"hg.startrev or --rev" + ) ) nodes = set() parents = set() @@ -635,7 +640,7 @@ if not self.ignoreerrors: raise self.ignored.add(name) - self.ui.warn(_("ignoring: %s\n") % e) + self.ui.warn(_(b"ignoring: %s\n") % e) return copies def getcommit(self, rev): @@ -647,7 +652,7 @@ return common.commit( author=ctx.user(), - date=dateutil.datestr(ctx.date(), "%Y-%m-%d %H:%M:%S %1%2"), + date=dateutil.datestr(ctx.date(), b"%Y-%m-%d %H:%M:%S %1%2"), desc=ctx.description(), rev=crev, parents=parents, @@ -668,7 +673,7 @@ tags = [ t for t in self.repo.tagslist() - if self.repo.tagtype(t[0]) == "global" + if self.repo.tagtype(t[0]) == b"global" ] return dict( [ @@ -696,15 +701,15 @@ def converted(self, rev, destrev): if self.convertfp is None: - self.convertfp = open(self.repo.vfs.join("shamap"), "ab") - self.convertfp.write(util.tonativeeol("%s %s\n" % (destrev, rev))) + self.convertfp = open(self.repo.vfs.join(b"shamap"), b"ab") + self.convertfp.write(util.tonativeeol(b"%s %s\n" % (destrev, rev))) self.convertfp.flush() def before(self): - self.ui.debug("run hg source pre-conversion action\n") + self.ui.debug(b"run hg source pre-conversion action\n") def after(self): - self.ui.debug("run hg source post-conversion action\n") + self.ui.debug(b"run hg source post-conversion action\n") def hasnativeorder(self): return True @@ -721,6 +726,6 @@ def getbookmarks(self): return bookmarks.listbookmarks(self.repo) - def checkrevformat(self, revstr, mapname="splicemap"): + def checkrevformat(self, revstr, mapname=b"splicemap"): """ Mercurial, revision string is a 40 byte hex """ self.checkhexformat(revstr, mapname) diff --git a/hgext/convert/monotone.py b/hgext/convert/monotone.py --- a/hgext/convert/monotone.py +++ b/hgext/convert/monotone.py @@ -26,11 +26,11 @@ if revs and len(revs) > 1: raise error.Abort( _( - "monotone source does not support specifying " - "multiple revs" + b"monotone source does not support specifying " + b"multiple revs" ) ) - common.commandline.__init__(self, ui, "mtn") + common.commandline.__init__(self, ui, b"mtn") self.ui = ui self.path = path @@ -38,17 +38,17 @@ self.revs = revs norepo = common.NoRepo( - _("%s does not look like a monotone repository") % path + _(b"%s does not look like a monotone repository") % path ) - if not os.path.exists(os.path.join(path, "_MTN")): + if not os.path.exists(os.path.join(path, b"_MTN")): # Could be a monotone repository (SQLite db file) try: - f = open(path, "rb") + f = open(path, b"rb") header = f.read(16) f.close() except IOError: - header = "" - if header != "SQLite format 3\x00": + header = b"" + if header != b"SQLite format 3\x00": raise norepo # regular expressions for parsing monotone output @@ -58,24 +58,26 @@ revision = br"\s+\[(\w+)\]\s*" lines = br"(?:.|\n)+" - self.dir_re = re.compile(space + "dir" + name) - self.file_re = re.compile(space + "file" + name + "content" + revision) + self.dir_re = re.compile(space + b"dir" + name) + self.file_re = re.compile( + space + b"file" + name + b"content" + revision + ) self.add_file_re = re.compile( - space + "add_file" + name + "content" + revision + space + b"add_file" + name + b"content" + revision ) self.patch_re = re.compile( - space + "patch" + name + "from" + revision + "to" + revision + space + b"patch" + name + b"from" + revision + b"to" + revision ) - self.rename_re = re.compile(space + "rename" + name + "to" + name) - self.delete_re = re.compile(space + "delete" + name) - self.tag_re = re.compile(space + "tag" + name + "revision" + revision) + self.rename_re = re.compile(space + b"rename" + name + b"to" + name) + self.delete_re = re.compile(space + b"delete" + name) + self.tag_re = re.compile(space + b"tag" + name + b"revision" + revision) self.cert_re = re.compile( - lines + space + "name" + name + "value" + value + lines + space + b"name" + name + b"value" + value ) - attr = space + "file" + lines + space + "attr" + space + attr = space + b"file" + lines + space + b"attr" + space self.attr_execute_re = re.compile( - attr + '"mtn:execute"' + space + '"true"' + attr + b'"mtn:execute"' + space + b'"true"' ) # cached data @@ -84,7 +86,7 @@ self.files = None self.dirs = None - common.checktool("mtn", abort=False) + common.checktool(b"mtn", abort=False) def mtnrun(self, *args, **kwargs): if self.automatestdio: @@ -94,27 +96,27 @@ def mtnrunsingle(self, *args, **kwargs): kwargs[r"d"] = self.path - return self.run0("automate", *args, **kwargs) + return self.run0(b"automate", *args, **kwargs) def mtnrunstdio(self, *args, **kwargs): # Prepare the command in automate stdio format kwargs = pycompat.byteskwargs(kwargs) command = [] for k, v in kwargs.iteritems(): - command.append("%d:%s" % (len(k), k)) + command.append(b"%d:%s" % (len(k), k)) if v: - command.append("%d:%s" % (len(v), v)) + command.append(b"%d:%s" % (len(v), v)) if command: - command.insert(0, "o") - command.append("e") + command.insert(0, b"o") + command.append(b"e") - command.append("l") + command.append(b"l") for arg in args: - command.append("%d:%s" % (len(arg), arg)) - command.append("e") - command = "".join(command) + command.append(b"%d:%s" % (len(arg), arg)) + command.append(b"e") + command = b"".join(command) - self.ui.debug("mtn: sending '%s'\n" % command) + self.ui.debug(b"mtn: sending '%s'\n" % command) self.mtnwritefp.write(command) self.mtnwritefp.flush() @@ -122,42 +124,44 @@ def mtnstdioreadpacket(self): read = None - commandnbr = "" - while read != ":": + commandnbr = b"" + while read != b":": read = self.mtnreadfp.read(1) if not read: - raise error.Abort(_("bad mtn packet - no end of commandnbr")) + raise error.Abort(_(b"bad mtn packet - no end of commandnbr")) commandnbr += read commandnbr = commandnbr[:-1] stream = self.mtnreadfp.read(1) - if stream not in "mewptl": - raise error.Abort(_("bad mtn packet - bad stream type %s") % stream) + if stream not in b"mewptl": + raise error.Abort( + _(b"bad mtn packet - bad stream type %s") % stream + ) read = self.mtnreadfp.read(1) - if read != ":": - raise error.Abort(_("bad mtn packet - no divider before size")) + if read != b":": + raise error.Abort(_(b"bad mtn packet - no divider before size")) read = None - lengthstr = "" - while read != ":": + lengthstr = b"" + while read != b":": read = self.mtnreadfp.read(1) if not read: - raise error.Abort(_("bad mtn packet - no end of packet size")) + raise error.Abort(_(b"bad mtn packet - no end of packet size")) lengthstr += read try: length = pycompat.long(lengthstr[:-1]) except TypeError: raise error.Abort( - _("bad mtn packet - bad packet size %s") % lengthstr + _(b"bad mtn packet - bad packet size %s") % lengthstr ) read = self.mtnreadfp.read(length) if len(read) != length: raise error.Abort( _( - "bad mtn packet - unable to read full packet " - "read %s of %s" + b"bad mtn packet - unable to read full packet " + b"read %s of %s" ) % (len(read), length) ) @@ -169,33 +173,33 @@ while True: commandnbr, stream, length, output = self.mtnstdioreadpacket() self.ui.debug( - "mtn: read packet %s:%s:%d\n" % (commandnbr, stream, length) + b"mtn: read packet %s:%s:%d\n" % (commandnbr, stream, length) ) - if stream == "l": + if stream == b"l": # End of command - if output != "0": + if output != b"0": raise error.Abort( - _("mtn command '%s' returned %s") % (command, output) + _(b"mtn command '%s' returned %s") % (command, output) ) break - elif stream in "ew": + elif stream in b"ew": # Error, warning output - self.ui.warn(_("%s error:\n") % self.command) + self.ui.warn(_(b"%s error:\n") % self.command) self.ui.warn(output) - elif stream == "p": + elif stream == b"p": # Progress messages - self.ui.debug("mtn: " + output) - elif stream == "m": + self.ui.debug(b"mtn: " + output) + elif stream == b"m": # Main stream - command output retval.append(output) - return "".join(retval) + return b"".join(retval) def mtnloadmanifest(self, rev): if self.manifest_rev == rev: return - self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n") + self.manifest = self.mtnrun(b"get_manifest_of", rev).split(b"\n\n") self.manifest_rev = rev self.files = {} self.dirs = {} @@ -203,11 +207,11 @@ for e in self.manifest: m = self.file_re.match(e) if m: - attr = "" + attr = b"" name = m.group(1) node = m.group(2) if self.attr_execute_re.match(e): - attr += "x" + attr += b"x" self.files[name] = (node, attr) m = self.dir_re.match(e) if m: @@ -224,12 +228,12 @@ def mtngetcerts(self, rev): certs = { - "author": "", - "date": "", - "changelog": "", - "branch": "", + b"author": b"", + b"date": b"", + b"changelog": b"", + b"branch": b"", } - certlist = self.mtnrun("certs", rev) + certlist = self.mtnrun(b"certs", rev) # mtn < 0.45: # key "test@selenic.com" # mtn >= 0.45: @@ -239,28 +243,28 @@ m = self.cert_re.match(e) if m: name, value = m.groups() - value = value.replace(br"\"", '"') - value = value.replace(br"\\", "\\") + value = value.replace(br"\"", b'"') + value = value.replace(br"\\", b"\\") certs[name] = value # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306 # and all times are stored in UTC - certs["date"] = certs["date"].split(".")[0] + " UTC" + certs[b"date"] = certs[b"date"].split(b".")[0] + b" UTC" return certs # implement the converter_source interface: def getheads(self): if not self.revs: - return self.mtnrun("leaves").splitlines() + return self.mtnrun(b"leaves").splitlines() else: return self.revs def getchanges(self, rev, full): if full: raise error.Abort( - _("convert from monotone does not support " "--full") + _(b"convert from monotone does not support " b"--full") ) - revision = self.mtnrun("get_revision", rev).split("\n\n") + revision = self.mtnrun(b"get_revision", rev).split(b"\n\n") files = {} ignoremove = {} renameddirs = [] @@ -298,7 +302,7 @@ for tofile in self.files: if tofile in ignoremove: continue - if tofile.startswith(todir + "/"): + if tofile.startswith(todir + b"/"): renamed[tofile] = fromdir + tofile[len(todir) :] # Avoid chained moves like: # d1(/a) => d3/d1(/a) @@ -306,9 +310,9 @@ ignoremove[tofile] = 1 for tofile, fromfile in renamed.items(): self.ui.debug( - "copying file in renamed directory from '%s' to '%s'" + b"copying file in renamed directory from '%s' to '%s'" % (fromfile, tofile), - "\n", + b"\n", ) files[tofile] = rev copies[tofile] = fromfile @@ -321,32 +325,32 @@ if not self.mtnisfile(name, rev): return None, None try: - data = self.mtnrun("get_file_of", name, r=rev) + data = self.mtnrun(b"get_file_of", name, r=rev) except Exception: return None, None self.mtnloadmanifest(rev) - node, attr = self.files.get(name, (None, "")) + node, attr = self.files.get(name, (None, b"")) return data, attr def getcommit(self, rev): extra = {} certs = self.mtngetcerts(rev) - if certs.get("suspend") == certs["branch"]: - extra["close"] = 1 - dateformat = "%Y-%m-%dT%H:%M:%S" + if certs.get(b"suspend") == certs[b"branch"]: + extra[b"close"] = 1 + dateformat = b"%Y-%m-%dT%H:%M:%S" return common.commit( - author=certs["author"], - date=dateutil.datestr(dateutil.strdate(certs["date"], dateformat)), - desc=certs["changelog"], + author=certs[b"author"], + date=dateutil.datestr(dateutil.strdate(certs[b"date"], dateformat)), + desc=certs[b"changelog"], rev=rev, - parents=self.mtnrun("parents", rev).splitlines(), - branch=certs["branch"], + parents=self.mtnrun(b"parents", rev).splitlines(), + branch=certs[b"branch"], extra=extra, ) def gettags(self): tags = {} - for e in self.mtnrun("tags").split("\n\n"): + for e in self.mtnrun(b"tags").split(b"\n\n"): m = self.tag_re.match(e) if m: tags[m.group(1)] = m.group(2) @@ -360,42 +364,42 @@ def before(self): # Check if we have a new enough version to use automate stdio try: - versionstr = self.mtnrunsingle("interface_version") + versionstr = self.mtnrunsingle(b"interface_version") version = float(versionstr) except Exception: raise error.Abort( - _("unable to determine mtn automate interface " "version") + _(b"unable to determine mtn automate interface " b"version") ) if version >= 12.0: self.automatestdio = True self.ui.debug( - "mtn automate version %f - using automate stdio\n" % version + b"mtn automate version %f - using automate stdio\n" % version ) # launch the long-running automate stdio process self.mtnwritefp, self.mtnreadfp = self._run2( - "automate", "stdio", "-d", self.path + b"automate", b"stdio", b"-d", self.path ) # read the headers read = self.mtnreadfp.readline() - if read != "format-version: 2\n": + if read != b"format-version: 2\n": raise error.Abort( - _("mtn automate stdio header unexpected: %s") % read + _(b"mtn automate stdio header unexpected: %s") % read ) - while read != "\n": + while read != b"\n": read = self.mtnreadfp.readline() if not read: raise error.Abort( _( - "failed to reach end of mtn automate " - "stdio headers" + b"failed to reach end of mtn automate " + b"stdio headers" ) ) else: self.ui.debug( - "mtn automate version %s - not using automate stdio " - "(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version + b"mtn automate version %s - not using automate stdio " + b"(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version ) def after(self): diff --git a/hgext/convert/p4.py b/hgext/convert/p4.py --- a/hgext/convert/p4.py +++ b/hgext/convert/p4.py @@ -24,7 +24,7 @@ def loaditer(f): - "Yield the dictionary objects generated by p4" + b"Yield the dictionary objects generated by p4" try: while True: d = marshal.load(f) @@ -44,7 +44,12 @@ >>> decodefilename(b'//Depot/Directory/%2525/%2523/%23%40.%2A') '//Depot/Directory/%25/%23/#@.*' """ - replacements = [("%2A", "*"), ("%23", "#"), ("%40", "@"), ("%25", "%")] + replacements = [ + (b"%2A", b"*"), + (b"%23", b"#"), + (b"%40", b"@"), + (b"%25", b"%"), + ] for k, v in replacements: filename = filename.replace(k, v) return filename @@ -57,16 +62,16 @@ super(p4_source, self).__init__(ui, repotype, path, revs=revs) - if "/" in path and not path.startswith("//"): + if b"/" in path and not path.startswith(b"//"): raise common.NoRepo( - _("%s does not look like a P4 repository") % path + _(b"%s does not look like a P4 repository") % path ) - common.checktool("p4", abort=False) + common.checktool(b"p4", abort=False) self.revmap = {} self.encoding = self.ui.config( - "convert", "p4.encoding", convcmd.orig_encoding + b"convert", b"p4.encoding", convcmd.orig_encoding ) self.re_type = re.compile( br"([a-z]+)?(text|binary|symlink|apple|resource|unicode|utf\d+)" @@ -80,7 +85,10 @@ if revs and len(revs) > 1: raise error.Abort( - _("p4 source does not support specifying " "multiple revisions") + _( + b"p4 source does not support specifying " + b"multiple revisions" + ) ) def setrevmap(self, revmap): @@ -97,18 +105,18 @@ self.revmap = revmap def _parse_view(self, path): - "Read changes affecting the path" - cmd = "p4 -G changes -s submitted %s" % procutil.shellquote(path) - stdout = procutil.popen(cmd, mode="rb") + b"Read changes affecting the path" + cmd = b"p4 -G changes -s submitted %s" % procutil.shellquote(path) + stdout = procutil.popen(cmd, mode=b"rb") p4changes = {} for d in loaditer(stdout): - c = d.get("change", None) + c = d.get(b"change", None) if c: p4changes[c] = True return p4changes def _parse(self, ui, path): - "Prepare list of P4 filenames and revisions to import" + b"Prepare list of P4 filenames and revisions to import" p4changes = {} changeset = {} files_map = {} @@ -117,29 +125,29 @@ depotname = {} heads = [] - ui.status(_("reading p4 views\n")) + ui.status(_(b"reading p4 views\n")) # read client spec or view - if "/" in path: + if b"/" in path: p4changes.update(self._parse_view(path)) - if path.startswith("//") and path.endswith("/..."): - views = {path[:-3]: ""} + if path.startswith(b"//") and path.endswith(b"/..."): + views = {path[:-3]: b""} else: - views = {"//": ""} + views = {b"//": b""} else: - cmd = "p4 -G client -o %s" % procutil.shellquote(path) - clientspec = marshal.load(procutil.popen(cmd, mode="rb")) + cmd = b"p4 -G client -o %s" % procutil.shellquote(path) + clientspec = marshal.load(procutil.popen(cmd, mode=b"rb")) views = {} for client in clientspec: - if client.startswith("View"): + if client.startswith(b"View"): sview, cview = clientspec[client].split() p4changes.update(self._parse_view(sview)) - if sview.endswith("...") and cview.endswith("..."): + if sview.endswith(b"...") and cview.endswith(b"..."): sview = sview[:-3] cview = cview[:-3] cview = cview[2:] - cview = cview[cview.find("/") + 1 :] + cview = cview[cview.find(b"/") + 1 :] views[sview] = cview # list of changes that affect our source files @@ -151,10 +159,10 @@ vieworder.sort(key=len, reverse=True) # handle revision limiting - startrev = self.ui.config("convert", "p4.startrev") + startrev = self.ui.config(b"convert", b"p4.startrev") # now read the full changelists to get the list of file revisions - ui.status(_("collecting p4 changelists\n")) + ui.status(_(b"collecting p4 changelists\n")) lastid = None for change in p4changes: if startrev and int(change) < int(startrev): @@ -176,28 +184,28 @@ descarr = c.desc.splitlines(True) if len(descarr) > 0: - shortdesc = descarr[0].rstrip("\r\n") + shortdesc = descarr[0].rstrip(b"\r\n") else: - shortdesc = "**empty changelist description**" + shortdesc = b"**empty changelist description**" - t = "%s %s" % (c.rev, repr(shortdesc)[1:-1]) - ui.status(stringutil.ellipsis(t, 80) + "\n") + t = b"%s %s" % (c.rev, repr(shortdesc)[1:-1]) + ui.status(stringutil.ellipsis(t, 80) + b"\n") files = [] copies = {} copiedfiles = [] i = 0 - while ("depotFile%d" % i) in d and ("rev%d" % i) in d: - oldname = d["depotFile%d" % i] + while (b"depotFile%d" % i) in d and (b"rev%d" % i) in d: + oldname = d[b"depotFile%d" % i] filename = None for v in vieworder: if oldname.lower().startswith(v.lower()): filename = decodefilename(views[v] + oldname[len(v) :]) break if filename: - files.append((filename, d["rev%d" % i])) + files.append((filename, d[b"rev%d" % i])) depotname[filename] = oldname - if d.get("action%d" % i) == "move/add": + if d.get(b"action%d" % i) == b"move/add": copiedfiles.append(filename) localname[oldname] = filename i += 1 @@ -206,23 +214,23 @@ for filename in copiedfiles: oldname = depotname[filename] - flcmd = "p4 -G filelog %s" % procutil.shellquote(oldname) - flstdout = procutil.popen(flcmd, mode="rb") + flcmd = b"p4 -G filelog %s" % procutil.shellquote(oldname) + flstdout = procutil.popen(flcmd, mode=b"rb") copiedfilename = None for d in loaditer(flstdout): copiedoldname = None i = 0 - while ("change%d" % i) in d: + while (b"change%d" % i) in d: if ( - d["change%d" % i] == change - and d["action%d" % i] == "move/add" + d[b"change%d" % i] == change + and d[b"action%d" % i] == b"move/add" ): j = 0 - while ("file%d,%d" % (i, j)) in d: - if d["how%d,%d" % (i, j)] == "moved from": - copiedoldname = d["file%d,%d" % (i, j)] + while (b"file%d,%d" % (i, j)) in d: + if d[b"how%d,%d" % (i, j)] == b"moved from": + copiedoldname = d[b"file%d,%d" % (i, j)] break j += 1 i += 1 @@ -235,7 +243,7 @@ copies[filename] = copiedfilename else: ui.warn( - _("cannot find source for copied file: %s@%s\n") + _(b"cannot find source for copied file: %s@%s\n") % (filename, change) ) @@ -248,11 +256,11 @@ heads = [lastid] return { - "changeset": changeset, - "files": files_map, - "copies": copies_map, - "heads": heads, - "depotname": depotname, + b"changeset": changeset, + b"files": files_map, + b"copies": copies_map, + b"heads": heads, + b"depotname": depotname, } @util.propertycache @@ -261,74 +269,74 @@ @util.propertycache def copies(self): - return self._parse_once["copies"] + return self._parse_once[b"copies"] @util.propertycache def files(self): - return self._parse_once["files"] + return self._parse_once[b"files"] @util.propertycache def changeset(self): - return self._parse_once["changeset"] + return self._parse_once[b"changeset"] @util.propertycache def heads(self): - return self._parse_once["heads"] + return self._parse_once[b"heads"] @util.propertycache def depotname(self): - return self._parse_once["depotname"] + return self._parse_once[b"depotname"] def getheads(self): return self.heads def getfile(self, name, rev): - cmd = "p4 -G print %s" % procutil.shellquote( - "%s#%s" % (self.depotname[name], rev) + cmd = b"p4 -G print %s" % procutil.shellquote( + b"%s#%s" % (self.depotname[name], rev) ) lasterror = None while True: - stdout = procutil.popen(cmd, mode="rb") + stdout = procutil.popen(cmd, mode=b"rb") mode = None contents = [] keywords = None for d in loaditer(stdout): - code = d["code"] - data = d.get("data") + code = d[b"code"] + data = d.get(b"data") - if code == "error": + if code == b"error": # if this is the first time error happened # re-attempt getting the file if not lasterror: - lasterror = IOError(d["generic"], data) + lasterror = IOError(d[b"generic"], data) # this will exit inner-most for-loop break else: raise lasterror - elif code == "stat": - action = d.get("action") - if action in ["purge", "delete", "move/delete"]: + elif code == b"stat": + action = d.get(b"action") + if action in [b"purge", b"delete", b"move/delete"]: return None, None - p4type = self.re_type.match(d["type"]) + p4type = self.re_type.match(d[b"type"]) if p4type: - mode = "" - flags = (p4type.group(1) or "") + ( - p4type.group(3) or "" + mode = b"" + flags = (p4type.group(1) or b"") + ( + p4type.group(3) or b"" ) - if "x" in flags: - mode = "x" - if p4type.group(2) == "symlink": - mode = "l" - if "ko" in flags: + if b"x" in flags: + mode = b"x" + if p4type.group(2) == b"symlink": + mode = b"l" + if b"ko" in flags: keywords = self.re_keywords_old - elif "k" in flags: + elif b"k" in flags: keywords = self.re_keywords - elif code == "text" or code == "binary": + elif code == b"text" or code == b"binary": contents.append(data) lasterror = None @@ -339,18 +347,18 @@ if mode is None: return None, None - contents = "".join(contents) + contents = b"".join(contents) if keywords: - contents = keywords.sub("$\\1$", contents) - if mode == "l" and contents.endswith("\n"): + contents = keywords.sub(b"$\\1$", contents) + if mode == b"l" and contents.endswith(b"\n"): contents = contents[:-1] return contents, mode def getchanges(self, rev, full): if full: - raise error.Abort(_("convert from p4 does not support --full")) + raise error.Abort(_(b"convert from p4 does not support --full")) return self.files[rev], self.copies[rev], set() def _construct_commit(self, obj, parents=None): @@ -358,26 +366,26 @@ Constructs a common.commit object from an unmarshalled `p4 describe` output """ - desc = self.recode(obj.get("desc", "")) - date = (int(obj["time"]), 0) # timezone not set + desc = self.recode(obj.get(b"desc", b"")) + date = (int(obj[b"time"]), 0) # timezone not set if parents is None: parents = [] return common.commit( - author=self.recode(obj["user"]), - date=dateutil.datestr(date, "%Y-%m-%d %H:%M:%S %1%2"), + author=self.recode(obj[b"user"]), + date=dateutil.datestr(date, b"%Y-%m-%d %H:%M:%S %1%2"), parents=parents, desc=desc, branch=None, - rev=obj["change"], - extra={"p4": obj["change"], "convert_revision": obj["change"]}, + rev=obj[b"change"], + extra={b"p4": obj[b"change"], b"convert_revision": obj[b"change"]}, ) def _fetch_revision(self, rev): """Return an output of `p4 describe` including author, commit date as a dictionary.""" - cmd = "p4 -G describe -s %s" % rev - stdout = procutil.popen(cmd, mode="rb") + cmd = b"p4 -G describe -s %s" % rev + stdout = procutil.popen(cmd, mode=b"rb") return marshal.load(stdout) def getcommit(self, rev): @@ -387,7 +395,7 @@ d = self._fetch_revision(rev) return self._construct_commit(d, parents=None) raise error.Abort( - _("cannot find %s in the revmap or parsed changesets") % rev + _(b"cannot find %s in the revmap or parsed changesets") % rev ) def gettags(self): diff --git a/hgext/convert/subversion.py b/hgext/convert/subversion.py --- a/hgext/convert/subversion.py +++ b/hgext/convert/subversion.py @@ -54,7 +54,7 @@ import warnings warnings.filterwarnings( - "ignore", module="svn.core", category=DeprecationWarning + b"ignore", module=b"svn.core", category=DeprecationWarning ) svn.core.SubversionException # trigger import to catch error @@ -80,16 +80,16 @@ >>> revsplit(b'bad') ('', '', 0) """ - parts = rev.rsplit("@", 1) + parts = rev.rsplit(b"@", 1) revnum = 0 if len(parts) > 1: revnum = int(parts[1]) - parts = parts[0].split("/", 1) - uuid = "" - mod = "" - if len(parts) > 1 and parts[0].startswith("svn:"): + parts = parts[0].split(b"/", 1) + uuid = b"" + mod = b"" + if len(parts) > 1 and parts[0].startswith(b"svn:"): uuid = parts[0][4:] - mod = "/" + parts[1] + mod = b"/" + parts[1] return uuid, mod, revnum @@ -101,7 +101,7 @@ # so we can extend it safely with new components. The "safe" # characters were taken from the "svn_uri__char_validity" table in # libsvn_subr/path.c. - return urlreq.quote(s, "!$&'()*+,-./:=@_~") + return urlreq.quote(s, b"!$&'()*+,-./:=@_~") def geturl(path): @@ -113,11 +113,11 @@ if os.path.isdir(path): path = os.path.normpath(os.path.abspath(path)) if pycompat.iswindows: - path = "/" + util.normpath(path) + path = b"/" + util.normpath(path) # Module URL is later compared with the repository URL returned # by svn API, which is UTF-8. path = encoding.tolocal(path) - path = "file://%s" % quote(path) + path = b"file://%s" % quote(path) return svn.core.svn_path_canonicalize(path) @@ -188,7 +188,7 @@ """ if svn is None: raise error.Abort( - _("debugsvnlog could not load Subversion python " "bindings") + _(b"debugsvnlog could not load Subversion python " b"bindings") ) args = decodeargs(ui.fin.read()) @@ -208,8 +208,8 @@ except EOFError: raise error.Abort( _( - "Mercurial failed to run itself, check" - " hg executable is in PATH" + b"Mercurial failed to run itself, check" + b" hg executable is in PATH" ) ) try: @@ -217,7 +217,7 @@ except (TypeError, ValueError): if entry is None: break - raise error.Abort(_("log stream exception '%s'") % entry) + raise error.Abort(_(b"log stream exception '%s'") % entry) yield entry def close(self): @@ -270,7 +270,7 @@ # looking for several svn-specific files and directories in the given # directory. def filecheck(ui, path, proto): - for x in ("locks", "hooks", "format", "db"): + for x in (b"locks", b"hooks", b"format", b"db"): if not os.path.exists(os.path.join(path, x)): return False return True @@ -282,16 +282,16 @@ def httpcheck(ui, path, proto): try: opener = urlreq.buildopener() - rsp = opener.open("%s://%s/!svn/ver/0/.svn" % (proto, path), "rb") + rsp = opener.open(b"%s://%s/!svn/ver/0/.svn" % (proto, path), b"rb") data = rsp.read() except urlerr.httperror as inst: if inst.code != 404: # Except for 404 we cannot know for sure this is not an svn repo ui.warn( _( - "svn: cannot probe remote repository, assume it could " - "be a subversion repository. Use --source-type if you " - "know better.\n" + b"svn: cannot probe remote repository, assume it could " + b"be a subversion repository. Use --source-type if you " + b"know better.\n" ) ) return True @@ -299,38 +299,38 @@ except Exception: # Could be urlerr.urlerror if the URL is invalid or anything else. return False - return '' in data + return b'' in data protomap = { - "http": httpcheck, - "https": httpcheck, - "file": filecheck, + b"http": httpcheck, + b"https": httpcheck, + b"file": filecheck, } def issvnurl(ui, url): try: - proto, path = url.split("://", 1) - if proto == "file": + proto, path = url.split(b"://", 1) + if proto == b"file": if ( pycompat.iswindows - and path[:1] == "/" + and path[:1] == b"/" and path[1:2].isalpha() - and path[2:6].lower() == "%3a/" + and path[2:6].lower() == b"%3a/" ): - path = path[:2] + ":/" + path[6:] + path = path[:2] + b":/" + path[6:] path = urlreq.url2pathname(path) except ValueError: - proto = "file" + proto = b"file" path = os.path.abspath(url) - if proto == "file": + if proto == b"file": path = util.pconvert(path) check = protomap.get(proto, lambda *args: False) - while "/" in path: + while b"/" in path: if check(ui, path, proto): return True - path = path.rsplit("/", 1)[0] + path = path.rsplit(b"/", 1)[0] return False @@ -353,35 +353,35 @@ super(svn_source, self).__init__(ui, repotype, url, revs=revs) if not ( - url.startswith("svn://") - or url.startswith("svn+ssh://") + url.startswith(b"svn://") + or url.startswith(b"svn+ssh://") or ( os.path.exists(url) - and os.path.exists(os.path.join(url, ".svn")) + and os.path.exists(os.path.join(url, b".svn")) ) or issvnurl(ui, url) ): raise NoRepo( - _("%s does not look like a Subversion repository") % url + _(b"%s does not look like a Subversion repository") % url ) if svn is None: - raise MissingTool(_("could not load Subversion python bindings")) + raise MissingTool(_(b"could not load Subversion python bindings")) try: version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR if version < (1, 4): raise MissingTool( _( - "Subversion python bindings %d.%d found, " - "1.4 or later required" + b"Subversion python bindings %d.%d found, " + b"1.4 or later required" ) % version ) except AttributeError: raise MissingTool( _( - "Subversion python bindings are too old, 1.4 " - "or later required" + b"Subversion python bindings are too old, 1.4 " + b"or later required" ) ) @@ -391,14 +391,14 @@ try: # Support file://path@rev syntax. Useful e.g. to convert # deleted branches. - at = url.rfind("@") + at = url.rfind(b"@") if at >= 0: latest = int(url[at + 1 :]) url = url[:at] except ValueError: pass self.url = geturl(url) - self.encoding = "UTF-8" # Subversion is always nominal UTF-8 + self.encoding = b"UTF-8" # Subversion is always nominal UTF-8 try: self.transport = transport.SvnRaTransport(url=self.url) self.ra = self.transport.ra @@ -414,15 +414,15 @@ self.uuid = svn.ra.get_uuid(self.ra) except svn.core.SubversionException: ui.traceback() - svnversion = "%d.%d.%d" % ( + svnversion = b"%d.%d.%d" % ( svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR, svn.core.SVN_VER_MICRO, ) raise NoRepo( _( - "%s does not look like a Subversion repository " - "to libsvn version %s" + b"%s does not look like a Subversion repository " + b"to libsvn version %s" ) % (self.url, svnversion) ) @@ -431,29 +431,29 @@ if len(revs) > 1: raise error.Abort( _( - "subversion source does not support " - "specifying multiple revisions" + b"subversion source does not support " + b"specifying multiple revisions" ) ) try: latest = int(revs[0]) except ValueError: raise error.Abort( - _("svn: revision %s is not an integer") % revs[0] + _(b"svn: revision %s is not an integer") % revs[0] ) - trunkcfg = self.ui.config("convert", "svn.trunk") + trunkcfg = self.ui.config(b"convert", b"svn.trunk") if trunkcfg is None: - trunkcfg = "trunk" - self.trunkname = trunkcfg.strip("/") - self.startrev = self.ui.config("convert", "svn.startrev") + trunkcfg = b"trunk" + self.trunkname = trunkcfg.strip(b"/") + self.startrev = self.ui.config(b"convert", b"svn.startrev") try: self.startrev = int(self.startrev) if self.startrev < 0: self.startrev = 0 except ValueError: raise error.Abort( - _("svn: start revision %s is not an integer") % self.startrev + _(b"svn: start revision %s is not an integer") % self.startrev ) try: @@ -461,12 +461,14 @@ except SvnPathNotFound: self.head = None if not self.head: - raise error.Abort(_("no revision found in module %s") % self.module) + raise error.Abort( + _(b"no revision found in module %s") % self.module + ) self.last_changed = self.revnum(self.head) self._changescache = (None, None) - if os.path.exists(os.path.join(url, ".svn/entries")): + if os.path.exists(os.path.join(url, b".svn/entries")): self.wc = url else: self.wc = None @@ -484,7 +486,7 @@ def exists(self, path, optrev): try: svn.client.ls( - self.url.rstrip("/") + "/" + quote(path), + self.url.rstrip(b"/") + b"/" + quote(path), optrev, False, self.ctx, @@ -499,61 +501,62 @@ return kind == svn.core.svn_node_dir def getcfgpath(name, rev): - cfgpath = self.ui.config("convert", "svn." + name) - if cfgpath is not None and cfgpath.strip() == "": + cfgpath = self.ui.config(b"convert", b"svn." + name) + if cfgpath is not None and cfgpath.strip() == b"": return None - path = (cfgpath or name).strip("/") + path = (cfgpath or name).strip(b"/") if not self.exists(path, rev): - if self.module.endswith(path) and name == "trunk": + if self.module.endswith(path) and name == b"trunk": # we are converting from inside this directory return None if cfgpath: raise error.Abort( - _("expected %s to be at %r, but not found") + _(b"expected %s to be at %r, but not found") % (name, path) ) return None - self.ui.note(_("found %s at %r\n") % (name, path)) + self.ui.note(_(b"found %s at %r\n") % (name, path)) return path rev = optrev(self.last_changed) - oldmodule = "" - trunk = getcfgpath("trunk", rev) - self.tags = getcfgpath("tags", rev) - branches = getcfgpath("branches", rev) + oldmodule = b"" + trunk = getcfgpath(b"trunk", rev) + self.tags = getcfgpath(b"tags", rev) + branches = getcfgpath(b"branches", rev) # If the project has a trunk or branches, we will extract heads # from them. We keep the project root otherwise. if trunk: - oldmodule = self.module or "" - self.module += "/" + trunk + oldmodule = self.module or b"" + self.module += b"/" + trunk self.head = self.latest(self.module, self.last_changed) if not self.head: raise error.Abort( - _("no revision found in module %s") % self.module + _(b"no revision found in module %s") % self.module ) # First head in the list is the module's head self.heads = [self.head] if self.tags is not None: - self.tags = "%s/%s" % (oldmodule, (self.tags or "tags")) + self.tags = b"%s/%s" % (oldmodule, (self.tags or b"tags")) # Check if branches bring a few more heads to the list if branches: - rpath = self.url.strip("/") + rpath = self.url.strip(b"/") branchnames = svn.client.ls( - rpath + "/" + quote(branches), rev, False, self.ctx + rpath + b"/" + quote(branches), rev, False, self.ctx ) for branch in sorted(branchnames): - module = "%s/%s/%s" % (oldmodule, branches, branch) + module = b"%s/%s/%s" % (oldmodule, branches, branch) if not isdir(module, self.last_changed): continue brevid = self.latest(module, self.last_changed) if not brevid: - self.ui.note(_("ignoring empty branch %s\n") % branch) + self.ui.note(_(b"ignoring empty branch %s\n") % branch) continue self.ui.note( - _("found branch %s at %d\n") % (branch, self.revnum(brevid)) + _(b"found branch %s at %d\n") + % (branch, self.revnum(brevid)) ) self.heads.append(brevid) @@ -561,14 +564,14 @@ if len(self.heads) > 1: raise error.Abort( _( - "svn: start revision is not supported " - "with more than one branch" + b"svn: start revision is not supported " + b"with more than one branch" ) ) revnum = self.revnum(self.heads[0]) if revnum < self.startrev: raise error.Abort( - _("svn: no revision found after start revision %d") + _(b"svn: no revision found after start revision %d") % self.startrev ) @@ -628,13 +631,13 @@ stop = revnum + 1 self._fetch_revisions(revnum, stop) if rev not in self.commits: - raise error.Abort(_("svn: revision %s not found") % revnum) + raise error.Abort(_(b"svn: revision %s not found") % revnum) revcommit = self.commits[rev] # caller caches the result, so free it here to release memory del self.commits[rev] return revcommit - def checkrevformat(self, revstr, mapname="splicemap"): + def checkrevformat(self, revstr, mapname=b"splicemap"): """ fails if revision format does not match the correct format""" if not re.match( r"svn:[0-9a-f]{8,8}-[0-9a-f]{4,4}-" @@ -643,12 +646,12 @@ revstr, ): raise error.Abort( - _("%s entry %s is not a valid revision" " identifier") + _(b"%s entry %s is not a valid revision" b" identifier") % (mapname, revstr) ) def numcommits(self): - return int(self.head.rsplit("@", 1)[1]) - self.startrev + return int(self.head.rsplit(b"@", 1)[1]) - self.startrev def gettags(self): tags = {} @@ -689,7 +692,7 @@ srctagspath = copies.pop()[0] for source, sourcerev, dest in copies: - if not dest.startswith(tagspath + "/"): + if not dest.startswith(tagspath + b"/"): continue for tag in pendings: if tag[0].startswith(dest): @@ -709,14 +712,14 @@ addeds = dict( (p, e.copyfrom_path) for p, e in origpaths.iteritems() - if e.action == "A" and e.copyfrom_path + if e.action == b"A" and e.copyfrom_path ) badroots = set() for destroot in addeds: for source, sourcerev, dest in pendings: if not dest.startswith( - destroot + "/" - ) or source.startswith(addeds[destroot] + "/"): + destroot + b"/" + ) or source.startswith(addeds[destroot] + b"/"): continue badroots.add(destroot) break @@ -726,13 +729,13 @@ p for p in pendings if p[2] != badroot - and not p[2].startswith(badroot + "/") + and not p[2].startswith(badroot + b"/") ] # Tell tag renamings from tag creations renamings = [] for source, sourcerev, dest in pendings: - tagname = dest.split("/")[-1] + tagname = dest.split(b"/")[-1] if source.startswith(srctagspath): renamings.append([source, sourcerev, tagname]) continue @@ -761,18 +764,18 @@ return if self.convertfp is None: self.convertfp = open( - os.path.join(self.wc, ".svn", "hg-shamap"), "ab" + os.path.join(self.wc, b".svn", b"hg-shamap"), b"ab" ) self.convertfp.write( - util.tonativeeol("%s %d\n" % (destrev, self.revnum(rev))) + util.tonativeeol(b"%s %d\n" % (destrev, self.revnum(rev))) ) self.convertfp.flush() def revid(self, revnum, module=None): - return "svn:%s%s@%s" % (self.uuid, module or self.module, revnum) + return b"svn:%s%s@%s" % (self.uuid, module or self.module, revnum) def revnum(self, rev): - return int(rev.split("@")[-1]) + return int(rev.split(b"@")[-1]) def latest(self, path, stop=None): """Find the latest revid affecting path, up to stop revision @@ -800,7 +803,7 @@ continue newpath = paths[p].copyfrom_path + path[len(p) :] self.ui.debug( - "branch renamed from %s to %s at %d\n" + b"branch renamed from %s to %s at %d\n" % (path, newpath, revnum) ) path = newpath @@ -813,20 +816,20 @@ if not path.startswith(self.rootmodule): # Requests on foreign branches may be forbidden at server level - self.ui.debug("ignoring foreign branch %r\n" % path) + self.ui.debug(b"ignoring foreign branch %r\n" % path) return None if stop is None: stop = svn.ra.get_latest_revnum(self.ra) try: - prevmodule = self.reparent("") - dirent = svn.ra.stat(self.ra, path.strip("/"), stop) + prevmodule = self.reparent(b"") + dirent = svn.ra.stat(self.ra, path.strip(b"/"), stop) self.reparent(prevmodule) except svn.core.SubversionException: dirent = None if not dirent: raise SvnPathNotFound( - _("%s not found up to revision %d") % (path, stop) + _(b"%s not found up to revision %d") % (path, stop) ) # stat() gives us the previous revision on this line of @@ -843,11 +846,11 @@ # the whole history. revnum, realpath = findchanges(path, stop) if revnum is None: - self.ui.debug("ignoring empty branch %r\n" % realpath) + self.ui.debug(b"ignoring empty branch %r\n" % realpath) return None if not realpath.startswith(self.rootmodule): - self.ui.debug("ignoring foreign branch %r\n" % realpath) + self.ui.debug(b"ignoring foreign branch %r\n" % realpath) return None return self.revid(revnum, realpath) @@ -858,8 +861,8 @@ svnurl = self.baseurl + quote(module) prevmodule = self.prevmodule if prevmodule is None: - prevmodule = "" - self.ui.debug("reparent to %s\n" % svnurl) + prevmodule = b"" + self.ui.debug(b"reparent to %s\n" % svnurl) svn.ra.reparent(self.ra, svnurl) self.prevmodule = module return prevmodule @@ -874,7 +877,7 @@ self.reparent(self.module) progress = self.ui.makeprogress( - _("scanning paths"), unit=_("paths"), total=len(paths) + _(b"scanning paths"), unit=_(b"paths"), total=len(paths) ) for i, (path, ent) in enumerate(paths): progress.update(i, item=path) @@ -894,37 +897,37 @@ if not copyfrom_path: continue self.ui.debug( - "copied to %s from %s@%s\n" + b"copied to %s from %s@%s\n" % (entrypath, copyfrom_path, ent.copyfrom_rev) ) copies[self.recode(entrypath)] = self.recode(copyfrom_path) elif kind == 0: # gone, but had better be a deleted *file* - self.ui.debug("gone from %s\n" % ent.copyfrom_rev) + self.ui.debug(b"gone from %s\n" % ent.copyfrom_rev) pmodule, prevnum = revsplit(parents[0])[1:] - parentpath = pmodule + "/" + entrypath + parentpath = pmodule + b"/" + entrypath fromkind = self._checkpath(entrypath, prevnum, pmodule) if fromkind == svn.core.svn_node_file: removed.add(self.recode(entrypath)) elif fromkind == svn.core.svn_node_dir: - oroot = parentpath.strip("/") - nroot = path.strip("/") + oroot = parentpath.strip(b"/") + nroot = path.strip(b"/") children = self._iterfiles(oroot, prevnum) for childpath in children: childpath = childpath.replace(oroot, nroot) - childpath = self.getrelpath("/" + childpath, pmodule) + childpath = self.getrelpath(b"/" + childpath, pmodule) if childpath: removed.add(self.recode(childpath)) else: self.ui.debug( - "unknown path in revision %d: %s\n" % (revnum, path) + b"unknown path in revision %d: %s\n" % (revnum, path) ) elif kind == svn.core.svn_node_dir: - if ent.action == "M": + if ent.action == b"M": # If the directory just had a prop change, # then we shouldn't need to look for its children. continue - if ent.action == "R" and parents: + if ent.action == b"R" and parents: # If a directory is replacing a file, mark the previous # file as deleted pmodule, prevnum = revsplit(parents[0])[1:] @@ -935,12 +938,12 @@ # We do not know what files were kept or removed, # mark them all as changed. for childpath in self._iterfiles(pmodule, prevnum): - childpath = self.getrelpath("/" + childpath) + childpath = self.getrelpath(b"/" + childpath) if childpath: changed.add(self.recode(childpath)) for childpath in self._iterfiles(path, revnum): - childpath = self.getrelpath("/" + childpath) + childpath = self.getrelpath(b"/" + childpath) if childpath: changed.add(self.recode(childpath)) @@ -956,12 +959,12 @@ if not copyfrompath: continue self.ui.debug( - "mark %s came from %s:%d\n" + b"mark %s came from %s:%d\n" % (path, copyfrompath, ent.copyfrom_rev) ) children = self._iterfiles(ent.copyfrom_path, ent.copyfrom_rev) for childpath in children: - childpath = self.getrelpath("/" + childpath, pmodule) + childpath = self.getrelpath(b"/" + childpath, pmodule) if not childpath: continue copytopath = path + childpath[len(copyfrompath) :] @@ -983,7 +986,8 @@ the revision is a branch root. """ self.ui.debug( - "parsing revision %d (%d changes)\n" % (revnum, len(orig_paths)) + b"parsing revision %d (%d changes)\n" + % (revnum, len(orig_paths)) ) branched = False @@ -1012,11 +1016,11 @@ if prevnum >= self.startrev: parents = [previd] self.ui.note( - _("found parent of branch %s at %d: %s\n") + _(b"found parent of branch %s at %d: %s\n") % (self.module, prevnum, prevmodule) ) else: - self.ui.debug("no copyfrom path, don't know what to do.\n") + self.ui.debug(b"no copyfrom path, don't know what to do.\n") paths = [] # filter out unrelated paths @@ -1028,22 +1032,24 @@ # Example SVN datetime. Includes microseconds. # ISO-8601 conformant # '2007-01-04T17:35:00.902377Z' - date = dateutil.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"]) - if self.ui.configbool("convert", "localtimezone"): + date = dateutil.parsedate( + date[:19] + b" UTC", [b"%Y-%m-%dT%H:%M:%S"] + ) + if self.ui.configbool(b"convert", b"localtimezone"): date = makedatetimestamp(date[0]) if message: log = self.recode(message) else: - log = "" + log = b"" if author: author = self.recode(author) else: - author = "" + author = b"" try: - branch = self.module.split("/")[-1] + branch = self.module.split(b"/")[-1] if branch == self.trunkname: branch = None except IndexError: @@ -1051,7 +1057,7 @@ cset = commit( author=author, - date=dateutil.datestr(date, "%Y-%m-%d %H:%M:%S %1%2"), + date=dateutil.datestr(date, b"%Y-%m-%d %H:%M:%S %1%2"), desc=log, parents=parents, branch=branch, @@ -1068,7 +1074,7 @@ return cset, branched self.ui.note( - _('fetching revision log for "%s" from %d to %d\n') + _(b'fetching revision log for "%s" from %d to %d\n') % (self.module, from_revnum, to_revnum) ) @@ -1083,7 +1089,7 @@ lastonbranch = True break if not paths: - self.ui.debug("revision %d has no entries\n" % revnum) + self.ui.debug(b"revision %d has no entries\n" % revnum) # If we ever leave the loop on an empty # revision, do not try to get a parent branch lastonbranch = lastonbranch or revnum == 0 @@ -1114,7 +1120,7 @@ (inst, num) = xxx_todo_changeme.args if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION: raise error.Abort( - _("svn: branch has no revision %s") % to_revnum + _(b"svn: branch has no revision %s") % to_revnum ) raise @@ -1135,8 +1141,8 @@ io.close() if isinstance(info, list): info = info[-1] - mode = ("svn:executable" in info) and "x" or "" - mode = ("svn:special" in info) and "l" or mode + mode = (b"svn:executable" in info) and b"x" or b"" + mode = (b"svn:special" in info) and b"l" or mode except svn.core.SubversionException as e: notfound = ( svn.core.SVN_ERR_FS_NOT_FOUND, @@ -1145,20 +1151,20 @@ if e.apr_err in notfound: # File not found return None, None raise - if mode == "l": - link_prefix = "link " + if mode == b"l": + link_prefix = b"link " if data.startswith(link_prefix): data = data[len(link_prefix) :] return data, mode def _iterfiles(self, path, revnum): """Enumerate all files in path at revnum, recursively.""" - path = path.strip("/") + path = path.strip(b"/") pool = svn.core.Pool() - rpath = "/".join([self.baseurl, quote(path)]).strip("/") + rpath = b"/".join([self.baseurl, quote(path)]).strip(b"/") entries = svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool) if path: - path += "/" + path += b"/" return ( (path + p) for p, e in entries.iteritems() @@ -1175,24 +1181,24 @@ # "/CMFPlone/branches/Plone-2_0-branch/tests/PloneTestCase.py" # that is to say "tests/PloneTestCase.py" if path.startswith(module): - relative = path.rstrip("/")[len(module) :] - if relative.startswith("/"): + relative = path.rstrip(b"/")[len(module) :] + if relative.startswith(b"/"): return relative[1:] - elif relative == "": + elif relative == b"": return relative # The path is outside our tracked tree... - self.ui.debug("%r is not under %r, ignoring\n" % (path, module)) + self.ui.debug(b"%r is not under %r, ignoring\n" % (path, module)) return None def _checkpath(self, path, revnum, module=None): if module is not None: - prevmodule = self.reparent("") - path = module + "/" + path + prevmodule = self.reparent(b"") + path = module + b"/" + path try: # ra.check_path does not like leading slashes very much, it leads # to PROPFIND subversion errors - return svn.ra.check_path(self.ra, path.strip("/"), revnum) + return svn.ra.check_path(self.ra, path.strip(b"/"), revnum) finally: if module is not None: self.reparent(prevmodule) @@ -1210,9 +1216,9 @@ # supplied URL relpaths = [] for p in paths: - if not p.startswith("/"): - p = self.module + "/" + p - relpaths.append(p.strip("/")) + if not p.startswith(b"/"): + p = self.module + b"/" + p + relpaths.append(p.strip(b"/")) args = [ self.baseurl, relpaths, @@ -1223,11 +1229,11 @@ strict_node_history, ] # developer config: convert.svn.debugsvnlog - if not self.ui.configbool("convert", "svn.debugsvnlog"): + if not self.ui.configbool(b"convert", b"svn.debugsvnlog"): return directlogstream(*args) arg = encodeargs(args) hgexe = procutil.hgexecutable() - cmd = "%s debugsvnlog" % procutil.shellquote(hgexe) + cmd = b"%s debugsvnlog" % procutil.shellquote(hgexe) stdin, stdout = procutil.popen2(procutil.quotecommand(cmd)) stdin.write(arg) try: @@ -1235,8 +1241,8 @@ except IOError: raise error.Abort( _( - "Mercurial failed to run itself, check" - " hg executable is in PATH" + b"Mercurial failed to run itself, check" + b" hg executable is in PATH" ) ) return logstream(stdout) @@ -1272,18 +1278,18 @@ os.chdir(self.cwd) def join(self, name): - return os.path.join(self.wc, ".svn", name) + return os.path.join(self.wc, b".svn", name) def revmapfile(self): - return self.join("hg-shamap") + return self.join(b"hg-shamap") def authorfile(self): - return self.join("hg-authormap") + return self.join(b"hg-authormap") def __init__(self, ui, repotype, path): converter_sink.__init__(self, ui, repotype, path) - commandline.__init__(self, ui, "svn") + commandline.__init__(self, ui, b"svn") self.delete = [] self.setexec = [] self.delexec = [] @@ -1292,51 +1298,53 @@ self.cwd = encoding.getcwd() created = False - if os.path.isfile(os.path.join(path, ".svn", "entries")): + if os.path.isfile(os.path.join(path, b".svn", b"entries")): self.wc = os.path.realpath(path) - self.run0("update") + self.run0(b"update") else: if not re.search(br"^(file|http|https|svn|svn\+ssh)\://", path): path = os.path.realpath(path) if os.path.isdir(os.path.dirname(path)): - if not os.path.exists(os.path.join(path, "db", "fs-type")): + if not os.path.exists( + os.path.join(path, b"db", b"fs-type") + ): ui.status( - _("initializing svn repository '%s'\n") + _(b"initializing svn repository '%s'\n") % os.path.basename(path) ) - commandline(ui, "svnadmin").run0("create", path) + commandline(ui, b"svnadmin").run0(b"create", path) created = path path = util.normpath(path) - if not path.startswith("/"): - path = "/" + path - path = "file://" + path + if not path.startswith(b"/"): + path = b"/" + path + path = b"file://" + path wcpath = os.path.join( - encoding.getcwd(), os.path.basename(path) + "-wc" + encoding.getcwd(), os.path.basename(path) + b"-wc" ) ui.status( - _("initializing svn working copy '%s'\n") + _(b"initializing svn working copy '%s'\n") % os.path.basename(wcpath) ) - self.run0("checkout", path, wcpath) + self.run0(b"checkout", path, wcpath) self.wc = wcpath self.opener = vfsmod.vfs(self.wc) self.wopener = vfsmod.vfs(self.wc) - self.childmap = mapfile(ui, self.join("hg-childmap")) + self.childmap = mapfile(ui, self.join(b"hg-childmap")) if util.checkexec(self.wc): self.is_exec = util.isexec else: self.is_exec = None if created: - hook = os.path.join(created, "hooks", "pre-revprop-change") - fp = open(hook, "wb") + hook = os.path.join(created, b"hooks", b"pre-revprop-change") + fp = open(hook, b"wb") fp.write(pre_revprop_change) fp.close() util.setflags(hook, False, True) - output = self.run0("info") + output = self.run0(b"info") self.uuid = self.uuid_re.search(output).group(1).strip() def wjoin(self, *names): @@ -1348,7 +1356,7 @@ # already tracked entries, so we have to track and filter them # ourselves. m = set() - output = self.run0("ls", recursive=True, xml=True) + output = self.run0(b"ls", recursive=True, xml=True) doc = xml.dom.minidom.parseString(output) for e in doc.getElementsByTagName(r"entry"): for n in e.childNodes: @@ -1367,7 +1375,7 @@ return m def putfile(self, filename, flags, data): - if "l" in flags: + if b"l" in flags: self.wopener.symlink(data, filename) else: try: @@ -1387,12 +1395,12 @@ if self.is_exec: if wasexec: - if "x" not in flags: + if b"x" not in flags: self.delexec.append(filename) else: - if "x" in flags: + if b"x" in flags: self.setexec.append(filename) - util.setflags(self.wjoin(filename), False, "x" in flags) + util.setflags(self.wjoin(filename), False, b"x" in flags) def _copyfile(self, source, dest): # SVN's copy command pukes if the destination file exists, but @@ -1402,13 +1410,13 @@ exists = os.path.lexists(wdest) if exists: fd, tempname = pycompat.mkstemp( - prefix="hg-copy-", dir=os.path.dirname(wdest) + prefix=b"hg-copy-", dir=os.path.dirname(wdest) ) os.close(fd) os.unlink(tempname) os.rename(wdest, tempname) try: - self.run0("copy", source, dest) + self.run0(b"copy", source, dest) finally: self.manifest.add(dest) if exists: @@ -1424,7 +1432,7 @@ if os.path.isdir(self.wjoin(f)): dirs.add(f) i = len(f) - for i in iter(lambda: f.rfind("/", 0, i), -1): + for i in iter(lambda: f.rfind(b"/", 0, i), -1): dirs.add(f[:i]) return dirs @@ -1434,21 +1442,21 @@ ] if add_dirs: self.manifest.update(add_dirs) - self.xargs(add_dirs, "add", non_recursive=True, quiet=True) + self.xargs(add_dirs, b"add", non_recursive=True, quiet=True) return add_dirs def add_files(self, files): files = [f for f in files if f not in self.manifest] if files: self.manifest.update(files) - self.xargs(files, "add", quiet=True) + self.xargs(files, b"add", quiet=True) return files def addchild(self, parent, child): self.childmap[parent] = child def revid(self, rev): - return "svn:%s@%s" % (self.uuid, rev) + return b"svn:%s@%s" % (self.uuid, rev) def putcommit( self, files, copies, parents, commit, source, revmap, full, cleanp2 @@ -1480,49 +1488,49 @@ self._copyfile(s, d) self.copies = [] if self.delete: - self.xargs(self.delete, "delete") + self.xargs(self.delete, b"delete") for f in self.delete: self.manifest.remove(f) self.delete = [] entries.update(self.add_files(files.difference(entries))) if self.delexec: - self.xargs(self.delexec, "propdel", "svn:executable") + self.xargs(self.delexec, b"propdel", b"svn:executable") self.delexec = [] if self.setexec: - self.xargs(self.setexec, "propset", "svn:executable", "*") + self.xargs(self.setexec, b"propset", b"svn:executable", b"*") self.setexec = [] - fd, messagefile = pycompat.mkstemp(prefix="hg-convert-") + fd, messagefile = pycompat.mkstemp(prefix=b"hg-convert-") fp = os.fdopen(fd, r"wb") fp.write(util.tonativeeol(commit.desc)) fp.close() try: output = self.run0( - "commit", + b"commit", username=stringutil.shortuser(commit.author), file=messagefile, - encoding="utf-8", + encoding=b"utf-8", ) try: rev = self.commit_re.search(output).group(1) except AttributeError: if not files: - return parents[0] if parents else "None" - self.ui.warn(_("unexpected svn output:\n")) + return parents[0] if parents else b"None" + self.ui.warn(_(b"unexpected svn output:\n")) self.ui.warn(output) - raise error.Abort(_("unable to cope with svn output")) + raise error.Abort(_(b"unable to cope with svn output")) if commit.rev: self.run( - "propset", - "hg:convert-rev", + b"propset", + b"hg:convert-rev", commit.rev, revprop=True, revision=rev, ) - if commit.branch and commit.branch != "default": + if commit.branch and commit.branch != b"default": self.run( - "propset", - "hg:convert-branch", + b"propset", + b"hg:convert-branch", commit.branch, revprop=True, revision=rev, @@ -1534,7 +1542,7 @@ os.unlink(messagefile) def puttags(self, tags): - self.ui.warn(_("writing Subversion tags is not yet implemented\n")) + self.ui.warn(_(b"writing Subversion tags is not yet implemented\n")) return None, None def hascommitfrommap(self, rev): @@ -1549,8 +1557,8 @@ return True raise error.Abort( _( - "splice map revision %s not found in subversion " - "child map (revision lookups are not implemented)" + b"splice map revision %s not found in subversion " + b"child map (revision lookups are not implemented)" ) % rev ) diff --git a/hgext/convert/transport.py b/hgext/convert/transport.py --- a/hgext/convert/transport.py +++ b/hgext/convert/transport.py @@ -54,13 +54,13 @@ ) if getprovider: # Available in svn >= 1.6 - for name in ("gnome_keyring", "keychain", "kwallet", "windows"): - for type in ("simple", "ssl_client_cert_pw", "ssl_server_trust"): + for name in (b"gnome_keyring", b"keychain", b"kwallet", b"windows"): + for type in (b"simple", b"ssl_client_cert_pw", b"ssl_server_trust"): p = getprovider(name, type, pool) if p: providers.append(p) else: - if util.safehasattr(svn.client, "get_windows_simple_provider"): + if util.safehasattr(svn.client, b"get_windows_simple_provider"): providers.append(svn.client.get_windows_simple_provider(pool)) return svn.core.svn_auth_open(providers, pool) @@ -75,14 +75,14 @@ Open an ra connection to a Subversion repository. """ - def __init__(self, url="", ra=None): + def __init__(self, url=b"", ra=None): self.pool = Pool() self.svn_url = url - self.username = "" - self.password = "" + self.username = b"" + self.password = b"" # Only Subversion 1.4 has reparent() - if ra is None or not util.safehasattr(svn.ra, "reparent"): + if ra is None or not util.safehasattr(svn.ra, b"reparent"): self.client = svn.client.create_context(self.pool) ab = _create_auth_baton(self.pool) self.client.auth_baton = ab diff --git a/hgext/eol.py b/hgext/eol.py --- a/hgext/eol.py +++ b/hgext/eol.py @@ -112,41 +112,41 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "eol", "fix-trailing-newline", default=False, + b"eol", b"fix-trailing-newline", default=False, ) configitem( - "eol", "native", default=pycompat.oslinesep, + b"eol", b"native", default=pycompat.oslinesep, ) configitem( - "eol", "only-consistent", default=True, + b"eol", b"only-consistent", default=True, ) # Matches a lone LF, i.e., one that is not part of CRLF. -singlelf = re.compile("(^|[^\r])\n") +singlelf = re.compile(b"(^|[^\r])\n") def inconsistenteol(data): - return "\r\n" in data and singlelf.search(data) + return b"\r\n" in data and singlelf.search(data) def tolf(s, params, ui, **kwargs): """Filter to convert to LF EOLs.""" if stringutil.binary(s): return s - if ui.configbool("eol", "only-consistent") and inconsistenteol(s): + if ui.configbool(b"eol", b"only-consistent") and inconsistenteol(s): return s if ( - ui.configbool("eol", "fix-trailing-newline") + ui.configbool(b"eol", b"fix-trailing-newline") and s - and not s.endswith("\n") + and not s.endswith(b"\n") ): - s = s + "\n" + s = s + b"\n" return util.tolf(s) @@ -154,14 +154,14 @@ """Filter to convert to CRLF EOLs.""" if stringutil.binary(s): return s - if ui.configbool("eol", "only-consistent") and inconsistenteol(s): + if ui.configbool(b"eol", b"only-consistent") and inconsistenteol(s): return s if ( - ui.configbool("eol", "fix-trailing-newline") + ui.configbool(b"eol", b"fix-trailing-newline") and s - and not s.endswith("\n") + and not s.endswith(b"\n") ): - s = s + "\n" + s = s + b"\n" return util.tocrlf(s) @@ -171,60 +171,68 @@ filters = { - "to-lf": tolf, - "to-crlf": tocrlf, - "is-binary": isbinary, + b"to-lf": tolf, + b"to-crlf": tocrlf, + b"is-binary": isbinary, # The following provide backwards compatibility with win32text - "cleverencode:": tolf, - "cleverdecode:": tocrlf, + b"cleverencode:": tolf, + b"cleverdecode:": tocrlf, } class eolfile(object): def __init__(self, ui, root, data): - self._decode = {"LF": "to-lf", "CRLF": "to-crlf", "BIN": "is-binary"} - self._encode = {"LF": "to-lf", "CRLF": "to-crlf", "BIN": "is-binary"} + self._decode = { + b"LF": b"to-lf", + b"CRLF": b"to-crlf", + b"BIN": b"is-binary", + } + self._encode = { + b"LF": b"to-lf", + b"CRLF": b"to-crlf", + b"BIN": b"is-binary", + } self.cfg = config.config() # Our files should not be touched. The pattern must be # inserted first override a '** = native' pattern. - self.cfg.set("patterns", ".hg*", "BIN", "eol") + self.cfg.set(b"patterns", b".hg*", b"BIN", b"eol") # We can then parse the user's patterns. - self.cfg.parse(".hgeol", data) + self.cfg.parse(b".hgeol", data) - isrepolf = self.cfg.get("repository", "native") != "CRLF" - self._encode["NATIVE"] = isrepolf and "to-lf" or "to-crlf" - iswdlf = ui.config("eol", "native") in ("LF", "\n") - self._decode["NATIVE"] = iswdlf and "to-lf" or "to-crlf" + isrepolf = self.cfg.get(b"repository", b"native") != b"CRLF" + self._encode[b"NATIVE"] = isrepolf and b"to-lf" or b"to-crlf" + iswdlf = ui.config(b"eol", b"native") in (b"LF", b"\n") + self._decode[b"NATIVE"] = iswdlf and b"to-lf" or b"to-crlf" include = [] exclude = [] self.patterns = [] - for pattern, style in self.cfg.items("patterns"): + for pattern, style in self.cfg.items(b"patterns"): key = style.upper() - if key == "BIN": + if key == b"BIN": exclude.append(pattern) else: include.append(pattern) - m = match.match(root, "", [pattern]) + m = match.match(root, b"", [pattern]) self.patterns.append((pattern, key, m)) # This will match the files for which we need to care # about inconsistent newlines. - self.match = match.match(root, "", [], include, exclude) + self.match = match.match(root, b"", [], include, exclude) def copytoui(self, ui): for pattern, key, m in self.patterns: try: - ui.setconfig("decode", pattern, self._decode[key], "eol") - ui.setconfig("encode", pattern, self._encode[key], "eol") + ui.setconfig(b"decode", pattern, self._decode[key], b"eol") + ui.setconfig(b"encode", pattern, self._encode[key], b"eol") except KeyError: ui.warn( - _("ignoring unknown EOL style '%s' from %s\n") - % (key, self.cfg.source("patterns", pattern)) + _(b"ignoring unknown EOL style '%s' from %s\n") + % (key, self.cfg.source(b"patterns", pattern)) ) # eol.only-consistent can be specified in ~/.hgrc or .hgeol - for k, v in self.cfg.items("eol"): - ui.setconfig("eol", k, v, "eol") + for k, v in self.cfg.items(b"eol"): + ui.setconfig(b"eol", k, v, b"eol") def checkrev(self, repo, ctx, files): failed = [] @@ -237,9 +245,9 @@ target = self._encode[key] data = ctx[f].data() if ( - target == "to-lf" - and "\r\n" in data - or target == "to-crlf" + target == b"to-lf" + and b"\r\n" in data + or target == b"to-crlf" and singlelf.search(data) ): failed.append((f, target, bytes(ctx))) @@ -254,15 +262,18 @@ if node is None: # Cannot use workingctx.data() since it would load # and cache the filters before we configure them. - data = repo.wvfs(".hgeol").read() + data = repo.wvfs(b".hgeol").read() else: - data = repo[node][".hgeol"].data() + data = repo[node][b".hgeol"].data() return eolfile(ui, repo.root, data) except (IOError, LookupError): pass except errormod.ParseError as inst: ui.warn( - _("warning: ignoring .hgeol file due to parse error " "at %s: %s\n") + _( + b"warning: ignoring .hgeol file due to parse error " + b"at %s: %s\n" + ) % (inst.args[1], inst.args[0]) ) return None @@ -276,10 +287,10 @@ never loaded. This function ensure the extension is enabled when running hooks. """ - if "eol" in ui._knownconfig: + if b"eol" in ui._knownconfig: return - ui.setconfig("extensions", "eol", "", source="internal") - extensions.loadall(ui, ["eol"]) + ui.setconfig(b"extensions", b"eol", b"", source=b"internal") + extensions.loadall(ui, [b"eol"]) def _checkhook(ui, repo, node, headsonly): @@ -302,14 +313,16 @@ failed.extend(eol.checkrev(repo, ctx, files)) if failed: - eols = {"to-lf": "CRLF", "to-crlf": "LF"} + eols = {b"to-lf": b"CRLF", b"to-crlf": b"LF"} msgs = [] for f, target, node in sorted(failed): msgs.append( - _(" %s in %s should not have %s line endings") + _(b" %s in %s should not have %s line endings") % (f, node, eols[target]) ) - raise errormod.Abort(_("end-of-line check failed:\n") + "\n".join(msgs)) + raise errormod.Abort( + _(b"end-of-line check failed:\n") + b"\n".join(msgs) + ) def checkallhook(ui, repo, node, hooktype, **kwargs): @@ -333,16 +346,16 @@ def uisetup(ui): - ui.setconfig("hooks", "preupdate.eol", preupdate, "eol") + ui.setconfig(b"hooks", b"preupdate.eol", preupdate, b"eol") def extsetup(ui): try: - extensions.find("win32text") + extensions.find(b"win32text") ui.warn( _( - "the eol extension is incompatible with the " - "win32text extension\n" + b"the eol extension is incompatible with the " + b"win32text extension\n" ) ) except KeyError: @@ -357,7 +370,7 @@ for name, fn in filters.iteritems(): repo.adddatafilter(name, fn) - ui.setconfig("patch", "eol", "auto", "eol") + ui.setconfig(b"patch", b"eol", b"auto", b"eol") class eolrepo(repo.__class__): def loadeol(self, nodes): @@ -368,37 +381,37 @@ return eol.match def _hgcleardirstate(self): - self._eolmatch = self.loadeol([None, "tip"]) + self._eolmatch = self.loadeol([None, b"tip"]) if not self._eolmatch: self._eolmatch = util.never return oldeol = None try: - cachemtime = os.path.getmtime(self.vfs.join("eol.cache")) + cachemtime = os.path.getmtime(self.vfs.join(b"eol.cache")) except OSError: cachemtime = 0 else: - olddata = self.vfs.read("eol.cache") + olddata = self.vfs.read(b"eol.cache") if olddata: oldeol = eolfile(self.ui, self.root, olddata) try: - eolmtime = os.path.getmtime(self.wjoin(".hgeol")) + eolmtime = os.path.getmtime(self.wjoin(b".hgeol")) except OSError: eolmtime = 0 if eolmtime > cachemtime: - self.ui.debug("eol: detected change in .hgeol\n") + self.ui.debug(b"eol: detected change in .hgeol\n") - hgeoldata = self.wvfs.read(".hgeol") + hgeoldata = self.wvfs.read(b".hgeol") neweol = eolfile(self.ui, self.root, hgeoldata) wlock = None try: wlock = self.wlock() for f in self.dirstate: - if self.dirstate[f] != "n": + if self.dirstate[f] != b"n": continue if oldeol is not None: if not oldeol.match(f) and not neweol.match(f): @@ -419,7 +432,7 @@ # the new .hgeol file specify a different filter self.dirstate.normallookup(f) # Write the cache to update mtime and cache .hgeol - with self.vfs("eol.cache", "w") as f: + with self.vfs(b"eol.cache", b"w") as f: f.write(hgeoldata) except errormod.LockUnavailable: # If we cannot lock the repository and clear the @@ -447,7 +460,7 @@ continue if inconsistenteol(data): raise errormod.Abort( - _("inconsistent newline style " "in %s\n") % f + _(b"inconsistent newline style " b"in %s\n") % f ) return super(eolrepo, self).commitctx(ctx, error, origctx) diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -118,26 +118,26 @@ configitem = registrar.configitem(configtable) configitem( - "extdiff", br"opts\..*", default="", generic=True, + b"extdiff", br"opts\..*", default=b"", generic=True, ) configitem( - "extdiff", br"gui\..*", generic=True, + b"extdiff", br"gui\..*", generic=True, ) configitem( - "diff-tools", br".*\.diffargs$", default=None, generic=True, + b"diff-tools", br".*\.diffargs$", default=None, generic=True, ) configitem( - "diff-tools", br".*\.gui$", generic=True, + b"diff-tools", br".*\.gui$", generic=True, ) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def snapshot(ui, repo, files, node, tmproot, listsubrepos): @@ -145,40 +145,40 @@ if not using snapshot, -I/-X does not work and recursive diff in tools like kdiff3 and meld displays too many files.""" dirname = os.path.basename(repo.root) - if dirname == "": - dirname = "root" + if dirname == b"": + dirname = b"root" if node is not None: - dirname = "%s.%s" % (dirname, short(node)) + dirname = b"%s.%s" % (dirname, short(node)) base = os.path.join(tmproot, dirname) os.mkdir(base) fnsandstat = [] if node is not None: ui.note( - _("making snapshot of %d files from rev %s\n") + _(b"making snapshot of %d files from rev %s\n") % (len(files), short(node)) ) else: ui.note( - _("making snapshot of %d files from working directory\n") + _(b"making snapshot of %d files from working directory\n") % (len(files)) ) if files: - repo.ui.setconfig("ui", "archivemeta", False) + repo.ui.setconfig(b"ui", b"archivemeta", False) archival.archive( repo, base, node, - "files", + b"files", match=scmutil.matchfiles(repo, files), subrepos=listsubrepos, ) for fn in sorted(files): wfn = util.pconvert(fn) - ui.note(" %s\n" % wfn) + ui.note(b" %s\n" % wfn) if node is None: dest = os.path.join(base, wfn) @@ -202,20 +202,20 @@ # When not operating in 3-way mode, an empty string is # returned for parent2 replace = { - "parent": parent1, - "parent1": parent1, - "parent2": parent2, - "plabel1": plabel1, - "plabel2": plabel2, - "child": child, - "clabel": clabel, - "root": repo_root, + b"parent": parent1, + b"parent1": parent1, + b"parent2": parent2, + b"plabel1": plabel1, + b"plabel2": plabel2, + b"child": child, + b"clabel": clabel, + b"root": repo_root, } def quote(match): pre = match.group(2) key = match.group(3) - if not do3way and key == "parent2": + if not do3way and key == b"parent2": return pre return pre + procutil.shellquote(replace[key]) @@ -225,7 +225,7 @@ br"\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)\1" ) if not do3way and not re.search(regex, cmdline): - cmdline += " $parent1 $child" + cmdline += b" $parent1 $child" return re.sub(regex, quote, cmdline) @@ -273,8 +273,8 @@ if not os.path.isfile(path1a): path1a = os.devnull - path1b = "" - label1b = "" + path1b = b"" + label1b = b"" if do3way: path1b = os.path.join(tmproot, dir1b, commonfile) label1b = commonfile + rev1b @@ -286,24 +286,24 @@ if confirm: # Prompt before showing this diff - difffiles = _("diff %s (%d of %d)") % ( + difffiles = _(b"diff %s (%d of %d)") % ( commonfile, idx + 1, totalfiles, ) responses = _( - "[Yns?]" - "$$ &Yes, show diff" - "$$ &No, skip this diff" - "$$ &Skip remaining diffs" - "$$ &? (display help)" + b"[Yns?]" + b"$$ &Yes, show diff" + b"$$ &No, skip this diff" + b"$$ &Skip remaining diffs" + b"$$ &? (display help)" ) - r = ui.promptchoice("%s %s" % (difffiles, responses)) + r = ui.promptchoice(b"%s %s" % (difffiles, responses)) if r == 3: # ? while r == 3: for c, t in ui.extractchoices(responses)[1]: - ui.write("%s - %s\n" % (c, encoding.lower(t))) - r = ui.promptchoice("%s %s" % (difffiles, responses)) + ui.write(b"%s - %s\n" % (c, encoding.lower(t))) + r = ui.promptchoice(b"%s %s" % (difffiles, responses)) if r == 0: # yes pass elif r == 1: # no @@ -331,22 +331,22 @@ # as we know, the tool doesn't have a GUI, in which case # we can't run multiple CLI programs at the same time. ui.debug( - "running %r in %s\n" % (pycompat.bytestr(curcmdline), tmproot) + b"running %r in %s\n" % (pycompat.bytestr(curcmdline), tmproot) ) - ui.system(curcmdline, cwd=tmproot, blockedtag="extdiff") + ui.system(curcmdline, cwd=tmproot, blockedtag=b"extdiff") else: # Run the comparison program but don't wait, as we're # going to rapid-fire each file diff and then wait on # the whole group. ui.debug( - "running %r in %s (backgrounded)\n" + b"running %r in %s (backgrounded)\n" % (pycompat.bytestr(curcmdline), tmproot) ) proc = _systembackground(curcmdline, cwd=tmproot) waitprocs.append(proc) if waitprocs: - with ui.timeblockedsection("extdiff"): + with ui.timeblockedsection(b"extdiff"): for proc in waitprocs: proc.wait() @@ -360,12 +360,12 @@ - just invoke the diff for a single file in the working dir """ - revs = opts.get("rev") - change = opts.get("change") - do3way = "$parent2" in cmdline + revs = opts.get(b"rev") + change = opts.get(b"change") + do3way = b"$parent2" in cmdline if revs and change: - msg = _("cannot specify --rev and --change at the same time") + msg = _(b"cannot specify --rev and --change at the same time") raise error.Abort(msg) elif change: ctx2 = scmutil.revsingle(repo, change, None) @@ -377,8 +377,8 @@ else: ctx1b = repo[nullid] - perfile = opts.get("per_file") - confirm = opts.get("confirm") + perfile = opts.get(b"per_file") + confirm = opts.get(b"confirm") node1a = ctx1a.node() node1b = ctx1b.node() @@ -389,17 +389,17 @@ if node1b == nullid: do3way = False - subrepos = opts.get("subrepos") + subrepos = opts.get(b"subrepos") matcher = scmutil.match(repo[node2], pats, opts) - if opts.get("patch"): + if opts.get(b"patch"): if subrepos: - raise error.Abort(_("--patch cannot be used with --subrepos")) + raise error.Abort(_(b"--patch cannot be used with --subrepos")) if perfile: - raise error.Abort(_("--patch cannot be used with --per-file")) + raise error.Abort(_(b"--patch cannot be used with --per-file")) if node2 is None: - raise error.Abort(_("--patch requires two revisions")) + raise error.Abort(_(b"--patch requires two revisions")) else: mod_a, add_a, rem_a = map( set, repo.status(node1a, node2, matcher, listsubrepos=subrepos)[:3] @@ -416,33 +416,33 @@ if not common: return 0 - tmproot = pycompat.mkdtemp(prefix="extdiff.") + tmproot = pycompat.mkdtemp(prefix=b"extdiff.") try: - if not opts.get("patch"): + if not opts.get(b"patch"): # Always make a copy of node1a (and node1b, if applicable) dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[ 0 ] - rev1a = "@%d" % repo[node1a].rev() + rev1a = b"@%d" % repo[node1a].rev() if do3way: dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) dir1b = snapshot( ui, repo, dir1b_files, node1b, tmproot, subrepos )[0] - rev1b = "@%d" % repo[node1b].rev() + rev1b = b"@%d" % repo[node1b].rev() else: dir1b = None - rev1b = "" + rev1b = b"" fnsandstat = [] # If node2 in not the wc or there is >1 change, copy it - dir2root = "" - rev2 = "" + dir2root = b"" + rev2 = b"" if node2: dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0] - rev2 = "@%d" % repo[node2].rev() + rev2 = b"@%d" % repo[node2].rev() elif len(common) > 1: # we only actually need to get the files to copy back to # the working dir in this case (because the other cases @@ -453,7 +453,7 @@ ) else: # This lets the diff tool open the changed file directly - dir2 = "" + dir2 = b"" dir2root = repo.root label1a = rev1a @@ -476,8 +476,8 @@ dir2 = os.path.join(dir2root, dir2, common_file) label2 = common_file + rev2 else: - template = "hg-%h.patch" - with formatter.nullformatter(ui, "extdiff", {}) as fm: + template = b"hg-%h.patch" + with formatter.nullformatter(ui, b"extdiff", {}) as fm: cmdutil.export( repo, [repo[node1a].rev(), repo[node2].rev()], @@ -507,9 +507,9 @@ clabel=label2, ) ui.debug( - "running %r in %s\n" % (pycompat.bytestr(cmdline), tmproot) + b"running %r in %s\n" % (pycompat.bytestr(cmdline), tmproot) ) - ui.system(cmdline, cwd=tmproot, blockedtag="extdiff") + ui.system(cmdline, cwd=tmproot, blockedtag=b"extdiff") else: # Run the external tool once for each pair of files _runperfilediff( @@ -545,35 +545,41 @@ or (cpstat.st_mode & 0o100) != (st.st_mode & 0o100) ): ui.debug( - "file changed while diffing. " - "Overwriting: %s (src: %s)\n" % (working_fn, copy_fn) + b"file changed while diffing. " + b"Overwriting: %s (src: %s)\n" % (working_fn, copy_fn) ) util.copyfile(copy_fn, working_fn) return 1 finally: - ui.note(_("cleaning up temp directory\n")) + ui.note(_(b"cleaning up temp directory\n")) shutil.rmtree(tmproot) extdiffopts = ( [ - ("o", "option", [], _("pass option to comparison program"), _("OPT")), - ("r", "rev", [], _("revision"), _("REV")), - ("c", "change", "", _("change made by revision"), _("REV")), ( - "", - "per-file", + b"o", + b"option", + [], + _(b"pass option to comparison program"), + _(b"OPT"), + ), + (b"r", b"rev", [], _(b"revision"), _(b"REV")), + (b"c", b"change", b"", _(b"change made by revision"), _(b"REV")), + ( + b"", + b"per-file", False, - _("compare each file instead of revision snapshots"), + _(b"compare each file instead of revision snapshots"), ), ( - "", - "confirm", + b"", + b"confirm", False, - _("prompt user before each external program invocation"), + _(b"prompt user before each external program invocation"), ), - ("", "patch", None, _("compare patches for two revisions")), + (b"", b"patch", None, _(b"compare patches for two revisions")), ] + cmdutil.walkopts + cmdutil.subrepoopts @@ -581,10 +587,10 @@ @command( - "extdiff", - [("p", "program", "", _("comparison program to run"), _("CMD")),] + b"extdiff", + [(b"p", b"program", b"", _(b"comparison program to run"), _(b"CMD")),] + extdiffopts, - _("hg extdiff [OPT]... [FILE]..."), + _(b"hg extdiff [OPT]... [FILE]..."), helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, ) @@ -620,12 +626,12 @@ the external program. It is ignored if --per-file isn't specified. """ opts = pycompat.byteskwargs(opts) - program = opts.get("program") - option = opts.get("option") + program = opts.get(b"program") + option = opts.get(b"option") if not program: - program = "diff" - option = option or ["-Npru"] - cmdline = " ".join(map(procutil.shellquote, [program] + option)) + program = b"diff" + option = option or [b"-Npru"] + cmdline = b" ".join(map(procutil.shellquote, [program] + option)) return dodiff(ui, repo, cmdline, pats, opts) @@ -655,29 +661,29 @@ def __call__(self, ui, repo, *pats, **opts): opts = pycompat.byteskwargs(opts) - options = " ".join(map(procutil.shellquote, opts["option"])) + options = b" ".join(map(procutil.shellquote, opts[b"option"])) if options: - options = " " + options + options = b" " + options return dodiff( ui, repo, self._cmdline + options, pats, opts, guitool=self._isgui ) def uisetup(ui): - for cmd, path in ui.configitems("extdiff"): + for cmd, path in ui.configitems(b"extdiff"): path = util.expandpath(path) - if cmd.startswith("cmd."): + if cmd.startswith(b"cmd."): cmd = cmd[4:] if not path: path = procutil.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd - diffopts = ui.config("extdiff", "opts." + cmd) + diffopts = ui.config(b"extdiff", b"opts." + cmd) cmdline = procutil.shellquote(path) if diffopts: - cmdline += " " + diffopts - isgui = ui.configbool("extdiff", "gui." + cmd) - elif cmd.startswith("opts.") or cmd.startswith("gui."): + cmdline += b" " + diffopts + isgui = ui.configbool(b"extdiff", b"gui." + cmd) + elif cmd.startswith(b"opts.") or cmd.startswith(b"gui."): continue else: if path: @@ -691,21 +697,21 @@ path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = procutil.shellquote(path) diffopts = False - isgui = ui.configbool("extdiff", "gui." + cmd) + isgui = ui.configbool(b"extdiff", b"gui." + cmd) # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: - key = cmd + ".diffargs" - for section in ("diff-tools", "merge-tools"): + key = cmd + b".diffargs" + for section in (b"diff-tools", b"merge-tools"): args = ui.config(section, key) if args: - cmdline += " " + args + cmdline += b" " + args if isgui is None: - isgui = ui.configbool(section, cmd + ".gui") or False + isgui = ui.configbool(section, cmd + b".gui") or False break command( cmd, extdiffopts[:], - _("hg %s [OPTION]... [FILE]...") % cmd, + _(b"hg %s [OPTION]... [FILE]...") % cmd, helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, )(savedcmd(path, cmdline, isgui)) diff --git a/hgext/factotum.py b/hgext/factotum.py --- a/hgext/factotum.py +++ b/hgext/factotum.py @@ -69,44 +69,44 @@ configitem = registrar.configitem(configtable) configitem( - "factotum", "executable", default="/bin/auth/factotum", + b"factotum", b"executable", default=b"/bin/auth/factotum", ) configitem( - "factotum", "mountpoint", default="/mnt/factotum", + b"factotum", b"mountpoint", default=b"/mnt/factotum", ) configitem( - "factotum", "service", default="hg", + b"factotum", b"service", default=b"hg", ) def auth_getkey(self, params): if not self.ui.interactive(): - raise error.Abort(_("factotum not interactive")) - if "user=" not in params: - params = "%s user?" % params - params = "%s !password?" % params - os.system(procutil.tonativestr("%s -g '%s'" % (_executable, params))) + raise error.Abort(_(b"factotum not interactive")) + if b"user=" not in params: + params = b"%s user?" % params + params = b"%s !password?" % params + os.system(procutil.tonativestr(b"%s -g '%s'" % (_executable, params))) def auth_getuserpasswd(self, getkey, params): - params = "proto=pass %s" % params + params = b"proto=pass %s" % params while True: - fd = os.open("%s/rpc" % _mountpoint, os.O_RDWR) + fd = os.open(b"%s/rpc" % _mountpoint, os.O_RDWR) try: - os.write(fd, "start %s" % params) + os.write(fd, b"start %s" % params) l = os.read(fd, ERRMAX).split() - if l[0] == "ok": - os.write(fd, "read") + if l[0] == b"ok": + os.write(fd, b"read") status, user, passwd = os.read(fd, ERRMAX).split(None, 2) - if status == "ok": - if passwd.startswith("'"): - if passwd.endswith("'"): - passwd = passwd[1:-1].replace("''", "'") + if status == b"ok": + if passwd.startswith(b"'"): + if passwd.endswith(b"'"): + passwd = passwd[1:-1].replace(b"''", b"'") else: - raise error.Abort(_("malformed password string")) + raise error.Abort(_(b"malformed password string")) return (user, passwd) except (OSError, IOError): - raise error.Abort(_("factotum not responding")) + raise error.Abort(_(b"factotum not responding")) finally: os.close(fd) getkey(self, params) @@ -127,18 +127,18 @@ self._writedebug(user, passwd) return (user, passwd) - prefix = "" + prefix = b"" res = httpconnection.readauthforuri(self.ui, authuri, user) if res: _, auth = res - prefix = auth.get("prefix") - user, passwd = auth.get("username"), auth.get("password") + prefix = auth.get(b"prefix") + user, passwd = auth.get(b"username"), auth.get(b"password") if not user or not passwd: if not prefix: - prefix = realm.split(" ")[0].lower() - params = "service=%s prefix=%s" % (_service, prefix) + prefix = realm.split(b" ")[0].lower() + params = b"service=%s prefix=%s" % (_service, prefix) if user: - params = "%s user=%s" % (params, user) + params = b"%s user=%s" % (params, user) user, passwd = auth_getuserpasswd(self, auth_getkey, params) self.add_password(realm, authuri, user, passwd) @@ -148,8 +148,8 @@ def uisetup(ui): global _executable - _executable = ui.config("factotum", "executable") + _executable = ui.config(b"factotum", b"executable") global _mountpoint - _mountpoint = ui.config("factotum", "mountpoint") + _mountpoint = ui.config(b"factotum", b"mountpoint") global _service - _service = ui.config("factotum", "service") + _service = ui.config(b"factotum", b"service") diff --git a/hgext/fastannotate/__init__.py b/hgext/fastannotate/__init__.py --- a/hgext/fastannotate/__init__.py +++ b/hgext/fastannotate/__init__.py @@ -119,56 +119,56 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = commands.cmdtable configtable = {} configitem = registrar.configitem(configtable) -configitem("fastannotate", "modes", default=["fastannotate"]) -configitem("fastannotate", "server", default=False) -configitem("fastannotate", "client", default=False) -configitem("fastannotate", "unfilteredrepo", default=True) -configitem("fastannotate", "defaultformat", default=["number"]) -configitem("fastannotate", "perfhack", default=False) -configitem("fastannotate", "mainbranch") -configitem("fastannotate", "forcetext", default=True) -configitem("fastannotate", "forcefollow", default=True) -configitem("fastannotate", "clientfetchthreshold", default=10) -configitem("fastannotate", "serverbuildondemand", default=True) -configitem("fastannotate", "remotepath", default="default") +configitem(b"fastannotate", b"modes", default=[b"fastannotate"]) +configitem(b"fastannotate", b"server", default=False) +configitem(b"fastannotate", b"client", default=False) +configitem(b"fastannotate", b"unfilteredrepo", default=True) +configitem(b"fastannotate", b"defaultformat", default=[b"number"]) +configitem(b"fastannotate", b"perfhack", default=False) +configitem(b"fastannotate", b"mainbranch") +configitem(b"fastannotate", b"forcetext", default=True) +configitem(b"fastannotate", b"forcefollow", default=True) +configitem(b"fastannotate", b"clientfetchthreshold", default=10) +configitem(b"fastannotate", b"serverbuildondemand", default=True) +configitem(b"fastannotate", b"remotepath", default=b"default") def uisetup(ui): - modes = set(ui.configlist("fastannotate", "modes")) - if "fctx" in modes: - modes.discard("hgweb") + modes = set(ui.configlist(b"fastannotate", b"modes")) + if b"fctx" in modes: + modes.discard(b"hgweb") for name in modes: - if name == "fastannotate": + if name == b"fastannotate": commands.registercommand() - elif name == "hgweb": + elif name == b"hgweb": from . import support support.replacehgwebannotate() - elif name == "fctx": + elif name == b"fctx": from . import support support.replacefctxannotate() commands.wrapdefault() else: - raise hgerror.Abort(_("fastannotate: invalid mode: %s") % name) + raise hgerror.Abort(_(b"fastannotate: invalid mode: %s") % name) - if ui.configbool("fastannotate", "server"): + if ui.configbool(b"fastannotate", b"server"): protocol.serveruisetup(ui) def extsetup(ui): # fastannotate has its own locking, without depending on repo lock # TODO: avoid mutating this unless the specific repo has it enabled - localrepo.localrepository._wlockfreeprefix.add("fastannotate/") + localrepo.localrepository._wlockfreeprefix.add(b"fastannotate/") def reposetup(ui, repo): - if ui.configbool("fastannotate", "client"): + if ui.configbool(b"fastannotate", b"client"): protocol.clientreposetup(ui, repo) diff --git a/hgext/fastannotate/commands.py b/hgext/fastannotate/commands.py --- a/hgext/fastannotate/commands.py +++ b/hgext/fastannotate/commands.py @@ -34,7 +34,7 @@ def _matchpaths(repo, rev, pats, opts, aopts=facontext.defaultopts): """generate paths matching given patterns""" - perfhack = repo.ui.configbool("fastannotate", "perfhack") + perfhack = repo.ui.configbool(b"fastannotate", b"perfhack") # disable perfhack if: # a) any walkopt is used @@ -44,8 +44,8 @@ # cwd related to reporoot reporoot = os.path.dirname(repo.path) reldir = os.path.relpath(encoding.getcwd(), reporoot) - if reldir == ".": - reldir = "" + if reldir == b".": + reldir = b"" if any(opts.get(o[1]) for o in commands.walkopts): # a) perfhack = False else: # b) @@ -56,7 +56,7 @@ # disable perfhack on '..' since it allows escaping from the repo if any( ( - ".." in f + b".." in f or not os.path.isfile( facontext.pathhelper(repo, f, aopts).linelogpath ) @@ -73,7 +73,7 @@ else: def bad(x, y): - raise error.Abort("%s: %s" % (x, y)) + raise error.Abort(b"%s: %s" % (x, y)) ctx = scmutil.revsingle(repo, rev) m = scmutil.match(ctx, pats, opts, badfn=bad) @@ -83,42 +83,57 @@ fastannotatecommandargs = { r"options": [ - ("r", "rev", ".", _("annotate the specified revision"), _("REV")), - ("u", "user", None, _("list the author (long with -v)")), - ("f", "file", None, _("list the filename")), - ("d", "date", None, _("list the date (short with -q)")), - ("n", "number", None, _("list the revision number (default)")), - ("c", "changeset", None, _("list the changeset")), + (b"r", b"rev", b".", _(b"annotate the specified revision"), _(b"REV")), + (b"u", b"user", None, _(b"list the author (long with -v)")), + (b"f", b"file", None, _(b"list the filename")), + (b"d", b"date", None, _(b"list the date (short with -q)")), + (b"n", b"number", None, _(b"list the revision number (default)")), + (b"c", b"changeset", None, _(b"list the changeset")), + ( + b"l", + b"line-number", + None, + _(b"show line number at the first " b"appearance"), + ), ( - "l", - "line-number", + b"e", + b"deleted", None, - _("show line number at the first " "appearance"), + _(b"show deleted lines (slow) (EXPERIMENTAL)"), ), - ("e", "deleted", None, _("show deleted lines (slow) (EXPERIMENTAL)")), - ("", "no-content", None, _("do not show file content (EXPERIMENTAL)")), - ("", "no-follow", None, _("don't follow copies and renames")), ( - "", - "linear", + b"", + b"no-content", + None, + _(b"do not show file content (EXPERIMENTAL)"), + ), + (b"", b"no-follow", None, _(b"don't follow copies and renames")), + ( + b"", + b"linear", None, _( - "enforce linear history, ignore second parent " - "of merges (EXPERIMENTAL)" + b"enforce linear history, ignore second parent " + b"of merges (EXPERIMENTAL)" ), ), - ("", "long-hash", None, _("show long changeset hash (EXPERIMENTAL)")), ( - "", - "rebuild", + b"", + b"long-hash", None, - _("rebuild cache even if it exists " "(EXPERIMENTAL)"), + _(b"show long changeset hash (EXPERIMENTAL)"), + ), + ( + b"", + b"rebuild", + None, + _(b"rebuild cache even if it exists " b"(EXPERIMENTAL)"), ), ] + commands.diffwsopts + commands.walkopts + commands.formatteropts, - r"synopsis": _("[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE..."), + r"synopsis": _(b"[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE..."), r"inferrepo": True, } @@ -155,52 +170,55 @@ affecting results are used. """ if not pats: - raise error.Abort(_("at least one filename or pattern is required")) + raise error.Abort(_(b"at least one filename or pattern is required")) # performance hack: filtered repo can be slow. unfilter by default. - if ui.configbool("fastannotate", "unfilteredrepo"): + if ui.configbool(b"fastannotate", b"unfilteredrepo"): repo = repo.unfiltered() opts = pycompat.byteskwargs(opts) - rev = opts.get("rev", ".") - rebuild = opts.get("rebuild", False) + rev = opts.get(b"rev", b".") + rebuild = opts.get(b"rebuild", False) diffopts = patch.difffeatureopts( - ui, opts, section="annotate", whitespace=True + ui, opts, section=b"annotate", whitespace=True ) aopts = facontext.annotateopts( diffopts=diffopts, - followmerge=not opts.get("linear", False), - followrename=not opts.get("no_follow", False), + followmerge=not opts.get(b"linear", False), + followrename=not opts.get(b"no_follow", False), ) if not any( - opts.get(s) for s in ["user", "date", "file", "number", "changeset"] + opts.get(s) + for s in [b"user", b"date", b"file", b"number", b"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"]): + for name in ui.configlist( + b"fastannotate", b"defaultformat", [b"number"] + ): opts[name] = True - ui.pager("fastannotate") - template = opts.get("template") - if template == "json": + ui.pager(b"fastannotate") + template = opts.get(b"template") + if template == b"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) + showdeleted = opts.get(b"deleted", False) + showlines = not bool(opts.get(b"no_content")) + showpath = opts.get(b"file", False) # find the head of the main (master) branch - master = ui.config("fastannotate", "mainbranch") or rev + master = ui.config(b"fastannotate", b"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"): + if util.safehasattr(repo, b"prefetchfastannotate"): repo.prefetchfastannotate(paths) for path in paths: @@ -238,7 +256,7 @@ _newopts = set() _knownopts = { - opt[1].replace("-", "_") + opt[1].replace(b"-", b"_") for opt in (fastannotatecommandargs[r"options"] + commands.globalopts) } @@ -246,16 +264,16 @@ def _annotatewrapper(orig, ui, repo, *pats, **opts): """used by wrapdefault""" # we need this hack until the obsstore has 0.0 seconds perf impact - if ui.configbool("fastannotate", "unfilteredrepo"): + if ui.configbool(b"fastannotate", b"unfilteredrepo"): repo = repo.unfiltered() # treat the file as text (skip the isbinary check) - if ui.configbool("fastannotate", "forcetext"): + if ui.configbool(b"fastannotate", b"forcetext"): opts[r"text"] = True # check if we need to do prefetch (client-side) rev = opts.get(r"rev") - if util.safehasattr(repo, "prefetchfastannotate") and rev is not None: + if util.safehasattr(repo, b"prefetchfastannotate") and rev is not None: paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts))) repo.prefetchfastannotate(paths) @@ -264,20 +282,20 @@ def registercommand(): """register the fastannotate command""" - name = "fastannotate|fastblame|fa" + name = b"fastannotate|fastblame|fa" command(name, helpbasic=True, **fastannotatecommandargs)(fastannotate) def wrapdefault(): """wrap the default annotate command, to be aware of the protocol""" - extensions.wrapcommand(commands.table, "annotate", _annotatewrapper) + extensions.wrapcommand(commands.table, b"annotate", _annotatewrapper) @command( - "debugbuildannotatecache", - [("r", "rev", "", _("build up to the specific revision"), _("REV"))] + b"debugbuildannotatecache", + [(b"r", b"rev", b"", _(b"build up to the specific revision"), _(b"REV"))] + commands.walkopts, - _("[-r REV] FILE..."), + _(b"[-r REV] FILE..."), ) def debugbuildannotatecache(ui, repo, *pats, **opts): """incrementally build fastannotate cache up to REV for specified files @@ -291,25 +309,25 @@ options and lives in '.hg/fastannotate/default'. """ opts = pycompat.byteskwargs(opts) - rev = opts.get("REV") or ui.config("fastannotate", "mainbranch") + rev = opts.get(b"REV") or ui.config(b"fastannotate", b"mainbranch") if not rev: raise error.Abort( - _("you need to provide a revision"), - hint=_("set fastannotate.mainbranch or use --rev"), + _(b"you need to provide a revision"), + hint=_(b"set fastannotate.mainbranch or use --rev"), ) - if ui.configbool("fastannotate", "unfilteredrepo"): + if ui.configbool(b"fastannotate", b"unfilteredrepo"): repo = repo.unfiltered() ctx = scmutil.revsingle(repo, rev) m = scmutil.match(ctx, pats, opts) paths = list(ctx.walk(m)) - if util.safehasattr(repo, "prefetchfastannotate"): + if util.safehasattr(repo, b"prefetchfastannotate"): # client - if opts.get("REV"): - raise error.Abort(_("--rev cannot be used for client")) + if opts.get(b"REV"): + raise error.Abort(_(b"--rev cannot be used for client")) repo.prefetchfastannotate(paths) else: # server, or full repo - progress = ui.makeprogress(_("building"), total=len(paths)) + progress = ui.makeprogress(_(b"building"), total=len(paths)) for i, path in enumerate(paths): progress.update(i) with facontext.annotatecontext(repo, path) as actx: @@ -321,7 +339,7 @@ # the cache is broken (could happen with renaming so the # file history gets invalidated). rebuild and try again. ui.debug( - "fastannotate: %s: rebuilding broken cache\n" % path + b"fastannotate: %s: rebuilding broken cache\n" % path ) actx.rebuild() try: @@ -331,8 +349,8 @@ # cache for other files. ui.warn( _( - "fastannotate: %s: failed to " - "build cache: %r\n" + b"fastannotate: %s: failed to " + b"build cache: %r\n" ) % (path, ex) ) diff --git a/hgext/fastannotate/context.py b/hgext/fastannotate/context.py --- a/hgext/fastannotate/context.py +++ b/hgext/fastannotate/context.py @@ -52,7 +52,7 @@ # renamed filectx won't have a filelog yet, so set it # from the cache to save time for p in pl: - if not "_filelog" in p.__dict__: + if not b"_filelog" in p.__dict__: p._filelog = _getflog(f._repo, p.path()) return pl @@ -62,8 +62,8 @@ # so it takes a fctx instead of a pair of text and fctx. def _decorate(fctx): text = fctx.data() - linecount = text.count("\n") - if text and not text.endswith("\n"): + linecount = text.count(b"\n") + if text and not text.endswith(b"\n"): linecount += 1 return ([(fctx, i) for i in pycompat.xrange(linecount)], text) @@ -75,7 +75,7 @@ for (a1, a2, b1, b2), t in blocks: # Changed blocks ('!') or blocks made only of blank lines ('~') # belong to the child. - if t == "=": + if t == b"=": child[0][b1:b2] = parent[0][a1:a2] return child @@ -119,7 +119,7 @@ fctx = repo.filectx(path, changeid=ctx.rev()) else: fctx = ctx[path] - if adjustctx == "linkrev": + if adjustctx == b"linkrev": introrev = fctx.linkrev() else: introrev = fctx.introrev() @@ -132,10 +132,10 @@ # like mercurial.store.encodedir, but use linelog suffixes: .m, .l, .lock def encodedir(path): return ( - path.replace(".hg/", ".hg.hg/") - .replace(".l/", ".l.hg/") - .replace(".m/", ".m.hg/") - .replace(".lock/", ".lock.hg/") + path.replace(b".hg/", b".hg.hg/") + .replace(b".l/", b".l.hg/") + .replace(b".m/", b".m.hg/") + .replace(b".lock/", b".lock.hg/") ) @@ -157,9 +157,9 @@ """ defaults = { - "diffopts": None, - "followrename": True, - "followmerge": True, + b"diffopts": None, + b"followrename": True, + b"followmerge": True, } def __init__(self, **opts): @@ -170,17 +170,17 @@ @util.propertycache def shortstr(self): """represent opts in a short string, suitable for a directory name""" - result = "" + result = b"" if not self.followrename: - result += "r0" + result += b"r0" if not self.followmerge: - result += "m0" + result += b"m0" if self.diffopts is not None: assert isinstance(self.diffopts, mdiff.diffopts) diffopthash = hashdiffopts(self.diffopts) if diffopthash != _defaultdiffopthash: - result += "i" + diffopthash - return result or "default" + result += b"i" + diffopthash + return result or b"default" defaultopts = annotateopts() @@ -206,7 +206,7 @@ def linelog(self): if self._linelog is None: if os.path.exists(self.linelogpath): - with open(self.linelogpath, "rb") as f: + with open(self.linelogpath, b"rb") as f: try: self._linelog = linelogmod.linelog.fromdata(f.read()) except linelogmod.LineLogError: @@ -226,7 +226,7 @@ self._revmap.flush() self._revmap = None if self._linelog is not None: - with open(self.linelogpath, "wb") as f: + with open(self.linelogpath, b"wb") as f: f.write(self._linelog.encode()) self._linelog = None @@ -308,11 +308,11 @@ if directly: if self.ui.debugflag: self.ui.debug( - "fastannotate: %s: using fast path " - "(resolved fctx: %s)\n" + b"fastannotate: %s: using fast path " + b"(resolved fctx: %s)\n" % ( self.path, - stringutil.pprint(util.safehasattr(revfctx, "node")), + stringutil.pprint(util.safehasattr(revfctx, b"node")), ) ) return self.annotatedirectly(revfctx, showpath, showlines) @@ -356,8 +356,8 @@ if masterfctx: if masterfctx.rev() is None: raise error.Abort( - _("cannot update linelog to wdir()"), - hint=_("set fastannotate.mainbranch"), + _(b"cannot update linelog to wdir()"), + hint=_(b"set fastannotate.mainbranch"), ) initvisit.append(masterfctx) visit = initvisit[:] @@ -403,13 +403,13 @@ if self.ui.debugflag: if newmainbranch: self.ui.debug( - "fastannotate: %s: %d new changesets in the main" - " branch\n" % (self.path, len(newmainbranch)) + b"fastannotate: %s: %d new changesets in the main" + b" branch\n" % (self.path, len(newmainbranch)) ) elif not hist: # no joints, no updates self.ui.debug( - "fastannotate: %s: linelog cannot help in " - "annotating this revision\n" % self.path + b"fastannotate: %s: linelog cannot help in " + b"annotating this revision\n" % self.path ) # prepare annotateresult so we can update linelog incrementally @@ -418,7 +418,7 @@ # 3rd DFS does the actual annotate visit = initvisit[:] progress = self.ui.makeprogress( - "building cache", total=len(newmainbranch) + b"building cache", total=len(newmainbranch) ) while visit: f = visit[-1] @@ -463,7 +463,7 @@ if len(pl) == 2 and self.opts.followmerge: # merge bannotated = curr[0] if blocks is None: # no parents, add an empty one - blocks = list(self._diffblocks("", curr[1])) + blocks = list(self._diffblocks(b"", curr[1])) self._appendrev(f, blocks, bannotated) elif showpath: # not append linelog, but we need to record path self._node2path[f.node()] = f.path() @@ -490,7 +490,7 @@ if hsh is not None and (hsh, self.path) in self.revmap: f = hsh if f is None: - adjustctx = "linkrev" if self._perfhack else True + adjustctx = b"linkrev" if self._perfhack else True f = self._resolvefctx(rev, adjustctx=adjustctx, resolverev=True) result = f in self.revmap if not result and self._perfhack: @@ -511,7 +511,7 @@ # find a chain from rev to anything in the mainbranch if revfctx not in self.revmap: chain = [revfctx] - a = "" + a = b"" while True: f = chain[-1] pl = self._parentfunc(f) @@ -589,8 +589,8 @@ hsh = annotateresult[idxs[0]][0] if self.ui.debugflag: self.ui.debug( - "fastannotate: reading %s line #%d " - "to resolve lines %r\n" + b"fastannotate: reading %s line #%d " + b"to resolve lines %r\n" % (node.short(hsh), linenum, idxs) ) fctx = self._resolvefctx(hsh, revmap.rev2path(rev)) @@ -603,14 +603,15 @@ # run the annotate and the lines should match to the file content self.ui.debug( - "fastannotate: annotate %s to resolve lines\n" % node.short(hsh) + b"fastannotate: annotate %s to resolve lines\n" + % node.short(hsh) ) linelog.annotate(rev) fctx = self._resolvefctx(hsh, revmap.rev2path(rev)) annotated = linelog.annotateresult lines = mdiff.splitnewlines(fctx.data()) if len(lines) != len(annotated): - raise faerror.CorruptedFileError("unexpected annotated lines") + raise faerror.CorruptedFileError(b"unexpected annotated lines") # resolve lines from the annotate result for i, line in enumerate(lines): k = annotated[i] @@ -633,11 +634,11 @@ llrev = self.revmap.hsh2rev(hsh) if not llrev: raise faerror.CorruptedFileError( - "%s is not in revmap" % node.hex(hsh) + b"%s is not in revmap" % node.hex(hsh) ) if (self.revmap.rev2flag(llrev) & revmapmod.sidebranchflag) != 0: raise faerror.CorruptedFileError( - "%s is not in revmap mainbranch" % node.hex(hsh) + b"%s is not in revmap mainbranch" % node.hex(hsh) ) self.linelog.annotate(llrev) result = [ @@ -677,7 +678,7 @@ """(fctx) -> int""" # f should not be a linelog revision if isinstance(f, int): - raise error.ProgrammingError("f should not be an int") + raise error.ProgrammingError(b"f should not be an int") # f is a fctx, allocate linelog rev on demand hsh = f.node() rev = revmap.hsh2rev(hsh) @@ -690,7 +691,7 @@ siderevmap = {} # node: int if bannotated is not None: for (a1, a2, b1, b2), op in blocks: - if op != "=": + if op != b"=": # f could be either linelong rev, or fctx. siderevs += [ f @@ -708,7 +709,7 @@ siderevmap[fctx] = llrev for (a1, a2, b1, b2), op in reversed(blocks): - if op == "=": + if op == b"=": continue if bannotated is None: linelog.replacelines(llrev, a1, a2, b1, b2) @@ -760,7 +761,7 @@ @util.propertycache def _perfhack(self): - return self.ui.configbool("fastannotate", "perfhack") + return self.ui.configbool(b"fastannotate", b"perfhack") def _resolvefctx(self, rev, path=None, **kwds): return resolvefctx(self.repo, rev, (path or self.path), **kwds) @@ -781,7 +782,7 @@ def __init__(self, repo, path, opts=defaultopts): # different options use different directories self._vfspath = os.path.join( - "fastannotate", opts.shortstr, encodedir(path) + b"fastannotate", opts.shortstr, encodedir(path) ) self._repo = repo @@ -791,14 +792,14 @@ @property def linelogpath(self): - return self._repo.vfs.join(self._vfspath + ".l") + return self._repo.vfs.join(self._vfspath + b".l") def lock(self): - return lockmod.lock(self._repo.vfs, self._vfspath + ".lock") + return lockmod.lock(self._repo.vfs, self._vfspath + b".lock") @property def revmappath(self): - return self._repo.vfs.join(self._vfspath + ".m") + return self._repo.vfs.join(self._vfspath + b".m") @contextlib.contextmanager @@ -831,7 +832,7 @@ except Exception: if actx is not None: actx.rebuild() - repo.ui.debug("fastannotate: %s: cache broken and deleted\n" % path) + repo.ui.debug(b"fastannotate: %s: cache broken and deleted\n" % path) raise finally: if actx is not None: @@ -844,7 +845,7 @@ """ repo = fctx._repo path = fctx._path - if repo.ui.configbool("fastannotate", "forcefollow", True): + if repo.ui.configbool(b"fastannotate", b"forcefollow", True): follow = True aopts = annotateopts(diffopts=diffopts, followrename=follow) return annotatecontext(repo, path, aopts, rebuild) diff --git a/hgext/fastannotate/formatter.py b/hgext/fastannotate/formatter.py --- a/hgext/fastannotate/formatter.py +++ b/hgext/fastannotate/formatter.py @@ -33,35 +33,35 @@ hexfunc = self._hexfunc # special handling working copy "changeset" and "rev" functions - if self.opts.get("rev") == "wdir()": + if self.opts.get(b"rev") == b"wdir()": orig = hexfunc hexfunc = lambda x: None if x is None else orig(x) - wnode = hexfunc(repo["."].node()) + "+" - wrev = "%d" % repo["."].rev() - wrevpad = "" - if not opts.get("changeset"): # only show + if changeset is hidden - wrev += "+" - wrevpad = " " - revenc = lambda x: wrev if x is None else ("%d" % x) + wrevpad + wnode = hexfunc(repo[b"."].node()) + b"+" + wrev = b"%d" % repo[b"."].rev() + wrevpad = b"" + if not opts.get(b"changeset"): # only show + if changeset is hidden + wrev += b"+" + wrevpad = b" " + revenc = lambda x: wrev if x is None else (b"%d" % x) + wrevpad def csetenc(x): if x is None: return wnode - return pycompat.bytestr(x) + " " + return pycompat.bytestr(x) + b" " else: revenc = csetenc = pycompat.bytestr # opt name, separator, raw value (for json/plain), encoder (for plain) opmap = [ - ("user", " ", lambda x: getctx(x).user(), ui.shortuser), - ("number", " ", lambda x: getctx(x).rev(), revenc), - ("changeset", " ", lambda x: hexfunc(x[0]), csetenc), - ("date", " ", lambda x: getctx(x).date(), datefunc), - ("file", " ", lambda x: x[2], pycompat.bytestr), - ("line_number", ":", lambda x: x[1] + 1, pycompat.bytestr), + (b"user", b" ", lambda x: getctx(x).user(), ui.shortuser), + (b"number", b" ", lambda x: getctx(x).rev(), revenc), + (b"changeset", b" ", lambda x: hexfunc(x[0]), csetenc), + (b"date", b" ", lambda x: getctx(x).date(), datefunc), + (b"file", b" ", lambda x: x[2], pycompat.bytestr), + (b"line_number", b":", lambda x: x[1] + 1, pycompat.bytestr), ] - fieldnamemap = {"number": "rev", "changeset": "node"} + fieldnamemap = {b"number": b"rev", b"changeset": b"node"} funcmap = [ (get, sep, fieldnamemap.get(op, op), enc) for op, sep, get, enc in opmap @@ -69,7 +69,7 @@ ] # no separator for first column funcmap[0] = list(funcmap[0]) - funcmap[0][1] = "" + funcmap[0][1] = b"" self.funcmap = funcmap def write(self, annotatedresult, lines=None, existinglines=None): @@ -83,39 +83,39 @@ for f, sep, name, enc in self.funcmap: l = [enc(f(x)) for x in annotatedresult] pieces.append(l) - if name in ["node", "date"]: # node and date has fixed size + if name in [b"node", b"date"]: # node and date has fixed size l = l[:1] widths = pycompat.maplist(encoding.colwidth, set(l)) maxwidth = max(widths) if widths else 0 maxwidths.append(maxwidth) # buffered output - result = "" + result = b"" for i in pycompat.xrange(len(annotatedresult)): for j, p in enumerate(pieces): sep = self.funcmap[j][1] - padding = " " * (maxwidths[j] - len(p[i])) + padding = b" " * (maxwidths[j] - len(p[i])) result += sep + padding + p[i] if lines: if existinglines is None: - result += ": " + lines[i] + result += b": " + lines[i] else: # extra formatting showing whether a line exists key = (annotatedresult[i][0], annotatedresult[i][1]) if key in existinglines: - result += ": " + lines[i] + result += b": " + lines[i] else: - result += ": " + self.ui.label( - "-" + lines[i], "diff.deleted" + result += b": " + self.ui.label( + b"-" + lines[i], b"diff.deleted" ) - if result[-1:] != "\n": - result += "\n" + if result[-1:] != b"\n": + result += b"\n" self.ui.write(result) @util.propertycache def _hexfunc(self): - if self.ui.debugflag or self.opts.get("long_hash"): + if self.ui.debugflag or self.opts.get(b"long_hash"): return node.hex else: return node.short @@ -127,7 +127,7 @@ class jsonformatter(defaultformatter): def __init__(self, ui, repo, opts): super(jsonformatter, self).__init__(ui, repo, opts) - self.ui.write("[") + self.ui.write(b"[") self.needcomma = False def write(self, annotatedresult, lines=None, existinglines=None): @@ -139,23 +139,23 @@ for f, sep, name, enc in self.funcmap ] if lines is not None: - pieces.append(("line", lines)) + pieces.append((b"line", lines)) pieces.sort() - seps = [","] * len(pieces[:-1]) + [""] + seps = [b","] * len(pieces[:-1]) + [b""] - result = "" + result = b"" lasti = len(annotatedresult) - 1 for i in pycompat.xrange(len(annotatedresult)): - result += "\n {\n" + result += b"\n {\n" for j, p in enumerate(pieces): k, vs = p - result += ' "%s": %s%s\n' % ( + result += b' "%s": %s%s\n' % ( k, templatefilters.json(vs[i], paranoid=False), seps[j], ) - result += " }%s" % ("" if i == lasti else ",") + result += b" }%s" % (b"" if i == lasti else b",") if lasti >= 0: self.needcomma = True @@ -163,7 +163,7 @@ def _writecomma(self): if self.needcomma: - self.ui.write(",") + self.ui.write(b",") self.needcomma = False @util.propertycache @@ -171,4 +171,4 @@ return node.hex def end(self): - self.ui.write("\n]\n") + self.ui.write(b"\n]\n") diff --git a/hgext/fastannotate/protocol.py b/hgext/fastannotate/protocol.py --- a/hgext/fastannotate/protocol.py +++ b/hgext/fastannotate/protocol.py @@ -25,12 +25,12 @@ def _getmaster(ui): """get the mainbranch, and enforce it is set""" - master = ui.config("fastannotate", "mainbranch") + master = ui.config(b"fastannotate", b"mainbranch") if not master: raise error.Abort( _( - "fastannotate.mainbranch is required " - "for both the client and the server" + b"fastannotate.mainbranch is required " + b"for both the client and the server" ) ) return master @@ -41,7 +41,7 @@ def _capabilities(orig, repo, proto): result = orig(repo, proto) - result.append("getannotate") + result.append(b"getannotate") return result @@ -49,9 +49,9 @@ # output: # FILE := vfspath + '\0' + str(size) + '\0' + content # OUTPUT := '' | FILE + OUTPUT - result = "" + result = b"" buildondemand = repo.ui.configbool( - "fastannotate", "serverbuildondemand", True + b"fastannotate", b"serverbuildondemand", True ) with context.annotatecontext(repo, path) as actx: if buildondemand: @@ -80,25 +80,25 @@ for p in [actx.revmappath, actx.linelogpath]: if not os.path.exists(p): continue - with open(p, "rb") as f: + with open(p, b"rb") as f: content = f.read() - vfsbaselen = len(repo.vfs.base + "/") + vfsbaselen = len(repo.vfs.base + b"/") relpath = p[vfsbaselen:] - result += "%s\0%d\0%s" % (relpath, len(content), content) + result += b"%s\0%d\0%s" % (relpath, len(content), content) return result def _registerwireprotocommand(): - if "getannotate" in wireprotov1server.commands: + if b"getannotate" in wireprotov1server.commands: return - wireprotov1server.wireprotocommand("getannotate", "path lastnode")( + wireprotov1server.wireprotocommand(b"getannotate", b"path lastnode")( _getannotate ) def serveruisetup(ui): _registerwireprotocommand() - extensions.wrapfunction(wireprotov1server, "_capabilities", _capabilities) + extensions.wrapfunction(wireprotov1server, b"_capabilities", _capabilities) # client-side @@ -109,15 +109,15 @@ i = 0 l = len(payload) - 1 state = 0 # 0: vfspath, 1: size - vfspath = size = "" + vfspath = size = b"" while i < l: ch = payload[i : i + 1] - if ch == "\0": + if ch == b"\0": if state == 1: result[vfspath] = payload[i + 1 : i + 1 + int(size)] i += int(size) state = 0 - vfspath = size = "" + vfspath = size = b"" elif state == 0: state = 1 else: @@ -133,11 +133,11 @@ class fastannotatepeer(peer.__class__): @wireprotov1peer.batchable def getannotate(self, path, lastnode=None): - if not self.capable("getannotate"): - ui.warn(_("remote peer cannot provide annotate cache\n")) + if not self.capable(b"getannotate"): + ui.warn(_(b"remote peer cannot provide annotate cache\n")) yield None, None else: - args = {"path": path, "lastnode": lastnode or ""} + args = {b"path": path, b"lastnode": lastnode or b""} f = wireprotov1peer.future() yield args, f yield _parseresponse(f.value) @@ -150,7 +150,7 @@ ui = repo.ui remotepath = ui.expandpath( - ui.config("fastannotate", "remotepath", "default") + ui.config(b"fastannotate", b"remotepath", b"default") ) peer = hg.peer(ui, {}, remotepath) @@ -175,11 +175,12 @@ ui = repo.ui results = [] with peer.commandexecutor() as batcher: - ui.debug("fastannotate: requesting %d files\n" % len(paths)) + ui.debug(b"fastannotate: requesting %d files\n" % len(paths)) for p in paths: results.append( batcher.callcommand( - "getannotate", {"path": p, "lastnode": lastnodemap.get(p)} + b"getannotate", + {b"path": p, b"lastnode": lastnodemap.get(p)}, ) ) @@ -189,19 +190,21 @@ r = {util.pconvert(p): v for p, v in r.iteritems()} for path in sorted(r): # ignore malicious paths - if not path.startswith("fastannotate/") or "/../" in ( - path + "/" + if not path.startswith(b"fastannotate/") or b"/../" in ( + path + b"/" ): - ui.debug("fastannotate: ignored malicious path %s\n" % path) + ui.debug( + b"fastannotate: ignored malicious path %s\n" % path + ) continue content = r[path] if ui.debugflag: ui.debug( - "fastannotate: writing %d bytes to %s\n" + b"fastannotate: writing %d bytes to %s\n" % (len(content), path) ) repo.vfs.makedirs(os.path.dirname(path)) - with repo.vfs(path, "wb") as f: + with repo.vfs(path, b"wb") as f: f.write(content) @@ -209,7 +212,7 @@ """return a subset of paths whose history is long and need to fetch linelog from the server. works with remotefilelog and non-remotefilelog repos. """ - threshold = repo.ui.configint("fastannotate", "clientfetchthreshold", 10) + threshold = repo.ui.configint(b"fastannotate", b"clientfetchthreshold", 10) if threshold <= 0: return paths @@ -240,7 +243,7 @@ clientfetch(self, needupdatepaths, lastnodemap, peer) except Exception as ex: # could be directory not writable or so, not fatal - self.ui.debug("fastannotate: prefetch failed: %r\n" % ex) + self.ui.debug(b"fastannotate: prefetch failed: %r\n" % ex) repo.__class__ = fastannotaterepo diff --git a/hgext/fastannotate/revmap.py b/hgext/fastannotate/revmap.py --- a/hgext/fastannotate/revmap.py +++ b/hgext/fastannotate/revmap.py @@ -70,7 +70,7 @@ # since rename does not happen frequently, do not store path for every # revision. self._renamerevs can be used for bisecting. self._renamerevs = [0] - self._renamepaths = [""] + self._renamepaths = [b""] self._lastmaxrev = -1 if path: if os.path.exists(path): @@ -98,9 +98,13 @@ if flush is True, incrementally update the file. """ if hsh in self._hsh2rev: - raise error.CorruptedFileError("%r is in revmap already" % hex(hsh)) + raise error.CorruptedFileError( + b"%r is in revmap already" % hex(hsh) + ) if len(hsh) != _hshlen: - raise hgerror.ProgrammingError("hsh must be %d-char long" % _hshlen) + raise hgerror.ProgrammingError( + b"hsh must be %d-char long" % _hshlen + ) idx = len(self._rev2hsh) flag = 0 if sidebranch: @@ -149,7 +153,7 @@ self._rev2hsh = [None] self._rev2flag = [None] self._hsh2rev = {} - self._rev2path = [""] + self._rev2path = [b""] self._lastmaxrev = -1 if flush: self.flush() @@ -159,12 +163,12 @@ if not self.path: return if self._lastmaxrev == -1: # write the entire file - with open(self.path, "wb") as f: + with open(self.path, b"wb") as f: f.write(self.HEADER) for i in pycompat.xrange(1, len(self._rev2hsh)): self._writerev(i, f) else: # append incrementally - with open(self.path, "ab") as f: + with open(self.path, b"ab") as f: for i in pycompat.xrange( self._lastmaxrev + 1, len(self._rev2hsh) ): @@ -179,7 +183,7 @@ # which is faster than both LOAD_CONST and LOAD_GLOBAL. flaglen = 1 hshlen = _hshlen - with open(self.path, "rb") as f: + with open(self.path, b"rb") as f: if f.read(len(self.HEADER)) != self.HEADER: raise error.CorruptedFileError() self.clear(flush=False) @@ -205,23 +209,23 @@ """append a revision data to file""" flag = self._rev2flag[rev] hsh = self._rev2hsh[rev] - f.write(struct.pack("B", flag)) + f.write(struct.pack(b"B", flag)) if flag & renameflag: path = self.rev2path(rev) if path is None: - raise error.CorruptedFileError("cannot find path for %s" % rev) + raise error.CorruptedFileError(b"cannot find path for %s" % rev) f.write(path + b"\0") f.write(hsh) @staticmethod def _readcstr(f): """read a C-language-like '\0'-terminated string""" - buf = "" + buf = b"" while True: ch = f.read(1) if not ch: # unexpected eof raise error.CorruptedFileError() - if ch == "\0": + if ch == b"\0": break buf += ch return buf @@ -249,7 +253,7 @@ """ hsh = None try: - with open(path, "rb") as f: + with open(path, b"rb") as f: f.seek(-_hshlen, io.SEEK_END) if f.tell() > len(revmap.HEADER): hsh = f.read(_hshlen) diff --git a/hgext/fastannotate/support.py b/hgext/fastannotate/support.py --- a/hgext/fastannotate/support.py +++ b/hgext/fastannotate/support.py @@ -64,7 +64,7 @@ def _getmaster(fctx): """(fctx) -> str""" - return fctx._repo.ui.config("fastannotate", "mainbranch") or "default" + return fctx._repo.ui.config(b"fastannotate", b"mainbranch") or b"default" def _doannotate(fctx, follow=True, diffopts=None): @@ -83,7 +83,7 @@ except Exception: ac.rebuild() # try rebuild once fctx._repo.ui.debug( - "fastannotate: %s: rebuilding broken cache\n" % fctx._path + b"fastannotate: %s: rebuilding broken cache\n" % fctx._path ) try: annotated, contents = ac.annotate( @@ -98,7 +98,7 @@ def _hgwebannotate(orig, fctx, ui): diffopts = patch.difffeatureopts( - ui, untrusted=True, section="annotate", whitespace=True + ui, untrusted=True, section=b"annotate", whitespace=True ) return _doannotate(fctx, diffopts=diffopts) @@ -115,7 +115,7 @@ return _doannotate(self, follow, diffopts) except Exception as ex: self._repo.ui.debug( - "fastannotate: falling back to the vanilla " "annotate: %r\n" % ex + b"fastannotate: falling back to the vanilla " b"annotate: %r\n" % ex ) return orig(self, follow=follow, skiprevs=skiprevs, diffopts=diffopts) @@ -130,8 +130,8 @@ def replacehgwebannotate(): - extensions.wrapfunction(hgweb.webutil, "annotate", _hgwebannotate) + extensions.wrapfunction(hgweb.webutil, b"annotate", _hgwebannotate) def replacefctxannotate(): - extensions.wrapfunction(hgcontext.basefilectx, "annotate", _fctxannotate) + extensions.wrapfunction(hgcontext.basefilectx, b"annotate", _fctxannotate) diff --git a/hgext/fetch.py b/hgext/fetch.py --- a/hgext/fetch.py +++ b/hgext/fetch.py @@ -30,30 +30,30 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "fetch", + b"fetch", [ ( - "r", - "rev", + b"r", + b"rev", [], - _("a specific revision you would like to pull"), - _("REV"), + _(b"a specific revision you would like to pull"), + _(b"REV"), ), - ("", "edit", None, _("invoke editor on commit messages")), - ("", "force-editor", None, _("edit commit message (DEPRECATED)")), - ("", "switch-parent", None, _("switch parents when merging")), + (b"", b"edit", None, _(b"invoke editor on commit messages")), + (b"", b"force-editor", None, _(b"edit commit message (DEPRECATED)")), + (b"", b"switch-parent", None, _(b"switch parents when merging")), ] + cmdutil.commitopts + cmdutil.commitopts2 + cmdutil.remoteopts, - _("hg fetch [SOURCE]"), + _(b"hg fetch [SOURCE]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, ) -def fetch(ui, repo, source="default", **opts): +def fetch(ui, repo, source=b"default", **opts): """pull changes from a remote repository, merge new changes if needed. This finds all changes from the repository at the specified path @@ -74,9 +74,9 @@ """ opts = pycompat.byteskwargs(opts) - date = opts.get("date") + date = opts.get(b"date") if date: - opts["date"] = dateutil.parsedate(date) + opts[b"date"] = dateutil.parsedate(date) parent = repo.dirstate.p1() branch = repo.dirstate.branch() @@ -86,8 +86,8 @@ branchnode = None if parent != branchnode: raise error.Abort( - _("working directory not at branch tip"), - hint=_("use 'hg update' to check out branch tip"), + _(b"working directory not at branch tip"), + hint=_(b"use 'hg update' to check out branch tip"), ) wlock = lock = None @@ -102,23 +102,23 @@ if len(bheads) > 1: raise error.Abort( _( - "multiple heads in this branch " - '(use "hg heads ." and "hg merge" to merge)' + b"multiple heads in this branch " + b'(use "hg heads ." and "hg merge" to merge)' ) ) other = hg.peer(repo, opts, ui.expandpath(source)) ui.status( - _("pulling from %s\n") % util.hidepassword(ui.expandpath(source)) + _(b"pulling from %s\n") % util.hidepassword(ui.expandpath(source)) ) revs = None - if opts["rev"]: + if opts[b"rev"]: try: - revs = [other.lookup(rev) for rev in opts["rev"]] + revs = [other.lookup(rev) for rev in opts[b"rev"]] except error.CapabilityError: err = _( - "other repository doesn't support revision lookup, " - "so a rev cannot be specified." + b"other repository doesn't support revision lookup, " + b"so a rev cannot be specified." ) raise error.Abort(err) @@ -146,8 +146,8 @@ if len(newheads) > 1: ui.status( _( - "not merging with %d other new branch heads " - '(use "hg heads ." and "hg merge" to merge them)\n' + b"not merging with %d other new branch heads " + b'(use "hg heads ." and "hg merge" to merge them)\n' ) % (len(newheads) - 1) ) @@ -162,17 +162,17 @@ # By default, we consider the repository we're pulling # *from* as authoritative, so we merge our changes into # theirs. - if opts["switch_parent"]: + if opts[b"switch_parent"]: firstparent, secondparent = newparent, newheads[0] else: firstparent, secondparent = newheads[0], newparent ui.status( - _("updating to %d:%s\n") + _(b"updating to %d:%s\n") % (repo.changelog.rev(firstparent), short(firstparent)) ) hg.clean(repo, firstparent) ui.status( - _("merging with %d:%s\n") + _(b"merging with %d:%s\n") % (repo.changelog.rev(secondparent), short(secondparent)) ) err = hg.merge(repo, secondparent, remind=False) @@ -180,13 +180,15 @@ if not err: # we don't translate commit messages message = cmdutil.logmessage(ui, opts) or ( - "Automated merge with %s" % util.removeauth(other.url()) + b"Automated merge with %s" % util.removeauth(other.url()) ) - editopt = opts.get("edit") or opts.get("force_editor") - editor = cmdutil.getcommiteditor(edit=editopt, editform="fetch") - n = repo.commit(message, opts["user"], opts["date"], editor=editor) + editopt = opts.get(b"edit") or opts.get(b"force_editor") + editor = cmdutil.getcommiteditor(edit=editopt, editform=b"fetch") + n = repo.commit( + message, opts[b"user"], opts[b"date"], editor=editor + ) ui.status( - _("new changeset %d:%s merges remote changes " "with local\n") + _(b"new changeset %d:%s merges remote changes " b"with local\n") % (repo.changelog.rev(n), short(n)) ) diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -157,7 +157,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @@ -167,60 +167,60 @@ # Register the suboptions allowed for each configured fixer, and default values. FIXER_ATTRS = { - "command": None, - "linerange": None, - "pattern": None, - "priority": 0, - "metadata": "false", - "skipclean": "true", + b"command": None, + b"linerange": None, + b"pattern": None, + b"priority": 0, + b"metadata": b"false", + b"skipclean": b"true", } for key, default in FIXER_ATTRS.items(): - configitem("fix", ".*(:%s)?" % key, default=default, generic=True) + configitem(b"fix", b".*(:%s)?" % key, default=default, generic=True) # A good default size allows most source code files to be fixed, but avoids # letting fixer tools choke on huge inputs, which could be surprising to the # user. -configitem("fix", "maxfilesize", default="2MB") +configitem(b"fix", b"maxfilesize", default=b"2MB") # Allow fix commands to exit non-zero if an executed fixer tool exits non-zero. # This helps users do shell scripts that stop when a fixer tool signals a # problem. -configitem("fix", "failure", default="continue") +configitem(b"fix", b"failure", default=b"continue") def checktoolfailureaction(ui, message, hint=None): """Abort with 'message' if fix.failure=abort""" - action = ui.config("fix", "failure") - if action not in ("continue", "abort"): + action = ui.config(b"fix", b"failure") + if action not in (b"continue", b"abort"): raise error.Abort( - _("unknown fix.failure action: %s") % (action,), - hint=_('use "continue" or "abort"'), + _(b"unknown fix.failure action: %s") % (action,), + hint=_(b'use "continue" or "abort"'), ) - if action == "abort": + if action == b"abort": raise error.Abort(message, hint=hint) -allopt = ("", "all", False, _("fix all non-public non-obsolete revisions")) +allopt = (b"", b"all", False, _(b"fix all non-public non-obsolete revisions")) baseopt = ( - "", - "base", + b"", + b"base", [], _( - "revisions to diff against (overrides automatic " - "selection, and applies to every revision being " - "fixed)" + b"revisions to diff against (overrides automatic " + b"selection, and applies to every revision being " + b"fixed)" ), - _("REV"), + _(b"REV"), ) -revopt = ("r", "rev", [], _("revisions to fix"), _("REV")) -wdiropt = ("w", "working-dir", False, _("fix the working directory")) -wholeopt = ("", "whole", False, _("always fix every line of a file")) -usage = _("[OPTION]... [FILE]...") +revopt = (b"r", b"rev", [], _(b"revisions to fix"), _(b"REV")) +wdiropt = (b"w", b"working-dir", False, _(b"fix the working directory")) +wholeopt = (b"", b"whole", False, _(b"always fix every line of a file")) +usage = _(b"[OPTION]... [FILE]...") @command( - "fix", + b"fix", [allopt, baseopt, revopt, wdiropt, wholeopt], usage, helpcategory=command.CATEGORY_FILE_CONTENTS, @@ -249,12 +249,12 @@ override this default behavior, though it is not usually desirable to do so. """ opts = pycompat.byteskwargs(opts) - if opts["all"]: - if opts["rev"]: - raise error.Abort(_('cannot specify both "--rev" and "--all"')) - opts["rev"] = ["not public() and not obsolete()"] - opts["working_dir"] = True - with repo.wlock(), repo.lock(), repo.transaction("fix"): + if opts[b"all"]: + if opts[b"rev"]: + raise error.Abort(_(b'cannot specify both "--rev" and "--all"')) + opts[b"rev"] = [b"not public() and not obsolete()"] + opts[b"working_dir"] = True + with repo.wlock(), repo.lock(), repo.transaction(b"fix"): revstofix = getrevstofix(ui, repo, opts) basectxs = getbasectxs(repo, opts, revstofix) workqueue, numitems = getworkqueue( @@ -296,7 +296,7 @@ wdirwritten = False commitorder = sorted(revstofix, reverse=True) with ui.makeprogress( - topic=_("fixing"), unit=_("files"), total=sum(numitems.values()) + topic=_(b"fixing"), unit=_(b"files"), total=sum(numitems.values()) ) as progress: for rev, path, filerevmetadata, newdata in results: progress.increment(item=path) @@ -305,12 +305,12 @@ if newdata is not None: filedata[rev][path] = newdata hookargs = { - "rev": rev, - "path": path, - "metadata": filerevmetadata, + b"rev": rev, + b"path": path, + b"metadata": filerevmetadata, } repo.hook( - "postfixfile", + b"postfixfile", throw=False, **pycompat.strkwargs(hookargs) ) @@ -331,11 +331,11 @@ cleanup(repo, replacements, wdirwritten) hookargs = { - "replacements": replacements, - "wdirwritten": wdirwritten, - "metadata": aggregatemetadata, + b"replacements": replacements, + b"wdirwritten": wdirwritten, + b"metadata": aggregatemetadata, } - repo.hook("postfix", throw=True, **pycompat.strkwargs(hookargs)) + repo.hook(b"postfix", throw=True, **pycompat.strkwargs(hookargs)) def cleanup(repo, replacements, wdirwritten): @@ -352,7 +352,7 @@ effects of the command, though we choose not to output anything here. """ replacements = {prec: [succ] for prec, succ in replacements.iteritems()} - scmutil.cleanupnodes(repo, replacements, "fix", fixphase=True) + scmutil.cleanupnodes(repo, replacements, b"fix", fixphase=True) def getworkqueue(ui, repo, pats, opts, revstofix, basectxs): @@ -374,7 +374,7 @@ """ workqueue = [] numitems = collections.defaultdict(int) - maxfilesize = ui.configbytes("fix", "maxfilesize") + maxfilesize = ui.configbytes(b"fix", b"maxfilesize") for rev in sorted(revstofix): fixctx = repo[rev] match = scmutil.match(fixctx, pats, opts) @@ -386,7 +386,7 @@ continue if fctx.size() > maxfilesize: ui.warn( - _("ignoring file larger than %s: %s\n") + _(b"ignoring file larger than %s: %s\n") % (util.bytecount(maxfilesize), path) ) continue @@ -397,29 +397,29 @@ def getrevstofix(ui, repo, opts): """Returns the set of revision numbers that should be fixed""" - revs = set(scmutil.revrange(repo, opts["rev"])) + revs = set(scmutil.revrange(repo, opts[b"rev"])) for rev in revs: checkfixablectx(ui, repo, repo[rev]) if revs: cmdutil.checkunfinished(repo) checknodescendants(repo, revs) - if opts.get("working_dir"): + if opts.get(b"working_dir"): revs.add(wdirrev) if list(merge.mergestate.read(repo).unresolved()): - raise error.Abort("unresolved conflicts", hint="use 'hg resolve'") + raise error.Abort(b"unresolved conflicts", hint=b"use 'hg resolve'") if not revs: raise error.Abort( - "no changesets specified", hint="use --rev or --working-dir" + b"no changesets specified", hint=b"use --rev or --working-dir" ) return revs def checknodescendants(repo, revs): if not obsolete.isenabled(repo, obsolete.allowunstableopt) and repo.revs( - "(%ld::) - (%ld)", revs, revs + b"(%ld::) - (%ld)", revs, revs ): raise error.Abort( - _("can only fix a changeset together " "with all its descendants") + _(b"can only fix a changeset together " b"with all its descendants") ) @@ -427,15 +427,17 @@ """Aborts if the revision shouldn't be replaced with a fixed one.""" if not ctx.mutable(): raise error.Abort( - "can't fix immutable changeset %s" % (scmutil.formatchangeid(ctx),) + b"can't fix immutable changeset %s" % (scmutil.formatchangeid(ctx),) ) if ctx.obsolete(): # It would be better to actually check if the revision has a successor. allowdivergence = ui.configbool( - "experimental", "evolution.allowdivergence" + b"experimental", b"evolution.allowdivergence" ) if not allowdivergence: - raise error.Abort("fixing obsolete revision could cause divergence") + raise error.Abort( + b"fixing obsolete revision could cause divergence" + ) def pathstofix(ui, repo, pats, opts, match, basectxs, fixctx): @@ -472,10 +474,10 @@ Another way to understand this is that we exclude line ranges that are common to the file in all base contexts. """ - if opts.get("whole"): + if opts.get(b"whole"): # Return a range containing all lines. Rely on the diff implementation's # idea of how many lines are in the file, instead of reimplementing it. - return difflineranges("", content2) + return difflineranges(b"", content2) rangeslist = [] for basectx in basectxs: @@ -483,7 +485,7 @@ if basepath in basectx: content1 = basectx[basepath].data() else: - content1 = "" + content1 = b"" rangeslist.extend(difflineranges(content1, content2)) return unionranges(rangeslist) @@ -565,7 +567,7 @@ ranges = [] for lines, kind in mdiff.allblocks(content1, content2): firstline, lastline = lines[2:4] - if kind == "!" and firstline != lastline: + if kind == b"!" and firstline != lastline: ranges.append((firstline + 1, lastline)) return ranges @@ -580,8 +582,8 @@ """ # The --base flag overrides the usual logic, and we give every revision # exactly the set of baserevs that the user specified. - if opts.get("base"): - baserevs = set(scmutil.revrange(repo, opts.get("base"))) + if opts.get(b"base"): + baserevs = set(scmutil.revrange(repo, opts.get(b"base"))) if not baserevs: baserevs = {nullrev} basectxs = {repo[rev] for rev in baserevs} @@ -620,7 +622,7 @@ command = fixer.command(ui, path, ranges) if command is None: continue - ui.debug("subprocess: %s\n" % (command,)) + ui.debug(b"subprocess: %s\n" % (command,)) proc = subprocess.Popen( procutil.tonativestr(command), shell=True, @@ -635,11 +637,11 @@ newerdata = stdout if fixer.shouldoutputmetadata(): try: - metadatajson, newerdata = stdout.split("\0", 1) + metadatajson, newerdata = stdout.split(b"\0", 1) metadata[fixername] = json.loads(metadatajson) except ValueError: ui.warn( - _("ignored invalid output from fixer tool: %s\n") + _(b"ignored invalid output from fixer tool: %s\n") % (fixername,) ) continue @@ -649,14 +651,14 @@ newdata = newerdata else: if not stderr: - message = _("exited with status %d\n") % (proc.returncode,) + message = _(b"exited with status %d\n") % (proc.returncode,) showstderr(ui, fixctx.rev(), fixername, message) checktoolfailureaction( ui, - _("no fixes will be applied"), + _(b"no fixes will be applied"), hint=_( - "use --config fix.failure=continue to apply any " - "successful fixes anyway" + b"use --config fix.failure=continue to apply any " + b"successful fixes anyway" ), ) return metadata, newdata @@ -670,14 +672,14 @@ space and would tend to be included in the error message if they were relevant. """ - for line in re.split("[\r\n]+", stderr): + for line in re.split(b"[\r\n]+", stderr): if line: - ui.warn("[") + ui.warn(b"[") if rev is None: - ui.warn(_("wdir"), label="evolve.rev") + ui.warn(_(b"wdir"), label=b"evolve.rev") else: - ui.warn((str(rev)), label="evolve.rev") - ui.warn("] %s: %s\n" % (fixername, line)) + ui.warn((str(rev)), label=b"evolve.rev") + ui.warn(b"] %s: %s\n" % (fixername, line)) def writeworkingdir(repo, ctx, filedata, replacements): @@ -693,7 +695,7 @@ for path, data in filedata.iteritems(): fctx = ctx[path] fctx.write(data, fctx.flags()) - if repo.dirstate[path] == "n": + if repo.dirstate[path] == b"n": repo.dirstate.normallookup(path) oldparentnodes = repo.dirstate.parents() @@ -756,7 +758,7 @@ ) extra = ctx.extra().copy() - extra["fix_source"] = ctx.hex() + extra[b"fix_source"] = ctx.hex() memctx = context.memctx( repo, @@ -773,7 +775,7 @@ sucnode = memctx.commit() prenode = ctx.node() if prenode == sucnode: - ui.debug("node %s already existed\n" % (ctx.hex())) + ui.debug(b"node %s already existed\n" % (ctx.hex())) else: replacements[ctx.node()] = sucnode @@ -787,11 +789,11 @@ fixers = {} for name in fixernames(ui): fixers[name] = Fixer() - attrs = ui.configsuboptions("fix", name)[1] + attrs = ui.configsuboptions(b"fix", name)[1] for key, default in FIXER_ATTRS.items(): setattr( fixers[name], - pycompat.sysstr("_" + key), + pycompat.sysstr(b"_" + key), attrs.get(key, default), ) fixers[name]._priority = int(fixers[name]._priority) @@ -803,7 +805,7 @@ # default. if fixers[name]._pattern is None: ui.warn( - _("fixer tool has no pattern configuration: %s\n") % (name,) + _(b"fixer tool has no pattern configuration: %s\n") % (name,) ) del fixers[name] return collections.OrderedDict( @@ -814,9 +816,9 @@ def fixernames(ui): """Returns the names of [fix] config options that have suboptions""" names = set() - for k, v in ui.configitems("fix"): - if ":" in k: - names.add(k.split(":", 1)[0]) + for k, v in ui.configitems(b"fix"): + if b":" in k: + names.add(k.split(b":", 1)[0]) return names @@ -844,7 +846,7 @@ expand( ui, self._command, - {"rootpath": path, "basename": os.path.basename(path)}, + {b"rootpath": path, b"basename": os.path.basename(path)}, ) ] if self._linerange: @@ -853,6 +855,8 @@ return None for first, last in ranges: parts.append( - expand(ui, self._linerange, {"first": first, "last": last}) + expand( + ui, self._linerange, {b"first": first, b"last": last} + ) ) - return " ".join(parts) + return b" ".join(parts) diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py --- a/hgext/fsmonitor/__init__.py +++ b/hgext/fsmonitor/__init__.py @@ -143,60 +143,60 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "fsmonitor", "mode", default="on", + b"fsmonitor", b"mode", default=b"on", ) configitem( - "fsmonitor", "walk_on_invalidate", default=False, + b"fsmonitor", b"walk_on_invalidate", default=False, ) configitem( - "fsmonitor", "timeout", default="2", + b"fsmonitor", b"timeout", default=b"2", ) configitem( - "fsmonitor", "blacklistusers", default=list, + b"fsmonitor", b"blacklistusers", default=list, ) configitem( - "fsmonitor", "watchman_exe", default="watchman", + b"fsmonitor", b"watchman_exe", default=b"watchman", ) configitem( - "fsmonitor", "verbose", default=True, experimental=True, + b"fsmonitor", b"verbose", default=True, experimental=True, ) configitem( - "experimental", "fsmonitor.transaction_notify", default=False, + b"experimental", b"fsmonitor.transaction_notify", default=False, ) # This extension is incompatible with the following blacklisted extensions # and will disable itself when encountering one of these: -_blacklist = ["largefiles", "eol"] +_blacklist = [b"largefiles", b"eol"] def debuginstall(ui, fm): fm.write( - "fsmonitor-watchman", - _("fsmonitor checking for watchman binary... (%s)\n"), - ui.configpath("fsmonitor", "watchman_exe"), + b"fsmonitor-watchman", + _(b"fsmonitor checking for watchman binary... (%s)\n"), + ui.configpath(b"fsmonitor", b"watchman_exe"), ) root = tempfile.mkdtemp() c = watchmanclient.client(ui, root) err = None try: - v = c.command("version") + v = c.command(b"version") fm.write( - "fsmonitor-watchman-version", - _(" watchman binary version %s\n"), - v["version"], + b"fsmonitor-watchman-version", + _(b" watchman binary version %s\n"), + v[b"version"], ) except watchmanclient.Unavailable as e: err = str(e) fm.condwrite( err, - "fsmonitor-watchman-error", - _(" watchman binary missing or broken: %s\n"), + b"fsmonitor-watchman-error", + _(b" watchman binary missing or broken: %s\n"), err, ) return 1 if err else 0 @@ -206,16 +206,16 @@ """Exception handler for Watchman interaction exceptions""" if isinstance(ex, watchmanclient.Unavailable): # experimental config: fsmonitor.verbose - if ex.warn and ui.configbool("fsmonitor", "verbose"): - if "illegal_fstypes" not in str(ex): - ui.warn(str(ex) + "\n") + if ex.warn and ui.configbool(b"fsmonitor", b"verbose"): + if b"illegal_fstypes" not in str(ex): + ui.warn(str(ex) + b"\n") if ex.invalidate: state.invalidate() # experimental config: fsmonitor.verbose - if ui.configbool("fsmonitor", "verbose"): - ui.log("fsmonitor", "Watchman unavailable: %s\n", ex.msg) + if ui.configbool(b"fsmonitor", b"verbose"): + ui.log(b"fsmonitor", b"Watchman unavailable: %s\n", ex.msg) else: - ui.log("fsmonitor", "Watchman exception: %s\n", ex) + ui.log(b"fsmonitor", b"Watchman exception: %s\n", ex) def _hashignore(ignore): @@ -245,7 +245,7 @@ try: decoded = path.decode(_watchmanencoding) except UnicodeDecodeError as e: - raise error.Abort(str(e), hint="watchman encoding error") + raise error.Abort(str(e), hint=b"watchman encoding error") try: encoded = decoded.encode(_fsencoding, "strict") @@ -263,34 +263,34 @@ subset of files.""" def bail(reason): - self._ui.debug("fsmonitor: fallback to core status, %s\n" % reason) + self._ui.debug(b"fsmonitor: fallback to core status, %s\n" % reason) return orig(match, subrepos, unknown, ignored, full=True) if full: - return bail("full rewalk requested") + return bail(b"full rewalk requested") if ignored: - return bail("listing ignored files") + return bail(b"listing ignored files") if not self._watchmanclient.available(): - return bail("client unavailable") + return bail(b"client unavailable") state = self._fsmonitorstate clock, ignorehash, notefiles = state.get() if not clock: if state.walk_on_invalidate: - return bail("no clock") + return bail(b"no clock") # Initial NULL clock value, see # https://facebook.github.io/watchman/docs/clockspec.html - clock = "c:0:0" + clock = b"c:0:0" notefiles = [] ignore = self._ignore dirignore = self._dirignore if unknown: - if _hashignore(ignore) != ignorehash and clock != "c:0:0": + if _hashignore(ignore) != ignorehash and clock != b"c:0:0": # ignore list changed -- can't rely on Watchman state any more if state.walk_on_invalidate: - return bail("ignore rules changed") + return bail(b"ignore rules changed") notefiles = [] - clock = "c:0:0" + clock = b"c:0:0" else: # always ignore ignore = util.always @@ -299,7 +299,7 @@ matchfn = match.matchfn matchalways = match.always() dmap = self._map - if util.safehasattr(dmap, "_map"): + if util.safehasattr(dmap, b"_map"): # for better performance, directly access the inner dirstate map if the # standard dirstate implementation is in use. dmap = dmap._map @@ -339,7 +339,7 @@ if not work and (exact or skipstep3): for s in subrepos: del results[s] - del results[".hg"] + del results[b".hg"] return results # step 2: query Watchman @@ -349,30 +349,34 @@ # overheads while transferring the data self._watchmanclient.settimeout(state.timeout + 0.1) result = self._watchmanclient.command( - "query", + b"query", { - "fields": ["mode", "mtime", "size", "exists", "name"], - "since": clock, - "expression": [ - "not", - ["anyof", ["dirname", ".hg"], ["name", ".hg", "wholename"]], + b"fields": [b"mode", b"mtime", b"size", b"exists", b"name"], + b"since": clock, + b"expression": [ + b"not", + [ + b"anyof", + [b"dirname", b".hg"], + [b"name", b".hg", b"wholename"], + ], ], - "sync_timeout": int(state.timeout * 1000), - "empty_on_fresh_instance": state.walk_on_invalidate, + b"sync_timeout": int(state.timeout * 1000), + b"empty_on_fresh_instance": state.walk_on_invalidate, }, ) except Exception as ex: _handleunavailable(self._ui, state, ex) self._watchmanclient.clearconnection() - return bail("exception during run") + return bail(b"exception during run") else: # We need to propagate the last observed clock up so that we # can use it for our next query - state.setlastclock(result["clock"]) - if result["is_fresh_instance"]: + state.setlastclock(result[b"clock"]) + if result[b"is_fresh_instance"]: if state.walk_on_invalidate: state.invalidate() - return bail("fresh instance") + return bail(b"fresh instance") fresh_instance = True # Ignore any prior noteable files from the state info notefiles = [] @@ -382,7 +386,7 @@ if normalize: foldmap = dict((normcase(k), k) for k in results) - switch_slashes = pycompat.ossep == "\\" + switch_slashes = pycompat.ossep == b"\\" # The order of the results is, strictly speaking, undefined. # For case changes on a case insensitive filesystem we may receive # two entries, one with exists=True and another with exists=False. @@ -390,22 +394,22 @@ # as being happens-after the exists=False entries due to the way that # Watchman tracks files. We use this property to reconcile deletes # for name case changes. - for entry in result["files"]: - fname = entry["name"] + for entry in result[b"files"]: + fname = entry[b"name"] if _fixencoding: fname = _watchmantofsencoding(fname) if switch_slashes: - fname = fname.replace("\\", "/") + fname = fname.replace(b"\\", b"/") if normalize: normed = normcase(fname) fname = normalize(fname, True, True) foldmap[normed] = fname - fmode = entry["mode"] - fexists = entry["exists"] + fmode = entry[b"mode"] + fexists = entry[b"exists"] kind = getkind(fmode) - if "/.hg/" in fname or fname.endswith("/.hg"): - return bail("nested-repo-detected") + if b"/.hg/" in fname or fname.endswith(b"/.hg"): + return bail(b"nested-repo-detected") if not fexists: # if marked as deleted and we don't already have a change @@ -488,14 +492,14 @@ for s in subrepos: del results[s] - del results[".hg"] + del results[b".hg"] return results def overridestatus( orig, self, - node1=".", + node1=b".", node2=None, match=None, ignored=False, @@ -509,22 +513,22 @@ def _cmpsets(l1, l2): try: - if "FSMONITOR_LOG_FILE" in encoding.environ: - fn = encoding.environ["FSMONITOR_LOG_FILE"] - f = open(fn, "wb") + if b"FSMONITOR_LOG_FILE" in encoding.environ: + fn = encoding.environ[b"FSMONITOR_LOG_FILE"] + f = open(fn, b"wb") else: - fn = "fsmonitorfail.log" - f = self.vfs.open(fn, "wb") + fn = b"fsmonitorfail.log" + f = self.vfs.open(fn, b"wb") except (IOError, OSError): - self.ui.warn(_("warning: unable to write to %s\n") % fn) + self.ui.warn(_(b"warning: unable to write to %s\n") % fn) return try: for i, (s1, s2) in enumerate(zip(l1, l2)): if set(s1) != set(s2): - f.write("sets at position %d are unequal\n" % i) - f.write("watchman returned: %s\n" % s1) - f.write("stat returned: %s\n" % s2) + f.write(b"sets at position %d are unequal\n" % i) + f.write(b"watchman returned: %s\n" % s1) + f.write(b"stat returned: %s\n" % s2) finally: f.close() @@ -538,7 +542,7 @@ ctx2 = self[node2] working = ctx2.rev() is None - parentworking = working and ctx1 == self["."] + parentworking = working and ctx1 == self[b"."] match = match or matchmod.always() # Maybe we can use this opportunity to update Watchman's state. @@ -552,7 +556,7 @@ parentworking and match.always() and not isinstance(ctx2, (context.workingcommitctx, context.memctx)) - and "HG_PENDING" not in encoding.environ + and b"HG_PENDING" not in encoding.environ ) try: @@ -607,7 +611,7 @@ # don't do paranoid checks if we're not going to query Watchman anyway full = listclean or match.traversedir is not None - if self._fsmonitorstate.mode == "paranoid" and not full: + if self._fsmonitorstate.mode == b"paranoid" and not full: # run status again and fall back to the old walk this time self.dirstate._fsmonitordisable = True @@ -615,7 +619,7 @@ quiet = self.ui.quiet self.ui.quiet = True fout, ferr = self.ui.fout, self.ui.ferr - self.ui.fout = self.ui.ferr = open(os.devnull, "wb") + self.ui.fout = self.ui.ferr = open(os.devnull, b"wb") try: rv2 = orig( @@ -692,20 +696,20 @@ def wrapdirstate(orig, self): ds = orig(self) # only override the dirstate when Watchman is available for the repo - if util.safehasattr(self, "_fsmonitorstate"): + if util.safehasattr(self, b"_fsmonitorstate"): makedirstate(self, ds) return ds def extsetup(ui): extensions.wrapfilecache( - localrepo.localrepository, "dirstate", wrapdirstate + localrepo.localrepository, b"dirstate", wrapdirstate ) if pycompat.isdarwin: # An assist for avoiding the dangling-symlink fsevents bug - extensions.wrapfunction(os, "symlink", wrapsymlink) + extensions.wrapfunction(os, b"symlink", wrapsymlink) - extensions.wrapfunction(merge, "update", wrapupdate) + extensions.wrapfunction(merge, b"update", wrapupdate) def wrapsymlink(orig, source, link_name): @@ -756,14 +760,14 @@ # merge.update is going to take the wlock almost immediately. We are # effectively extending the lock around several short sanity checks. if self.oldnode is None: - self.oldnode = self.repo["."].node() + self.oldnode = self.repo[b"."].node() if self.repo.currentwlock() is None: - if util.safehasattr(self.repo, "wlocknostateupdate"): + if util.safehasattr(self.repo, b"wlocknostateupdate"): self._lock = self.repo.wlocknostateupdate() else: self._lock = self.repo.wlock() - self.need_leave = self._state("state-enter", hex(self.oldnode)) + self.need_leave = self._state(b"state-enter", hex(self.oldnode)) return self def __exit__(self, type_, value, tb): @@ -773,36 +777,36 @@ def exit(self, abort=False): try: if self.need_leave: - status = "failed" if abort else "ok" + status = b"failed" if abort else b"ok" if self.newnode is None: - self.newnode = self.repo["."].node() + self.newnode = self.repo[b"."].node() if self.distance is None: self.distance = calcdistance( self.repo, self.oldnode, self.newnode ) - self._state("state-leave", hex(self.newnode), status=status) + self._state(b"state-leave", hex(self.newnode), status=status) finally: self.need_leave = False if self._lock: self._lock.release() - def _state(self, cmd, commithash, status="ok"): - if not util.safehasattr(self.repo, "_watchmanclient"): + def _state(self, cmd, commithash, status=b"ok"): + if not util.safehasattr(self.repo, b"_watchmanclient"): return False try: self.repo._watchmanclient.command( cmd, { - "name": self.name, - "metadata": { + b"name": self.name, + b"metadata": { # the target revision - "rev": commithash, + b"rev": commithash, # approximate number of commits between current and target - "distance": self.distance if self.distance else 0, + b"distance": self.distance if self.distance else 0, # success/failure (only really meaningful for state-leave) - "status": status, + b"status": status, # whether the working copy parent is changing - "partial": self.partial, + b"partial": self.partial, }, }, ) @@ -810,7 +814,7 @@ except Exception as e: # Swallow any errors; fire and forget self.repo.ui.log( - "watchman", "Exception %s while running %s\n", e, cmd + b"watchman", b"Exception %s while running %s\n", e, cmd ) return False @@ -844,7 +848,7 @@ distance = 0 partial = True - oldnode = repo["."].node() + oldnode = repo[b"."].node() newnode = repo[node].node() if matcher is None or matcher.always(): partial = False @@ -852,7 +856,7 @@ with state_update( repo, - name="hg.update", + name=b"hg.update", oldnode=oldnode, newnode=newnode, distance=distance, @@ -873,8 +877,8 @@ def repo_has_depth_one_nested_repo(repo): for f in repo.wvfs.listdir(): - if os.path.isdir(os.path.join(repo.root, f, ".hg")): - msg = "fsmonitor: sub-repository %r detected, fsmonitor disabled\n" + if os.path.isdir(os.path.join(repo.root, f, b".hg")): + msg = b"fsmonitor: sub-repository %r detected, fsmonitor disabled\n" repo.ui.debug(msg % f) return True return False @@ -887,8 +891,8 @@ if ext in exts: ui.warn( _( - "The fsmonitor extension is incompatible with the %s " - "extension and has been disabled.\n" + b"The fsmonitor extension is incompatible with the %s " + b"extension and has been disabled.\n" ) % ext ) @@ -899,14 +903,14 @@ # # if repo[None].substate can cause a dirstate parse, which is too # slow. Instead, look for a file called hgsubstate, - if repo.wvfs.exists(".hgsubstate") or repo.wvfs.exists(".hgsub"): + if repo.wvfs.exists(b".hgsubstate") or repo.wvfs.exists(b".hgsub"): return if repo_has_depth_one_nested_repo(repo): return fsmonitorstate = state.state(repo) - if fsmonitorstate.mode == "off": + if fsmonitorstate.mode == b"off": return try: @@ -918,7 +922,7 @@ repo._fsmonitorstate = fsmonitorstate repo._watchmanclient = client - dirstate, cached = localrepo.isfilecached(repo, "dirstate") + dirstate, cached = localrepo.isfilecached(repo, b"dirstate") if cached: # at this point since fsmonitorstate wasn't present, # repo.dirstate is not a fsmonitordirstate @@ -935,7 +939,7 @@ def wlock(self, *args, **kwargs): l = super(fsmonitorrepo, self).wlock(*args, **kwargs) if not ui.configbool( - "experimental", "fsmonitor.transaction_notify" + b"experimental", b"fsmonitor.transaction_notify" ): return l if l.held != 1: @@ -951,12 +955,14 @@ try: l.stateupdate = None - l.stateupdate = state_update(self, name="hg.transaction") + l.stateupdate = state_update(self, name=b"hg.transaction") l.stateupdate.enter() l.releasefn = staterelease except Exception as e: # Swallow any errors; fire and forget - self.ui.log("watchman", "Exception in state update %s\n", e) + self.ui.log( + b"watchman", b"Exception in state update %s\n", e + ) return l repo.__class__ = fsmonitorrepo diff --git a/hgext/fsmonitor/pywatchman/__init__.py b/hgext/fsmonitor/pywatchman/__init__.py --- a/hgext/fsmonitor/pywatchman/__init__.py +++ b/hgext/fsmonitor/pywatchman/__init__.py @@ -62,7 +62,7 @@ ) -if os.name == "nt": +if os.name == b"nt": import ctypes import ctypes.wintypes @@ -90,11 +90,11 @@ class OVERLAPPED(ctypes.Structure): _fields_ = [ - ("Internal", ULONG_PTR), - ("InternalHigh", ULONG_PTR), - ("Offset", wintypes.DWORD), - ("OffsetHigh", wintypes.DWORD), - ("hEvent", wintypes.HANDLE), + (b"Internal", ULONG_PTR), + (b"InternalHigh", ULONG_PTR), + (b"Offset", wintypes.DWORD), + (b"OffsetHigh", wintypes.DWORD), + (b"hEvent", wintypes.HANDLE), ] def __init__(self): @@ -217,9 +217,9 @@ def log(fmt, *args): print( - "[%s] %s" + b"[%s] %s" % ( - time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()), + time.strftime(b"%a, %d %b %Y %H:%M:%S", time.gmtime()), fmt % args[:], ) ) @@ -263,21 +263,21 @@ def __str__(self): if self.cmd: - return "%s, while executing %s" % (self.msg, self.cmd) + return b"%s, while executing %s" % (self.msg, self.cmd) return self.msg class WatchmanEnvironmentError(WatchmanError): def __init__(self, msg, errno, errmsg, cmd=None): super(WatchmanEnvironmentError, self).__init__( - "{0}: errno={1} errmsg={2}".format(msg, errno, errmsg), cmd + b"{0}: errno={1} errmsg={2}".format(msg, errno, errmsg), cmd ) class SocketConnectError(WatchmanError): def __init__(self, sockpath, exc): super(SocketConnectError, self).__init__( - "unable to connect to %s: %s" % (sockpath, exc) + b"unable to connect to %s: %s" % (sockpath, exc) ) self.sockpath = sockpath self.exc = exc @@ -301,7 +301,7 @@ def __init__(self, msg, cmd=None): super(CommandError, self).__init__( - "watchman command error: %s" % (msg,), cmd, + b"watchman command error: %s" % (msg,), cmd, ) @@ -398,16 +398,16 @@ try: buf = [self.sock.recv(size)] if not buf[0]: - raise WatchmanError("empty watchman response") + raise WatchmanError(b"empty watchman response") return buf[0] except socket.timeout: - raise SocketTimeout("timed out waiting for response") + raise SocketTimeout(b"timed out waiting for response") def write(self, data): try: self.sock.sendall(data) except socket.timeout: - raise SocketTimeout("timed out sending query command") + raise SocketTimeout(b"timed out sending query command") def _get_overlapped_result_ex_impl(pipe, olap, nbytes, millis, alertable): @@ -420,7 +420,7 @@ source code (see get_overlapped_result_ex_impl in stream_win.c). This way, maintenance should be simplified. """ - log("Preparing to wait for maximum %dms", millis) + log(b"Preparing to wait for maximum %dms", millis) if millis != 0: waitReturnCode = WaitForSingleObjectEx(olap.hEvent, millis, alertable) if waitReturnCode == WAIT_OBJECT_0: @@ -439,12 +439,12 @@ elif waitReturnCode == WAIT_FAILED: # something went wrong calling WaitForSingleObjectEx err = GetLastError() - log("WaitForSingleObjectEx failed: %s", _win32_strerror(err)) + log(b"WaitForSingleObjectEx failed: %s", _win32_strerror(err)) return False else: # unexpected situation deserving investigation. err = GetLastError() - log("Unexpected error: %s", _win32_strerror(err)) + log(b"Unexpected error: %s", _win32_strerror(err)) return False return GetOverlappedResult(pipe, olap, nbytes, False) @@ -471,29 +471,29 @@ if self.pipe == INVALID_HANDLE_VALUE: self.pipe = None self._raise_win_err( - "failed to open pipe %s" % sockpath, GetLastError() + b"failed to open pipe %s" % sockpath, GetLastError() ) # event for the overlapped I/O operations self._waitable = CreateEvent(None, True, False, None) if self._waitable is None: - self._raise_win_err("CreateEvent failed", GetLastError()) + self._raise_win_err(b"CreateEvent failed", GetLastError()) self._get_overlapped_result_ex = GetOverlappedResultEx if ( - os.getenv("WATCHMAN_WIN7_COMPAT") == "1" + os.getenv(b"WATCHMAN_WIN7_COMPAT") == b"1" or self._get_overlapped_result_ex is None ): self._get_overlapped_result_ex = _get_overlapped_result_ex_impl def _raise_win_err(self, msg, err): raise IOError( - "%s win32 error code: %d %s" % (msg, err, _win32_strerror(err)) + b"%s win32 error code: %d %s" % (msg, err, _win32_strerror(err)) ) def close(self): if self.pipe: - log("Closing pipe") + log(b"Closing pipe") CloseHandle(self.pipe) self.pipe = None @@ -527,7 +527,7 @@ olap = OVERLAPPED() olap.hEvent = self._waitable - log("made read buff of size %d", size) + log(b"made read buff of size %d", size) # ReadFile docs warn against sending in the nread parameter for async # operations, so we always collect it via GetOverlappedResultEx @@ -537,7 +537,7 @@ err = GetLastError() if err != ERROR_IO_PENDING: self._raise_win_err( - "failed to read %d bytes" % size, GetLastError() + b"failed to read %d bytes" % size, GetLastError() ) nread = wintypes.DWORD() @@ -548,13 +548,13 @@ CancelIoEx(self.pipe, olap) if err == WAIT_TIMEOUT: - log("GetOverlappedResultEx timedout") + log(b"GetOverlappedResultEx timedout") raise SocketTimeout( - "timed out after waiting %dms for read" % self.timeout + b"timed out after waiting %dms for read" % self.timeout ) - log("GetOverlappedResultEx reports error %d", err) - self._raise_win_err("error while waiting for read", err) + log(b"GetOverlappedResultEx reports error %d", err) + self._raise_win_err(b"error while waiting for read", err) nread = nread.value if nread == 0: @@ -563,7 +563,7 @@ # other way this shows up is if the client has gotten in a weird # state, so let's bail out CancelIoEx(self.pipe, olap) - raise IOError("Async read yielded 0 bytes; unpossible!") + raise IOError(b"Async read yielded 0 bytes; unpossible!") # Holds precisely the bytes that we read from the prior request buf = buf[:nread] @@ -588,7 +588,7 @@ err = GetLastError() if err != ERROR_IO_PENDING: self._raise_win_err( - "failed to write %d bytes" % len(data), GetLastError() + b"failed to write %d bytes" % len(data), GetLastError() ) # Obtain results, waiting if needed @@ -596,7 +596,7 @@ if self._get_overlapped_result_ex( self.pipe, olap, nwrote, 0 if immediate else self.timeout, True ): - log("made write of %d bytes", nwrote.value) + log(b"made write of %d bytes", nwrote.value) return nwrote.value err = GetLastError() @@ -607,10 +607,10 @@ if err == WAIT_TIMEOUT: raise SocketTimeout( - "timed out after waiting %dms for write" % self.timeout + b"timed out after waiting %dms for write" % self.timeout ) self._raise_win_err( - "error while waiting for write of %d bytes" % len(data), err + b"error while waiting for write of %d bytes" % len(data), err ) @@ -655,13 +655,13 @@ return self.proc args = [ self.watchman_exe, - "--sockname={0}".format(self.sockpath), - "--logfile=/BOGUS", - "--statefile=/BOGUS", - "--no-spawn", - "--no-local", - "--no-pretty", - "-j", + b"--sockname={0}".format(self.sockpath), + b"--logfile=/BOGUS", + b"--statefile=/BOGUS", + b"--no-spawn", + b"--no-local", + b"--no-pretty", + b"-j", ] self.proc = subprocess.Popen( pycompat.rapply(procutil.tonativestr, args), @@ -673,8 +673,8 @@ def readBytes(self, size): self._connect() res = self.proc.stdout.read(size) - if res == "": - raise WatchmanError("EOF on CLI process transport") + if res == b"": + raise WatchmanError(b"EOF on CLI process transport") return res def write(self, data): @@ -697,7 +697,7 @@ def receive(self): buf = [self.transport.readBytes(sniff_len)] if not buf[0]: - raise WatchmanError("empty watchman response") + raise WatchmanError(b"empty watchman response") _1, _2, elen = bser.pdu_info(buf[0]) @@ -711,7 +711,7 @@ res = self._loads(response) return res except ValueError as e: - raise WatchmanError("watchman response decode error: %s" % e) + raise WatchmanError(b"watchman response decode error: %s" % e) def send(self, *args): cmd = bser.dumps(*args) # Defaults to BSER v1 @@ -733,14 +733,14 @@ super(Bser2WithFallbackCodec, self).__init__(transport) # Once the server advertises support for bser-v2 we should switch this # to 'required' on Python 3. - self.send(["version", {"optional": ["bser-v2"]}]) + self.send([b"version", {b"optional": [b"bser-v2"]}]) capabilities = self.receive() - if "error" in capabilities: - raise Exception("Unsupported BSER version") + if b"error" in capabilities: + raise Exception(b"Unsupported BSER version") - if capabilities["capabilities"]["bser-v2"]: + if capabilities[b"capabilities"][b"bser-v2"]: self.bser_version = 2 self.bser_capabilities = 0 else: @@ -753,7 +753,7 @@ def receive(self): buf = [self.transport.readBytes(sniff_len)] if not buf[0]: - raise WatchmanError("empty watchman response") + raise WatchmanError(b"empty watchman response") recv_bser_version, recv_bser_capabilities, elen = bser.pdu_info(buf[0]) @@ -772,7 +772,7 @@ res = self._loads(response) return res except ValueError as e: - raise WatchmanError("watchman response decode error: %s" % e) + raise WatchmanError(b"watchman response decode error: %s" % e) def send(self, *args): if hasattr(self, "bser_version"): @@ -835,7 +835,7 @@ subs = {} # Keyed by subscription name sub_by_root = {} # Keyed by root, then by subscription name logs = [] # When log level is raised - unilateral = ["log", "subscription"] + unilateral = [b"log", b"subscription"] tport = None useImmutableBser = None watchman_exe = None @@ -858,41 +858,43 @@ if inspect.isclass(transport) and issubclass(transport, Transport): self.transport = transport else: - transport = transport or os.getenv("WATCHMAN_TRANSPORT") or "local" - if transport == "local" and os.name == "nt": + transport = ( + transport or os.getenv(b"WATCHMAN_TRANSPORT") or b"local" + ) + if transport == b"local" and os.name == b"nt": self.transport = WindowsNamedPipeTransport - elif transport == "local": + elif transport == b"local": self.transport = UnixSocketTransport - elif transport == "cli": + elif transport == b"cli": self.transport = CLIProcessTransport if sendEncoding is None: - sendEncoding = "json" + sendEncoding = b"json" if recvEncoding is None: recvEncoding = sendEncoding else: - raise WatchmanError("invalid transport %s" % transport) + raise WatchmanError(b"invalid transport %s" % transport) sendEncoding = str( - sendEncoding or os.getenv("WATCHMAN_ENCODING") or "bser" + sendEncoding or os.getenv(b"WATCHMAN_ENCODING") or b"bser" ) recvEncoding = str( - recvEncoding or os.getenv("WATCHMAN_ENCODING") or "bser" + recvEncoding or os.getenv(b"WATCHMAN_ENCODING") or b"bser" ) self.recvCodec = self._parseEncoding(recvEncoding) self.sendCodec = self._parseEncoding(sendEncoding) def _parseEncoding(self, enc): - if enc == "bser": + if enc == b"bser": if self.useImmutableBser: return ImmutableBserCodec return BserCodec - elif enc == "experimental-bser-v2": + elif enc == b"experimental-bser-v2": return Bser2WithFallbackCodec - elif enc == "json": + elif enc == b"json": return JsonCodec else: - raise WatchmanError("invalid encoding %s" % enc) + raise WatchmanError(b"invalid encoding %s" % enc) def _hasprop(self, result, name): if self.useImmutableBser: @@ -902,42 +904,42 @@ def _resolvesockname(self): # if invoked via a trigger, watchman will set this env var; we # should use it unless explicitly set otherwise - path = os.getenv("WATCHMAN_SOCK") + path = os.getenv(b"WATCHMAN_SOCK") if path: return path - cmd = [self.watchman_exe, "--output-encoding=bser", "get-sockname"] + cmd = [self.watchman_exe, b"--output-encoding=bser", b"get-sockname"] try: args = dict( stdout=subprocess.PIPE, stderr=subprocess.PIPE, - close_fds=os.name != "nt", + close_fds=os.name != b"nt", ) - if os.name == "nt": + if os.name == b"nt": # if invoked via an application with graphical user interface, # this call will cause a brief command window pop-up. # Using the flag STARTF_USESHOWWINDOW to avoid this behavior. startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - args["startupinfo"] = startupinfo + args[b"startupinfo"] = startupinfo p = subprocess.Popen( pycompat.rapply(procutil.tonativestr, cmd), **args ) except OSError as e: - raise WatchmanError('"watchman" executable not in PATH (%s)' % e) + raise WatchmanError(b'"watchman" executable not in PATH (%s)' % e) stdout, stderr = p.communicate() exitcode = p.poll() if exitcode: - raise WatchmanError("watchman exited with code %d" % exitcode) + raise WatchmanError(b"watchman exited with code %d" % exitcode) result = bser.loads(stdout) if b"error" in result: - raise WatchmanError("get-sockname error: %s" % result["error"]) + raise WatchmanError(b"get-sockname error: %s" % result[b"error"]) return result[b"sockname"] @@ -983,26 +985,26 @@ self._connect() result = self.recvConn.receive() - if self._hasprop(result, "error"): - error = result["error"] + if self._hasprop(result, b"error"): + error = result[b"error"] if compat.PYTHON3 and isinstance(self.recvConn, BserCodec): - error = result["error"].decode("utf-8", "surrogateescape") + error = result[b"error"].decode("utf-8", "surrogateescape") raise CommandError(error) - if self._hasprop(result, "log"): - log = result["log"] + if self._hasprop(result, b"log"): + log = result[b"log"] if compat.PYTHON3 and isinstance(self.recvConn, BserCodec): log = log.decode("utf-8", "surrogateescape") self.logs.append(log) - if self._hasprop(result, "subscription"): - sub = result["subscription"] + if self._hasprop(result, b"subscription"): + sub = result[b"subscription"] if not (sub in self.subs): self.subs[sub] = [] self.subs[sub].append(result) # also accumulate in {root,sub} keyed store - root = os.path.normcase(result["root"]) + root = os.path.normcase(result[b"root"]) if not root in self.sub_by_root: self.sub_by_root[root] = {} if not sub in self.sub_by_root[root]: @@ -1012,7 +1014,7 @@ return result def isUnilateralResponse(self, res): - if "unilateral" in res and res["unilateral"]: + if b"unilateral" in res and res[b"unilateral"]: return True # Fall back to checking for known unilateral responses for k in self.unilateral: @@ -1082,7 +1084,7 @@ and NOT returned via this method. """ - log("calling client.query") + log(b"calling client.query") self._connect() try: self.sendConn.send(args) @@ -1096,7 +1098,7 @@ # When we can depend on Python 3, we can use PEP 3134 # exception chaining here. raise WatchmanEnvironmentError( - "I/O error communicating with watchman daemon", + b"I/O error communicating with watchman daemon", ee.errno, ee.strerror, args, @@ -1108,15 +1110,16 @@ def capabilityCheck(self, optional=None, required=None): """ Perform a server capability check """ res = self.query( - "version", {"optional": optional or [], "required": required or []} + b"version", + {b"optional": optional or [], b"required": required or []}, ) - if not self._hasprop(res, "capabilities"): + if not self._hasprop(res, b"capabilities"): # Server doesn't support capabilities, so we need to # synthesize the results based on the version capabilities.synthesize(res, optional) - if "error" in res: - raise CommandError(res["error"]) + if b"error" in res: + raise CommandError(res[b"error"]) return res diff --git a/hgext/fsmonitor/pywatchman/capabilities.py b/hgext/fsmonitor/pywatchman/capabilities.py --- a/hgext/fsmonitor/pywatchman/capabilities.py +++ b/hgext/fsmonitor/pywatchman/capabilities.py @@ -37,19 +37,19 @@ def parse_version(vstr): res = 0 - for n in vstr.split("."): + for n in vstr.split(b"."): res = res * 1000 res = res + int(n) return res cap_versions = { - "cmd-watch-del-all": "3.1.1", - "cmd-watch-project": "3.1", - "relative_root": "3.3", - "term-dirname": "3.1", - "term-idirname": "3.1", - "wildmatch": "3.7", + b"cmd-watch-del-all": b"3.1.1", + b"cmd-watch-project": b"3.1", + b"relative_root": b"3.3", + b"term-dirname": b"3.1", + b"term-idirname": b"3.1", + b"wildmatch": b"3.7", } @@ -63,17 +63,17 @@ """ Synthesize a capability enabled version response This is a very limited emulation for relatively recent feature sets """ - parsed_version = parse_version(vers["version"]) - vers["capabilities"] = {} - for name in opts["optional"]: - vers["capabilities"][name] = check(parsed_version, name) - for name in opts["required"]: + parsed_version = parse_version(vers[b"version"]) + vers[b"capabilities"] = {} + for name in opts[b"optional"]: + vers[b"capabilities"][name] = check(parsed_version, name) + for name in opts[b"required"]: have = check(parsed_version, name) - vers["capabilities"][name] = have + vers[b"capabilities"][name] = have if not have: - vers["error"] = ( - "client required capability `" + vers[b"error"] = ( + b"client required capability `" + name - + "` is not supported by this server" + + b"` is not supported by this server" ) return vers diff --git a/hgext/fsmonitor/pywatchman/encoding.py b/hgext/fsmonitor/pywatchman/encoding.py --- a/hgext/fsmonitor/pywatchman/encoding.py +++ b/hgext/fsmonitor/pywatchman/encoding.py @@ -40,12 +40,12 @@ from . import compat if compat.PYTHON3: - default_local_errors = "surrogateescape" + default_local_errors = b"surrogateescape" def get_local_encoding(): - if sys.platform == "win32": + if sys.platform == b"win32": # Watchman always returns UTF-8 encoded strings on Windows. - return "utf-8" + return b"utf-8" # On the Python 3 versions we support, sys.getfilesystemencoding never # returns None. return sys.getfilesystemencoding() @@ -55,16 +55,16 @@ # Python 2 doesn't support surrogateescape, so use 'strict' by # default. Users can register a custom surrogateescape error handler and use # that if they so desire. - default_local_errors = "strict" + default_local_errors = b"strict" def get_local_encoding(): - if sys.platform == "win32": + if sys.platform == b"win32": # Watchman always returns UTF-8 encoded strings on Windows. - return "utf-8" + return b"utf-8" fsencoding = sys.getfilesystemencoding() if fsencoding is None: # This is very unlikely to happen, but if it does, just use UTF-8 - fsencoding = "utf-8" + fsencoding = b"utf-8" return fsencoding diff --git a/hgext/fsmonitor/pywatchman/load.py b/hgext/fsmonitor/pywatchman/load.py --- a/hgext/fsmonitor/pywatchman/load.py +++ b/hgext/fsmonitor/pywatchman/load.py @@ -100,7 +100,7 @@ ) read_len = _read_bytes(fp, body) if read_len < len(body): - raise RuntimeError("bser data ended early") + raise RuntimeError(b"bser data ended early") return bser.loads( (ctypes.c_char * total_len).from_buffer(buf, 0), diff --git a/hgext/fsmonitor/pywatchman/pybser.py b/hgext/fsmonitor/pywatchman/pybser.py --- a/hgext/fsmonitor/pywatchman/pybser.py +++ b/hgext/fsmonitor/pywatchman/pybser.py @@ -85,7 +85,7 @@ elif long(-0x8000000000000000) <= x <= long(0x7FFFFFFFFFFFFFFF): return 8 else: - raise RuntimeError("Cannot represent value: " + str(x)) + raise RuntimeError(b"Cannot represent value: " + str(x)) def _buf_pos(buf, pos): @@ -133,7 +133,7 @@ elif size == 8: struct.pack_into(b"=cq", self.buf, self.wpos, BSER_INT64, val) else: - raise RuntimeError("Cannot represent this long value") + raise RuntimeError(b"Cannot represent this long value") self.wpos += to_write def append_string(self, s): @@ -184,7 +184,7 @@ s, ) else: - raise RuntimeError("Cannot represent this string value") + raise RuntimeError(b"Cannot represent this string value") self.wpos += to_write def append_recursive(self, val): @@ -255,7 +255,7 @@ val_len, ) else: - raise RuntimeError("Cannot represent this mapping value") + raise RuntimeError(b"Cannot represent this mapping value") self.wpos += needed if compat.PYTHON3: iteritems = val.items() @@ -303,12 +303,12 @@ val_len, ) else: - raise RuntimeError("Cannot represent this sequence value") + raise RuntimeError(b"Cannot represent this sequence value") self.wpos += needed for v in val: self.append_recursive(v) else: - raise RuntimeError("Cannot represent unknown value type") + raise RuntimeError(b"Cannot represent unknown value type") def dumps(obj, version=1, capabilities=0): @@ -329,7 +329,7 @@ # It provides by getattr accessors and getitem for both index # and name. class _BunserDict(object): - __slots__ = ("_keys", "_values") + __slots__ = (b"_keys", b"_values") def __init__(self, keys, values): self._keys = keys @@ -341,14 +341,14 @@ def __getitem__(self, key): if isinstance(key, (int, long)): return self._values[key] - elif key.startswith("st_"): + elif key.startswith(b"st_"): # hack^Wfeature to allow mercurial to use "st_size" to # reference "size" key = key[3:] try: return self._values[self._keys.index(key)] except ValueError: - raise KeyError("_BunserDict has no key %s" % key) + raise KeyError(b"_BunserDict has no key %s" % key) def __len__(self): return len(self._keys) @@ -362,7 +362,7 @@ if value_encoding is None: self.value_errors = None elif value_errors is None: - self.value_errors = "strict" + self.value_errors = b"strict" else: self.value_errors = value_errors @@ -371,7 +371,7 @@ try: int_type = _buf_pos(buf, pos) except IndexError: - raise ValueError("Invalid bser int encoding, pos out of range") + raise ValueError(b"Invalid bser int encoding, pos out of range") if int_type == BSER_INT8: needed = 2 fmt = b"=b" @@ -386,7 +386,7 @@ fmt = b"=q" else: raise ValueError( - "Invalid bser int encoding 0x%s" + b"Invalid bser int encoding 0x%s" % binascii.hexlify(int_type).decode("ascii") ) int_val = struct.unpack_from(fmt, buf, pos + 1)[0] @@ -442,9 +442,9 @@ def unser_template(self, buf, pos): val_type = _buf_pos(buf, pos + 1) if val_type != BSER_ARRAY: - raise RuntimeError("Expect ARRAY to follow TEMPLATE") + raise RuntimeError(b"Expect ARRAY to follow TEMPLATE") # force UTF-8 on keys - keys_bunser = Bunser(mutable=self.mutable, value_encoding="utf-8") + keys_bunser = Bunser(mutable=self.mutable, value_encoding=b"utf-8") keys, pos = keys_bunser.unser_array(buf, pos + 1) nitems, pos = self.unser_int(buf, pos) arr = [] @@ -503,7 +503,7 @@ return self.unser_template(buf, pos) else: raise ValueError( - "unhandled bser opcode 0x%s" + b"unhandled bser opcode 0x%s" % binascii.hexlify(val_type).decode("ascii") ) @@ -515,12 +515,12 @@ expected_len, pos2 = Bunser.unser_int(buf, 2) elif buf[0:2] == EMPTY_HEADER_V2[0:2]: if len(buf) < 8: - raise ValueError("Invalid BSER header") + raise ValueError(b"Invalid BSER header") bser_version = 2 - bser_capabilities = struct.unpack_from("I", buf, 2)[0] + bser_capabilities = struct.unpack_from(b"I", buf, 2)[0] expected_len, pos2 = Bunser.unser_int(buf, 6) else: - raise ValueError("Invalid BSER header") + raise ValueError(b"Invalid BSER header") return bser_version, bser_capabilities, expected_len, pos2 @@ -559,7 +559,7 @@ pos = info[3] if len(buf) != expected_len + pos: - raise ValueError("bser data len != header len") + raise ValueError(b"bser data len != header len") bunser = Bunser( mutable=mutable, diff --git a/hgext/fsmonitor/state.py b/hgext/fsmonitor/state.py --- a/hgext/fsmonitor/state.py +++ b/hgext/fsmonitor/state.py @@ -19,7 +19,7 @@ ) _version = 4 -_versionformat = ">I" +_versionformat = b">I" class state(object): @@ -30,15 +30,15 @@ self._lastclock = None self._identity = util.filestat(None) - self.mode = self._ui.config("fsmonitor", "mode") + self.mode = self._ui.config(b"fsmonitor", b"mode") self.walk_on_invalidate = self._ui.configbool( - "fsmonitor", "walk_on_invalidate" + b"fsmonitor", b"walk_on_invalidate" ) - self.timeout = float(self._ui.config("fsmonitor", "timeout")) + self.timeout = float(self._ui.config(b"fsmonitor", b"timeout")) def get(self): try: - file = self._vfs("fsmonitor.state", "rb") + file = self._vfs(b"fsmonitor.state", b"rb") except IOError as inst: self._identity = util.filestat(None) if inst.errno != errno.ENOENT: @@ -50,9 +50,9 @@ versionbytes = file.read(4) if len(versionbytes) < 4: self._ui.log( - "fsmonitor", - "fsmonitor: state file only has %d bytes, " - "nuking state\n" % len(versionbytes), + b"fsmonitor", + b"fsmonitor: state file only has %d bytes, " + b"nuking state\n" % len(versionbytes), ) self.invalidate() return None, None, None @@ -61,21 +61,21 @@ if diskversion != _version: # different version, nuke state and start over self._ui.log( - "fsmonitor", - "fsmonitor: version switch from %d to " - "%d, nuking state\n" % (diskversion, _version), + b"fsmonitor", + b"fsmonitor: version switch from %d to " + b"%d, nuking state\n" % (diskversion, _version), ) self.invalidate() return None, None, None - state = file.read().split("\0") + state = file.read().split(b"\0") # state = hostname\0clock\0ignorehash\0 + list of files, each # followed by a \0 if len(state) < 3: self._ui.log( - "fsmonitor", - "fsmonitor: state file truncated (expected " - "3 chunks, found %d), nuking state\n", + b"fsmonitor", + b"fsmonitor: state file truncated (expected " + b"3 chunks, found %d), nuking state\n", len(state), ) self.invalidate() @@ -85,9 +85,9 @@ if diskhostname != hostname: # file got moved to a different host self._ui.log( - "fsmonitor", - 'fsmonitor: stored hostname "%s" ' - 'different from current "%s", nuking state\n' + b"fsmonitor", + b'fsmonitor: stored hostname "%s" ' + b'different from current "%s", nuking state\n' % (diskhostname, hostname), ) self.invalidate() @@ -110,31 +110,33 @@ # Read the identity from the file on disk rather than from the open file # pointer below, because the latter is actually a brand new file. - identity = util.filestat.frompath(self._vfs.join("fsmonitor.state")) + identity = util.filestat.frompath(self._vfs.join(b"fsmonitor.state")) if identity != self._identity: - self._ui.debug("skip updating fsmonitor.state: identity mismatch\n") + self._ui.debug( + b"skip updating fsmonitor.state: identity mismatch\n" + ) return try: file = self._vfs( - "fsmonitor.state", "wb", atomictemp=True, checkambig=True + b"fsmonitor.state", b"wb", atomictemp=True, checkambig=True ) except (IOError, OSError): - self._ui.warn(_("warning: unable to write out fsmonitor state\n")) + self._ui.warn(_(b"warning: unable to write out fsmonitor state\n")) return with file: file.write(struct.pack(_versionformat, _version)) - file.write(socket.gethostname() + "\0") - file.write(clock + "\0") - file.write(ignorehash + "\0") + file.write(socket.gethostname() + b"\0") + file.write(clock + b"\0") + file.write(ignorehash + b"\0") if notefiles: - file.write("\0".join(notefiles)) - file.write("\0") + file.write(b"\0".join(notefiles)) + file.write(b"\0") def invalidate(self): try: - os.unlink(os.path.join(self._rootdir, ".hg", "fsmonitor.state")) + os.unlink(os.path.join(self._rootdir, b".hg", b"fsmonitor.state")) except OSError as inst: if inst.errno != errno.ENOENT: raise diff --git a/hgext/fsmonitor/watchmanclient.py b/hgext/fsmonitor/watchmanclient.py --- a/hgext/fsmonitor/watchmanclient.py +++ b/hgext/fsmonitor/watchmanclient.py @@ -18,15 +18,15 @@ def __init__(self, msg, warn=True, invalidate=False): self.msg = msg self.warn = warn - if self.msg == "timed out waiting for response": + if self.msg == b"timed out waiting for response": self.warn = False self.invalidate = invalidate def __str__(self): if self.warn: - return "warning: Watchman unavailable: %s" % self.msg + return b"warning: Watchman unavailable: %s" % self.msg else: - return "Watchman unavailable: %s" % self.msg + return b"Watchman unavailable: %s" % self.msg class WatchmanNoRoot(Unavailable): @@ -39,10 +39,10 @@ def __init__(self, ui, root, timeout=1.0): err = None if not self._user: - err = "couldn't get user" + err = b"couldn't get user" warn = True - if self._user in ui.configlist("fsmonitor", "blacklistusers"): - err = "user %s in blacklist" % self._user + if self._user in ui.configlist(b"fsmonitor", b"blacklistusers"): + err = b"user %s in blacklist" % self._user warn = False if err: @@ -60,10 +60,10 @@ self._watchmanclient.setTimeout(timeout) def getcurrentclock(self): - result = self.command("clock") - if not util.safehasattr(result, "clock"): + result = self.command(b"clock") + if not util.safehasattr(result, b"clock"): raise Unavailable( - "clock result is missing clock value", invalidate=True + b"clock result is missing clock value", invalidate=True ) return result.clock @@ -86,7 +86,9 @@ try: if self._watchmanclient is None: self._firsttime = False - watchman_exe = self._ui.configpath("fsmonitor", "watchman_exe") + watchman_exe = self._ui.configpath( + b"fsmonitor", b"watchman_exe" + ) self._watchmanclient = pywatchman.client( timeout=self._timeout, useImmutableBser=True, @@ -94,7 +96,7 @@ ) return self._watchmanclient.query(*watchmanargs) except pywatchman.CommandError as ex: - if "unable to resolve root" in ex.msg: + if b"unable to resolve root" in ex.msg: raise WatchmanNoRoot(self._root, ex.msg) raise Unavailable(ex.msg) except pywatchman.WatchmanError as ex: @@ -107,7 +109,7 @@ except WatchmanNoRoot: # this 'watch' command can also raise a WatchmanNoRoot if # watchman refuses to accept this root - self._command("watch") + self._command(b"watch") return self._command(*args) except Unavailable: # this is in an outer scope to catch Unavailable form any of the diff --git a/hgext/githelp.py b/hgext/githelp.py --- a/hgext/githelp.py +++ b/hgext/githelp.py @@ -35,26 +35,26 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) def convert(s): - if s.startswith("origin/"): + if s.startswith(b"origin/"): return s[7:] - if "HEAD" in s: - s = s.replace("HEAD", ".") + if b"HEAD" in s: + s = s.replace(b"HEAD", b".") # HEAD~ in git is .~1 in mercurial - s = re.sub("~$", "~1", s) + s = re.sub(b"~$", b"~1", s) return s @command( - "githelp|git", + b"githelp|git", [], - _("hg githelp"), + _(b"hg githelp"), helpcategory=command.CATEGORY_HELP, helpbasic=True, ) @@ -64,19 +64,19 @@ Usage: hg githelp -- """ - if len(args) == 0 or (len(args) == 1 and args[0] == "git"): + if len(args) == 0 or (len(args) == 1 and args[0] == b"git"): raise error.Abort( - _("missing git command - " "usage: hg githelp -- ") + _(b"missing git command - " b"usage: hg githelp -- ") ) - if args[0] == "git": + if args[0] == b"git": args = args[1:] cmd = args[0] if not cmd in gitcommands: - raise error.Abort(_("error: unknown git command %s") % cmd) + raise error.Abort(_(b"error: unknown git command %s") % cmd) - ui.pager("githelp") + ui.pager(b"githelp") args = args[1:] return gitcommands[cmd](ui, repo, *args, **kwargs) @@ -93,24 +93,24 @@ if r"requires argument" in ex.msg: raise if (r"--" + ex.opt) in ex.msg: - flag = "--" + pycompat.bytestr(ex.opt) + flag = b"--" + pycompat.bytestr(ex.opt) elif (r"-" + ex.opt) in ex.msg: - flag = "-" + pycompat.bytestr(ex.opt) + flag = b"-" + pycompat.bytestr(ex.opt) else: raise error.Abort( - _("unknown option %s") % pycompat.bytestr(ex.opt) + _(b"unknown option %s") % pycompat.bytestr(ex.opt) ) try: args.remove(flag) except Exception: - msg = _("unknown option '%s' packed with other options") - hint = _("please try passing the option as its own flag: -%s") + msg = _(b"unknown option '%s' packed with other options") + hint = _(b"please try passing the option as its own flag: -%s") raise error.Abort( msg % pycompat.bytestr(ex.opt), hint=hint % pycompat.bytestr(ex.opt), ) - ui.warn(_("ignoring unknown option %s\n") % flag) + ui.warn(_(b"ignoring unknown option %s\n") % flag) args = list([convert(x) for x in args]) opts = dict( @@ -130,22 +130,22 @@ self.opts = {} def __bytes__(self): - cmd = "hg " + self.name + cmd = b"hg " + self.name if self.opts: for k, values in sorted(self.opts.iteritems()): for v in values: if v: if isinstance(v, int): - fmt = " %s %d" + fmt = b" %s %d" else: - fmt = " %s %s" + fmt = b" %s %s" cmd += fmt % (k, v) else: - cmd += " %s" % (k,) + cmd += b" %s" % (k,) if self.args: - cmd += " " - cmd += " ".join(self.args) + cmd += b" " + cmd += b" ".join(self.args) return cmd __str__ = encoding.strmethod(__bytes__) @@ -170,7 +170,7 @@ self.right = right def __str__(self): - return "%s && %s" % (self.left, self.right) + return b"%s && %s" % (self.left, self.right) def __and__(self, other): return AndCommand(self, other) @@ -178,113 +178,113 @@ def add(ui, repo, *args, **kwargs): cmdoptions = [ - ("A", "all", None, ""), - ("p", "patch", None, ""), + (b"A", b"all", None, b""), + (b"p", b"patch", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - if opts.get("patch"): + if opts.get(b"patch"): ui.status( _( - "note: Mercurial will commit when complete, " - "as there is no staging area in Mercurial\n\n" + b"note: Mercurial will commit when complete, " + b"as there is no staging area in Mercurial\n\n" ) ) - cmd = Command("commit --interactive") + cmd = Command(b"commit --interactive") else: - cmd = Command("add") + cmd = Command(b"add") - if not opts.get("all"): + if not opts.get(b"all"): cmd.extend(args) else: ui.status( _( - "note: use hg addremove to remove files that have " - "been deleted\n\n" + b"note: use hg addremove to remove files that have " + b"been deleted\n\n" ) ) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def am(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("import") - ui.status(bytes(cmd), "\n") + cmd = Command(b"import") + ui.status(bytes(cmd), b"\n") def apply(ui, repo, *args, **kwargs): cmdoptions = [ - ("p", "p", int, ""), - ("", "directory", "", ""), + (b"p", b"p", int, b""), + (b"", b"directory", b"", b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("import --no-commit") - if opts.get("p"): - cmd["-p"] = opts.get("p") - if opts.get("directory"): - cmd["--prefix"] = opts.get("directory") + cmd = Command(b"import --no-commit") + if opts.get(b"p"): + cmd[b"-p"] = opts.get(b"p") + if opts.get(b"directory"): + cmd[b"--prefix"] = opts.get(b"directory") cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def bisect(ui, repo, *args, **kwargs): - ui.status(_("see 'hg help bisect' for how to use bisect\n\n")) + ui.status(_(b"see 'hg help bisect' for how to use bisect\n\n")) def blame(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("annotate -udl") + cmd = Command(b"annotate -udl") cmd.extend([convert(v) for v in args]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def branch(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "set-upstream", None, ""), - ("", "set-upstream-to", "", ""), - ("d", "delete", None, ""), - ("D", "delete", None, ""), - ("m", "move", None, ""), - ("M", "move", None, ""), + (b"", b"set-upstream", None, b""), + (b"", b"set-upstream-to", b"", b""), + (b"d", b"delete", None, b""), + (b"D", b"delete", None, b""), + (b"m", b"move", None, b""), + (b"M", b"move", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("bookmark") + cmd = Command(b"bookmark") - if opts.get("set_upstream") or opts.get("set_upstream_to"): - ui.status(_("Mercurial has no concept of upstream branches\n")) + if opts.get(b"set_upstream") or opts.get(b"set_upstream_to"): + ui.status(_(b"Mercurial has no concept of upstream branches\n")) return - elif opts.get("delete"): - cmd = Command("strip") + elif opts.get(b"delete"): + cmd = Command(b"strip") for branch in args: - cmd["-B"] = branch + cmd[b"-B"] = branch else: - cmd["-B"] = None - elif opts.get("move"): + cmd[b"-B"] = None + elif opts.get(b"move"): if len(args) > 0: if len(args) > 1: old = args.pop(0) else: # shell command to output the active bookmark for the active # revision - old = '`hg log -T"{activebookmark}" -r .`' + old = b'`hg log -T"{activebookmark}" -r .`' else: - raise error.Abort(_("missing newbranch argument")) + raise error.Abort(_(b"missing newbranch argument")) new = args[0] - cmd["-m"] = old + cmd[b"-m"] = old cmd.append(new) else: if len(args) > 1: - cmd["-r"] = args[1] + cmd[b"-r"] = args[1] cmd.append(args[0]) elif len(args) == 1: cmd.append(args[0]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def ispath(repo, string): @@ -300,16 +300,16 @@ return False cwd = repo.getcwd() - if cwd == "": + if cwd == b"": repopath = string else: - repopath = cwd + "/" + string + repopath = cwd + b"/" + string exists = repo.wvfs.exists(repopath) if exists: return True - manifest = repo["."].manifest() + manifest = repo[b"."].manifest() didexist = (repopath in manifest) or manifest.hasdir(repopath) @@ -318,14 +318,14 @@ def checkout(ui, repo, *args, **kwargs): cmdoptions = [ - ("b", "branch", "", ""), - ("B", "branch", "", ""), - ("f", "force", None, ""), - ("p", "patch", None, ""), + (b"b", b"branch", b"", b""), + (b"B", b"branch", b"", b""), + (b"f", b"force", None, b""), + (b"p", b"patch", None, b""), ] paths = [] - if "--" in args: - sepindex = args.index("--") + if b"--" in args: + sepindex = args.index(b"--") paths.extend(args[sepindex + 1 :]) args = args[:sepindex] @@ -338,410 +338,410 @@ rev = args[0] paths = args[1:] + paths - cmd = Command("update") + cmd = Command(b"update") - if opts.get("force"): + if opts.get(b"force"): if paths or rev: - cmd["-C"] = None + cmd[b"-C"] = None - if opts.get("patch"): - cmd = Command("revert") - cmd["-i"] = None + if opts.get(b"patch"): + cmd = Command(b"revert") + cmd[b"-i"] = None - if opts.get("branch"): + if opts.get(b"branch"): if len(args) == 0: - cmd = Command("bookmark") - cmd.append(opts.get("branch")) + cmd = Command(b"bookmark") + cmd.append(opts.get(b"branch")) else: cmd.append(args[0]) - bookcmd = Command("bookmark") - bookcmd.append(opts.get("branch")) + bookcmd = Command(b"bookmark") + bookcmd.append(opts.get(b"branch")) cmd = cmd & bookcmd # if there is any path argument supplied, use revert instead of update elif len(paths) > 0: - ui.status(_("note: use --no-backup to avoid creating .orig files\n\n")) - cmd = Command("revert") - if opts.get("patch"): - cmd["-i"] = None + ui.status(_(b"note: use --no-backup to avoid creating .orig files\n\n")) + cmd = Command(b"revert") + if opts.get(b"patch"): + cmd[b"-i"] = None if rev: - cmd["-r"] = rev + cmd[b"-r"] = rev cmd.extend(paths) elif rev: - if opts.get("patch"): - cmd["-r"] = rev + if opts.get(b"patch"): + cmd[b"-r"] = rev else: cmd.append(rev) - elif opts.get("force"): - cmd = Command("revert") - cmd["--all"] = None + elif opts.get(b"force"): + cmd = Command(b"revert") + cmd[b"--all"] = None else: - raise error.Abort(_("a commit must be specified")) + raise error.Abort(_(b"a commit must be specified")) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def cherrypick(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "continue", None, ""), - ("", "abort", None, ""), - ("e", "edit", None, ""), + (b"", b"continue", None, b""), + (b"", b"abort", None, b""), + (b"e", b"edit", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("graft") + cmd = Command(b"graft") - if opts.get("edit"): - cmd["--edit"] = None - if opts.get("continue"): - cmd["--continue"] = None - elif opts.get("abort"): - ui.status(_("note: hg graft does not have --abort\n\n")) + if opts.get(b"edit"): + cmd[b"--edit"] = None + if opts.get(b"continue"): + cmd[b"--continue"] = None + elif opts.get(b"abort"): + ui.status(_(b"note: hg graft does not have --abort\n\n")) return else: cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def clean(ui, repo, *args, **kwargs): cmdoptions = [ - ("d", "d", None, ""), - ("f", "force", None, ""), - ("x", "x", None, ""), + (b"d", b"d", None, b""), + (b"f", b"force", None, b""), + (b"x", b"x", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("purge") - if opts.get("x"): - cmd["--all"] = None + cmd = Command(b"purge") + if opts.get(b"x"): + cmd[b"--all"] = None cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def clone(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "bare", None, ""), - ("n", "no-checkout", None, ""), - ("b", "branch", "", ""), + (b"", b"bare", None, b""), + (b"n", b"no-checkout", None, b""), + (b"b", b"branch", b"", b""), ] args, opts = parseoptions(ui, cmdoptions, args) if len(args) == 0: - raise error.Abort(_("a repository to clone must be specified")) + raise error.Abort(_(b"a repository to clone must be specified")) - cmd = Command("clone") + cmd = Command(b"clone") cmd.append(args[0]) if len(args) > 1: cmd.append(args[1]) - if opts.get("bare"): - cmd["-U"] = None + if opts.get(b"bare"): + cmd[b"-U"] = None ui.status( _( - "note: Mercurial does not have bare clones. " - "-U will clone the repo without checking out a commit\n\n" + b"note: Mercurial does not have bare clones. " + b"-U will clone the repo without checking out a commit\n\n" ) ) - elif opts.get("no_checkout"): - cmd["-U"] = None + elif opts.get(b"no_checkout"): + cmd[b"-U"] = None - if opts.get("branch"): - cocmd = Command("update") - cocmd.append(opts.get("branch")) + if opts.get(b"branch"): + cocmd = Command(b"update") + cocmd.append(opts.get(b"branch")) cmd = cmd & cocmd - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def commit(ui, repo, *args, **kwargs): cmdoptions = [ - ("a", "all", None, ""), - ("m", "message", "", ""), - ("p", "patch", None, ""), - ("C", "reuse-message", "", ""), - ("F", "file", "", ""), - ("", "author", "", ""), - ("", "date", "", ""), - ("", "amend", None, ""), - ("", "no-edit", None, ""), + (b"a", b"all", None, b""), + (b"m", b"message", b"", b""), + (b"p", b"patch", None, b""), + (b"C", b"reuse-message", b"", b""), + (b"F", b"file", b"", b""), + (b"", b"author", b"", b""), + (b"", b"date", b"", b""), + (b"", b"amend", None, b""), + (b"", b"no-edit", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("commit") - if opts.get("patch"): - cmd = Command("commit --interactive") + cmd = Command(b"commit") + if opts.get(b"patch"): + cmd = Command(b"commit --interactive") - if opts.get("amend"): - if opts.get("no_edit"): - cmd = Command("amend") + if opts.get(b"amend"): + if opts.get(b"no_edit"): + cmd = Command(b"amend") else: - cmd["--amend"] = None + cmd[b"--amend"] = None - if opts.get("reuse_message"): - cmd["-M"] = opts.get("reuse_message") + if opts.get(b"reuse_message"): + cmd[b"-M"] = opts.get(b"reuse_message") - if opts.get("message"): - cmd["-m"] = "'%s'" % (opts.get("message"),) + if opts.get(b"message"): + cmd[b"-m"] = b"'%s'" % (opts.get(b"message"),) - if opts.get("all"): + if opts.get(b"all"): ui.status( _( - "note: Mercurial doesn't have a staging area, " - "so there is no --all. -A will add and remove files " - "for you though.\n\n" + b"note: Mercurial doesn't have a staging area, " + b"so there is no --all. -A will add and remove files " + b"for you though.\n\n" ) ) - if opts.get("file"): - cmd["-l"] = opts.get("file") + if opts.get(b"file"): + cmd[b"-l"] = opts.get(b"file") - if opts.get("author"): - cmd["-u"] = opts.get("author") + if opts.get(b"author"): + cmd[b"-u"] = opts.get(b"author") - if opts.get("date"): - cmd["-d"] = opts.get("date") + if opts.get(b"date"): + cmd[b"-d"] = opts.get(b"date") cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def deprecated(ui, repo, *args, **kwargs): ui.warn( _( - "this command has been deprecated in the git project, " - "thus isn't supported by this tool\n\n" + b"this command has been deprecated in the git project, " + b"thus isn't supported by this tool\n\n" ) ) def diff(ui, repo, *args, **kwargs): cmdoptions = [ - ("a", "all", None, ""), - ("", "cached", None, ""), - ("R", "reverse", None, ""), + (b"a", b"all", None, b""), + (b"", b"cached", None, b""), + (b"R", b"reverse", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("diff") + cmd = Command(b"diff") - if opts.get("cached"): + if opts.get(b"cached"): ui.status( _( - "note: Mercurial has no concept of a staging area, " - "so --cached does nothing\n\n" + b"note: Mercurial has no concept of a staging area, " + b"so --cached does nothing\n\n" ) ) - if opts.get("reverse"): - cmd["--reverse"] = None + if opts.get(b"reverse"): + cmd[b"--reverse"] = None for a in list(args): args.remove(a) try: repo.revs(a) - cmd["-r"] = a + cmd[b"-r"] = a except Exception: cmd.append(a) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def difftool(ui, repo, *args, **kwargs): ui.status( _( - "Mercurial does not enable external difftool by default. You " - "need to enable the extdiff extension in your .hgrc file by adding\n" - "extdiff =\n" - "to the [extensions] section and then running\n\n" - "hg extdiff -p \n\n" - "See 'hg help extdiff' and 'hg help -e extdiff' for more " - "information.\n" + b"Mercurial does not enable external difftool by default. You " + b"need to enable the extdiff extension in your .hgrc file by adding\n" + b"extdiff =\n" + b"to the [extensions] section and then running\n\n" + b"hg extdiff -p \n\n" + b"See 'hg help extdiff' and 'hg help -e extdiff' for more " + b"information.\n" ) ) def fetch(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "all", None, ""), - ("f", "force", None, ""), + (b"", b"all", None, b""), + (b"f", b"force", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("pull") + cmd = Command(b"pull") if len(args) > 0: cmd.append(args[0]) if len(args) > 1: ui.status( _( - "note: Mercurial doesn't have refspecs. " - "-r can be used to specify which commits you want to " - "pull. -B can be used to specify which bookmark you " - "want to pull.\n\n" + b"note: Mercurial doesn't have refspecs. " + b"-r can be used to specify which commits you want to " + b"pull. -B can be used to specify which bookmark you " + b"want to pull.\n\n" ) ) for v in args[1:]: if v in repo._bookmarks: - cmd["-B"] = v + cmd[b"-B"] = v else: - cmd["-r"] = v + cmd[b"-r"] = v - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def grep(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("grep") + cmd = Command(b"grep") # For basic usage, git grep and hg grep are the same. They both have the # pattern first, followed by paths. cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def init(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("init") + cmd = Command(b"init") if len(args) > 0: cmd.append(args[0]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def log(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "follow", None, ""), - ("", "decorate", None, ""), - ("n", "number", "", ""), - ("1", "1", None, ""), - ("", "pretty", "", ""), - ("", "format", "", ""), - ("", "oneline", None, ""), - ("", "stat", None, ""), - ("", "graph", None, ""), - ("p", "patch", None, ""), + (b"", b"follow", None, b""), + (b"", b"decorate", None, b""), + (b"n", b"number", b"", b""), + (b"1", b"1", None, b""), + (b"", b"pretty", b"", b""), + (b"", b"format", b"", b""), + (b"", b"oneline", None, b""), + (b"", b"stat", None, b""), + (b"", b"graph", None, b""), + (b"p", b"patch", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) ui.status( _( - "note: -v prints the entire commit message like Git does. To " - "print just the first line, drop the -v.\n\n" + b"note: -v prints the entire commit message like Git does. To " + b"print just the first line, drop the -v.\n\n" ) ) ui.status( _( - "note: see hg help revset for information on how to filter " - "log output\n\n" + b"note: see hg help revset for information on how to filter " + b"log output\n\n" ) ) - cmd = Command("log") - cmd["-v"] = None + cmd = Command(b"log") + cmd[b"-v"] = None - if opts.get("number"): - cmd["-l"] = opts.get("number") - if opts.get("1"): - cmd["-l"] = "1" - if opts.get("stat"): - cmd["--stat"] = None - if opts.get("graph"): - cmd["-G"] = None - if opts.get("patch"): - cmd["-p"] = None + if opts.get(b"number"): + cmd[b"-l"] = opts.get(b"number") + if opts.get(b"1"): + cmd[b"-l"] = b"1" + if opts.get(b"stat"): + cmd[b"--stat"] = None + if opts.get(b"graph"): + cmd[b"-G"] = None + if opts.get(b"patch"): + cmd[b"-p"] = None - if opts.get("pretty") or opts.get("format") or opts.get("oneline"): - format = opts.get("format", "") - if "format:" in format: + if opts.get(b"pretty") or opts.get(b"format") or opts.get(b"oneline"): + format = opts.get(b"format", b"") + if b"format:" in format: ui.status( _( - "note: --format format:??? equates to Mercurial's " - "--template. See hg help templates for more info.\n\n" + b"note: --format format:??? equates to Mercurial's " + b"--template. See hg help templates for more info.\n\n" ) ) - cmd["--template"] = "???" + cmd[b"--template"] = b"???" else: ui.status( _( - "note: --pretty/format/oneline equate to Mercurial's " - "--style or --template. See hg help templates for " - "more info.\n\n" + b"note: --pretty/format/oneline equate to Mercurial's " + b"--style or --template. See hg help templates for " + b"more info.\n\n" ) ) - cmd["--style"] = "???" + cmd[b"--style"] = b"???" if len(args) > 0: - if ".." in args[0]: - since, until = args[0].split("..") - cmd["-r"] = "'%s::%s'" % (since, until) + if b".." in args[0]: + since, until = args[0].split(b"..") + cmd[b"-r"] = b"'%s::%s'" % (since, until) del args[0] cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def lsfiles(ui, repo, *args, **kwargs): cmdoptions = [ - ("c", "cached", None, ""), - ("d", "deleted", None, ""), - ("m", "modified", None, ""), - ("o", "others", None, ""), - ("i", "ignored", None, ""), - ("s", "stage", None, ""), - ("z", "_zero", None, ""), + (b"c", b"cached", None, b""), + (b"d", b"deleted", None, b""), + (b"m", b"modified", None, b""), + (b"o", b"others", None, b""), + (b"i", b"ignored", None, b""), + (b"s", b"stage", None, b""), + (b"z", b"_zero", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) if ( - opts.get("modified") - or opts.get("deleted") - or opts.get("others") - or opts.get("ignored") + opts.get(b"modified") + or opts.get(b"deleted") + or opts.get(b"others") + or opts.get(b"ignored") ): - cmd = Command("status") - if opts.get("deleted"): - cmd["-d"] = None - if opts.get("modified"): - cmd["-m"] = None - if opts.get("others"): - cmd["-o"] = None - if opts.get("ignored"): - cmd["-i"] = None + cmd = Command(b"status") + if opts.get(b"deleted"): + cmd[b"-d"] = None + if opts.get(b"modified"): + cmd[b"-m"] = None + if opts.get(b"others"): + cmd[b"-o"] = None + if opts.get(b"ignored"): + cmd[b"-i"] = None else: - cmd = Command("files") - if opts.get("stage"): + cmd = Command(b"files") + if opts.get(b"stage"): ui.status( _( - "note: Mercurial doesn't have a staging area, ignoring " - "--stage\n" + b"note: Mercurial doesn't have a staging area, ignoring " + b"--stage\n" ) ) - if opts.get("_zero"): - cmd["-0"] = None - cmd.append(".") + if opts.get(b"_zero"): + cmd[b"-0"] = None + cmd.append(b".") for include in args: - cmd["-I"] = procutil.shellquote(include) + cmd[b"-I"] = procutil.shellquote(include) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def merge(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("merge") + cmd = Command(b"merge") if len(args) > 0: cmd.append(args[len(args) - 1]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def mergebase(ui, repo, *args, **kwargs): @@ -749,228 +749,228 @@ args, opts = parseoptions(ui, cmdoptions, args) if len(args) != 2: - args = ["A", "B"] + args = [b"A", b"B"] cmd = Command( - "log -T '{node}\\n' -r 'ancestor(%s,%s)'" % (args[0], args[1]) + b"log -T '{node}\\n' -r 'ancestor(%s,%s)'" % (args[0], args[1]) ) ui.status( - _("note: ancestors() is part of the revset language\n"), - _("(learn more about revsets with 'hg help revsets')\n\n"), + _(b"note: ancestors() is part of the revset language\n"), + _(b"(learn more about revsets with 'hg help revsets')\n\n"), ) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def mergetool(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("resolve") + cmd = Command(b"resolve") if len(args) == 0: - cmd["--all"] = None + cmd[b"--all"] = None cmd.extend(args) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def mv(ui, repo, *args, **kwargs): cmdoptions = [ - ("f", "force", None, ""), - ("n", "dry-run", None, ""), + (b"f", b"force", None, b""), + (b"n", b"dry-run", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("mv") + cmd = Command(b"mv") cmd.extend(args) - if opts.get("force"): - cmd["-f"] = None - if opts.get("dry_run"): - cmd["-n"] = None + if opts.get(b"force"): + cmd[b"-f"] = None + if opts.get(b"dry_run"): + cmd[b"-n"] = None - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def pull(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "all", None, ""), - ("f", "force", None, ""), - ("r", "rebase", None, ""), + (b"", b"all", None, b""), + (b"f", b"force", None, b""), + (b"r", b"rebase", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("pull") - cmd["--rebase"] = None + cmd = Command(b"pull") + cmd[b"--rebase"] = None if len(args) > 0: cmd.append(args[0]) if len(args) > 1: ui.status( _( - "note: Mercurial doesn't have refspecs. " - "-r can be used to specify which commits you want to " - "pull. -B can be used to specify which bookmark you " - "want to pull.\n\n" + b"note: Mercurial doesn't have refspecs. " + b"-r can be used to specify which commits you want to " + b"pull. -B can be used to specify which bookmark you " + b"want to pull.\n\n" ) ) for v in args[1:]: if v in repo._bookmarks: - cmd["-B"] = v + cmd[b"-B"] = v else: - cmd["-r"] = v + cmd[b"-r"] = v - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def push(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "all", None, ""), - ("f", "force", None, ""), + (b"", b"all", None, b""), + (b"f", b"force", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("push") + cmd = Command(b"push") if len(args) > 0: cmd.append(args[0]) if len(args) > 1: ui.status( _( - "note: Mercurial doesn't have refspecs. " - "-r can be used to specify which commits you want " - "to push. -B can be used to specify which bookmark " - "you want to push.\n\n" + b"note: Mercurial doesn't have refspecs. " + b"-r can be used to specify which commits you want " + b"to push. -B can be used to specify which bookmark " + b"you want to push.\n\n" ) ) for v in args[1:]: if v in repo._bookmarks: - cmd["-B"] = v + cmd[b"-B"] = v else: - cmd["-r"] = v + cmd[b"-r"] = v - if opts.get("force"): - cmd["-f"] = None + if opts.get(b"force"): + cmd[b"-f"] = None - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def rebase(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "all", None, ""), - ("i", "interactive", None, ""), - ("", "onto", "", ""), - ("", "abort", None, ""), - ("", "continue", None, ""), - ("", "skip", None, ""), + (b"", b"all", None, b""), + (b"i", b"interactive", None, b""), + (b"", b"onto", b"", b""), + (b"", b"abort", None, b""), + (b"", b"continue", None, b""), + (b"", b"skip", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - if opts.get("interactive"): + if opts.get(b"interactive"): ui.status( _( - "note: hg histedit does not perform a rebase. " - "It just edits history.\n\n" + b"note: hg histedit does not perform a rebase. " + b"It just edits history.\n\n" ) ) - cmd = Command("histedit") + cmd = Command(b"histedit") if len(args) > 0: ui.status( _( - "also note: 'hg histedit' will automatically detect" - " your stack, so no second argument is necessary\n\n" + b"also note: 'hg histedit' will automatically detect" + b" your stack, so no second argument is necessary\n\n" ) ) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") return - if opts.get("skip"): - cmd = Command("revert --all -r .") - ui.status((bytes(cmd)), "\n") + if opts.get(b"skip"): + cmd = Command(b"revert --all -r .") + ui.status((bytes(cmd)), b"\n") - cmd = Command("rebase") + cmd = Command(b"rebase") - if opts.get("continue") or opts.get("skip"): - cmd["--continue"] = None - if opts.get("abort"): - cmd["--abort"] = None + if opts.get(b"continue") or opts.get(b"skip"): + cmd[b"--continue"] = None + if opts.get(b"abort"): + cmd[b"--abort"] = None - if opts.get("onto"): + if opts.get(b"onto"): ui.status( _( - "note: if you're trying to lift a commit off one branch, " - "try hg rebase -d -s \n\n" + b"note: if you're trying to lift a commit off one branch, " + b"try hg rebase -d -s \n\n" ) ) - cmd["-d"] = convert(opts.get("onto")) + cmd[b"-d"] = convert(opts.get(b"onto")) if len(args) < 2: - raise error.Abort(_("expected format: git rebase --onto X Y Z")) - cmd["-s"] = "'::%s - ::%s'" % (convert(args[1]), convert(args[0])) + raise error.Abort(_(b"expected format: git rebase --onto X Y Z")) + cmd[b"-s"] = b"'::%s - ::%s'" % (convert(args[1]), convert(args[0])) else: if len(args) == 1: - cmd["-d"] = convert(args[0]) + cmd[b"-d"] = convert(args[0]) elif len(args) == 2: - cmd["-d"] = convert(args[0]) - cmd["-b"] = convert(args[1]) + cmd[b"-d"] = convert(args[0]) + cmd[b"-b"] = convert(args[1]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def reflog(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "all", None, ""), + (b"", b"all", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("journal") - if opts.get("all"): - cmd["--all"] = None + cmd = Command(b"journal") + if opts.get(b"all"): + cmd[b"--all"] = None if len(args) > 0: cmd.append(args[0]) - ui.status(bytes(cmd), "\n\n") + ui.status(bytes(cmd), b"\n\n") ui.status( _( - "note: in hg commits can be deleted from repo but we always" - " have backups\n" + b"note: in hg commits can be deleted from repo but we always" + b" have backups\n" ) ) def reset(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "soft", None, ""), - ("", "hard", None, ""), - ("", "mixed", None, ""), + (b"", b"soft", None, b""), + (b"", b"hard", None, b""), + (b"", b"mixed", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - commit = convert(args[0] if len(args) > 0 else ".") - hard = opts.get("hard") + commit = convert(args[0] if len(args) > 0 else b".") + hard = opts.get(b"hard") - if opts.get("mixed"): + if opts.get(b"mixed"): ui.status( _( - "note: --mixed has no meaning since Mercurial has no " - "staging area\n\n" + b"note: --mixed has no meaning since Mercurial has no " + b"staging area\n\n" ) ) - if opts.get("soft"): + if opts.get(b"soft"): ui.status( _( - "note: --soft has no meaning since Mercurial has no " - "staging area\n\n" + b"note: --soft has no meaning since Mercurial has no " + b"staging area\n\n" ) ) - cmd = Command("update") + cmd = Command(b"update") if hard: - cmd.append("--clean") + cmd.append(b"--clean") cmd.append(commit) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def revert(ui, repo, *args, **kwargs): @@ -980,158 +980,158 @@ if len(args) > 1: ui.status( _( - "note: hg backout doesn't support multiple commits at " - "once\n\n" + b"note: hg backout doesn't support multiple commits at " + b"once\n\n" ) ) - cmd = Command("backout") + cmd = Command(b"backout") if args: cmd.append(args[0]) - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def revparse(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "show-cdup", None, ""), - ("", "show-toplevel", None, ""), + (b"", b"show-cdup", None, b""), + (b"", b"show-toplevel", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - if opts.get("show_cdup") or opts.get("show_toplevel"): - cmd = Command("root") - if opts.get("show_cdup"): - ui.status(_("note: hg root prints the root of the repository\n\n")) - ui.status((bytes(cmd)), "\n") + if opts.get(b"show_cdup") or opts.get(b"show_toplevel"): + cmd = Command(b"root") + if opts.get(b"show_cdup"): + ui.status(_(b"note: hg root prints the root of the repository\n\n")) + ui.status((bytes(cmd)), b"\n") else: - ui.status(_("note: see hg help revset for how to refer to commits\n")) + ui.status(_(b"note: see hg help revset for how to refer to commits\n")) def rm(ui, repo, *args, **kwargs): cmdoptions = [ - ("f", "force", None, ""), - ("n", "dry-run", None, ""), + (b"f", b"force", None, b""), + (b"n", b"dry-run", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("rm") + cmd = Command(b"rm") cmd.extend(args) - if opts.get("force"): - cmd["-f"] = None - if opts.get("dry_run"): - cmd["-n"] = None + if opts.get(b"force"): + cmd[b"-f"] = None + if opts.get(b"dry_run"): + cmd[b"-n"] = None - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def show(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "name-status", None, ""), - ("", "pretty", "", ""), - ("U", "unified", int, ""), + (b"", b"name-status", None, b""), + (b"", b"pretty", b"", b""), + (b"U", b"unified", int, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - if opts.get("name_status"): - if opts.get("pretty") == "format:": - cmd = Command("status") - cmd["--change"] = "." + if opts.get(b"name_status"): + if opts.get(b"pretty") == b"format:": + cmd = Command(b"status") + cmd[b"--change"] = b"." else: - cmd = Command("log") - cmd.append("--style status") - cmd.append("-r .") + cmd = Command(b"log") + cmd.append(b"--style status") + cmd.append(b"-r .") elif len(args) > 0: if ispath(repo, args[0]): - cmd = Command("cat") + cmd = Command(b"cat") else: - cmd = Command("export") + cmd = Command(b"export") cmd.extend(args) - if opts.get("unified"): - cmd.append("--config diff.unified=%d" % (opts["unified"],)) - elif opts.get("unified"): - cmd = Command("export") - cmd.append("--config diff.unified=%d" % (opts["unified"],)) + if opts.get(b"unified"): + cmd.append(b"--config diff.unified=%d" % (opts[b"unified"],)) + elif opts.get(b"unified"): + cmd = Command(b"export") + cmd.append(b"--config diff.unified=%d" % (opts[b"unified"],)) else: - cmd = Command("export") + cmd = Command(b"export") - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def stash(ui, repo, *args, **kwargs): cmdoptions = [ - ("p", "patch", None, ""), + (b"p", b"patch", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("shelve") + cmd = Command(b"shelve") action = args[0] if len(args) > 0 else None - if action == "list": - cmd["-l"] = None - if opts.get("patch"): - cmd["-p"] = None - elif action == "show": - if opts.get("patch"): - cmd["-p"] = None + if action == b"list": + cmd[b"-l"] = None + if opts.get(b"patch"): + cmd[b"-p"] = None + elif action == b"show": + if opts.get(b"patch"): + cmd[b"-p"] = None else: - cmd["--stat"] = None + cmd[b"--stat"] = None if len(args) > 1: cmd.append(args[1]) - elif action == "clear": - cmd["--cleanup"] = None - elif action == "drop": - cmd["-d"] = None + elif action == b"clear": + cmd[b"--cleanup"] = None + elif action == b"drop": + cmd[b"-d"] = None if len(args) > 1: cmd.append(args[1]) else: - cmd.append("") - elif action == "pop" or action == "apply": - cmd = Command("unshelve") + cmd.append(b"") + elif action == b"pop" or action == b"apply": + cmd = Command(b"unshelve") if len(args) > 1: cmd.append(args[1]) - if action == "apply": - cmd["--keep"] = None - elif action == "branch" or action == "create": + if action == b"apply": + cmd[b"--keep"] = None + elif action == b"branch" or action == b"create": ui.status( _( - "note: Mercurial doesn't have equivalents to the " - "git stash branch or create actions\n\n" + b"note: Mercurial doesn't have equivalents to the " + b"git stash branch or create actions\n\n" ) ) return else: if len(args) > 0: - if args[0] != "save": - cmd["--name"] = args[0] + if args[0] != b"save": + cmd[b"--name"] = args[0] elif len(args) > 1: - cmd["--name"] = args[1] + cmd[b"--name"] = args[1] - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def status(ui, repo, *args, **kwargs): cmdoptions = [ - ("", "ignored", None, ""), + (b"", b"ignored", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("status") + cmd = Command(b"status") cmd.extend(args) - if opts.get("ignored"): - cmd["-i"] = None + if opts.get(b"ignored"): + cmd[b"-i"] = None - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def svn(ui, repo, *args, **kwargs): if not args: - raise error.Abort(_("missing svn command")) + raise error.Abort(_(b"missing svn command")) svncmd = args[0] if svncmd not in gitsvncommands: - raise error.Abort(_('unknown git svn command "%s"') % svncmd) + raise error.Abort(_(b'unknown git svn command "%s"') % svncmd) args = args[1:] return gitsvncommands[svncmd](ui, repo, *args, **kwargs) @@ -1141,19 +1141,19 @@ cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("push") + cmd = Command(b"push") - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def svnfetch(ui, repo, *args, **kwargs): cmdoptions = [] args, opts = parseoptions(ui, cmdoptions, args) - cmd = Command("pull") - cmd.append("default-push") + cmd = Command(b"pull") + cmd.append(b"default-push") - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def svnfindrev(ui, repo, *args, **kwargs): @@ -1161,101 +1161,101 @@ args, opts = parseoptions(ui, cmdoptions, args) if not args: - raise error.Abort(_("missing find-rev argument")) + raise error.Abort(_(b"missing find-rev argument")) - cmd = Command("log") - cmd["-r"] = args[0] + cmd = Command(b"log") + cmd[b"-r"] = args[0] - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def svnrebase(ui, repo, *args, **kwargs): cmdoptions = [ - ("l", "local", None, ""), + (b"l", b"local", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - pullcmd = Command("pull") - pullcmd.append("default-push") - rebasecmd = Command("rebase") - rebasecmd.append("tip") + pullcmd = Command(b"pull") + pullcmd.append(b"default-push") + rebasecmd = Command(b"rebase") + rebasecmd.append(b"tip") cmd = pullcmd & rebasecmd - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") def tag(ui, repo, *args, **kwargs): cmdoptions = [ - ("f", "force", None, ""), - ("l", "list", None, ""), - ("d", "delete", None, ""), + (b"f", b"force", None, b""), + (b"l", b"list", None, b""), + (b"d", b"delete", None, b""), ] args, opts = parseoptions(ui, cmdoptions, args) - if opts.get("list"): - cmd = Command("tags") + if opts.get(b"list"): + cmd = Command(b"tags") else: - cmd = Command("tag") + cmd = Command(b"tag") if not args: - raise error.Abort(_("missing tag argument")) + raise error.Abort(_(b"missing tag argument")) cmd.append(args[0]) if len(args) > 1: - cmd["-r"] = args[1] + cmd[b"-r"] = args[1] - if opts.get("delete"): - cmd["--remove"] = None + if opts.get(b"delete"): + cmd[b"--remove"] = None - if opts.get("force"): - cmd["-f"] = None + if opts.get(b"force"): + cmd[b"-f"] = None - ui.status((bytes(cmd)), "\n") + ui.status((bytes(cmd)), b"\n") gitcommands = { - "add": add, - "am": am, - "apply": apply, - "bisect": bisect, - "blame": blame, - "branch": branch, - "checkout": checkout, - "cherry-pick": cherrypick, - "clean": clean, - "clone": clone, - "commit": commit, - "diff": diff, - "difftool": difftool, - "fetch": fetch, - "grep": grep, - "init": init, - "log": log, - "ls-files": lsfiles, - "merge": merge, - "merge-base": mergebase, - "mergetool": mergetool, - "mv": mv, - "pull": pull, - "push": push, - "rebase": rebase, - "reflog": reflog, - "reset": reset, - "revert": revert, - "rev-parse": revparse, - "rm": rm, - "show": show, - "stash": stash, - "status": status, - "svn": svn, - "tag": tag, - "whatchanged": deprecated, + b"add": add, + b"am": am, + b"apply": apply, + b"bisect": bisect, + b"blame": blame, + b"branch": branch, + b"checkout": checkout, + b"cherry-pick": cherrypick, + b"clean": clean, + b"clone": clone, + b"commit": commit, + b"diff": diff, + b"difftool": difftool, + b"fetch": fetch, + b"grep": grep, + b"init": init, + b"log": log, + b"ls-files": lsfiles, + b"merge": merge, + b"merge-base": mergebase, + b"mergetool": mergetool, + b"mv": mv, + b"pull": pull, + b"push": push, + b"rebase": rebase, + b"reflog": reflog, + b"reset": reset, + b"revert": revert, + b"rev-parse": revparse, + b"rm": rm, + b"show": show, + b"stash": stash, + b"status": status, + b"svn": svn, + b"tag": tag, + b"whatchanged": deprecated, } gitsvncommands = { - "dcommit": svndcommit, - "fetch": svnfetch, - "find-rev": svnfindrev, - "rebase": svnrebase, + b"dcommit": svndcommit, + b"fetch": svnfetch, + b"find-rev": svnfindrev, + b"rebase": svnrebase, } diff --git a/hgext/gpg.py b/hgext/gpg.py --- a/hgext/gpg.py +++ b/hgext/gpg.py @@ -31,36 +31,36 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "gpg", "cmd", default="gpg", + b"gpg", b"cmd", default=b"gpg", ) configitem( - "gpg", "key", default=None, + b"gpg", b"key", default=None, ) configitem( - "gpg", ".*", default=None, generic=True, + b"gpg", b".*", default=None, generic=True, ) # Custom help category -_HELP_CATEGORY = "gpg" +_HELP_CATEGORY = b"gpg" help.CATEGORY_ORDER.insert( help.CATEGORY_ORDER.index(registrar.command.CATEGORY_HELP), _HELP_CATEGORY ) -help.CATEGORY_NAMES[_HELP_CATEGORY] = "Signing changes (GPG)" +help.CATEGORY_NAMES[_HELP_CATEGORY] = b"Signing changes (GPG)" class gpg(object): def __init__(self, path, key=None): self.path = path - self.key = (key and ' --local-user "%s"' % key) or "" + self.key = (key and b' --local-user "%s"' % key) or b"" def sign(self, data): - gpgcmd = "%s --sign --detach-sign%s" % (self.path, self.key) + gpgcmd = b"%s --sign --detach-sign%s" % (self.path, self.key) return procutil.filter(data, gpgcmd) def verify(self, data, sig): @@ -68,20 +68,20 @@ sigfile = datafile = None try: # create temporary files - fd, sigfile = pycompat.mkstemp(prefix="hg-gpg-", suffix=".sig") + fd, sigfile = pycompat.mkstemp(prefix=b"hg-gpg-", suffix=b".sig") fp = os.fdopen(fd, r"wb") fp.write(sig) fp.close() - fd, datafile = pycompat.mkstemp(prefix="hg-gpg-", suffix=".txt") + fd, datafile = pycompat.mkstemp(prefix=b"hg-gpg-", suffix=b".txt") fp = os.fdopen(fd, r"wb") fp.write(data) fp.close() - gpgcmd = "%s --logger-fd 1 --status-fd 1 --verify " '"%s" "%s"' % ( + gpgcmd = b"%s --logger-fd 1 --status-fd 1 --verify " b'"%s" "%s"' % ( self.path, sigfile, datafile, ) - ret = procutil.filter("", gpgcmd) + ret = procutil.filter(b"", gpgcmd) finally: for f in (sigfile, datafile): try: @@ -94,25 +94,25 @@ for l in ret.splitlines(): # see DETAILS in the gnupg documentation # filter the logger output - if not l.startswith("[GNUPG:]"): + if not l.startswith(b"[GNUPG:]"): continue l = l[9:] - if l.startswith("VALIDSIG"): + if l.startswith(b"VALIDSIG"): # fingerprint of the primary key fingerprint = l.split()[10] - elif l.startswith("ERRSIG"): - key = l.split(" ", 3)[:2] - key.append("") + elif l.startswith(b"ERRSIG"): + key = l.split(b" ", 3)[:2] + key.append(b"") fingerprint = None elif ( - l.startswith("GOODSIG") - or l.startswith("EXPSIG") - or l.startswith("EXPKEYSIG") - or l.startswith("BADSIG") + l.startswith(b"GOODSIG") + or l.startswith(b"EXPSIG") + or l.startswith(b"EXPKEYSIG") + or l.startswith(b"BADSIG") ): if key is not None: keys.append(key + [fingerprint]) - key = l.split(" ", 2) + key = l.split(b" ", 2) fingerprint = None if key is not None: keys.append(key + [fingerprint]) @@ -121,10 +121,10 @@ def newgpg(ui, **opts): """create a new gpg instance""" - gpgpath = ui.config("gpg", "cmd") + gpgpath = ui.config(b"gpg", b"cmd") gpgkey = opts.get(r"key") if not gpgkey: - gpgkey = ui.config("gpg", "key") + gpgkey = ui.config(b"gpg", b"key") return gpg(gpgpath, gpgkey) @@ -139,18 +139,18 @@ for l in fileiter: if not l: continue - yield (l.split(" ", 2), (context, ln)) + yield (l.split(b" ", 2), (context, ln)) ln += 1 # read the heads - fl = repo.file(".hgsigs") + fl = repo.file(b".hgsigs") for r in reversed(fl.heads()): - fn = ".hgsigs|%s" % hgnode.short(r) + fn = b".hgsigs|%s" % hgnode.short(r) for item in parsefile(fl.read(r).splitlines(), fn): yield item try: # read local signatures - fn = "localsigs" + fn = b"localsigs" for item in parsefile(repo.vfs(fn), fn): yield item except IOError: @@ -161,7 +161,7 @@ """get the keys who signed a data""" fn, ln = context node, version, sig = sigdata - prefix = "%s:%d" % (fn, ln) + prefix = b"%s:%d" % (fn, ln) node = hgnode.bin(node) data = node2txt(repo, node, version) @@ -171,27 +171,27 @@ validkeys = [] # warn for expired key and/or sigs for key in keys: - if key[0] == "ERRSIG": - ui.write(_('%s Unknown key ID "%s"\n') % (prefix, key[1])) + if key[0] == b"ERRSIG": + ui.write(_(b'%s Unknown key ID "%s"\n') % (prefix, key[1])) continue - if key[0] == "BADSIG": - ui.write(_('%s Bad signature from "%s"\n') % (prefix, key[2])) + if key[0] == b"BADSIG": + ui.write(_(b'%s Bad signature from "%s"\n') % (prefix, key[2])) continue - if key[0] == "EXPSIG": + if key[0] == b"EXPSIG": ui.write( - _("%s Note: Signature has expired" ' (signed by: "%s")\n') + _(b"%s Note: Signature has expired" b' (signed by: "%s")\n') % (prefix, key[2]) ) - elif key[0] == "EXPKEYSIG": + elif key[0] == b"EXPKEYSIG": ui.write( - _("%s Note: This key has expired" ' (signed by: "%s")\n') + _(b"%s Note: This key has expired" b' (signed by: "%s")\n') % (prefix, key[2]) ) validkeys.append((key[1], key[2], key[3])) return validkeys -@command("sigs", [], _("hg sigs"), helpcategory=_HELP_CATEGORY) +@command(b"sigs", [], _(b"hg sigs"), helpcategory=_HELP_CATEGORY) def sigs(ui, repo): """list signed changesets""" mygpg = newgpg(ui) @@ -203,7 +203,7 @@ try: n = repo.lookup(node) except KeyError: - ui.warn(_("%s:%d node does not exist\n") % (fn, ln)) + ui.warn(_(b"%s:%d node does not exist\n") % (fn, ln)) continue r = repo.changelog.rev(n) keys = getkeys(ui, repo, mygpg, data, context) @@ -213,11 +213,11 @@ revs[r].extend(keys) for rev in sorted(revs, reverse=True): for k in revs[rev]: - r = "%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev))) - ui.write("%-30s %s\n" % (keystr(ui, k), r)) + r = b"%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev))) + ui.write(b"%-30s %s\n" % (keystr(ui, k), r)) -@command("sigcheck", [], _("hg sigcheck REV"), helpcategory=_HELP_CATEGORY) +@command(b"sigcheck", [], _(b"hg sigcheck REV"), helpcategory=_HELP_CATEGORY) def sigcheck(ui, repo, rev): """verify all the signatures there may be for a particular revision""" mygpg = newgpg(ui) @@ -233,37 +233,42 @@ keys.extend(k) if not keys: - ui.write(_("no valid signature for %s\n") % hgnode.short(rev)) + ui.write(_(b"no valid signature for %s\n") % hgnode.short(rev)) return # print summary - ui.write(_("%s is signed by:\n") % hgnode.short(rev)) + ui.write(_(b"%s is signed by:\n") % hgnode.short(rev)) for key in keys: - ui.write(" %s\n" % keystr(ui, key)) + ui.write(b" %s\n" % keystr(ui, key)) def keystr(ui, key): """associate a string to a key (username, comment)""" keyid, user, fingerprint = key - comment = ui.config("gpg", fingerprint) + comment = ui.config(b"gpg", fingerprint) if comment: - return "%s (%s)" % (user, comment) + return b"%s (%s)" % (user, comment) else: return user @command( - "sign", + b"sign", [ - ("l", "local", None, _("make the signature local")), - ("f", "force", None, _("sign even if the sigfile is modified")), - ("", "no-commit", None, _("do not commit the sigfile after signing")), - ("k", "key", "", _("the key id to sign with"), _("ID")), - ("m", "message", "", _("use text as commit message"), _("TEXT")), - ("e", "edit", False, _("invoke editor on commit messages")), + (b"l", b"local", None, _(b"make the signature local")), + (b"f", b"force", None, _(b"sign even if the sigfile is modified")), + ( + b"", + b"no-commit", + None, + _(b"do not commit the sigfile after signing"), + ), + (b"k", b"key", b"", _(b"the key id to sign with"), _(b"ID")), + (b"m", b"message", b"", _(b"use text as commit message"), _(b"TEXT")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), ] + cmdutil.commitopts2, - _("hg sign [OPTION]... [REV]..."), + _(b"hg sign [OPTION]... [REV]..."), helpcategory=_HELP_CATEGORY, ) def sign(ui, repo, *revs, **opts): @@ -284,12 +289,12 @@ def _dosign(ui, repo, *revs, **opts): mygpg = newgpg(ui, **opts) opts = pycompat.byteskwargs(opts) - sigver = "0" - sigmessage = "" + sigver = b"0" + sigmessage = b"" - date = opts.get("date") + date = opts.get(b"date") if date: - opts["date"] = dateutil.parsedate(date) + opts[b"date"] = dateutil.parsedate(date) if revs: nodes = [repo.lookup(n) for n in revs] @@ -299,7 +304,7 @@ ] if len(nodes) > 1: raise error.Abort( - _("uncommitted merge - please provide a " "specific revision") + _(b"uncommitted merge - please provide a " b"specific revision") ) if not nodes: nodes = [repo.changelog.tip()] @@ -307,55 +312,55 @@ for n in nodes: hexnode = hgnode.hex(n) ui.write( - _("signing %d:%s\n") % (repo.changelog.rev(n), hgnode.short(n)) + _(b"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")) + raise error.Abort(_(b"error while signing")) sig = binascii.b2a_base64(sig) - sig = sig.replace("\n", "") - sigmessage += "%s %s %s\n" % (hexnode, sigver, sig) + sig = sig.replace(b"\n", b"") + sigmessage += b"%s %s %s\n" % (hexnode, sigver, sig) # write it - if opts["local"]: - repo.vfs.append("localsigs", sigmessage) + if opts[b"local"]: + repo.vfs.append(b"localsigs", sigmessage) return - if not opts["force"]: - msigs = match.exact([".hgsigs"]) + if not opts[b"force"]: + msigs = match.exact([b".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"), + _(b"working copy of .hgsigs is changed "), + hint=_(b"please commit .hgsigs manually"), ) - sigsfile = repo.wvfs(".hgsigs", "ab") + sigsfile = repo.wvfs(b".hgsigs", b"ab") sigsfile.write(sigmessage) sigsfile.close() - if ".hgsigs" not in repo.dirstate: - repo[None].add([".hgsigs"]) + if b".hgsigs" not in repo.dirstate: + repo[None].add([b".hgsigs"]) - if opts["no_commit"]: + if opts[b"no_commit"]: return - message = opts["message"] + message = opts[b"message"] if not message: # we don't translate commit messages - message = "\n".join( + message = b"\n".join( [ - "Added signature for changeset %s" % hgnode.short(n) + b"Added signature for changeset %s" % hgnode.short(n) for n in nodes ] ) try: editor = cmdutil.getcommiteditor( - editform="gpg.sign", **pycompat.strkwargs(opts) + editform=b"gpg.sign", **pycompat.strkwargs(opts) ) repo.commit( - message, opts["user"], opts["date"], match=msigs, editor=editor + message, opts[b"user"], opts[b"date"], match=msigs, editor=editor ) except ValueError as inst: raise error.Abort(pycompat.bytestr(inst)) @@ -363,10 +368,10 @@ def node2txt(repo, node, ver): """map a manifest into some text""" - if ver == "0": - return "%s\n" % hgnode.hex(node) + if ver == b"0": + return b"%s\n" % hgnode.hex(node) else: - raise error.Abort(_("unknown signature version")) + raise error.Abort(_(b"unknown signature version")) def extsetup(ui): @@ -374,4 +379,4 @@ help.CATEGORY_ORDER.insert( help.CATEGORY_ORDER.index(command.CATEGORY_MAINTENANCE), _HELP_CATEGORY ) - help.CATEGORY_NAMES[_HELP_CATEGORY] = "GPG signing" + help.CATEGORY_NAMES[_HELP_CATEGORY] = b"GPG signing" diff --git a/hgext/graphlog.py b/hgext/graphlog.py --- a/hgext/graphlog.py +++ b/hgext/graphlog.py @@ -30,66 +30,83 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "glog", + b"glog", [ ( - "f", - "follow", + b"f", + b"follow", None, _( - "follow changeset history, or file history across copies and renames" + b"follow changeset history, or file history across copies and renames" ), ), ( - "", - "follow-first", + b"", + b"follow-first", None, - _("only follow the first parent of merge changesets (DEPRECATED)"), + _(b"only follow the first parent of merge changesets (DEPRECATED)"), ), - ("d", "date", "", _("show revisions matching date spec"), _("DATE")), - ("C", "copies", None, _("show copied files")), ( - "k", - "keyword", + b"d", + b"date", + b"", + _(b"show revisions matching date spec"), + _(b"DATE"), + ), + (b"C", b"copies", None, _(b"show copied files")), + ( + b"k", + b"keyword", [], - _("do case-insensitive search for a given text"), - _("TEXT"), + _(b"do case-insensitive search for a given text"), + _(b"TEXT"), + ), + ( + b"r", + b"rev", + [], + _(b"show the specified revision or revset"), + _(b"REV"), ), - ("r", "rev", [], _("show the specified revision or revset"), _("REV")), - ("", "removed", None, _("include revisions where files were removed")), - ("m", "only-merges", None, _("show only merges (DEPRECATED)")), - ("u", "user", [], _("revisions committed by user"), _("USER")), ( - "", - "only-branch", + b"", + b"removed", + None, + _(b"include revisions where files were removed"), + ), + (b"m", b"only-merges", None, _(b"show only merges (DEPRECATED)")), + (b"u", b"user", [], _(b"revisions committed by user"), _(b"USER")), + ( + b"", + b"only-branch", [], _( - "show only changesets within the given named branch (DEPRECATED)" + b"show only changesets within the given named branch (DEPRECATED)" ), - _("BRANCH"), + _(b"BRANCH"), ), ( - "b", - "branch", + b"b", + b"branch", [], - _("show changesets within the given named branch"), - _("BRANCH"), + _(b"show changesets within the given named branch"), + _(b"BRANCH"), ), ( - "P", - "prune", + b"P", + b"prune", [], - _("do not display revision or any of its ancestors"), - _("REV"), + _(b"do not display revision or any of its ancestors"), + _(b"REV"), ), ] + cmdutil.logopts + cmdutil.walkopts, - _("[OPTION]... [FILE]"), + _(b"[OPTION]... [FILE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, inferrepo=True, ) diff --git a/hgext/hgk.py b/hgext/hgk.py --- a/hgext/hgk.py +++ b/hgext/hgk.py @@ -59,27 +59,27 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "hgk", "path", default="hgk", + b"hgk", b"path", default=b"hgk", ) @command( - "debug-diff-tree", + b"debug-diff-tree", [ - ("p", "patch", None, _("generate patch")), - ("r", "recursive", None, _("recursive")), - ("P", "pretty", None, _("pretty")), - ("s", "stdin", None, _("stdin")), - ("C", "copy", None, _("detect copies")), - ("S", "search", "", _("search")), + (b"p", b"patch", None, _(b"generate patch")), + (b"r", b"recursive", None, _(b"recursive")), + (b"P", b"pretty", None, _(b"pretty")), + (b"s", b"stdin", None, _(b"stdin")), + (b"C", b"copy", None, _(b"detect copies")), + (b"S", b"search", b"", _(b"search")), ], - "[OPTION]... NODE1 NODE2 [FILE]...", + b"[OPTION]... NODE1 NODE2 [FILE]...", inferrepo=True, ) def difftree(ui, repo, node1=None, node2=None, *files, **opts): @@ -98,17 +98,17 @@ for f in modified: # TODO get file permissions ui.write( - ":100664 100664 %s %s M\t%s\t%s\n" + b":100664 100664 %s %s M\t%s\t%s\n" % (short(mmap[f]), short(mmap2[f]), f, f) ) for f in added: ui.write( - ":000000 100664 %s %s N\t%s\t%s\n" + b":000000 100664 %s %s N\t%s\t%s\n" % (empty, short(mmap2[f]), f, f) ) for f in removed: ui.write( - ":100664 000000 %s %s D\t%s\t%s\n" + b":100664 000000 %s %s D\t%s\t%s\n" % (short(mmap[f]), empty, f, f) ) @@ -133,7 +133,7 @@ node1 = repo.changelog.parents(node1)[0] if opts[r"patch"]: if opts[r"pretty"]: - catcommit(ui, repo, node2, "") + catcommit(ui, repo, node2, b"") m = scmutil.match(repo[node1], files) diffopts = patch.difffeatureopts(ui) diffopts.git = True @@ -147,51 +147,51 @@ def catcommit(ui, repo, n, prefix, ctx=None): - nlprefix = "\n" + prefix + nlprefix = b"\n" + prefix if ctx is None: ctx = repo[n] # use ctx.node() instead ?? - ui.write(("tree %s\n" % short(ctx.changeset()[0]))) + ui.write((b"tree %s\n" % short(ctx.changeset()[0]))) for p in ctx.parents(): - ui.write(("parent %s\n" % p)) + ui.write((b"parent %s\n" % p)) date = ctx.date() - description = ctx.description().replace("\0", "") - ui.write(("author %s %d %d\n" % (ctx.user(), int(date[0]), date[1]))) + description = ctx.description().replace(b"\0", b"") + ui.write((b"author %s %d %d\n" % (ctx.user(), int(date[0]), date[1]))) - if "committer" in ctx.extra(): - ui.write(("committer %s\n" % ctx.extra()["committer"])) + if b"committer" in ctx.extra(): + ui.write((b"committer %s\n" % ctx.extra()[b"committer"])) - ui.write(("revision %d\n" % ctx.rev())) - ui.write(("branch %s\n" % ctx.branch())) + ui.write((b"revision %d\n" % ctx.rev())) + ui.write((b"branch %s\n" % ctx.branch())) if obsolete.isenabled(repo, obsolete.createmarkersopt): if ctx.obsolete(): - ui.write("obsolete\n") - ui.write(("phase %s\n\n" % ctx.phasestr())) + ui.write(b"obsolete\n") + ui.write((b"phase %s\n\n" % ctx.phasestr())) - if prefix != "": + if prefix != b"": ui.write( - "%s%s\n" % (prefix, description.replace("\n", nlprefix).strip()) + b"%s%s\n" % (prefix, description.replace(b"\n", nlprefix).strip()) ) else: - ui.write(description + "\n") + ui.write(description + b"\n") if prefix: - ui.write("\0") + ui.write(b"\0") -@command("debug-merge-base", [], _("REV REV")) +@command(b"debug-merge-base", [], _(b"REV REV")) def base(ui, repo, node1, node2): """output common ancestor information""" node1 = repo.lookup(node1) node2 = repo.lookup(node2) n = repo.changelog.ancestor(node1, node2) - ui.write(short(n) + "\n") + ui.write(short(n) + b"\n") @command( - "debug-cat-file", - [("s", "stdin", None, _("stdin"))], - _("[OPTION]... TYPE FILE"), + b"debug-cat-file", + [(b"s", b"stdin", None, _(b"stdin"))], + _(b"[OPTION]... TYPE FILE"), inferrepo=True, ) def catfile(ui, repo, type=None, r=None, **opts): @@ -200,21 +200,21 @@ # spaces. This way the our caller can find the commit without magic # strings # - prefix = "" + prefix = b"" if opts[r"stdin"]: line = ui.fin.readline() if not line: return (type, r) = line.rstrip(pycompat.oslinesep).split(b" ") - prefix = " " + prefix = b" " else: if not type or not r: - ui.warn(_("cat-file: type or revision not supplied\n")) - commands.help_(ui, "cat-file") + ui.warn(_(b"cat-file: type or revision not supplied\n")) + commands.help_(ui, b"cat-file") while r: - if type != "commit": - ui.warn(_("aborting hg cat-file only understands commits\n")) + if type != b"commit": + ui.warn(_(b"aborting hg cat-file only understands commits\n")) return 1 n = repo.lookup(r) catcommit(ui, repo, n, prefix) @@ -232,7 +232,7 @@ # telling you which commits are reachable from the supplied ones via # a bitmask based on arg position. # you can specify a commit to stop at by starting the sha1 with ^ -def revtree(ui, args, repo, full="tree", maxnr=0, parents=False): +def revtree(ui, args, repo, full=b"tree", maxnr=0, parents=False): def chlogwalk(): count = len(repo) i = count @@ -281,11 +281,11 @@ # figure out which commits they are asking for and which ones they # want us to stop on for i, arg in enumerate(args): - if arg.startswith("^"): + if arg.startswith(b"^"): s = repo.lookup(arg[1:]) stop_sha1.append(s) want_sha1.append(s) - elif arg != "HEAD": + elif arg != b"HEAD": want_sha1.append(repo.lookup(arg)) # calculate the graph for the supplied commits @@ -312,32 +312,32 @@ n = repo.changelog.node(i) mask = is_reachable(want_sha1, reachable, n) if mask: - parentstr = "" + parentstr = b"" if parents: pp = repo.changelog.parents(n) if pp[0] != nullid: - parentstr += " " + short(pp[0]) + parentstr += b" " + short(pp[0]) if pp[1] != nullid: - parentstr += " " + short(pp[1]) + parentstr += b" " + short(pp[1]) if not full: - ui.write("%s%s\n" % (short(n), parentstr)) - elif full == "commit": - ui.write("%s%s\n" % (short(n), parentstr)) - catcommit(ui, repo, n, " ", ctx) + ui.write(b"%s%s\n" % (short(n), parentstr)) + elif full == b"commit": + ui.write(b"%s%s\n" % (short(n), parentstr)) + catcommit(ui, repo, n, b" ", ctx) else: (p1, p2) = repo.changelog.parents(n) (h, h1, h2) = map(short, (n, p1, p2)) (i1, i2) = map(repo.changelog.rev, (p1, p2)) date = ctx.date()[0] - ui.write("%s %s:%s" % (date, h, mask)) + ui.write(b"%s %s:%s" % (date, h, mask)) mask = is_reachable(want_sha1, reachable, p1) if i1 != nullrev and mask > 0: - ui.write("%s:%s " % (h1, mask)), + ui.write(b"%s:%s " % (h1, mask)), mask = is_reachable(want_sha1, reachable, p2) if i2 != nullrev and mask > 0: - ui.write("%s:%s " % (h2, mask)) - ui.write("\n") + ui.write(b"%s:%s " % (h2, mask)) + ui.write(b"\n") if maxnr and count >= maxnr: break count += 1 @@ -347,19 +347,19 @@ # at a given commit without walking the whole repo. TODO add the stop # parameter @command( - "debug-rev-list", + b"debug-rev-list", [ - ("H", "header", None, _("header")), - ("t", "topo-order", None, _("topo-order")), - ("p", "parents", None, _("parents")), - ("n", "max-count", 0, _("max-count")), + (b"H", b"header", None, _(b"header")), + (b"t", b"topo-order", None, _(b"topo-order")), + (b"p", b"parents", None, _(b"parents")), + (b"n", b"max-count", 0, _(b"max-count")), ], - "[OPTION]... REV...", + b"[OPTION]... REV...", ) def revlist(ui, repo, *revs, **opts): """print revisions""" - if opts["header"]: - full = "commit" + if opts[b"header"]: + full = b"commit" else: full = None copy = [x for x in revs] @@ -367,19 +367,19 @@ @command( - "view", - [("l", "limit", "", _("limit number of changes displayed"), _("NUM"))], - _("[-l LIMIT] [REVRANGE]"), + b"view", + [(b"l", b"limit", b"", _(b"limit number of changes displayed"), _(b"NUM"))], + _(b"[-l LIMIT] [REVRANGE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, ) def view(ui, repo, *etc, **opts): - "start interactive history viewer" + b"start interactive history viewer" opts = pycompat.byteskwargs(opts) os.chdir(repo.root) - optstr = " ".join(["--%s %s" % (k, v) for k, v in opts.iteritems() if v]) + optstr = b" ".join([b"--%s %s" % (k, v) for k, v in opts.iteritems() if v]) if repo.filtername is None: - optstr += "--hidden" + optstr += b"--hidden" - cmd = ui.config("hgk", "path") + " %s %s" % (optstr, " ".join(etc)) - ui.debug("running %s\n" % cmd) - ui.system(cmd, blockedtag="hgk_view") + cmd = ui.config(b"hgk", b"path") + b" %s %s" % (optstr, b" ".join(etc)) + ui.debug(b"running %s\n" % cmd) + ui.system(cmd, blockedtag=b"hgk_view") diff --git a/hgext/highlight/__init__.py b/hgext/highlight/__init__.py --- a/hgext/highlight/__init__.py +++ b/hgext/highlight/__init__.py @@ -43,13 +43,13 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def pygmentize(web, field, fctx, tmpl): - style = web.config("web", "pygments_style", "colorful") - expr = web.config("web", "highlightfiles", "size('<5M')") - filenameonly = web.configbool("web", "highlightonlymatchfilename", False) + style = web.config(b"web", b"pygments_style", b"colorful") + expr = web.config(b"web", b"highlightfiles", b"size('<5M')") + filenameonly = web.configbool(b"web", b"highlightonlymatchfilename", False) ctx = fctx.changectx() m = ctx.matchfileset(expr) @@ -60,7 +60,7 @@ def filerevision_highlight(orig, web, fctx): - mt = web.res.headers["Content-Type"] + mt = web.res.headers[b"Content-Type"] # only pygmentize for mimetype containing 'html' so we both match # 'text/html' and possibly 'application/xhtml+xml' in the future # so that we don't have to touch the extension when the mimetype @@ -68,30 +68,30 @@ # raw file is sent using rawfile() and doesn't call us, so we # can't clash with the file's content-type here in case we # pygmentize a html file - if "html" in mt: - pygmentize(web, "fileline", fctx, web.tmpl) + if b"html" in mt: + pygmentize(web, b"fileline", fctx, web.tmpl) return orig(web, fctx) def annotate_highlight(orig, web): - mt = web.res.headers["Content-Type"] - if "html" in mt: + mt = web.res.headers[b"Content-Type"] + if b"html" in mt: fctx = webutil.filectx(web.repo, web.req) - pygmentize(web, "annotateline", fctx, web.tmpl) + pygmentize(web, b"annotateline", fctx, web.tmpl) return orig(web) def generate_css(web): - pg_style = web.config("web", "pygments_style", "colorful") + pg_style = web.config(b"web", b"pygments_style", b"colorful") fmter = highlight.HtmlFormatter(style=pycompat.sysstr(pg_style)) - web.res.headers["Content-Type"] = "text/css" - style_defs = fmter.get_style_defs(pycompat.sysstr("")) + web.res.headers[b"Content-Type"] = b"text/css" + style_defs = fmter.get_style_defs(pycompat.sysstr(b"")) web.res.setbodybytes( - "".join( + b"".join( [ - "/* pygments_style = %s */\n\n" % pg_style, + b"/* pygments_style = %s */\n\n" % pg_style, pycompat.bytestr(style_defs), ] ) @@ -102,8 +102,8 @@ def extsetup(ui): # monkeypatch in the new version extensions.wrapfunction( - webcommands, "_filerevision", filerevision_highlight + webcommands, b"_filerevision", filerevision_highlight ) - extensions.wrapfunction(webcommands, "annotate", annotate_highlight) + extensions.wrapfunction(webcommands, b"annotate", annotate_highlight) webcommands.highlightcss = generate_css - webcommands.__all__.append("highlightcss") + webcommands.__all__.append(b"highlightcss") diff --git a/hgext/highlight/highlight.py b/hgext/highlight/highlight.py --- a/hgext/highlight/highlight.py +++ b/hgext/highlight/highlight.py @@ -12,7 +12,7 @@ from mercurial import demandimport -demandimport.IGNORES.update(["pkgutil", "pkg_resources", "__main__"]) +demandimport.IGNORES.update([b"pkgutil", b"pkg_resources", b"__main__"]) from mercurial import ( encoding, @@ -39,27 +39,27 @@ HtmlFormatter = pygments.formatters.HtmlFormatter SYNTAX_CSS = ( - '\n' + b'\n' ) def pygmentize(field, fctx, style, tmpl, guessfilenameonly=False): # append a to the syntax highlighting css - tmpl.load("header") - old_header = tmpl.cache["header"] + tmpl.load(b"header") + old_header = tmpl.cache[b"header"] if SYNTAX_CSS not in old_header: new_header = old_header + SYNTAX_CSS - tmpl.cache["header"] = new_header + tmpl.cache[b"header"] = new_header text = fctx.data() if stringutil.binary(text): return # str.splitlines() != unicode.splitlines() because "reasons" - for c in "\x0c\x1c\x1d\x1e": + for c in b"\x0c\x1c\x1d\x1e": if c in text: - text = text.replace(c, "") + text = text.replace(c, b"") # Pygments is best used with Unicode strings: # @@ -94,8 +94,8 @@ for s in colorized.splitlines() ) - tmpl._filters["colorize"] = lambda x: next(coloriter) + tmpl._filters[b"colorize"] = lambda x: next(coloriter) oldl = tmpl.cache[field] - newl = oldl.replace("line|escape", "line|colorize") + newl = oldl.replace(b"line|escape", b"line|colorize") tmpl.cache[field] = newl diff --git a/hgext/histedit.py b/hgext/histedit.py --- a/hgext/histedit.py +++ b/hgext/histedit.py @@ -241,30 +241,30 @@ configtable = {} configitem = registrar.configitem(configtable) configitem( - "experimental", "histedit.autoverb", default=False, + b"experimental", b"histedit.autoverb", default=False, ) configitem( - "histedit", "defaultrev", default=None, + b"histedit", b"defaultrev", default=None, ) configitem( - "histedit", "dropmissing", default=False, + b"histedit", b"dropmissing", default=False, ) configitem( - "histedit", "linelen", default=80, + b"histedit", b"linelen", default=80, ) configitem( - "histedit", "singletransaction", default=False, + b"histedit", b"singletransaction", default=False, ) configitem( - "ui", "interface.histedit", default=None, + b"ui", b"interface.histedit", default=None, ) -configitem("histedit", "summary-template", default="{rev} {desc|firstline}") +configitem(b"histedit", b"summary-template", default=b"{rev} {desc|firstline}") # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" actiontable = {} primaryactions = set() @@ -298,11 +298,11 @@ def addverb(v): a = actiontable[v] - lines = a.message.split("\n") + lines = a.message.split(b"\n") if len(a.verbs): - v = ", ".join(sorted(a.verbs, key=lambda v: len(v))) - actions.append(" %s = %s" % (v, lines[0])) - actions.extend([" %s" for l in lines[1:]]) + v = b", ".join(sorted(a.verbs, key=lambda v: len(v))) + actions.append(b" %s = %s" % (v, lines[0])) + actions.extend([b" %s" for l in lines[1:]]) for v in ( sorted(primaryactions) @@ -310,18 +310,18 @@ + sorted(tertiaryactions) ): addverb(v) - actions.append("") + actions.append(b"") hints = [] - if ui.configbool("histedit", "dropmissing"): + if ui.configbool(b"histedit", b"dropmissing"): hints.append( - "Deleting a changeset from the list " - "will DISCARD it from the edited history!" + b"Deleting a changeset from the list " + b"will DISCARD it from the edited history!" ) - lines = (intro % (first, last)).split("\n") + actions + hints - - return "".join(["# %s\n" % l if l else "#\n" for l in lines]) + lines = (intro % (first, last)).split(b"\n") + actions + hints + + return b"".join([b"# %s\n" % l if l else b"#\n" for l in lines]) class histeditstate(object): @@ -334,80 +334,80 @@ self.lock = None self.wlock = None self.backupfile = None - self.stateobj = statemod.cmdstate(repo, "histedit-state") + self.stateobj = statemod.cmdstate(repo, b"histedit-state") self.replacements = [] def read(self): """Load histedit state from disk and set fields appropriately.""" if not self.stateobj.exists(): - cmdutil.wrongtooltocontinue(self.repo, _("histedit")) + cmdutil.wrongtooltocontinue(self.repo, _(b"histedit")) data = self._read() - self.parentctxnode = data["parentctxnode"] - actions = parserules(data["rules"], self) + self.parentctxnode = data[b"parentctxnode"] + actions = parserules(data[b"rules"], self) self.actions = actions - self.keep = data["keep"] - self.topmost = data["topmost"] - self.replacements = data["replacements"] - self.backupfile = data["backupfile"] + self.keep = data[b"keep"] + self.topmost = data[b"topmost"] + self.replacements = data[b"replacements"] + self.backupfile = data[b"backupfile"] def _read(self): - fp = self.repo.vfs.read("histedit-state") - if fp.startswith("v1\n"): + fp = self.repo.vfs.read(b"histedit-state") + if fp.startswith(b"v1\n"): data = self._load() parentctxnode, rules, keep, topmost, replacements, backupfile = data else: data = pickle.loads(fp) parentctxnode, rules, keep, topmost, replacements = data backupfile = None - rules = "\n".join(["%s %s" % (verb, rest) for [verb, rest] in rules]) + rules = b"\n".join([b"%s %s" % (verb, rest) for [verb, rest] in rules]) return { - "parentctxnode": parentctxnode, - "rules": rules, - "keep": keep, - "topmost": topmost, - "replacements": replacements, - "backupfile": backupfile, + b"parentctxnode": parentctxnode, + b"rules": rules, + b"keep": keep, + b"topmost": topmost, + b"replacements": replacements, + b"backupfile": backupfile, } def write(self, tr=None): if tr: tr.addfilegenerator( - "histedit-state", - ("histedit-state",), + b"histedit-state", + (b"histedit-state",), self._write, - location="plain", + location=b"plain", ) else: - with self.repo.vfs("histedit-state", "w") as f: + with self.repo.vfs(b"histedit-state", b"w") as f: self._write(f) def _write(self, fp): - fp.write("v1\n") - fp.write("%s\n" % node.hex(self.parentctxnode)) - fp.write("%s\n" % node.hex(self.topmost)) - fp.write("%s\n" % ("True" if self.keep else "False")) - fp.write("%d\n" % len(self.actions)) + fp.write(b"v1\n") + fp.write(b"%s\n" % node.hex(self.parentctxnode)) + fp.write(b"%s\n" % node.hex(self.topmost)) + fp.write(b"%s\n" % (b"True" if self.keep else b"False")) + fp.write(b"%d\n" % len(self.actions)) for action in self.actions: - fp.write("%s\n" % action.tostate()) - fp.write("%d\n" % len(self.replacements)) + fp.write(b"%s\n" % action.tostate()) + fp.write(b"%d\n" % len(self.replacements)) for replacement in self.replacements: fp.write( - "%s%s\n" + b"%s%s\n" % ( node.hex(replacement[0]), - "".join(node.hex(r) for r in replacement[1]), + b"".join(node.hex(r) for r in replacement[1]), ) ) backupfile = self.backupfile if not backupfile: - backupfile = "" - fp.write("%s\n" % backupfile) + backupfile = b"" + fp.write(b"%s\n" % backupfile) def _load(self): - fp = self.repo.vfs("histedit-state", "r") + fp = self.repo.vfs(b"histedit-state", b"r") lines = [l[:-1] for l in fp.readlines()] index = 0 @@ -420,7 +420,7 @@ topmost = node.bin(lines[index]) index += 1 - keep = lines[index] == "True" + keep = lines[index] == b"True" index += 1 # Rules @@ -457,10 +457,10 @@ def clear(self): if self.inprogress(): - self.repo.vfs.unlink("histedit-state") + self.repo.vfs.unlink(b"histedit-state") def inprogress(self): - return self.repo.vfs.exists("histedit-state") + return self.repo.vfs.exists(b"histedit-state") class histeditaction(object): @@ -473,7 +473,7 @@ def fromrule(cls, state, rule): """Parses the given rule, returning an instance of the histeditaction. """ - ruleid = rule.strip().split(" ", 1)[0] + ruleid = rule.strip().split(b" ", 1)[0] # ruleid can be anything from rev numbers, hashes, "bookmarks" etc # Check for validation of rule ids and get the rulehash try: @@ -484,7 +484,7 @@ rulehash = _ctx.hex() rev = node.bin(rulehash) except error.RepoLookupError: - raise error.ParseError(_("invalid changeset %s") % ruleid) + raise error.ParseError(_(b"invalid changeset %s") % ruleid) return cls(state, rev) def verify(self, prev, expected, seen): @@ -493,21 +493,22 @@ ha = node.hex(self.node) self.node = scmutil.resolvehexnodeidprefix(repo, ha) if self.node is None: - raise error.ParseError(_("unknown changeset %s listed") % ha[:12]) + raise error.ParseError(_(b"unknown changeset %s listed") % ha[:12]) self._verifynodeconstraints(prev, expected, seen) def _verifynodeconstraints(self, prev, expected, seen): # by default command need a node in the edited list if self.node not in expected: raise error.ParseError( - _('%s "%s" changeset was not a candidate') + _(b'%s "%s" changeset was not a candidate') % (self.verb, node.short(self.node)), - hint=_("only use listed changesets"), + hint=_(b"only use listed changesets"), ) # and only one command per node if self.node in seen: raise error.ParseError( - _("duplicated command for changeset %s") % node.short(self.node) + _(b"duplicated command for changeset %s") + % node.short(self.node) ) def torule(self): @@ -520,15 +521,15 @@ ui = self.repo.ui summary = ( cmdutil.rendertemplate( - ctx, ui.config("histedit", "summary-template") + ctx, ui.config(b"histedit", b"summary-template") ) - or "" + or b"" ) summary = summary.splitlines()[0] - line = "%s %s %s" % (self.verb, ctx, summary) + line = b"%s %s %s" % (self.verb, ctx, summary) # trim to 75 columns by default so it's not stupidly wide in my editor # (the 5 more are left for verb) - maxlen = self.repo.ui.configint("histedit", "linelen") + maxlen = self.repo.ui.configint(b"histedit", b"linelen") maxlen = max(maxlen, 22) # avoid truncating hash return stringutil.ellipsis(line, maxlen) @@ -536,7 +537,7 @@ """Print an action in format used by histedit state files (the first line is a verb, the remainder is the second) """ - return "%s\n%s" % (self.verb, node.hex(self.node)) + return b"%s\n%s" % (self.verb, node.hex(self.node)) def run(self): """Runs the action. The default behavior is simply apply the action's @@ -557,9 +558,9 @@ repo.dirstate.setbranch(rulectx.branch()) if stats.unresolvedcount: raise error.InterventionRequired( - _("Fix up the change (%s %s)") + _(b"Fix up the change (%s %s)") % (self.verb, node.short(self.node)), - hint=_("hg histedit --continue to resume"), + hint=_(b"hg histedit --continue to resume"), ) def continuedirty(self): @@ -570,7 +571,7 @@ editor = self.commiteditor() commit = commitfuncfor(repo, rulectx) - if repo.ui.configbool("rewrite", "update-timestamp"): + if repo.ui.configbool(b"rewrite", b"update-timestamp"): date = dateutil.makedate() else: date = rulectx.date() @@ -590,10 +591,10 @@ """Continues the action when the working copy is clean. The default behavior is to accept the current commit as the new version of the rulectx.""" - ctx = self.repo["."] + ctx = self.repo[b"."] if ctx.node() == self.state.parentctxnode: self.repo.ui.warn( - _("%s: skipping changeset (no changes)\n") + _(b"%s: skipping changeset (no changes)\n") % node.short(self.node) ) return ctx, [(self.node, tuple())] @@ -616,10 +617,10 @@ phasemin = src.phase() def commitfunc(**kwargs): - overrides = {("phases", "new-commit"): phasemin} - with repo.ui.configoverride(overrides, "histedit"): + overrides = {(b"phases", b"new-commit"): phasemin} + with repo.ui.configoverride(overrides, b"histedit"): extra = kwargs.get(r"extra", {}).copy() - extra["histedit_source"] = src.hex() + extra[b"histedit_source"] = src.hex() kwargs[r"extra"] = extra return repo.commit(**kwargs) @@ -640,11 +641,11 @@ try: # ui.forcemerge is an internal variable, do not document repo.ui.setconfig( - "ui", "forcemerge", opts.get("tool", ""), "histedit" + b"ui", b"forcemerge", opts.get(b"tool", b""), b"histedit" ) - stats = mergemod.graft(repo, ctx, ctx.p1(), ["local", "histedit"]) + stats = mergemod.graft(repo, ctx, ctx.p1(), [b"local", b"histedit"]) finally: - repo.ui.setconfig("ui", "forcemerge", "", "histedit") + repo.ui.setconfig(b"ui", b"forcemerge", b"", b"histedit") return stats @@ -658,13 +659,13 @@ Commit message is edited in all cases. This function works in memory.""" - ctxs = list(repo.set("%d::%d", firstctx.rev(), lastctx.rev())) + ctxs = list(repo.set(b"%d::%d", firstctx.rev(), lastctx.rev())) if not ctxs: return None for c in ctxs: if not c.mutable(): raise error.ParseError( - _("cannot fold into public change %s") % node.short(c.node()) + _(b"cannot fold into public change %s") % node.short(c.node()) ) base = firstctx.p1() @@ -691,25 +692,25 @@ ctx, fctx.path(), fctx.data(), - islink="l" in flags, - isexec="x" in flags, + islink=b"l" in flags, + isexec=b"x" in flags, copysource=copied.get(path), ) return mctx return None - if commitopts.get("message"): - message = commitopts["message"] + if commitopts.get(b"message"): + message = commitopts[b"message"] else: message = firstctx.description() - user = commitopts.get("user") - date = commitopts.get("date") - extra = commitopts.get("extra") + user = commitopts.get(b"user") + date = commitopts.get(b"date") + extra = commitopts.get(b"extra") parents = (firstctx.p1().node(), firstctx.p2().node()) editor = None if not skipprompt: - editor = cmdutil.getcommiteditor(edit=True, editform="histedit.fold") + editor = cmdutil.getcommiteditor(edit=True, editform=b"histedit.fold") new = context.memctx( repo, parents=parents, @@ -730,10 +731,10 @@ def abortdirty(): raise error.Abort( - _("working copy has pending changes"), + _(b"working copy has pending changes"), hint=_( - "amend, commit, or revert them and run histedit " - "--continue, or abort with histedit --abort" + b"amend, commit, or revert them and run histedit " + b"--continue, or abort with histedit --abort" ), ) @@ -761,18 +762,18 @@ return wrap -@action(["pick", "p"], _("use commit"), priority=True) +@action([b"pick", b"p"], _(b"use commit"), priority=True) class pick(histeditaction): def run(self): rulectx = self.repo[self.node] if rulectx.p1().node() == self.state.parentctxnode: - self.repo.ui.debug("node %s unchanged\n" % node.short(self.node)) + self.repo.ui.debug(b"node %s unchanged\n" % node.short(self.node)) return rulectx, [] return super(pick, self).run() -@action(["edit", "e"], _("use commit, but stop for amending"), priority=True) +@action([b"edit", b"e"], _(b"use commit, but stop for amending"), priority=True) class edit(histeditaction): def run(self): repo = self.repo @@ -780,16 +781,16 @@ hg.update(repo, self.state.parentctxnode, quietempty=True) applychanges(repo.ui, repo, rulectx, {}) raise error.InterventionRequired( - _("Editing (%s), you may commit or record as needed now.") + _(b"Editing (%s), you may commit or record as needed now.") % node.short(self.node), - hint=_("hg histedit --continue to resume"), + hint=_(b"hg histedit --continue to resume"), ) def commiteditor(self): - return cmdutil.getcommiteditor(edit=True, editform="histedit.edit") - - -@action(["fold", "f"], _("use commit, but combine it with the one above")) + return cmdutil.getcommiteditor(edit=True, editform=b"histedit.edit") + + +@action([b"fold", b"f"], _(b"use commit, but combine it with the one above")) class fold(histeditaction): def verify(self, prev, expected, seen): """ Verifies semantic correctness of the fold rule""" @@ -797,13 +798,13 @@ repo = self.repo if not prev: c = repo[self.node].p1() - elif not prev.verb in ("pick", "base"): + elif not prev.verb in (b"pick", b"base"): return else: c = repo[prev.node] if not c.mutable(): raise error.ParseError( - _("cannot fold into public change %s") % node.short(c.node()) + _(b"cannot fold into public change %s") % node.short(c.node()) ) def continuedirty(self): @@ -812,7 +813,7 @@ commit = commitfuncfor(repo, rulectx) commit( - text="fold-temp-revision %s" % node.short(self.node), + text=b"fold-temp-revision %s" % node.short(self.node), user=rulectx.user(), date=rulectx.date(), extra=rulectx.extra(), @@ -820,23 +821,23 @@ def continueclean(self): repo = self.repo - ctx = repo["."] + ctx = repo[b"."] rulectx = repo[self.node] parentctxnode = self.state.parentctxnode if ctx.node() == parentctxnode: - repo.ui.warn(_("%s: empty changeset\n") % node.short(self.node)) + repo.ui.warn(_(b"%s: empty changeset\n") % node.short(self.node)) return ctx, [(self.node, (parentctxnode,))] parentctx = repo[parentctxnode] newcommits = set( c.node() - for c in repo.set("(%d::. - %d)", parentctx.rev(), parentctx.rev()) + for c in repo.set(b"(%d::. - %d)", parentctx.rev(), parentctx.rev()) ) if not newcommits: repo.ui.warn( _( - "%s: cannot fold - working copy is not a " - "descendant of previous commit %s\n" + b"%s: cannot fold - working copy is not a " + b"descendant of previous commit %s\n" ) % (node.short(self.node), node.short(parentctxnode)) ) @@ -879,38 +880,38 @@ hg.updaterepo(repo, parent, overwrite=False) ### prepare new commit data commitopts = {} - commitopts["user"] = ctx.user() + commitopts[b"user"] = ctx.user() # commit message if not self.mergedescs(): newmessage = ctx.description() else: newmessage = ( - "\n***\n".join( + b"\n***\n".join( [ctx.description()] + [repo[r].description() for r in internalchanges] + [oldctx.description()] ) - + "\n" + + b"\n" ) - commitopts["message"] = newmessage + commitopts[b"message"] = newmessage # date if self.firstdate(): - commitopts["date"] = ctx.date() + commitopts[b"date"] = ctx.date() else: - commitopts["date"] = max(ctx.date(), oldctx.date()) + commitopts[b"date"] = max(ctx.date(), oldctx.date()) # if date is to be updated to current - if ui.configbool("rewrite", "update-timestamp"): - commitopts["date"] = dateutil.makedate() + if ui.configbool(b"rewrite", b"update-timestamp"): + commitopts[b"date"] = dateutil.makedate() extra = ctx.extra().copy() # histedit_source # note: ctx is likely a temporary commit but that the best we can do # here. This is sufficient to solve issue3681 anyway. - extra["histedit_source"] = "%s,%s" % (ctx.hex(), oldctx.hex()) - commitopts["extra"] = extra + extra[b"histedit_source"] = b"%s,%s" % (ctx.hex(), oldctx.hex()) + commitopts[b"extra"] = extra phasemin = max(ctx.phase(), oldctx.phase()) - overrides = {("phases", "new-commit"): phasemin} - with repo.ui.configoverride(overrides, "histedit"): + overrides = {(b"phases", b"new-commit"): phasemin} + with repo.ui.configoverride(overrides, b"histedit"): n = collapse( repo, ctx, @@ -932,12 +933,12 @@ @action( - ["base", "b"], - _("checkout changeset and apply further changesets from there"), + [b"base", b"b"], + _(b"checkout changeset and apply further changesets from there"), ) class base(histeditaction): def run(self): - if self.repo["."].node() != self.node: + if self.repo[b"."].node() != self.node: mergemod.update(self.repo, self.node, branchmerge=False, force=True) return self.continueclean() @@ -945,21 +946,21 @@ abortdirty() def continueclean(self): - basectx = self.repo["."] + basectx = self.repo[b"."] return basectx, [] def _verifynodeconstraints(self, prev, expected, seen): # base can only be use with a node not in the edited set if self.node in expected: - msg = _('%s "%s" changeset was an edited list candidate') + msg = _(b'%s "%s" changeset was an edited list candidate') raise error.ParseError( msg % (self.verb, node.short(self.node)), - hint=_("base must only use unlisted changesets"), + hint=_(b"base must only use unlisted changesets"), ) @action( - ["_multifold"], + [b"_multifold"], _( """fold subclass used for when multiple folds happen in a row @@ -978,8 +979,8 @@ @action( - ["roll", "r"], - _("like fold, but discard this commit's description and date"), + [b"roll", b"r"], + _(b"like fold, but discard this commit's description and date"), ) class rollup(fold): def mergedescs(self): @@ -992,7 +993,7 @@ return True -@action(["drop", "d"], _("remove commit from history")) +@action([b"drop", b"d"], _(b"remove commit from history")) class drop(histeditaction): def run(self): parentctx = self.repo[self.state.parentctxnode] @@ -1000,13 +1001,13 @@ @action( - ["mess", "m"], - _("edit commit message without changing commit content"), + [b"mess", b"m"], + _(b"edit commit message without changing commit content"), priority=True, ) class message(histeditaction): def commiteditor(self): - return cmdutil.getcommiteditor(edit=True, editform="histedit.mess") + return cmdutil.getcommiteditor(edit=True, editform=b"histedit.mess") def findoutgoing(ui, repo, remote=None, force=False, opts=None): @@ -1015,9 +1016,9 @@ Used by initialization code""" if opts is None: opts = {} - dest = ui.expandpath(remote or "default-push", remote or "default") + dest = ui.expandpath(remote or b"default-push", remote or b"default") dest, branches = hg.parseurl(dest, None)[:2] - ui.status(_("comparing with %s\n") % util.hidepassword(dest)) + ui.status(_(b"comparing with %s\n") % util.hidepassword(dest)) revs, checkout = hg.addbranchrevs(repo, repo, branches, None) other = hg.peer(repo, opts, dest) @@ -1027,11 +1028,11 @@ outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force) if not outgoing.missing: - raise error.Abort(_("no outgoing ancestors")) - roots = list(repo.revs("roots(%ln)", outgoing.missing)) + raise error.Abort(_(b"no outgoing ancestors")) + roots = list(repo.revs(b"roots(%ln)", outgoing.missing)) if len(roots) > 1: - msg = _("there are ambiguous outgoing revisions") - hint = _("see 'hg help histedit' for more detail") + msg = _(b"there are ambiguous outgoing revisions") + hint = _(b"see 'hg help histedit' for more detail") raise error.Abort(msg, hint=hint) return repo[roots[0]].node() @@ -1042,10 +1043,10 @@ except ImportError: curses = None -KEY_LIST = ["pick", "edit", "fold", "drop", "mess", "roll"] +KEY_LIST = [b"pick", b"edit", b"fold", b"drop", b"mess", b"roll"] ACTION_LABELS = { - "fold": "^fold", - "roll": "^roll", + b"fold": b"^fold", + b"roll": b"^roll", } COLOR_HELP, COLOR_SELECTED, COLOR_OK, COLOR_WARN, COLOR_CURRENT = 1, 2, 3, 4, 5 @@ -1056,56 +1057,56 @@ MODE_INIT, MODE_PATCH, MODE_RULES, MODE_HELP = 0, 1, 2, 3 KEYTABLE = { - "global": { - "h": "next-action", - "KEY_RIGHT": "next-action", - "l": "prev-action", - "KEY_LEFT": "prev-action", - "q": "quit", - "c": "histedit", - "C": "histedit", - "v": "showpatch", - "?": "help", + b"global": { + b"h": b"next-action", + b"KEY_RIGHT": b"next-action", + b"l": b"prev-action", + b"KEY_LEFT": b"prev-action", + b"q": b"quit", + b"c": b"histedit", + b"C": b"histedit", + b"v": b"showpatch", + b"?": b"help", }, MODE_RULES: { - "d": "action-drop", - "e": "action-edit", - "f": "action-fold", - "m": "action-mess", - "p": "action-pick", - "r": "action-roll", - " ": "select", - "j": "down", - "k": "up", - "KEY_DOWN": "down", - "KEY_UP": "up", - "J": "move-down", - "K": "move-up", - "KEY_NPAGE": "move-down", - "KEY_PPAGE": "move-up", - "0": "goto", # Used for 0..9 + b"d": b"action-drop", + b"e": b"action-edit", + b"f": b"action-fold", + b"m": b"action-mess", + b"p": b"action-pick", + b"r": b"action-roll", + b" ": b"select", + b"j": b"down", + b"k": b"up", + b"KEY_DOWN": b"down", + b"KEY_UP": b"up", + b"J": b"move-down", + b"K": b"move-up", + b"KEY_NPAGE": b"move-down", + b"KEY_PPAGE": b"move-up", + b"0": b"goto", # Used for 0..9 }, MODE_PATCH: { - " ": "page-down", - "KEY_NPAGE": "page-down", - "KEY_PPAGE": "page-up", - "j": "line-down", - "k": "line-up", - "KEY_DOWN": "line-down", - "KEY_UP": "line-up", - "J": "down", - "K": "up", + b" ": b"page-down", + b"KEY_NPAGE": b"page-down", + b"KEY_PPAGE": b"page-up", + b"j": b"line-down", + b"k": b"line-up", + b"KEY_DOWN": b"line-down", + b"KEY_UP": b"line-up", + b"J": b"down", + b"K": b"up", }, MODE_HELP: {}, } def screen_size(): - return struct.unpack("hh", fcntl.ioctl(1, termios.TIOCGWINSZ, " ")) + return struct.unpack(b"hh", fcntl.ioctl(1, termios.TIOCGWINSZ, b" ")) class histeditrule(object): - def __init__(self, ctx, pos, action="pick"): + def __init__(self, ctx, pos, action=b"pick"): self.ctx = ctx self.action = action self.origpos = pos @@ -1128,9 +1129,9 @@ h = self.ctx.hex()[0:12] r = self.ctx.rev() desc = self.ctx.description().splitlines()[0].strip() - if self.action == "roll": - desc = "" - return "#{0:<2} {1:<6} {2}:{3} {4}".format( + if self.action == b"roll": + desc = b"" + return b"#{0:<2} {1:<6} {2}:{3} {4}".format( self.origpos, action, r, h, desc ) @@ -1149,39 +1150,39 @@ def movecursor(state, oldpos, newpos): """Change the rule/changeset that the cursor is pointing to, regardless of current mode (you can switch between patches from the view patch window).""" - state["pos"] = newpos - - mode, _ = state["mode"] + state[b"pos"] = newpos + + mode, _ = state[b"mode"] if mode == MODE_RULES: # Scroll through the list by updating the view for MODE_RULES, so that # even if we are not currently viewing the rules, switching back will # result in the cursor's rule being visible. - modestate = state["modes"][MODE_RULES] - if newpos < modestate["line_offset"]: - modestate["line_offset"] = newpos - elif newpos > modestate["line_offset"] + state["page_height"] - 1: - modestate["line_offset"] = newpos - state["page_height"] + 1 + modestate = state[b"modes"][MODE_RULES] + if newpos < modestate[b"line_offset"]: + modestate[b"line_offset"] = newpos + elif newpos > modestate[b"line_offset"] + state[b"page_height"] - 1: + modestate[b"line_offset"] = newpos - state[b"page_height"] + 1 # Reset the patch view region to the top of the new patch. - state["modes"][MODE_PATCH]["line_offset"] = 0 + state[b"modes"][MODE_PATCH][b"line_offset"] = 0 def changemode(state, mode): - curmode, _ = state["mode"] - state["mode"] = (mode, curmode) + curmode, _ = state[b"mode"] + state[b"mode"] = (mode, curmode) if mode == MODE_PATCH: - state["modes"][MODE_PATCH]["patchcontents"] = patchcontents(state) + state[b"modes"][MODE_PATCH][b"patchcontents"] = patchcontents(state) def makeselection(state, pos): - state["selected"] = pos + state[b"selected"] = pos def swap(state, oldpos, newpos): """Swap two positions and calculate necessary conflicts in O(|newpos-oldpos|) time""" - rules = state["rules"] + rules = state[b"rules"] assert 0 <= oldpos < len(rules) and 0 <= newpos < len(rules) rules[oldpos], rules[newpos] = rules[newpos], rules[oldpos] @@ -1196,13 +1197,13 @@ rules[newpos].checkconflicts(rules[r]) rules[oldpos].checkconflicts(rules[r]) - if state["selected"]: + if state[b"selected"]: makeselection(state, newpos) def changeaction(state, pos, action): """Change the action state on the given position to the new action""" - rules = state["rules"] + rules = state[b"rules"] assert 0 <= pos < len(rules) rules[pos].action = action @@ -1210,7 +1211,7 @@ def cycleaction(state, pos, next=False): """Changes the action state the next or the previous action from the action list""" - rules = state["rules"] + rules = state[b"rules"] assert 0 <= pos < len(rules) current = rules[pos].action @@ -1227,17 +1228,17 @@ def changeview(state, delta, unit): """Change the region of whatever is being viewed (a patch or the list of changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 'line'.""" - mode, _ = state["mode"] + mode, _ = state[b"mode"] if mode != MODE_PATCH: return - mode_state = state["modes"][mode] - num_lines = len(mode_state["patchcontents"]) - page_height = state["page_height"] - unit = page_height if unit == "page" else 1 + mode_state = state[b"modes"][mode] + num_lines = len(mode_state[b"patchcontents"]) + page_height = state[b"page_height"] + unit = page_height if unit == b"page" else 1 num_pages = 1 + (num_lines - 1) / page_height max_offset = (num_pages - 1) * page_height - newline = mode_state["line_offset"] + delta * unit - mode_state["line_offset"] = max(0, min(max_offset, newline)) + newline = mode_state[b"line_offset"] + delta * unit + mode_state[b"line_offset"] = max(0, min(max_offset, newline)) def event(state, ch): @@ -1246,60 +1247,62 @@ This takes the current state and based on the current character input from the user we change the state. """ - selected = state["selected"] - oldpos = state["pos"] - rules = state["rules"] - - if ch in (curses.KEY_RESIZE, "KEY_RESIZE"): + selected = state[b"selected"] + oldpos = state[b"pos"] + rules = state[b"rules"] + + if ch in (curses.KEY_RESIZE, b"KEY_RESIZE"): return E_RESIZE lookup_ch = ch - if "0" <= ch <= "9": - lookup_ch = "0" - - curmode, prevmode = state["mode"] - action = KEYTABLE[curmode].get(lookup_ch, KEYTABLE["global"].get(lookup_ch)) + if b"0" <= ch <= b"9": + lookup_ch = b"0" + + curmode, prevmode = state[b"mode"] + action = KEYTABLE[curmode].get( + lookup_ch, KEYTABLE[b"global"].get(lookup_ch) + ) if action is None: return - if action in ("down", "move-down"): + if action in (b"down", b"move-down"): newpos = min(oldpos + 1, len(rules) - 1) movecursor(state, oldpos, newpos) - if selected is not None or action == "move-down": + if selected is not None or action == b"move-down": swap(state, oldpos, newpos) - elif action in ("up", "move-up"): + elif action in (b"up", b"move-up"): newpos = max(0, oldpos - 1) movecursor(state, oldpos, newpos) - if selected is not None or action == "move-up": + if selected is not None or action == b"move-up": swap(state, oldpos, newpos) - elif action == "next-action": + elif action == b"next-action": cycleaction(state, oldpos, next=True) - elif action == "prev-action": + elif action == b"prev-action": cycleaction(state, oldpos, next=False) - elif action == "select": + elif action == b"select": selected = oldpos if selected is None else None makeselection(state, selected) - elif action == "goto" and int(ch) < len(rules) and len(rules) <= 10: + elif action == b"goto" and int(ch) < len(rules) and len(rules) <= 10: newrule = next((r for r in rules if r.origpos == int(ch))) movecursor(state, oldpos, newrule.pos) if selected is not None: swap(state, oldpos, newrule.pos) - elif action.startswith("action-"): + elif action.startswith(b"action-"): changeaction(state, oldpos, action[7:]) - elif action == "showpatch": + elif action == b"showpatch": changemode(state, MODE_PATCH if curmode != MODE_PATCH else prevmode) - elif action == "help": + elif action == b"help": changemode(state, MODE_HELP if curmode != MODE_HELP else prevmode) - elif action == "quit": + elif action == b"quit": return E_QUIT - elif action == "histedit": + elif action == b"histedit": return E_HISTEDIT - elif action == "page-down": + elif action == b"page-down": return E_PAGEDOWN - elif action == "page-up": + elif action == b"page-up": return E_PAGEUP - elif action == "line-down": + elif action == b"line-down": return E_LINEDOWN - elif action == "line-up": + elif action == b"line-up": return E_LINEUP @@ -1308,7 +1311,7 @@ our list of rules""" commands = [] for rules in rules: - commands.append("{0} {1}\n".format(rules.action, rules.ctx)) + commands.append(b"{0} {1}\n".format(rules.action, rules.ctx)) return commands @@ -1317,7 +1320,7 @@ whitespace characters, so that the color appears on the whole line""" maxy, maxx = win.getmaxyx() length = maxx - 1 - x - line = ("{0:<%d}" % length).format(str(line).strip())[:length] + line = (b"{0:<%d}" % length).format(str(line).strip())[:length] if y < 0: y = maxy + y if x < 0: @@ -1331,23 +1334,23 @@ def _trunc_head(line, n): if len(line) <= n: return line - return "> " + line[-(n - 2) :] + return b"> " + line[-(n - 2) :] def _trunc_tail(line, n): if len(line) <= n: return line - return line[: n - 2] + " >" + return line[: n - 2] + b" >" def patchcontents(state): - repo = state["repo"] - rule = state["rules"][state["pos"]] + repo = state[b"repo"] + rule = state[b"rules"][state[b"pos"]] displayer = logcmdutil.changesetdisplayer( - repo.ui, repo, {"patch": True, "template": "status"}, buffered=True + repo.ui, repo, {b"patch": True, b"template": b"status"}, buffered=True ) - overrides = {("ui", "verbose"): True} - with repo.ui.configoverride(overrides, source="histedit"): + overrides = {(b"ui", b"verbose"): True} + with repo.ui.configoverride(overrides, source=b"histedit"): displayer.show(rule.ctx) displayer.close() return displayer.hunk[rule.ctx.rev()].splitlines() @@ -1378,8 +1381,8 @@ def rendercommit(win, state): """Renders the commit window that shows the log of the current selected commit""" - pos = state["pos"] - rules = state["rules"] + pos = state[b"pos"] + rules = state[b"rules"] rule = rules[pos] ctx = rule.ctx @@ -1388,20 +1391,20 @@ maxy, maxx = win.getmaxyx() length = maxx - 3 - line = "changeset: {0}:{1:<12}".format(ctx.rev(), ctx) + line = b"changeset: {0}:{1:<12}".format(ctx.rev(), ctx) win.addstr(1, 1, line[:length]) - line = "user: {0}".format(ctx.user()) + line = b"user: {0}".format(ctx.user()) win.addstr(2, 1, line[:length]) bms = repo.nodebookmarks(ctx.node()) - line = "bookmark: {0}".format(" ".join(bms)) + line = b"bookmark: {0}".format(b" ".join(bms)) win.addstr(3, 1, line[:length]) - line = "summary: {0}".format(ctx.description().splitlines()[0]) + line = b"summary: {0}".format(ctx.description().splitlines()[0]) win.addstr(4, 1, line[:length]) - line = "files: " + line = b"files: " win.addstr(5, 1, line) fnx = 1 + len(line) fnmaxx = length - fnx + 1 @@ -1410,7 +1413,7 @@ files = ctx.files() for i, line1 in enumerate(files): if len(files) > fnmaxn and i == fnmaxn - 1: - win.addstr(y, fnx, _trunc_tail(",".join(files[i:]), fnmaxx)) + win.addstr(y, fnx, _trunc_tail(b",".join(files[i:]), fnmaxx)) y = y + 1 break win.addstr(y, fnx, _trunc_head(line1, fnmaxx)) @@ -1418,22 +1421,22 @@ conflicts = rule.conflicts if len(conflicts) > 0: - conflictstr = ",".join(map(lambda r: str(r.ctx), conflicts)) - conflictstr = "changed files overlap with {0}".format(conflictstr) + conflictstr = b",".join(map(lambda r: str(r.ctx), conflicts)) + conflictstr = b"changed files overlap with {0}".format(conflictstr) else: - conflictstr = "no overlap" + conflictstr = b"no overlap" win.addstr(y, 1, conflictstr[:length]) win.noutrefresh() def helplines(mode): if mode == MODE_PATCH: - help = """\ + help = b"""\ ?: help, k/up: line up, j/down: line down, v: stop viewing patch pgup: prev page, space/pgdn: next page, c: commit, q: abort """ else: - help = """\ + help = b"""\ ?: help, k/up: move up, j/down: move down, space: select, v: view patch d: drop, e: edit, f: fold, m: mess, p: pick, r: roll pgup/K: move patch up, pgdn/J: move patch down, c: commit, q: abort @@ -1442,7 +1445,7 @@ def renderhelp(win, state): maxy, maxx = win.getmaxyx() - mode, _ = state["mode"] + mode, _ = state[b"mode"] for y, line in enumerate(helplines(mode)): if y >= maxy: break @@ -1450,23 +1453,23 @@ win.noutrefresh() def renderrules(rulesscr, state): - rules = state["rules"] - pos = state["pos"] - selected = state["selected"] - start = state["modes"][MODE_RULES]["line_offset"] + rules = state[b"rules"] + pos = state[b"pos"] + selected = state[b"selected"] + start = state[b"modes"][MODE_RULES][b"line_offset"] conflicts = [r.ctx for r in rules if r.conflicts] if len(conflicts) > 0: - line = "potential conflict in %s" % ",".join(map(str, conflicts)) + line = b"potential conflict in %s" % b",".join(map(str, conflicts)) addln(rulesscr, -1, 0, line, curses.color_pair(COLOR_WARN)) for y, rule in enumerate(rules[start:]): - if y >= state["page_height"]: + if y >= state[b"page_height"]: break if len(rule.conflicts) > 0: - rulesscr.addstr(y, 0, " ", curses.color_pair(COLOR_WARN)) + rulesscr.addstr(y, 0, b" ", curses.color_pair(COLOR_WARN)) else: - rulesscr.addstr(y, 0, " ", curses.COLOR_BLACK) + rulesscr.addstr(y, 0, b" ", curses.COLOR_BLACK) if y + start == selected: addln(rulesscr, y, 2, rule, curses.color_pair(COLOR_SELECTED)) elif y + start == pos: @@ -1487,15 +1490,15 @@ for y in range(0, length): line = output[y] if diffcolors: - if line and line[0] == "+": + if line and line[0] == b"+": win.addstr( y, 0, line, curses.color_pair(COLOR_DIFF_ADD_LINE) ) - elif line and line[0] == "-": + elif line and line[0] == b"-": win.addstr( y, 0, line, curses.color_pair(COLOR_DIFF_DEL_LINE) ) - elif line.startswith("@@ "): + elif line.startswith(b"@@ "): win.addstr(y, 0, line, curses.color_pair(COLOR_DIFF_OFFSET)) else: win.addstr(y, 0, line) @@ -1504,17 +1507,17 @@ win.noutrefresh() def renderpatch(win, state): - start = state["modes"][MODE_PATCH]["line_offset"] - content = state["modes"][MODE_PATCH]["patchcontents"] + start = state[b"modes"][MODE_PATCH][b"line_offset"] + content = state[b"modes"][MODE_PATCH][b"patchcontents"] renderstring(win, state, content[start:], diffcolors=True) def layout(mode): maxy, maxx = stdscr.getmaxyx() helplen = len(helplines(mode)) return { - "commit": (12, maxx), - "help": (helplen, maxx), - "main": (maxy - helplen - 12, maxx), + b"commit": (12, maxx), + b"help": (helplen, maxx), + b"main": (maxy - helplen - 12, maxx), } def drawvertwin(size, y, x): @@ -1523,16 +1526,16 @@ return win, y, x state = { - "pos": 0, - "rules": rules, - "selected": None, - "mode": (MODE_INIT, MODE_INIT), - "page_height": None, - "modes": { - MODE_RULES: {"line_offset": 0,}, - MODE_PATCH: {"line_offset": 0,}, + b"pos": 0, + b"rules": rules, + b"selected": None, + b"mode": (MODE_INIT, MODE_INIT), + b"page_height": None, + b"modes": { + MODE_RULES: {b"line_offset": 0,}, + MODE_PATCH: {b"line_offset": 0,}, }, - "repo": repo, + b"repo": repo, } # eventloop @@ -1541,7 +1544,7 @@ stdscr.refresh() while True: try: - oldmode, _ = state["mode"] + oldmode, _ = state[b"mode"] if oldmode == MODE_INIT: changemode(state, MODE_RULES) e = event(state, ch) @@ -1549,36 +1552,36 @@ if e == E_QUIT: return False if e == E_HISTEDIT: - return state["rules"] + return state[b"rules"] else: if e == E_RESIZE: size = screen_size() if size != stdscr.getmaxyx(): curses.resizeterm(*size) - curmode, _ = state["mode"] + curmode, _ = state[b"mode"] sizes = layout(curmode) if curmode != oldmode: - state["page_height"] = sizes["main"][0] + state[b"page_height"] = sizes[b"main"][0] # Adjust the view to fit the current screen size. - movecursor(state, state["pos"], state["pos"]) + movecursor(state, state[b"pos"], state[b"pos"]) # Pack the windows against the top, each pane spread across the # full width of the screen. y, x = (0, 0) - helpwin, y, x = drawvertwin(sizes["help"], y, x) - mainwin, y, x = drawvertwin(sizes["main"], y, x) - commitwin, y, x = drawvertwin(sizes["commit"], y, x) + helpwin, y, x = drawvertwin(sizes[b"help"], y, x) + mainwin, y, x = drawvertwin(sizes[b"main"], y, x) + commitwin, y, x = drawvertwin(sizes[b"commit"], y, x) if e in (E_PAGEDOWN, E_PAGEUP, E_LINEDOWN, E_LINEUP): if e == E_PAGEDOWN: - changeview(state, +1, "page") + changeview(state, +1, b"page") elif e == E_PAGEUP: - changeview(state, -1, "page") + changeview(state, -1, b"page") elif e == E_LINEDOWN: - changeview(state, +1, "line") + changeview(state, +1, b"line") elif e == E_LINEUP: - changeview(state, -1, "line") + changeview(state, -1, b"line") # start rendering commitwin.erase() @@ -1606,22 +1609,22 @@ to see an extensive help. Requires python-curses to be installed.""" if curses is None: - raise error.Abort(_("Python curses library required")) + raise error.Abort(_(b"Python curses library required")) # disable color ui._colormode = None try: - keep = opts.get("keep") - revs = opts.get("rev", [])[:] + keep = opts.get(b"keep") + revs = opts.get(b"rev", [])[:] cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) - if os.path.exists(os.path.join(repo.path, "histedit-state")): + if os.path.exists(os.path.join(repo.path, b"histedit-state")): raise error.Abort( _( - "history edit already in progress, try " - "--continue or --abort" + b"history edit already in progress, try " + b"--continue or --abort" ) ) revs.extend(freeargs) @@ -1631,15 +1634,15 @@ revs.append(defaultrev) if len(revs) != 1: raise error.Abort( - _("histedit requires exactly one ancestor revision") + _(b"histedit requires exactly one ancestor revision") ) - rr = list(repo.set("roots(%ld)", scmutil.revrange(repo, revs))) + rr = list(repo.set(b"roots(%ld)", scmutil.revrange(repo, revs))) if len(rr) != 1: raise error.Abort( _( - "The specified revisions must have " - "exactly one common root" + b"The specified revisions must have " + b"exactly one common root" ) ) root = rr[0].node() @@ -1648,7 +1651,7 @@ revs = between(repo, root, topmost, keep) if not revs: raise error.Abort( - _("%s is not an ancestor of working directory") + _(b"%s is not an ancestor of working directory") % node.short(root) ) @@ -1663,16 +1666,16 @@ curses.echo() curses.endwin() if rc is False: - ui.write(_("histedit aborted\n")) + ui.write(_(b"histedit aborted\n")) return 0 if type(rc) is list: - ui.status(_("performing changes\n")) + ui.status(_(b"performing changes\n")) rules = makecommands(rc) - filename = repo.vfs.join("chistedit") - with open(filename, "w+") as fp: + filename = repo.vfs.join(b"chistedit") + with open(filename, b"w+") as fp: for r in rules: fp.write(r) - opts["commands"] = filename + opts[b"commands"] = filename return _texthistedit(ui, repo, *freeargs, **opts) except KeyboardInterrupt: pass @@ -1680,30 +1683,35 @@ @command( - "histedit", + b"histedit", [ ( - "", - "commands", - "", - _("read history edits from the specified file"), - _("FILE"), + b"", + b"commands", + b"", + _(b"read history edits from the specified file"), + _(b"FILE"), ), - ("c", "continue", False, _("continue an edit already in progress")), - ("", "edit-plan", False, _("edit remaining actions list")), - ("k", "keep", False, _("don't strip old nodes after edit is complete")), - ("", "abort", False, _("abort an edit in progress")), - ("o", "outgoing", False, _("changesets not found in destination")), + (b"c", b"continue", False, _(b"continue an edit already in progress")), + (b"", b"edit-plan", False, _(b"edit remaining actions list")), ( - "f", - "force", + b"k", + b"keep", False, - _("force outgoing even for unrelated repositories"), + _(b"don't strip old nodes after edit is complete"), ), - ("r", "rev", [], _("first revision to be edited"), _("REV")), + (b"", b"abort", False, _(b"abort an edit in progress")), + (b"o", b"outgoing", False, _(b"changesets not found in destination")), + ( + b"f", + b"force", + False, + _(b"force outgoing even for unrelated repositories"), + ), + (b"r", b"rev", [], _(b"first revision to be edited"), _(b"REV")), ] + cmdutil.formatteropts, - _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"), + _(b"[OPTIONS] ([ANCESTOR] | --outgoing [URL])"), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def histedit(ui, repo, *freeargs, **opts): @@ -1809,7 +1817,7 @@ # or continuing, so fall back to regular _texthistedit for those # operations. if ( - ui.interface("histedit") == "curses" + ui.interface(b"histedit") == b"curses" and _getgoal(pycompat.byteskwargs(opts)) == goalnew ): return _chistedit(ui, repo, *freeargs, **opts) @@ -1824,10 +1832,10 @@ _histedit(ui, repo, state, *freeargs, **opts) -goalcontinue = "continue" -goalabort = "abort" -goaleditplan = "edit-plan" -goalnew = "new" +goalcontinue = b"continue" +goalabort = b"abort" +goaleditplan = b"edit-plan" +goalnew = b"new" def _getgoal(opts): @@ -1841,11 +1849,11 @@ def _readfile(ui, path): - if path == "-": - with ui.timeblockedsection("histedit"): + if path == b"-": + with ui.timeblockedsection(b"histedit"): return ui.fin.read() else: - with open(path, "rb") as f: + with open(path, b"rb") as f: return f.read() @@ -1854,40 +1862,40 @@ # blanket if mq patches are applied somewhere mq = getattr(repo, "mq", None) if mq and mq.applied: - raise error.Abort(_("source has mq patches applied")) + raise error.Abort(_(b"source has mq patches applied")) # basic argument incompatibility processing - outg = opts.get("outgoing") - editplan = opts.get("edit_plan") - abort = opts.get("abort") - force = opts.get("force") + outg = opts.get(b"outgoing") + editplan = opts.get(b"edit_plan") + abort = opts.get(b"abort") + force = opts.get(b"force") if force and not outg: - raise error.Abort(_("--force only allowed with --outgoing")) - if goal == "continue": + raise error.Abort(_(b"--force only allowed with --outgoing")) + if goal == b"continue": if any((outg, abort, revs, freeargs, rules, editplan)): - raise error.Abort(_("no arguments allowed with --continue")) - elif goal == "abort": + raise error.Abort(_(b"no arguments allowed with --continue")) + elif goal == b"abort": if any((outg, revs, freeargs, rules, editplan)): - raise error.Abort(_("no arguments allowed with --abort")) - elif goal == "edit-plan": + raise error.Abort(_(b"no arguments allowed with --abort")) + elif goal == b"edit-plan": if any((outg, revs, freeargs)): raise error.Abort( - _("only --commands argument allowed with " "--edit-plan") + _(b"only --commands argument allowed with " b"--edit-plan") ) else: if state.inprogress(): raise error.Abort( _( - "history edit already in progress, try " - "--continue or --abort" + b"history edit already in progress, try " + b"--continue or --abort" ) ) if outg: if revs: - raise error.Abort(_("no revisions allowed with --outgoing")) + raise error.Abort(_(b"no revisions allowed with --outgoing")) if len(freeargs) > 1: raise error.Abort( - _("only one repo argument allowed with --outgoing") + _(b"only one repo argument allowed with --outgoing") ) else: revs.extend(freeargs) @@ -1898,19 +1906,19 @@ if len(revs) != 1: raise error.Abort( - _("histedit requires exactly one ancestor revision") + _(b"histedit requires exactly one ancestor revision") ) def _histedit(ui, repo, state, *freeargs, **opts): opts = pycompat.byteskwargs(opts) - fm = ui.formatter("histedit", opts) + fm = ui.formatter(b"histedit", opts) fm.startitem() goal = _getgoal(opts) - revs = opts.get("rev", []) - nobackup = not ui.configbool("rewrite", "backup-bundle") - rules = opts.get("commands", "") - state.keep = opts.get("keep", False) + revs = opts.get(b"rev", []) + nobackup = not ui.configbool(b"rewrite", b"backup-bundle") + rules = opts.get(b"commands", b"") + state.keep = opts.get(b"keep", False) _validateargs(ui, repo, state, freeargs, opts, goal, rules, revs) @@ -1919,19 +1927,19 @@ revs = scmutil.revrange(repo, revs) ctxs = [repo[rev] for rev in revs] for ctx in ctxs: - tags = [tag for tag in ctx.tags() if tag != "tip"] + tags = [tag for tag in ctx.tags() if tag != b"tip"] if not hastags: hastags = len(tags) if hastags: if ui.promptchoice( _( - "warning: tags associated with the given" - " changeset will be lost after histedit.\n" - "do you want to continue (yN)? $$ &Yes $$ &No" + b"warning: tags associated with the given" + b" changeset will be lost after histedit.\n" + b"do you want to continue (yN)? $$ &Yes $$ &No" ), default=1, ): - raise error.Abort(_("histedit cancelled\n")) + raise error.Abort(_(b"histedit cancelled\n")) # rebuild state if goal == goalcontinue: state.read() @@ -1960,7 +1968,7 @@ # and only show one editor actions = state.actions[:] for idx, (action, nextact) in enumerate(zip(actions, actions[1:] + [None])): - if action.verb == "fold" and nextact and nextact.verb == "fold": + if action.verb == b"fold" and nextact and nextact.verb == b"fold": state.actions[idx].__class__ = _multifold # Force an initial state file write, so the user can run --abort/continue @@ -1971,13 +1979,13 @@ # Don't use singletransaction by default since it rolls the entire # transaction back if an unexpected exception happens (like a # pretxncommit hook throws, or the user aborts the commit msg editor). - if ui.configbool("histedit", "singletransaction"): + if ui.configbool(b"histedit", b"singletransaction"): # Don't use a 'with' for the transaction, since actions may close # and reopen a transaction. For example, if the action executes an # external process it may choose to commit the transaction first. - tr = repo.transaction("histedit") + tr = repo.transaction(b"histedit") progress = ui.makeprogress( - _("editing"), unit=_("changes"), total=len(state.actions) + _(b"editing"), unit=_(b"changes"), total=len(state.actions) ) with progress, util.acceptintervention(tr): while state.actions: @@ -1985,7 +1993,7 @@ actobj = state.actions[0] progress.increment(item=actobj.torule()) ui.debug( - "histedit: processing %s %s\n" % (actobj.verb, actobj.torule()) + b"histedit: processing %s %s\n" % (actobj.verb, actobj.torule()) ) parentctx, replacement_ = actobj.run() state.parentctxnode = parentctx.node() @@ -2003,14 +2011,14 @@ if mapping: for prec, succs in mapping.iteritems(): if not succs: - ui.debug("histedit: %s is dropped\n" % node.short(prec)) + ui.debug(b"histedit: %s is dropped\n" % node.short(prec)) else: ui.debug( - "histedit: %s is replaced by %s\n" + b"histedit: %s is replaced by %s\n" % (node.short(prec), node.short(succs[0])) ) if len(succs) > 1: - m = "histedit: %s" + m = b"histedit: %s" for n in succs[1:]: ui.debug(m % node.short(n)) @@ -2032,48 +2040,52 @@ for k, v in mapping.items() if k in nodemap and all(n in nodemap for n in v) } - scmutil.cleanupnodes(repo, mapping, "histedit") + scmutil.cleanupnodes(repo, mapping, b"histedit") hf = fm.hexfunc fl = fm.formatlist fd = fm.formatdict nodechanges = fd( { - hf(oldn): fl([hf(n) for n in newn], name="node") + hf(oldn): fl([hf(n) for n in newn], name=b"node") for oldn, newn in mapping.iteritems() }, - key="oldnode", - value="newnodes", + key=b"oldnode", + value=b"newnodes", ) fm.data(nodechanges=nodechanges) state.clear() - if os.path.exists(repo.sjoin("undo")): - os.unlink(repo.sjoin("undo")) - if repo.vfs.exists("histedit-last-edit.txt"): - repo.vfs.unlink("histedit-last-edit.txt") + if os.path.exists(repo.sjoin(b"undo")): + os.unlink(repo.sjoin(b"undo")) + if repo.vfs.exists(b"histedit-last-edit.txt"): + repo.vfs.unlink(b"histedit-last-edit.txt") def _aborthistedit(ui, repo, state, nobackup=False): try: state.read() __, leafs, tmpnodes, __ = processreplacement(state) - ui.debug("restore wc to old parent %s\n" % node.short(state.topmost)) + ui.debug(b"restore wc to old parent %s\n" % node.short(state.topmost)) # Recover our old commits if necessary if not state.topmost in repo and state.backupfile: backupfile = repo.vfs.join(state.backupfile) f = hg.openpath(ui, backupfile) gen = exchange.readbundle(ui, f, backupfile) - with repo.transaction("histedit.abort") as tr: + with repo.transaction(b"histedit.abort") as tr: bundle2.applybundle( - repo, gen, tr, source="histedit", url="bundle:" + backupfile + repo, + gen, + tr, + source=b"histedit", + url=b"bundle:" + backupfile, ) os.remove(backupfile) # check whether we should update away if repo.unfiltered().revs( - "parents() and (%n or %ln::)", + b"parents() and (%n or %ln::)", state.parentctxnode, leafs | tmpnodes, ): @@ -2084,9 +2096,9 @@ if state.inprogress(): ui.warn( _( - "warning: encountered an exception during histedit " - "--abort; the repository may not have been completely " - "cleaned up\n" + b"warning: encountered an exception during histedit " + b"--abort; the repository may not have been completely " + b"cleaned up\n" ) ) raise @@ -2096,7 +2108,7 @@ def hgaborthistedit(ui, repo): state = histeditstate(repo) - nobackup = not ui.configbool("rewrite", "backup-bundle") + nobackup = not ui.configbool(b"rewrite", b"backup-bundle") with repo.wlock() as wlock, repo.lock() as lock: state.wlock = wlock state.lock = lock @@ -2120,9 +2132,9 @@ def _newhistedit(ui, repo, state, revs, freeargs, opts): - outg = opts.get("outgoing") - rules = opts.get("commands", "") - force = opts.get("force") + outg = opts.get(b"outgoing") + rules = opts.get(b"commands", b"") + force = opts.get(b"force") cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) @@ -2135,12 +2147,12 @@ remote = None root = findoutgoing(ui, repo, remote, force, opts) else: - rr = list(repo.set("roots(%ld)", scmutil.revrange(repo, revs))) + rr = list(repo.set(b"roots(%ld)", scmutil.revrange(repo, revs))) if len(rr) != 1: raise error.Abort( _( - "The specified revisions must have " - "exactly one common root" + b"The specified revisions must have " + b"exactly one common root" ) ) root = rr[0].node() @@ -2148,7 +2160,7 @@ revs = between(repo, root, topmost, state.keep) if not revs: raise error.Abort( - _("%s is not an ancestor of working directory") % node.short(root) + _(b"%s is not an ancestor of working directory") % node.short(root) ) ctxs = [repo[r] for r in revs] @@ -2157,7 +2169,7 @@ # Please don't ask me why `ancestors` is this value. I figured it # out with print-debugging, not by actually understanding what the # merge code is doing. :( - ancs = [repo["."]] + ancs = [repo[b"."]] # Sniff-test to make sure we won't collide with untracked files in # the working directory. If we don't do this, we can get a # collision after we've started histedit and backing out gets ugly @@ -2179,7 +2191,7 @@ except error.Abort: raise error.Abort( _( - "untracked files in working directory conflict with files in %s" + b"untracked files in working directory conflict with files in %s" ) % c ) @@ -2201,8 +2213,8 @@ state.replacements = [] ui.log( - "histedit", - "%d actions to histedit\n", + b"histedit", + b"%d actions to histedit\n", len(actions), histedit_num_actions=len(actions), ) @@ -2211,7 +2223,7 @@ backupfile = None if not obsolete.isenabled(repo, obsolete.createmarkersopt): backupfile = repair.backupbundle( - repo, [parentctxnode], [topmost], root, "histedit" + repo, [parentctxnode], [topmost], root, b"histedit" ) state.backupfile = backupfile @@ -2219,7 +2231,7 @@ def _getsummary(ctx): # a common pattern is to extract the summary but default to the empty # string - summary = ctx.description() or "" + summary = ctx.description() or b"" if summary: summary = summary.splitlines()[0] return summary @@ -2251,43 +2263,43 @@ """select and validate the set of revision to edit When keep is false, the specified set can't have children.""" - revs = repo.revs("%n::%n", old, new) + revs = repo.revs(b"%n::%n", old, new) if revs and not keep: if not obsolete.isenabled( repo, obsolete.allowunstableopt - ) and repo.revs("(%ld::) - (%ld)", revs, revs): + ) and repo.revs(b"(%ld::) - (%ld)", revs, revs): raise error.Abort( _( - "can only histedit a changeset together " - "with all its descendants" + b"can only histedit a changeset together " + b"with all its descendants" ) ) - if repo.revs("(%ld) and merge()", revs): - raise error.Abort(_("cannot edit history that contains merges")) + if repo.revs(b"(%ld) and merge()", revs): + raise error.Abort(_(b"cannot edit history that contains merges")) root = repo[revs.first()] # list is already sorted by repo.revs() if not root.mutable(): raise error.Abort( - _("cannot edit public changeset: %s") % root, - hint=_("see 'hg help phases' for details"), + _(b"cannot edit public changeset: %s") % root, + hint=_(b"see 'hg help phases' for details"), ) return pycompat.maplist(repo.changelog.node, revs) -def ruleeditor(repo, ui, actions, editcomment=""): +def ruleeditor(repo, ui, actions, editcomment=b""): """open an editor to edit rules rules are in the format [ [act, ctx], ...] like in state.rules """ - if repo.ui.configbool("experimental", "histedit.autoverb"): + if repo.ui.configbool(b"experimental", b"histedit.autoverb"): newact = util.sortdict() for act in actions: ctx = repo[act.node] summary = _getsummary(ctx) - fword = summary.split(" ", 1)[0].lower() + fword = summary.split(b" ", 1)[0].lower() added = False # if it doesn't end with the special character '!' just skip this - if fword.endswith("!"): + if fword.endswith(b"!"): fword = fword[:-1] if fword in primaryactions | secondaryactions | tertiaryactions: act.verb = fword @@ -2312,21 +2324,21 @@ actions.append(na) actions += l - rules = "\n".join([act.torule() for act in actions]) - rules += "\n\n" + rules = b"\n".join([act.torule() for act in actions]) + rules += b"\n\n" rules += editcomment rules = ui.edit( rules, ui.username(), - {"prefix": "histedit"}, + {b"prefix": b"histedit"}, repopath=repo.path, - action="histedit", + action=b"histedit", ) # Save edit rules in .hg/histedit-last-edit.txt in case # the user needs to ask for help after something # surprising happens. - with repo.vfs("histedit-last-edit.txt", "wb") as f: + with repo.vfs(b"histedit-last-edit.txt", b"wb") as f: f.write(rules) return rules @@ -2337,16 +2349,16 @@ rules = [ l for l in (r.strip() for r in rules.splitlines()) - if l and not l.startswith("#") + if l and not l.startswith(b"#") ] actions = [] for r in rules: - if " " not in r: - raise error.ParseError(_('malformed line "%s"') % r) - verb, rest = r.split(" ", 1) + if b" " not in r: + raise error.ParseError(_(b'malformed line "%s"') % r) + verb, rest = r.split(b" ", 1) if verb not in actiontable: - raise error.ParseError(_('unknown action "%s"') % verb) + raise error.ParseError(_(b'unknown action "%s"') % verb) action = actiontable[verb].fromrule(state, rest) actions.append(action) @@ -2357,11 +2369,11 @@ try: verifyactions(actions, state, ctxs) except error.ParseError: - if repo.vfs.exists("histedit-last-edit.txt"): + if repo.vfs.exists(b"histedit-last-edit.txt"): ui.warn( _( - "warning: histedit rules saved " - "to: .hg/histedit-last-edit.txt\n" + b"warning: histedit rules saved " + b"to: .hg/histedit-last-edit.txt\n" ) ) raise @@ -2378,9 +2390,9 @@ seen = set() prev = None - if actions and actions[0].verb in ["roll", "fold"]: + if actions and actions[0].verb in [b"roll", b"fold"]: raise error.ParseError( - _('first changeset cannot use verb "%s"') % actions[0].verb + _(b'first changeset cannot use verb "%s"') % actions[0].verb ) for action in actions: @@ -2390,11 +2402,11 @@ seen.add(action.node) missing = sorted(expected - seen) # sort to stabilize output - if state.repo.ui.configbool("histedit", "dropmissing"): + if state.repo.ui.configbool(b"histedit", b"dropmissing"): if len(actions) == 0: raise error.ParseError( - _("no rules provided"), - hint=_("use strip extension to remove commits"), + _(b"no rules provided"), + hint=_(b"use strip extension to remove commits"), ) drops = [drop(state, n) for n in missing] @@ -2403,10 +2415,10 @@ actions[:0] = drops elif missing: raise error.ParseError( - _("missing rules for changeset %s") % node.short(missing[0]), + _(b"missing rules for changeset %s") % node.short(missing[0]), hint=_( - 'use "drop %s" to discard, see also: ' - "'hg help -e histedit.config'" + b'use "drop %s" to discard, see also: ' + b"'hg help -e histedit.config'" ) % node.short(missing[0]), ) @@ -2522,7 +2534,7 @@ return oldbmarks = repo.nodebookmarks(oldtopmost) if oldbmarks: - with repo.lock(), repo.transaction("histedit") as tr: + with repo.lock(), repo.transaction(b"histedit") as tr: marks = repo._bookmarks changes = [] for name in oldbmarks: @@ -2543,7 +2555,7 @@ # (we use %lr instead of %ln to silently ignore unknown items) nm = repo.changelog.nodemap nodes = sorted(n for n in nodes if n in nm) - roots = [c.node() for c in repo.set("roots(%ln)", nodes)] + roots = [c.node() for c in repo.set(b"roots(%ln)", nodes)] if roots: backup = not nobackup repair.strip(ui, repo, roots, backup=backup) @@ -2561,13 +2573,13 @@ common_nodes = histedit_nodes & set(nodelist) if common_nodes: raise error.Abort( - _("histedit in progress, can't strip %s") - % ", ".join(node.short(x) for x in common_nodes) + _(b"histedit in progress, can't strip %s") + % b", ".join(node.short(x) for x in common_nodes) ) return orig(ui, repo, nodelist, *args, **kwargs) -extensions.wrapfunction(repair, "strip", stripwrapper) +extensions.wrapfunction(repair, b"strip", stripwrapper) def summaryhook(ui, repo): @@ -2578,19 +2590,19 @@ if state.actions: # i18n: column positioning for "hg summary" ui.write( - _("hist: %s (histedit --continue)\n") + _(b"hist: %s (histedit --continue)\n") % ( - ui.label(_("%d remaining"), "histedit.remaining") + ui.label(_(b"%d remaining"), b"histedit.remaining") % len(state.actions) ) ) def extsetup(ui): - cmdutil.summaryhooks.add("histedit", summaryhook) + cmdutil.summaryhooks.add(b"histedit", summaryhook) statemod.addunfinished( - "histedit", - fname="histedit-state", + b"histedit", + fname=b"histedit-state", allowcommit=True, continueflag=True, abortfunc=hgaborthistedit, diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -138,48 +138,48 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "infinitepush", "server", default=False, + b"infinitepush", b"server", default=False, ) configitem( - "infinitepush", "storetype", default="", + b"infinitepush", b"storetype", default=b"", ) configitem( - "infinitepush", "indextype", default="", + b"infinitepush", b"indextype", default=b"", ) configitem( - "infinitepush", "indexpath", default="", + b"infinitepush", b"indexpath", default=b"", ) configitem( - "infinitepush", "storeallparts", default=False, + b"infinitepush", b"storeallparts", default=False, ) configitem( - "infinitepush", "reponame", default="", + b"infinitepush", b"reponame", default=b"", ) configitem( - "scratchbranch", "storepath", default="", + b"scratchbranch", b"storepath", default=b"", ) configitem( - "infinitepush", "branchpattern", default="", + b"infinitepush", b"branchpattern", default=b"", ) configitem( - "infinitepush", "pushtobundlestore", default=False, + b"infinitepush", b"pushtobundlestore", default=False, ) configitem( - "experimental", "server-bundlestore-bookmark", default="", + b"experimental", b"server-bundlestore-bookmark", default=b"", ) configitem( - "experimental", "infinitepush-scratchpush", default=False, + b"experimental", b"infinitepush-scratchpush", default=False, ) -experimental = "experimental" -configbookmark = "server-bundlestore-bookmark" -configscratchpush = "infinitepush-scratchpush" +experimental = b"experimental" +configbookmark = b"server-bundlestore-bookmark" +configscratchpush = b"infinitepush-scratchpush" scratchbranchparttype = bundleparts.scratchbranchparttype revsetpredicate = registrar.revsetpredicate() @@ -189,31 +189,31 @@ def _buildexternalbundlestore(ui): - put_args = ui.configlist("infinitepush", "put_args", []) - put_binary = ui.config("infinitepush", "put_binary") + put_args = ui.configlist(b"infinitepush", b"put_args", []) + put_binary = ui.config(b"infinitepush", b"put_binary") if not put_binary: - raise error.Abort("put binary is not specified") - get_args = ui.configlist("infinitepush", "get_args", []) - get_binary = ui.config("infinitepush", "get_binary") + raise error.Abort(b"put binary is not specified") + get_args = ui.configlist(b"infinitepush", b"get_args", []) + get_binary = ui.config(b"infinitepush", b"get_binary") if not get_binary: - raise error.Abort("get binary is not specified") + raise error.Abort(b"get binary is not specified") from . import store return store.externalbundlestore(put_binary, put_args, get_binary, get_args) def _buildsqlindex(ui): - sqlhost = ui.config("infinitepush", "sqlhost") + sqlhost = ui.config(b"infinitepush", b"sqlhost") if not sqlhost: - raise error.Abort(_("please set infinitepush.sqlhost")) - host, port, db, user, password = sqlhost.split(":") - reponame = ui.config("infinitepush", "reponame") + raise error.Abort(_(b"please set infinitepush.sqlhost")) + host, port, db, user, password = sqlhost.split(b":") + reponame = ui.config(b"infinitepush", b"reponame") if not reponame: - raise error.Abort(_("please set infinitepush.reponame")) + raise error.Abort(_(b"please set infinitepush.reponame")) - logfile = ui.config("infinitepush", "logfile", "") - waittimeout = ui.configint("infinitepush", "waittimeout", 300) - locktimeout = ui.configint("infinitepush", "locktimeout", 120) + logfile = ui.config(b"infinitepush", b"logfile", b"") + waittimeout = ui.configint(b"infinitepush", b"waittimeout", 300) + locktimeout = ui.configint(b"infinitepush", b"locktimeout", 120) from . import sqlindexapi return sqlindexapi.sqlindexapi( @@ -231,10 +231,10 @@ def _getloglevel(ui): - loglevel = ui.config("infinitepush", "loglevel", "DEBUG") + loglevel = ui.config(b"infinitepush", b"loglevel", b"DEBUG") numeric_loglevel = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_loglevel, int): - raise error.Abort(_("invalid log level %s") % loglevel) + raise error.Abort(_(b"invalid log level %s") % loglevel) return numeric_loglevel @@ -248,7 +248,7 @@ """ if common.isremotebooksenabled(ui): - hoist = ui.config("remotenames", "hoistedpeer") + "/" + hoist = ui.config(b"remotenames", b"hoistedpeer") + b"/" if remotebookmark.startswith(hoist): return remotebookmark[len(hoist) :] return remotebookmark @@ -257,33 +257,33 @@ class bundlestore(object): def __init__(self, repo): self._repo = repo - storetype = self._repo.ui.config("infinitepush", "storetype") - if storetype == "disk": + storetype = self._repo.ui.config(b"infinitepush", b"storetype") + if storetype == b"disk": from . import store self.store = store.filebundlestore(self._repo.ui, self._repo) - elif storetype == "external": + elif storetype == b"external": self.store = _buildexternalbundlestore(self._repo.ui) else: raise error.Abort( - _("unknown infinitepush store type specified %s") % storetype + _(b"unknown infinitepush store type specified %s") % storetype ) - indextype = self._repo.ui.config("infinitepush", "indextype") - if indextype == "disk": + indextype = self._repo.ui.config(b"infinitepush", b"indextype") + if indextype == b"disk": from . import fileindexapi self.index = fileindexapi.fileindexapi(self._repo) - elif indextype == "sql": + elif indextype == b"sql": self.index = _buildsqlindex(self._repo.ui) else: raise error.Abort( - _("unknown infinitepush index type specified %s") % indextype + _(b"unknown infinitepush index type specified %s") % indextype ) def _isserver(ui): - return ui.configbool("infinitepush", "server") + return ui.configbool(b"infinitepush", b"server") def reposetup(ui, repo): @@ -300,11 +300,11 @@ def commonsetup(ui): - wireprotov1server.commands["listkeyspatterns"] = ( + wireprotov1server.commands[b"listkeyspatterns"] = ( wireprotolistkeyspatterns, - "namespace patterns", + b"namespace patterns", ) - scratchbranchpat = ui.config("infinitepush", "branchpattern") + scratchbranchpat = ui.config(b"infinitepush", b"branchpattern") if scratchbranchpat: global _scratchbranchmatcher kind, pat, _scratchbranchmatcher = stringutil.stringmatcher( @@ -313,53 +313,53 @@ def serverextsetup(ui): - origpushkeyhandler = bundle2.parthandlermapping["pushkey"] + origpushkeyhandler = bundle2.parthandlermapping[b"pushkey"] def newpushkeyhandler(*args, **kwargs): bundle2pushkey(origpushkeyhandler, *args, **kwargs) newpushkeyhandler.params = origpushkeyhandler.params - bundle2.parthandlermapping["pushkey"] = newpushkeyhandler + bundle2.parthandlermapping[b"pushkey"] = newpushkeyhandler - orighandlephasehandler = bundle2.parthandlermapping["phase-heads"] + orighandlephasehandler = bundle2.parthandlermapping[b"phase-heads"] newphaseheadshandler = lambda *args, **kwargs: bundle2handlephases( orighandlephasehandler, *args, **kwargs ) newphaseheadshandler.params = orighandlephasehandler.params - bundle2.parthandlermapping["phase-heads"] = newphaseheadshandler + bundle2.parthandlermapping[b"phase-heads"] = newphaseheadshandler extensions.wrapfunction( - localrepo.localrepository, "listkeys", localrepolistkeys + localrepo.localrepository, b"listkeys", localrepolistkeys ) - wireprotov1server.commands["lookup"] = ( - _lookupwrap(wireprotov1server.commands["lookup"][0]), - "key", + wireprotov1server.commands[b"lookup"] = ( + _lookupwrap(wireprotov1server.commands[b"lookup"][0]), + b"key", ) - extensions.wrapfunction(exchange, "getbundlechunks", getbundlechunks) + extensions.wrapfunction(exchange, b"getbundlechunks", getbundlechunks) - extensions.wrapfunction(bundle2, "processparts", processparts) + extensions.wrapfunction(bundle2, b"processparts", processparts) def clientextsetup(ui): - entry = extensions.wrapcommand(commands.table, "push", _push) + entry = extensions.wrapcommand(commands.table, b"push", _push) entry[1].append( ( - "", - "bundle-store", + b"", + b"bundle-store", None, - _("force push to go to bundle store (EXPERIMENTAL)"), + _(b"force push to go to bundle store (EXPERIMENTAL)"), ) ) - extensions.wrapcommand(commands.table, "pull", _pull) + extensions.wrapcommand(commands.table, b"pull", _pull) - extensions.wrapfunction(discovery, "checkheads", _checkheads) + extensions.wrapfunction(discovery, b"checkheads", _checkheads) wireprotov1peer.wirepeer.listkeyspatterns = listkeyspatterns partorder = exchange.b2partsgenorder - index = partorder.index("changeset") + index = partorder.index(b"changeset") partorder.insert( index, partorder.pop(partorder.index(scratchbranchparttype)) ) @@ -378,14 +378,14 @@ def localrepolistkeys(orig, self, namespace, patterns=None): - if namespace == "bookmarks" and patterns: + if namespace == b"bookmarks" and patterns: index = self.bundlestore.index results = {} bookmarks = orig(self, namespace) for pattern in patterns: results.update(index.getbookmarks(pattern)) - if pattern.endswith("*"): - pattern = "re:^" + pattern[:-1] + ".*" + if pattern.endswith(b"*"): + pattern = b"re:^" + pattern[:-1] + b".*" kind, pat, matcher = stringutil.stringmatcher(pattern) for bookmark, node in bookmarks.iteritems(): if matcher(bookmark): @@ -397,21 +397,23 @@ @wireprotov1peer.batchable def listkeyspatterns(self, namespace, patterns): - if not self.capable("pushkey"): + if not self.capable(b"pushkey"): yield {}, None f = wireprotov1peer.future() - self.ui.debug('preparing listkeys for "%s"\n' % namespace) + self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) yield { - "namespace": encoding.fromlocal(namespace), - "patterns": wireprototypes.encodelist(patterns), + b"namespace": encoding.fromlocal(namespace), + b"patterns": wireprototypes.encodelist(patterns), }, f d = f.value - self.ui.debug('received listkey for "%s": %i bytes\n' % (namespace, len(d))) + self.ui.debug( + b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) + ) yield pushkey.decodekeys(d) def _readbundlerevs(bundlerepo): - return list(bundlerepo.revs("bundle()")) + return list(bundlerepo.revs(b"bundle()")) def _includefilelogstobundle(bundlecaps, bundlerepo, bundlerevs, ui): @@ -428,18 +430,18 @@ if not changedfiles: return bundlecaps - changedfiles = "\0".join(changedfiles) + changedfiles = b"\0".join(changedfiles) newcaps = [] appended = False for cap in bundlecaps or []: - if cap.startswith("excludepattern="): - newcaps.append("\0".join((cap, changedfiles))) + if cap.startswith(b"excludepattern="): + newcaps.append(b"\0".join((cap, changedfiles))) appended = True else: newcaps.append(cap) if not appended: # Not found excludepattern cap. Just append it - newcaps.append("excludepattern=" + changedfiles) + newcaps.append(b"excludepattern=" + changedfiles) return newcaps @@ -452,14 +454,14 @@ """ parts = [] - version = "02" + version = b"02" outgoing = discovery.outgoing( bundlerepo, commonheads=bundleroots, missingheads=[unknownhead] ) - cgstream = changegroup.makestream(bundlerepo, outgoing, version, "pull") + cgstream = changegroup.makestream(bundlerepo, outgoing, version, b"pull") cgstream = util.chunkbuffer(cgstream).read() - cgpart = bundle2.bundlepart("changegroup", data=cgstream) - cgpart.addparam("version", version) + cgpart = bundle2.bundlepart(b"changegroup", data=cgstream) + cgpart.addparam(b"version", version) parts.append(cgpart) return parts @@ -480,7 +482,7 @@ def _needsrebundling(head, bundlerepo): - bundleheads = list(bundlerepo.revs("heads(bundle())")) + bundleheads = list(bundlerepo.revs(b"heads(bundle())")) return not ( len(bundleheads) == 1 and bundlerepo[bundleheads[0]].node() == head ) @@ -493,18 +495,18 @@ """ parts = [] if not _needsrebundling(head, bundlerepo): - with util.posixfile(bundlefile, "rb") as f: + with util.posixfile(bundlefile, b"rb") as f: unbundler = exchange.readbundle(bundlerepo.ui, f, bundlefile) if isinstance(unbundler, changegroup.cg1unpacker): part = bundle2.bundlepart( - "changegroup", data=unbundler._stream.read() + b"changegroup", data=unbundler._stream.read() ) - part.addparam("version", "01") + part.addparam(b"version", b"01") parts.append(part) elif isinstance(unbundler, bundle2.unbundle20): haschangegroup = False for part in unbundler.iterparts(): - if part.type == "changegroup": + if part.type == b"changegroup": haschangegroup = True newpart = bundle2.bundlepart(part.type, data=part.read()) for key, value in part.params.iteritems(): @@ -513,12 +515,12 @@ if not haschangegroup: raise error.Abort( - "unexpected bundle without changegroup part, " - + "head: %s" % hex(head), - hint="report to administrator", + b"unexpected bundle without changegroup part, " + + b"head: %s" % hex(head), + hint=b"report to administrator", ) else: - raise error.Abort("unknown bundle type") + raise error.Abort(b"unknown bundle type") else: parts = _rebundle(bundlerepo, bundleroots, head) @@ -539,7 +541,7 @@ if head not in repo.changelog.nodemap: if head not in nodestobundle: newbundlefile = common.downloadbundle(repo, head) - bundlepath = "bundle:%s+%s" % (repo.root, newbundlefile) + bundlepath = b"bundle:%s+%s" % (repo.root, newbundlefile) bundlerepo = hg.repository(repo.ui, bundlepath) allbundlestocleanup.append((bundlerepo, newbundlefile)) @@ -576,7 +578,7 @@ pullfrombundlestore = bool(scratchbundles) wrappedchangegrouppart = False wrappedlistkeys = False - oldchangegrouppart = exchange.getbundle2partsmapping["changegroup"] + oldchangegrouppart = exchange.getbundle2partsmapping[b"changegroup"] try: def _changegrouppart(bundler, *args, **kwargs): @@ -589,20 +591,20 @@ bundler.addpart(part) return result - exchange.getbundle2partsmapping["changegroup"] = _changegrouppart + exchange.getbundle2partsmapping[b"changegroup"] = _changegrouppart wrappedchangegrouppart = True def _listkeys(orig, self, namespace): origvalues = orig(self, namespace) - if namespace == "phases" and pullfrombundlestore: - if origvalues.get("publishing") == "True": + if namespace == b"phases" and pullfrombundlestore: + if origvalues.get(b"publishing") == b"True": # Make repo non-publishing to preserve draft phase - del origvalues["publishing"] + del origvalues[b"publishing"] origvalues.update(newphases) return origvalues extensions.wrapfunction( - localrepo.localrepository, "listkeys", _listkeys + localrepo.localrepository, b"listkeys", _listkeys ) wrappedlistkeys = True heads = list((set(newheads) | set(heads)) - set(scratchheads)) @@ -611,10 +613,10 @@ ) finally: if wrappedchangegrouppart: - exchange.getbundle2partsmapping["changegroup"] = oldchangegrouppart + exchange.getbundle2partsmapping[b"changegroup"] = oldchangegrouppart if wrappedlistkeys: extensions.unwrapfunction( - localrepo.localrepository, "listkeys", _listkeys + localrepo.localrepository, b"listkeys", _listkeys ) return result @@ -626,64 +628,67 @@ if isinstance(localkey, str) and _scratchbranchmatcher(localkey): scratchnode = repo.bundlestore.index.getnode(localkey) if scratchnode: - return "%d %s\n" % (1, scratchnode) + return b"%d %s\n" % (1, scratchnode) else: - return "%d %s\n" % (0, "scratch branch %s not found" % localkey) + return b"%d %s\n" % ( + 0, + b"scratch branch %s not found" % localkey, + ) else: try: r = hex(repo.lookup(localkey)) - return "%d %s\n" % (1, r) + return b"%d %s\n" % (1, r) except Exception as inst: if repo.bundlestore.index.getbundle(localkey): - return "%d %s\n" % (1, localkey) + return b"%d %s\n" % (1, localkey) else: r = stringutil.forcebytestr(inst) - return "%d %s\n" % (0, r) + return b"%d %s\n" % (0, r) return _lookup -def _pull(orig, ui, repo, source="default", **opts): +def _pull(orig, ui, repo, source=b"default", **opts): opts = pycompat.byteskwargs(opts) # Copy paste from `pull` command - source, branches = hg.parseurl(ui.expandpath(source), opts.get("branch")) + source, branches = hg.parseurl(ui.expandpath(source), opts.get(b"branch")) scratchbookmarks = {} unfi = repo.unfiltered() unknownnodes = [] - for rev in opts.get("rev", []): + for rev in opts.get(b"rev", []): if rev not in unfi: unknownnodes.append(rev) - if opts.get("bookmark"): + if opts.get(b"bookmark"): bookmarks = [] - revs = opts.get("rev") or [] - for bookmark in opts.get("bookmark"): + revs = opts.get(b"rev") or [] + for bookmark in opts.get(b"bookmark"): if _scratchbranchmatcher(bookmark): # rev is not known yet # it will be fetched with listkeyspatterns next - scratchbookmarks[bookmark] = "REVTOFETCH" + scratchbookmarks[bookmark] = b"REVTOFETCH" else: bookmarks.append(bookmark) if scratchbookmarks: other = hg.peer(repo, opts, source) fetchedbookmarks = other.listkeyspatterns( - "bookmarks", patterns=scratchbookmarks + b"bookmarks", patterns=scratchbookmarks ) for bookmark in scratchbookmarks: if bookmark not in fetchedbookmarks: raise error.Abort( - "remote bookmark %s not found!" % bookmark + b"remote bookmark %s not found!" % bookmark ) scratchbookmarks[bookmark] = fetchedbookmarks[bookmark] revs.append(fetchedbookmarks[bookmark]) - opts["bookmark"] = bookmarks - opts["rev"] = revs + opts[b"bookmark"] = bookmarks + opts[b"rev"] = revs if scratchbookmarks or unknownnodes: # Set anyincoming to True extensions.wrapfunction( - discovery, "findcommonincoming", _findcommonincoming + discovery, b"findcommonincoming", _findcommonincoming ) try: # Remote scratch bookmarks will be deleted because remotenames doesn't @@ -701,12 +706,12 @@ return result finally: if scratchbookmarks: - extensions.unwrapfunction(discovery, "findcommonincoming") + extensions.unwrapfunction(discovery, b"findcommonincoming") def _readscratchremotebookmarks(ui, repo, other): if common.isremotebooksenabled(ui): - remotenamesext = extensions.find("remotenames") + remotenamesext = extensions.find(b"remotenames") remotepath = remotenamesext.activepath(repo.ui, other) result = {} # Let's refresh remotenames to make sure we have it up to date @@ -714,10 +719,10 @@ # and it results in deleting scratch bookmarks. Our best guess how to # fix it is to use `clearnames()` repo._remotenames.clearnames() - for remotebookmark in repo.names["remotebookmarks"].listnames(repo): + for remotebookmark in repo.names[b"remotebookmarks"].listnames(repo): path, bookname = remotenamesext.splitremotename(remotebookmark) if path == remotepath and _scratchbranchmatcher(bookname): - nodes = repo.names["remotebookmarks"].nodes( + nodes = repo.names[b"remotebookmarks"].nodes( repo, remotebookmark ) if nodes: @@ -728,7 +733,7 @@ def _saveremotebookmarks(repo, newbookmarks, remote): - remotenamesext = extensions.find("remotenames") + remotenamesext = extensions.find(b"remotenames") remotepath = remotenamesext.activepath(repo.ui, remote) branches = collections.defaultdict(list) bookmarks = {} @@ -736,14 +741,14 @@ for hexnode, nametype, remote, rname in remotenames: if remote != remotepath: continue - if nametype == "bookmarks": + if nametype == b"bookmarks": if rname in newbookmarks: # It's possible if we have a normal bookmark that matches # scratch branch pattern. In this case just use the current # bookmark node del newbookmarks[rname] bookmarks[rname] = hexnode - elif nametype == "branches": + elif nametype == b"branches": # saveremotenames expects 20 byte binary nodes for branches branches[rname].append(bin(hexnode)) @@ -755,7 +760,7 @@ def _savelocalbookmarks(repo, bookmarks): if not bookmarks: return - with repo.wlock(), repo.lock(), repo.transaction("bookmark") as tr: + with repo.wlock(), repo.lock(), repo.transaction(b"bookmark") as tr: changes = [] for scratchbook, node in bookmarks.iteritems(): changectx = repo[node] @@ -770,38 +775,38 @@ def _push(orig, ui, repo, dest=None, *args, **opts): opts = pycompat.byteskwargs(opts) - bookmark = opts.get("bookmark") + bookmark = opts.get(b"bookmark") # we only support pushing one infinitepush bookmark at once if len(bookmark) == 1: bookmark = bookmark[0] else: - bookmark = "" + bookmark = b"" oldphasemove = None overrides = {(experimental, configbookmark): bookmark} - with ui.configoverride(overrides, "infinitepush"): - scratchpush = opts.get("bundle_store") + with ui.configoverride(overrides, b"infinitepush"): + scratchpush = opts.get(b"bundle_store") if _scratchbranchmatcher(bookmark): scratchpush = True # bundle2 can be sent back after push (for example, bundle2 # containing `pushkey` part to update bookmarks) - ui.setconfig(experimental, "bundle2.pushback", True) + ui.setconfig(experimental, b"bundle2.pushback", True) if scratchpush: # this is an infinitepush, we don't want the bookmark to be applied # rather that should be stored in the bundlestore - opts["bookmark"] = [] + opts[b"bookmark"] = [] ui.setconfig(experimental, configscratchpush, True) oldphasemove = extensions.wrapfunction( - exchange, "_localphasemove", _phasemove + exchange, b"_localphasemove", _phasemove ) # Copy-paste from `push` command - path = ui.paths.getpath(dest, default=("default-push", "default")) + path = ui.paths.getpath(dest, default=(b"default-push", b"default")) if not path: raise error.Abort( - _("default repository not configured!"), - hint=_("see 'hg help config.paths'"), + _(b"default repository not configured!"), + hint=_(b"see 'hg help config.paths'"), ) destpath = path.pushloc or path.loc # Remote scratch bookmarks will be deleted because remotenames doesn't @@ -812,7 +817,7 @@ if bookmark and scratchpush: other = hg.peer(repo, opts, destpath) fetchedbookmarks = other.listkeyspatterns( - "bookmarks", patterns=[bookmark] + b"bookmarks", patterns=[bookmark] ) remotescratchbookmarks.update(fetchedbookmarks) _saveremotebookmarks(repo, remotescratchbookmarks, destpath) @@ -825,7 +830,7 @@ """Prune remote names by removing the bookmarks we don't want anymore, then writing the result back to disk """ - remotenamesext = extensions.find("remotenames") + remotenamesext = extensions.find(b"remotenames") # remotename format is: # (node, nametype ("branches" or "bookmarks"), remote, name) @@ -840,23 +845,24 @@ remote_bm_names = [ remotename[name_idx] for remotename in remotenames - if remotename[nametype_idx] == "bookmarks" + if remotename[nametype_idx] == b"bookmarks" ] for name in names: if name not in remote_bm_names: raise error.Abort( _( - "infinitepush bookmark '{}' does not exist " "in path '{}'" + b"infinitepush bookmark '{}' does not exist " + b"in path '{}'" ).format(name, path) ) bookmarks = {} branches = collections.defaultdict(list) for node, nametype, remote, name in remotenames: - if nametype == "bookmarks" and name not in names: + if nametype == b"bookmarks" and name not in names: bookmarks[name] = node - elif nametype == "branches": + elif nametype == b"branches": # saveremotenames wants binary nodes for branches branches[name].append(bin(node)) @@ -877,22 +883,22 @@ def partgen(pushop, bundler): bookmark = pushop.ui.config(experimental, configbookmark) scratchpush = pushop.ui.configbool(experimental, configscratchpush) - if "changesets" in pushop.stepsdone or not scratchpush: + if b"changesets" in pushop.stepsdone or not scratchpush: return if scratchbranchparttype not in bundle2.bundle2caps(pushop.remote): return - pushop.stepsdone.add("changesets") + pushop.stepsdone.add(b"changesets") if not pushop.outgoing.missing: - pushop.ui.status(_("no changes found\n")) + pushop.ui.status(_(b"no changes found\n")) pushop.cgresult = 0 return # This parameter tells the server that the following bundle is an # infinitepush. This let's it switch the part processing to our infinitepush # code path. - bundler.addparam("infinitepush", "True") + bundler.addparam(b"infinitepush", b"True") scratchparts = bundleparts.getscratchbranchparts( pushop.repo, pushop.remote, pushop.outgoing, pushop.ui, bookmark @@ -912,15 +918,15 @@ def _getrevs(bundle, oldnode, force, bookmark): - "extracts and validates the revs to be imported" - revs = [bundle[r] for r in bundle.revs("sort(bundle())")] + b"extracts and validates the revs to be imported" + revs = [bundle[r] for r in bundle.revs(b"sort(bundle())")] # new bookmark if oldnode is None: return revs # Fast forward update - if oldnode in bundle and list(bundle.set("bundle() & %s::", oldnode)): + if oldnode in bundle and list(bundle.set(b"bundle() & %s::", oldnode)): return revs return revs @@ -929,19 +935,19 @@ @contextlib.contextmanager def logservicecall(logger, service, **kwargs): start = time.time() - logger(service, eventtype="start", **kwargs) + logger(service, eventtype=b"start", **kwargs) try: yield logger( service, - eventtype="success", + eventtype=b"success", elapsedms=(time.time() - start) * 1000, **kwargs ) except Exception as e: logger( service, - eventtype="failure", + eventtype=b"failure", elapsedms=(time.time() - start) * 1000, errormsg=str(e), **kwargs @@ -950,13 +956,13 @@ def _getorcreateinfinitepushlogger(op): - logger = op.records["infinitepushlogger"] + logger = op.records[b"infinitepushlogger"] if not logger: ui = op.repo.ui try: username = procutil.getuser() except Exception: - username = "unknown" + username = b"unknown" # Generate random request id to be able to find all logged entries # for the same request. Since requestid is pseudo-generated it may # not be unique, but we assume that (hostname, username, requestid) @@ -966,13 +972,13 @@ hostname = socket.gethostname() logger = functools.partial( ui.log, - "infinitepush", + b"infinitepush", user=username, requestid=requestid, hostname=hostname, - reponame=ui.config("infinitepush", "reponame"), + reponame=ui.config(b"infinitepush", b"reponame"), ) - op.records.add("infinitepushlogger", logger) + op.records.add(b"infinitepushlogger", logger) else: logger = logger[0] return logger @@ -982,14 +988,14 @@ """stores the incoming bundle coming from push command to the bundlestore instead of applying on the revlogs""" - repo.ui.status(_("storing changesets on the bundlestore\n")) + repo.ui.status(_(b"storing changesets on the bundlestore\n")) bundler = bundle2.bundle20(repo.ui) # processing each part and storing it in bundler with bundle2.partiterator(repo, op, unbundler) as parts: for part in parts: bundlepart = None - if part.type == "replycaps": + if part.type == b"replycaps": # This configures the current operation to allow reply parts. bundle2._processpart(op, part) else: @@ -998,15 +1004,15 @@ bundlepart.addparam(key, value) # Certain parts require a response - if part.type in ("pushkey", "changegroup"): + if part.type in (b"pushkey", b"changegroup"): if op.reply is not None: - rpart = op.reply.newpart("reply:%s" % part.type) + rpart = op.reply.newpart(b"reply:%s" % part.type) rpart.addparam( - "in-reply-to", b"%d" % part.id, mandatory=False + b"in-reply-to", b"%d" % part.id, mandatory=False ) - rpart.addparam("return", "1", mandatory=False) + rpart.addparam(b"return", b"1", mandatory=False) - op.records.add(part.type, {"return": 1,}) + op.records.add(part.type, {b"return": 1,}) if bundlepart: bundler.addpart(bundlepart) @@ -1031,24 +1037,24 @@ def processparts(orig, repo, op, unbundler): # make sure we don't wrap processparts in case of `hg unbundle` - if op.source == "unbundle": + if op.source == b"unbundle": return orig(repo, op, unbundler) # this server routes each push to bundle store - if repo.ui.configbool("infinitepush", "pushtobundlestore"): + if repo.ui.configbool(b"infinitepush", b"pushtobundlestore"): return storetobundlestore(orig, repo, op, unbundler) - if unbundler.params.get("infinitepush") != "True": + if unbundler.params.get(b"infinitepush") != b"True": return orig(repo, op, unbundler) - handleallparts = repo.ui.configbool("infinitepush", "storeallparts") + handleallparts = repo.ui.configbool(b"infinitepush", b"storeallparts") bundler = bundle2.bundle20(repo.ui) cgparams = None with bundle2.partiterator(repo, op, unbundler) as parts: for part in parts: bundlepart = None - if part.type == "replycaps": + if part.type == b"replycaps": # This configures the current operation to allow reply parts. bundle2._processpart(op, part) elif part.type == bundleparts.scratchbranchparttype: @@ -1057,18 +1063,22 @@ # when we upload to the store. Eventually those parameters will # be put on the actual bundle instead of this part, then we can # send a vanilla changegroup instead of the scratchbranch part. - cgversion = part.params.get("cgversion", "01") - bundlepart = bundle2.bundlepart("changegroup", data=part.read()) - bundlepart.addparam("version", cgversion) + cgversion = part.params.get(b"cgversion", b"01") + bundlepart = bundle2.bundlepart( + b"changegroup", data=part.read() + ) + bundlepart.addparam(b"version", cgversion) cgparams = part.params # If we're not dumping all parts into the new bundle, we need to # alert the future pushkey and phase-heads handler to skip # the part. if not handleallparts: - op.records.add(scratchbranchparttype + "_skippushkey", True) op.records.add( - scratchbranchparttype + "_skipphaseheads", True + scratchbranchparttype + b"_skippushkey", True + ) + op.records.add( + scratchbranchparttype + b"_skipphaseheads", True ) else: if handleallparts: @@ -1081,18 +1091,18 @@ bundlepart.addparam(key, value) # Certain parts require a response - if part.type == "pushkey": + if part.type == b"pushkey": if op.reply is not None: - rpart = op.reply.newpart("reply:pushkey") + rpart = op.reply.newpart(b"reply:pushkey") rpart.addparam( - "in-reply-to", str(part.id), mandatory=False + b"in-reply-to", str(part.id), mandatory=False ) - rpart.addparam("return", "1", mandatory=False) + rpart.addparam(b"return", b"1", mandatory=False) else: bundle2._processpart(op, part) if handleallparts: - op.records.add(part.type, {"return": 1,}) + op.records.add(part.type, {b"return": 1,}) if bundlepart: bundler.addpart(bundlepart) @@ -1118,44 +1128,44 @@ def storebundle(op, params, bundlefile): log = _getorcreateinfinitepushlogger(op) parthandlerstart = time.time() - log(scratchbranchparttype, eventtype="start") + log(scratchbranchparttype, eventtype=b"start") index = op.repo.bundlestore.index store = op.repo.bundlestore.store - op.records.add(scratchbranchparttype + "_skippushkey", True) + op.records.add(scratchbranchparttype + b"_skippushkey", True) bundle = None try: # guards bundle - bundlepath = "bundle:%s+%s" % (op.repo.root, bundlefile) + bundlepath = b"bundle:%s+%s" % (op.repo.root, bundlefile) bundle = hg.repository(op.repo.ui, bundlepath) - bookmark = params.get("bookmark") - bookprevnode = params.get("bookprevnode", "") - force = params.get("force") + bookmark = params.get(b"bookmark") + bookprevnode = params.get(b"bookprevnode", b"") + force = params.get(b"force") if bookmark: oldnode = index.getnode(bookmark) else: oldnode = None - bundleheads = bundle.revs("heads(bundle())") + bundleheads = bundle.revs(b"heads(bundle())") if bookmark and len(bundleheads) > 1: raise error.Abort( - _("cannot push more than one head to a scratch branch") + _(b"cannot push more than one head to a scratch branch") ) revs = _getrevs(bundle, oldnode, force, bookmark) # Notify the user of what is being pushed - plural = "s" if len(revs) > 1 else "" - op.repo.ui.warn(_("pushing %d commit%s:\n") % (len(revs), plural)) + plural = b"s" if len(revs) > 1 else b"" + op.repo.ui.warn(_(b"pushing %d commit%s:\n") % (len(revs), plural)) maxoutput = 10 for i in range(0, min(len(revs), maxoutput)): - firstline = bundle[revs[i]].description().split("\n")[0][:50] - op.repo.ui.warn(" %s %s\n" % (revs[i], firstline)) + firstline = bundle[revs[i]].description().split(b"\n")[0][:50] + op.repo.ui.warn(b" %s %s\n" % (revs[i], firstline)) if len(revs) > maxoutput + 1: - op.repo.ui.warn(" ...\n") - firstline = bundle[revs[-1]].description().split("\n")[0][:50] - op.repo.ui.warn(" %s %s\n" % (revs[-1], firstline)) + op.repo.ui.warn(b" ...\n") + firstline = bundle[revs[-1]].description().split(b"\n")[0][:50] + op.repo.ui.warn(b" %s %s\n" % (revs[-1], firstline)) nodesctx = [bundle[rev] for rev in revs] inindex = lambda rev: bool(index.getbundle(bundle[rev].hex())) @@ -1170,21 +1180,21 @@ bookmarknode = nodesctx[-1].hex() if nodesctx else None key = None if newheadscount: - with open(bundlefile, "rb") as f: + with open(bundlefile, b"rb") as f: bundledata = f.read() with logservicecall( - log, "bundlestore", bundlesize=len(bundledata) + log, b"bundlestore", bundlesize=len(bundledata) ): bundlesizelimit = 100 * 1024 * 1024 # 100 MB if len(bundledata) > bundlesizelimit: error_msg = ( - "bundle is too big: %d bytes. " - + "max allowed size is 100 MB" + b"bundle is too big: %d bytes. " + + b"max allowed size is 100 MB" ) raise error.Abort(error_msg % (len(bundledata),)) key = store.write(bundledata) - with logservicecall(log, "index", newheadscount=newheadscount), index: + with logservicecall(log, b"index", newheadscount=newheadscount), index: if key: index.addbundle(key, nodesctx) if bookmark: @@ -1194,14 +1204,14 @@ ) log( scratchbranchparttype, - eventtype="success", + eventtype=b"success", elapsedms=(time.time() - parthandlerstart) * 1000, ) except Exception as e: log( scratchbranchparttype, - eventtype="failure", + eventtype=b"failure", elapsedms=(time.time() - parthandlerstart) * 1000, errormsg=str(e), ) @@ -1213,15 +1223,21 @@ @bundle2.parthandler( scratchbranchparttype, - ("bookmark", "bookprevnode", "force", "pushbackbookmarks", "cgversion"), + ( + b"bookmark", + b"bookprevnode", + b"force", + b"pushbackbookmarks", + b"cgversion", + ), ) def bundle2scratchbranch(op, part): """unbundle a bundle2 part containing a changegroup to store""" bundler = bundle2.bundle20(op.repo.ui) - cgversion = part.params.get("cgversion", "01") - cgpart = bundle2.bundlepart("changegroup", data=part.read()) - cgpart.addparam("version", cgversion) + cgversion = part.params.get(b"cgversion", b"01") + cgpart = bundle2.bundlepart(b"changegroup", data=part.read()) + cgpart.addparam(b"version", cgversion) bundler.addpart(cgpart) buf = util.chunkbuffer(bundler.getchunks()) @@ -1244,15 +1260,15 @@ def _maybeaddpushbackpart(op, bookmark, newnode, oldnode, params): - if params.get("pushbackbookmarks"): - if op.reply and "pushback" in op.reply.capabilities: + if params.get(b"pushbackbookmarks"): + if op.reply and b"pushback" in op.reply.capabilities: params = { - "namespace": "bookmarks", - "key": bookmark, - "new": newnode, - "old": oldnode, + b"namespace": b"bookmarks", + b"key": bookmark, + b"new": newnode, + b"old": oldnode, } - op.reply.newpart("pushkey", mandatoryparams=params.iteritems()) + op.reply.newpart(b"pushkey", mandatoryparams=params.iteritems()) def bundle2pushkey(orig, op, part): @@ -1261,11 +1277,11 @@ The only goal is to skip calling the original function if flag is set. It's set if infinitepush push is happening. """ - if op.records[scratchbranchparttype + "_skippushkey"]: + if op.records[scratchbranchparttype + b"_skippushkey"]: if op.reply is not None: - rpart = op.reply.newpart("reply:pushkey") - rpart.addparam("in-reply-to", str(part.id), mandatory=False) - rpart.addparam("return", "1", mandatory=False) + rpart = op.reply.newpart(b"reply:pushkey") + rpart.addparam(b"in-reply-to", str(part.id), mandatory=False) + rpart.addparam(b"return", b"1", mandatory=False) return 1 return orig(op, part) @@ -1278,7 +1294,7 @@ It's set if infinitepush push is happening. """ - if op.records[scratchbranchparttype + "_skipphaseheads"]: + if op.records[scratchbranchparttype + b"_skipphaseheads"]: return return orig(op, part) @@ -1296,13 +1312,13 @@ return nodesargs = [] for node in nodes: - nodesargs.append("--node") + nodesargs.append(b"--node") nodesargs.append(node) - with open(os.devnull, "w+b") as devnull: + with open(os.devnull, b"w+b") as devnull: cmdline = [ util.hgexecutable(), - "debugfillinfinitepushmetadata", - "-R", + b"debugfillinfinitepushmetadata", + b"-R", root, ] + nodesargs # Process will run in background. We don't care about the return code diff --git a/hgext/infinitepush/bundleparts.py b/hgext/infinitepush/bundleparts.py --- a/hgext/infinitepush/bundleparts.py +++ b/hgext/infinitepush/bundleparts.py @@ -21,42 +21,44 @@ isremotebooksenabled = common.isremotebooksenabled -scratchbranchparttype = "b2x:infinitepush" +scratchbranchparttype = b"b2x:infinitepush" def getscratchbranchparts(repo, peer, outgoing, ui, bookmark): if not outgoing.missing: - raise error.Abort(_("no commits to push")) + raise error.Abort(_(b"no commits to push")) if scratchbranchparttype not in bundle2.bundle2caps(peer): - raise error.Abort(_("no server support for %r") % scratchbranchparttype) + raise error.Abort( + _(b"no server support for %r") % scratchbranchparttype + ) _validaterevset( - repo, revsetlang.formatspec("%ln", outgoing.missing), bookmark + repo, revsetlang.formatspec(b"%ln", outgoing.missing), bookmark ) supportedversions = changegroup.supportedoutgoingversions(repo) # Explicitly avoid using '01' changegroup version in infinitepush to # support general delta - supportedversions.discard("01") + supportedversions.discard(b"01") cgversion = min(supportedversions) _handlelfs(repo, outgoing.missing) - cg = changegroup.makestream(repo, outgoing, cgversion, "push") + cg = changegroup.makestream(repo, outgoing, cgversion, b"push") params = {} - params["cgversion"] = cgversion + params[b"cgversion"] = cgversion if bookmark: - params["bookmark"] = bookmark + params[b"bookmark"] = bookmark # 'prevbooknode' is necessary for pushkey reply part - params["bookprevnode"] = "" + params[b"bookprevnode"] = b"" bookmarks = repo._bookmarks if bookmark in bookmarks: - params["bookprevnode"] = nodemod.hex(bookmarks[bookmark]) + params[b"bookprevnode"] = nodemod.hex(bookmarks[bookmark]) # Do not send pushback bundle2 part with bookmarks if remotenames extension # is enabled. It will be handled manually in `_push()` if not isremotebooksenabled(ui): - params["pushbackbookmarks"] = "1" + params[b"pushbackbookmarks"] = b"1" parts = [] @@ -76,13 +78,13 @@ def _validaterevset(repo, revset, bookmark): """Abort if the revs to be pushed aren't valid for a scratch branch.""" if not repo.revs(revset): - raise error.Abort(_("nothing to push")) + raise error.Abort(_(b"nothing to push")) if bookmark: # Allow bundle with many heads only if no bookmark is specified - heads = repo.revs("heads(%r)", revset) + heads = repo.revs(b"heads(%r)", revset) if len(heads) > 1: raise error.Abort( - _("cannot push more than one head to a scratch branch") + _(b"cannot push more than one head to a scratch branch") ) @@ -93,7 +95,7 @@ to make sure large files are uploaded to lfs """ try: - lfsmod = extensions.find("lfs") + lfsmod = extensions.find(b"lfs") lfsmod.wrapper.uploadblobsfromrevs(repo, missing) except KeyError: # Ignore if lfs extension is not enabled diff --git a/hgext/infinitepush/common.py b/hgext/infinitepush/common.py --- a/hgext/infinitepush/common.py +++ b/hgext/infinitepush/common.py @@ -17,8 +17,8 @@ def isremotebooksenabled(ui): - return "remotenames" in extensions._extensions and ui.configbool( - "remotenames", "bookmarks" + return b"remotenames" in extensions._extensions and ui.configbool( + b"remotenames", b"bookmarks" ) @@ -27,7 +27,7 @@ store = repo.bundlestore.store bundleid = index.getbundle(hex(unknownbinhead)) if bundleid is None: - raise error.Abort("%s head is not known" % hex(unknownbinhead)) + raise error.Abort(b"%s head is not known" % hex(unknownbinhead)) bundleraw = store.read(bundleid) return _makebundlefromraw(bundleraw) diff --git a/hgext/infinitepush/fileindexapi.py b/hgext/infinitepush/fileindexapi.py --- a/hgext/infinitepush/fileindexapi.py +++ b/hgext/infinitepush/fileindexapi.py @@ -26,13 +26,13 @@ def __init__(self, repo): super(fileindexapi, self).__init__() self._repo = repo - root = repo.ui.config("infinitepush", "indexpath") + root = repo.ui.config(b"infinitepush", b"indexpath") if not root: - root = os.path.join("scratchbranches", "index") + root = os.path.join(b"scratchbranches", b"index") - self._nodemap = os.path.join(root, "nodemap") - self._bookmarkmap = os.path.join(root, "bookmarkmap") - self._metadatamap = os.path.join(root, "nodemetadatamap") + self._nodemap = os.path.join(root, b"nodemap") + self._bookmarkmap = os.path.join(root, b"bookmarkmap") + self._metadatamap = os.path.join(root, b"nodemetadatamap") self._lock = None def __enter__(self): @@ -78,8 +78,8 @@ vfs.write(os.path.join(self._metadatamap, node), jsonmetadata) def _listbookmarks(self, pattern): - if pattern.endswith("*"): - pattern = "re:^" + pattern[:-1] + ".*" + if pattern.endswith(b"*"): + pattern = b"re:^" + pattern[:-1] + b".*" kind, pat, matcher = stringutil.stringmatcher(pattern) prefixlen = len(self._bookmarkmap) + 1 for dirpath, _, books in self._repo.vfs.walk(self._bookmarkmap): diff --git a/hgext/infinitepush/sqlindexapi.py b/hgext/infinitepush/sqlindexapi.py --- a/hgext/infinitepush/sqlindexapi.py +++ b/hgext/infinitepush/sqlindexapi.py @@ -18,10 +18,10 @@ def _convertbookmarkpattern(pattern): - pattern = pattern.replace("_", "\\_") - pattern = pattern.replace("%", "\\%") - if pattern.endswith("*"): - pattern = pattern[:-1] + "%" + pattern = pattern.replace(b"_", b"\\_") + pattern = pattern.replace(b"%", b"\\%") + if pattern.endswith(b"*"): + pattern = pattern[:-1] + b"%" return pattern @@ -46,11 +46,11 @@ super(sqlindexapi, self).__init__() self.reponame = reponame self.sqlargs = { - "host": host, - "port": port, - "database": database, - "user": user, - "password": password, + b"host": host, + b"port": port, + b"database": database, + b"user": user, + b"password": password, } self.sqlconn = None self.sqlcursor = None @@ -65,10 +65,10 @@ def sqlconnect(self): if self.sqlconn: - raise indexapi.indexexception("SQL connection already open") + raise indexapi.indexexception(b"SQL connection already open") if self.sqlcursor: raise indexapi.indexexception( - "SQL cursor already open without" " connection" + b"SQL cursor already open without" b" connection" ) retry = 3 while True: @@ -90,19 +90,19 @@ raise time.sleep(0.2) - waittimeout = self.sqlconn.converter.escape("%s" % self._waittimeout) + waittimeout = self.sqlconn.converter.escape(b"%s" % self._waittimeout) self.sqlcursor = self.sqlconn.cursor() - self.sqlcursor.execute("SET wait_timeout=%s" % waittimeout) + self.sqlcursor.execute(b"SET wait_timeout=%s" % waittimeout) self.sqlcursor.execute( - "SET innodb_lock_wait_timeout=%s" % self._locktimeout + b"SET innodb_lock_wait_timeout=%s" % self._locktimeout ) self._connected = True def close(self): """Cleans up the metadata store connection.""" with warnings.catch_warnings(): - warnings.simplefilter("ignore") + warnings.simplefilter(b"ignore") self.sqlcursor.close() self.sqlconn.close() self.sqlcursor = None @@ -122,29 +122,29 @@ def addbundle(self, bundleid, nodesctx): if not self._connected: self.sqlconnect() - self.log.info("ADD BUNDLE %r %r" % (self.reponame, bundleid)) + self.log.info(b"ADD BUNDLE %r %r" % (self.reponame, bundleid)) self.sqlcursor.execute( - "INSERT INTO bundles(bundle, reponame) VALUES " "(%s, %s)", + b"INSERT INTO bundles(bundle, reponame) VALUES " b"(%s, %s)", params=(bundleid, self.reponame), ) for ctx in nodesctx: self.sqlcursor.execute( - "INSERT INTO nodestobundle(node, bundle, reponame) " - "VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE " - "bundle=VALUES(bundle)", + b"INSERT INTO nodestobundle(node, bundle, reponame) " + b"VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE " + b"bundle=VALUES(bundle)", params=(ctx.hex(), bundleid, self.reponame), ) extra = ctx.extra() author_name = ctx.user() - committer_name = extra.get("committer", ctx.user()) + committer_name = extra.get(b"committer", ctx.user()) author_date = int(ctx.date()[0]) - committer_date = int(extra.get("committer_date", author_date)) + committer_date = int(extra.get(b"committer_date", author_date)) self.sqlcursor.execute( - "INSERT IGNORE INTO nodesmetadata(node, message, p1, p2, " - "author, committer, author_date, committer_date, " - "reponame) VALUES " - "(%s, %s, %s, %s, %s, %s, %s, %s, %s)", + b"INSERT IGNORE INTO nodesmetadata(node, message, p1, p2, " + b"author, committer, author_date, committer_date, " + b"reponame) VALUES " + b"(%s, %s, %s, %s, %s, %s, %s, %s, %s)", params=( ctx.hex(), ctx.description(), @@ -164,12 +164,12 @@ if not self._connected: self.sqlconnect() self.log.info( - "ADD BOOKMARKS %r bookmark: %r node: %r" + b"ADD BOOKMARKS %r bookmark: %r node: %r" % (self.reponame, bookmark, node) ) self.sqlcursor.execute( - "INSERT INTO bookmarkstonode(bookmark, node, reponame) " - "VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE node=VALUES(node)", + b"INSERT INTO bookmarkstonode(bookmark, node, reponame) " + b"VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE node=VALUES(node)", params=(bookmark, node, self.reponame), ) @@ -179,13 +179,13 @@ args = [] values = [] for bookmark, node in bookmarks.iteritems(): - args.append("(%s, %s, %s)") + args.append(b"(%s, %s, %s)") values.extend((bookmark, node, self.reponame)) - args = ",".join(args) + args = b",".join(args) self.sqlcursor.execute( - "INSERT INTO bookmarkstonode(bookmark, node, reponame) " - "VALUES %s ON DUPLICATE KEY UPDATE node=VALUES(node)" % args, + b"INSERT INTO bookmarkstonode(bookmark, node, reponame) " + b"VALUES %s ON DUPLICATE KEY UPDATE node=VALUES(node)" % args, params=values, ) @@ -196,12 +196,12 @@ """ if not self._connected: self.sqlconnect() - self.log.info("DELETE BOOKMARKS: %s" % patterns) + self.log.info(b"DELETE BOOKMARKS: %s" % patterns) for pattern in patterns: pattern = _convertbookmarkpattern(pattern) self.sqlcursor.execute( - "DELETE from bookmarkstonode WHERE bookmark LIKE (%s) " - "and reponame = %s", + b"DELETE from bookmarkstonode WHERE bookmark LIKE (%s) " + b"and reponame = %s", params=(pattern, self.reponame), ) @@ -209,18 +209,18 @@ """Returns the bundleid for the bundle that contains the given node.""" if not self._connected: self.sqlconnect() - self.log.info("GET BUNDLE %r %r" % (self.reponame, node)) + self.log.info(b"GET BUNDLE %r %r" % (self.reponame, node)) self.sqlcursor.execute( - "SELECT bundle from nodestobundle " - "WHERE node = %s AND reponame = %s", + b"SELECT bundle from nodestobundle " + b"WHERE node = %s AND reponame = %s", params=(node, self.reponame), ) result = self.sqlcursor.fetchall() if len(result) != 1 or len(result[0]) != 1: - self.log.info("No matching node") + self.log.info(b"No matching node") return None bundle = result[0][0] - self.log.info("Found bundle %r" % bundle) + self.log.info(b"Found bundle %r" % bundle) return bundle def getnode(self, bookmark): @@ -228,38 +228,38 @@ if not self._connected: self.sqlconnect() self.log.info( - "GET NODE reponame: %r bookmark: %r" % (self.reponame, bookmark) + b"GET NODE reponame: %r bookmark: %r" % (self.reponame, bookmark) ) self.sqlcursor.execute( - "SELECT node from bookmarkstonode WHERE " - "bookmark = %s AND reponame = %s", + b"SELECT node from bookmarkstonode WHERE " + b"bookmark = %s AND reponame = %s", params=(bookmark, self.reponame), ) result = self.sqlcursor.fetchall() if len(result) != 1 or len(result[0]) != 1: - self.log.info("No matching bookmark") + self.log.info(b"No matching bookmark") return None node = result[0][0] - self.log.info("Found node %r" % node) + self.log.info(b"Found node %r" % node) return node def getbookmarks(self, query): if not self._connected: self.sqlconnect() self.log.info( - "QUERY BOOKMARKS reponame: %r query: %r" % (self.reponame, query) + b"QUERY BOOKMARKS reponame: %r query: %r" % (self.reponame, query) ) query = _convertbookmarkpattern(query) self.sqlcursor.execute( - "SELECT bookmark, node from bookmarkstonode WHERE " - "reponame = %s AND bookmark LIKE %s", + b"SELECT bookmark, node from bookmarkstonode WHERE " + b"reponame = %s AND bookmark LIKE %s", params=(self.reponame, query), ) result = self.sqlcursor.fetchall() bookmarks = {} for row in result: if len(row) != 2: - self.log.info("Bad row returned: %s" % row) + self.log.info(b"Bad row returned: %s" % row) continue bookmarks[row[0]] = row[1] return bookmarks @@ -269,15 +269,15 @@ self.sqlconnect() self.log.info( ( - "INSERT METADATA, QUERY BOOKMARKS reponame: %r " - + "node: %r, jsonmetadata: %s" + b"INSERT METADATA, QUERY BOOKMARKS reponame: %r " + + b"node: %r, jsonmetadata: %s" ) % (self.reponame, node, jsonmetadata) ) self.sqlcursor.execute( - "UPDATE nodesmetadata SET optional_json_metadata=%s WHERE " - "reponame=%s AND node=%s", + b"UPDATE nodesmetadata SET optional_json_metadata=%s WHERE " + b"reponame=%s AND node=%s", params=(jsonmetadata, self.reponame, node), ) diff --git a/hgext/infinitepush/store.py b/hgext/infinitepush/store.py --- a/hgext/infinitepush/store.py +++ b/hgext/infinitepush/store.py @@ -68,10 +68,10 @@ def __init__(self, ui, repo): self.ui = ui self.repo = repo - self.storepath = ui.configpath("scratchbranch", "storepath") + self.storepath = ui.configpath(b"scratchbranch", b"storepath") if not self.storepath: self.storepath = self.repo.vfs.join( - "scratchbranches", "filebundlestore" + b"scratchbranches", b"filebundlestore" ) if not os.path.exists(self.storepath): os.makedirs(self.storepath) @@ -92,14 +92,14 @@ if not os.path.exists(dirpath): os.makedirs(dirpath) - with open(self._filepath(filename), "wb") as f: + with open(self._filepath(filename), b"wb") as f: f.write(data) return filename def read(self, key): try: - with open(self._filepath(key), "rb") as f: + with open(self._filepath(key), b"rb") as f: return f.read() except IOError: return None @@ -152,14 +152,14 @@ if returncode != 0: raise BundleWriteException( - "Failed to upload to external store: %s" % stderr + b"Failed to upload to external store: %s" % stderr ) stdout_lines = stdout.splitlines() if len(stdout_lines) == 1: return stdout_lines[0] else: raise BundleWriteException( - "Bad output from %s: %s" % (self.put_binary, stdout) + b"Bad output from %s: %s" % (self.put_binary, stdout) ) def read(self, handle): @@ -178,6 +178,6 @@ if returncode != 0: raise BundleReadException( - "Failed to download from external store: %s" % stderr + b"Failed to download from external store: %s" % stderr ) return temp.read() diff --git a/hgext/journal.py b/hgext/journal.py --- a/hgext/journal.py +++ b/hgext/journal.py @@ -49,14 +49,14 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" # storage format version; increment when the format changes storageversion = 0 # namespaces -bookmarktype = "bookmark" -wdirparenttype = "wdirparent" +bookmarktype = b"bookmark" +wdirparenttype = b"wdirparent" # In a shared repository, what shared feature name is used # to indicate this namespace is shared with the source? sharednamespaces = { @@ -65,21 +65,21 @@ # Journal recording, register hooks and storage object def extsetup(ui): - extensions.wrapfunction(dispatch, "runcommand", runcommand) - extensions.wrapfunction(bookmarks.bmstore, "_write", recordbookmarks) + extensions.wrapfunction(dispatch, b"runcommand", runcommand) + extensions.wrapfunction(bookmarks.bmstore, b"_write", recordbookmarks) extensions.wrapfilecache( - localrepo.localrepository, "dirstate", wrapdirstate + localrepo.localrepository, b"dirstate", wrapdirstate ) - extensions.wrapfunction(hg, "postshare", wrappostshare) - extensions.wrapfunction(hg, "copystore", unsharejournal) + extensions.wrapfunction(hg, b"postshare", wrappostshare) + extensions.wrapfunction(hg, b"copystore", unsharejournal) def reposetup(ui, repo): if repo.local(): repo.journal = journalstorage(repo) - repo._wlockfreeprefix.add("namejournal") + repo._wlockfreeprefix.add(b"namejournal") - dirstate, cached = localrepo.isfilecached(repo, "dirstate") + dirstate, cached = localrepo.isfilecached(repo, b"dirstate") if cached: # already instantiated dirstate isn't yet marked as # "journal"-ing, even though repo.dirstate() was already @@ -95,14 +95,14 @@ def _setupdirstate(repo, dirstate): dirstate.journalstorage = repo.journal - dirstate.addparentchangecallback("journal", recorddirstateparents) + dirstate.addparentchangecallback(b"journal", recorddirstateparents) # hooks to record dirstate changes def wrapdirstate(orig, repo): """Make journal storage available to the dirstate object""" dirstate = orig(repo) - if util.safehasattr(repo, "journal"): + if util.safehasattr(repo, b"journal"): _setupdirstate(repo, dirstate) return dirstate @@ -111,12 +111,12 @@ """Records all dirstate parent changes in the journal.""" old = list(old) new = list(new) - if util.safehasattr(dirstate, "journalstorage"): + if util.safehasattr(dirstate, b"journalstorage"): # only record two hashes if there was a merge oldhashes = old[:1] if old[1] == node.nullid else old newhashes = new[:1] if new[1] == node.nullid else new dirstate.journalstorage.record( - wdirparenttype, ".", oldhashes, newhashes + wdirparenttype, b".", oldhashes, newhashes ) @@ -124,7 +124,7 @@ def recordbookmarks(orig, store, fp): """Records all bookmark changes in the journal.""" repo = store._repo - if util.safehasattr(repo, "journal"): + if util.safehasattr(repo, b"journal"): oldmarks = bookmarks.bmstore(repo) for mark, value in store.iteritems(): oldvalue = oldmarks.get(mark, node.nullid) @@ -137,7 +137,7 @@ def _readsharedfeatures(repo): """A set of shared features for this repository""" try: - return set(repo.vfs.read("shared").splitlines()) + return set(repo.vfs.read(b"shared").splitlines()) except IOError as inst: if inst.errno != errno.ENOENT: raise @@ -177,8 +177,8 @@ """Mark this shared working copy as sharing journal information""" with destrepo.wlock(): orig(sourcerepo, destrepo, **kwargs) - with destrepo.vfs("shared", "a") as fp: - fp.write("journal\n") + with destrepo.vfs(b"shared", b"a") as fp: + fp.write(b"journal\n") def unsharejournal(orig, ui, repo, repopath): @@ -186,20 +186,20 @@ if ( repo.path == repopath and repo.shared() - and util.safehasattr(repo, "journal") + and util.safehasattr(repo, b"journal") ): sharedrepo = hg.sharedreposource(repo) sharedfeatures = _readsharedfeatures(repo) - if sharedrepo and sharedfeatures > {"journal"}: + if sharedrepo and sharedfeatures > {b"journal"}: # there is a shared repository and there are shared journal entries # to copy. move shared date over from source to destination but # move the local file first - if repo.vfs.exists("namejournal"): - journalpath = repo.vfs.join("namejournal") - util.rename(journalpath, journalpath + ".bak") + if repo.vfs.exists(b"namejournal"): + journalpath = repo.vfs.join(b"namejournal") + util.rename(journalpath, journalpath + b".bak") storage = repo.journal local = storage._open( - repo.vfs, filename="namejournal.bak", _newestfirst=False + repo.vfs, filename=b"namejournal.bak", _newestfirst=False ) shared = ( e @@ -245,11 +245,11 @@ name, oldhashes, newhashes, - ) = line.split("\n") + ) = line.split(b"\n") timestamp, tz = time.split() timestamp, tz = float(timestamp), int(tz) - oldhashes = tuple(node.bin(hash) for hash in oldhashes.split(",")) - newhashes = tuple(node.bin(hash) for hash in newhashes.split(",")) + oldhashes = tuple(node.bin(hash) for hash in oldhashes.split(b",")) + newhashes = tuple(node.bin(hash) for hash in newhashes.split(b",")) return cls( (timestamp, tz), user, @@ -262,10 +262,10 @@ def __bytes__(self): """bytes representation for storage""" - time = " ".join(map(pycompat.bytestr, self.timestamp)) - oldhashes = ",".join([node.hex(hash) for hash in self.oldhashes]) - newhashes = ",".join([node.hex(hash) for hash in self.newhashes]) - return "\n".join( + time = b" ".join(map(pycompat.bytestr, self.timestamp)) + oldhashes = b",".join([node.hex(hash) for hash in self.oldhashes]) + newhashes = b",".join([node.hex(hash) for hash in self.newhashes]) + return b"\n".join( ( time, self.user, @@ -311,19 +311,19 @@ if repo.shared(): features = _readsharedfeatures(repo) sharedrepo = hg.sharedreposource(repo) - if sharedrepo is not None and "journal" in features: + if sharedrepo is not None and b"journal" in features: self.sharedvfs = sharedrepo.vfs self.sharedfeatures = features # track the current command for recording in journal entries @property def command(self): - commandstr = " ".join( + commandstr = b" ".join( map(procutil.shellquote, journalstorage._currentcommand) ) - if "\n" in commandstr: + if b"\n" in commandstr: # truncate multi-line commands - commandstr = commandstr.partition("\n")[0] + " ..." + commandstr = commandstr.partition(b"\n")[0] + b" ..." return commandstr @classmethod @@ -348,22 +348,22 @@ def jlock(self, vfs): """Create a lock for the journal file""" if self._currentlock(self._lockref) is not None: - raise error.Abort(_("journal lock does not support nesting")) - desc = _("journal of %s") % vfs.base + raise error.Abort(_(b"journal lock does not support nesting")) + desc = _(b"journal of %s") % vfs.base try: - l = lock.lock(vfs, "namejournal.lock", 0, desc=desc) + l = lock.lock(vfs, b"namejournal.lock", 0, desc=desc) except error.LockHeld as inst: self.ui.warn( - _("waiting for lock on %s held by %r\n") % (desc, inst.locker) + _(b"waiting for lock on %s held by %r\n") % (desc, inst.locker) ) # default to 600 seconds timeout l = lock.lock( vfs, - "namejournal.lock", - self.ui.configint("ui", "timeout"), + b"namejournal.lock", + self.ui.configint(b"ui", b"timeout"), desc=desc, ) - self.ui.warn(_("got lock after %s seconds\n") % l.delay) + self.ui.warn(_(b"got lock after %s seconds\n") % l.delay) self._lockref = weakref.ref(l) return l @@ -406,25 +406,25 @@ def _write(self, vfs, entry): with self.jlock(vfs): # open file in amend mode to ensure it is created if missing - with vfs("namejournal", mode="a+b") as f: + with vfs(b"namejournal", mode=b"a+b") as f: f.seek(0, os.SEEK_SET) # Read just enough bytes to get a version number (up to 2 # digits plus separator) - version = f.read(3).partition("\0")[0] - if version and version != "%d" % storageversion: + version = f.read(3).partition(b"\0")[0] + if version and version != b"%d" % storageversion: # different version of the storage. Exit early (and not # write anything) if this is not a version we can handle or # the file is corrupt. In future, perhaps rotate the file # instead? self.ui.warn( - _("unsupported journal file version '%s'\n") % version + _(b"unsupported journal file version '%s'\n") % version ) return if not version: # empty file, write version first - f.write(("%d" % storageversion) + "\0") + f.write((b"%d" % storageversion) + b"\0") f.seek(0, os.SEEK_END) - f.write(bytes(entry) + "\0") + f.write(bytes(entry) + b"\0") def filtered(self, namespace=None, name=None): """Yield all journal entries with the given namespace or name @@ -467,18 +467,18 @@ ) return _mergeentriesiter(local, shared) - def _open(self, vfs, filename="namejournal", _newestfirst=True): + def _open(self, vfs, filename=b"namejournal", _newestfirst=True): if not vfs.exists(filename): return with vfs(filename) as f: raw = f.read() - lines = raw.split("\0") + lines = raw.split(b"\0") version = lines and lines[0] - if version != "%d" % storageversion: - version = version or _("not available") - raise error.Abort(_("unknown journal file version '%s'") % version) + if version != b"%d" % storageversion: + version = version or _(b"not available") + raise error.Abort(_(b"unknown journal file version '%s'") % version) # Skip the first line, it's a version number. Normally we iterate over # these in reverse order to list newest first; only when copying across @@ -494,17 +494,17 @@ # journal reading # log options that don't make sense for journal -_ignoreopts = ("no-merges", "graph") +_ignoreopts = (b"no-merges", b"graph") @command( - "journal", + b"journal", [ - ("", "all", None, "show history for all names"), - ("c", "commits", None, "show commit metadata"), + (b"", b"all", None, b"show history for all names"), + (b"c", b"commits", None, b"show commit metadata"), ] + [opt for opt in cmdutil.logopts if opt[1] not in _ignoreopts], - "[OPTION]... [BOOKMARKNAME]", + b"[OPTION]... [BOOKMARKNAME]", helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def journal(ui, repo, *args, **opts): @@ -533,72 +533,72 @@ """ opts = pycompat.byteskwargs(opts) - name = "." - if opts.get("all"): + name = b"." + if opts.get(b"all"): if args: raise error.Abort( - _("You can't combine --all and filtering on a name") + _(b"You can't combine --all and filtering on a name") ) name = None if args: name = args[0] - fm = ui.formatter("journal", opts) + fm = ui.formatter(b"journal", opts) def formatnodes(nodes): - return fm.formatlist(map(fm.hexfunc, nodes), name="node", sep=",") + return fm.formatlist(map(fm.hexfunc, nodes), name=b"node", sep=b",") - if opts.get("template") != "json": + if opts.get(b"template") != b"json": if name is None: - displayname = _("the working copy and bookmarks") + displayname = _(b"the working copy and bookmarks") else: - displayname = "'%s'" % name - ui.status(_("previous locations of %s:\n") % displayname) + displayname = b"'%s'" % name + ui.status(_(b"previous locations of %s:\n") % displayname) limit = logcmdutil.getlimit(opts) entry = None - ui.pager("journal") + ui.pager(b"journal") for count, entry in enumerate(repo.journal.filtered(name=name)): if count == limit: break fm.startitem() fm.condwrite( - ui.verbose, "oldnodes", "%s -> ", formatnodes(entry.oldhashes) + ui.verbose, b"oldnodes", b"%s -> ", formatnodes(entry.oldhashes) ) - fm.write("newnodes", "%s", formatnodes(entry.newhashes)) - fm.condwrite(ui.verbose, "user", " %-8s", entry.user) + fm.write(b"newnodes", b"%s", formatnodes(entry.newhashes)) + fm.condwrite(ui.verbose, b"user", b" %-8s", entry.user) fm.condwrite( - opts.get("all") or name.startswith("re:"), - "name", - " %-8s", + opts.get(b"all") or name.startswith(b"re:"), + b"name", + b" %-8s", entry.name, ) fm.condwrite( ui.verbose, - "date", - " %s", - fm.formatdate(entry.timestamp, "%Y-%m-%d %H:%M %1%2"), + b"date", + b" %s", + fm.formatdate(entry.timestamp, b"%Y-%m-%d %H:%M %1%2"), ) - fm.write("command", " %s\n", entry.command) + fm.write(b"command", b" %s\n", entry.command) - if opts.get("commits"): + if opts.get(b"commits"): if fm.isplain(): displayer = logcmdutil.changesetdisplayer(ui, repo, opts) else: displayer = logcmdutil.changesetformatter( - ui, repo, fm.nested("changesets"), diffopts=opts + ui, repo, fm.nested(b"changesets"), diffopts=opts ) for hash in entry.newhashes: try: ctx = repo[hash] displayer.show(ctx) except error.RepoLookupError as e: - fm.plain("%s\n\n" % pycompat.bytestr(e)) + fm.plain(b"%s\n\n" % pycompat.bytestr(e)) displayer.close() fm.end() if entry is None: - ui.status(_("no recorded locations\n")) + ui.status(_(b"no recorded locations\n")) diff --git a/hgext/keyword.py b/hgext/keyword.py --- a/hgext/keyword.py +++ b/hgext/keyword.py @@ -122,33 +122,33 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" # hg commands that do not act on keywords nokwcommands = ( - "add addremove annotate bundle export grep incoming init log" - " outgoing push tip verify convert email glog" + b"add addremove annotate bundle export grep incoming init log" + b" outgoing push tip verify convert email glog" ) # webcommands that do not act on keywords -nokwwebcommands = "annotate changeset rev filediff diff comparison" +nokwwebcommands = b"annotate changeset rev filediff diff comparison" # hg commands that trigger expansion only when writing to working dir, # not when reading filelog, and unexpand when reading from working dir restricted = ( - "merge kwexpand kwshrink record qrecord resolve transplant" - " unshelve rebase graft backout histedit fetch" + b"merge kwexpand kwshrink record qrecord resolve transplant" + b" unshelve rebase graft backout histedit fetch" ) # names of extensions using dorecord -recordextensions = "record" +recordextensions = b"record" colortable = { - "kwfiles.enabled": "green bold", - "kwfiles.deleted": "cyan bold underline", - "kwfiles.enabledunknown": "green", - "kwfiles.ignored": "bold", - "kwfiles.ignoredunknown": "none", + b"kwfiles.enabled": b"green bold", + b"kwfiles.deleted": b"cyan bold underline", + b"kwfiles.enabledunknown": b"green", + b"kwfiles.ignored": b"bold", + b"kwfiles.ignoredunknown": b"none", } templatefilter = registrar.templatefilter() @@ -157,65 +157,65 @@ configitem = registrar.configitem(configtable) configitem( - "keywordset", "svn", default=False, + b"keywordset", b"svn", default=False, ) # date like in cvs' $Date -@templatefilter("utcdate", intype=templateutil.date) +@templatefilter(b"utcdate", intype=templateutil.date) def utcdate(date): """Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". """ - dateformat = "%Y/%m/%d %H:%M:%S" + dateformat = b"%Y/%m/%d %H:%M:%S" return dateutil.datestr((date[0], 0), dateformat) # date like in svn's $Date -@templatefilter("svnisodate", intype=templateutil.date) +@templatefilter(b"svnisodate", intype=templateutil.date) def svnisodate(date): """Date. Returns a date in this format: "2009-08-18 13:00:13 +0200 (Tue, 18 Aug 2009)". """ - return dateutil.datestr(date, "%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)") + return dateutil.datestr(date, b"%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)") # date like in svn's $Id -@templatefilter("svnutcdate", intype=templateutil.date) +@templatefilter(b"svnutcdate", intype=templateutil.date) def svnutcdate(date): """Date. Returns a UTC-date in this format: "2009-08-18 11:00:13Z". """ - dateformat = "%Y-%m-%d %H:%M:%SZ" + dateformat = b"%Y-%m-%d %H:%M:%SZ" return dateutil.datestr((date[0], 0), dateformat) # make keyword tools accessible -kwtools = {"hgcmd": ""} +kwtools = {b"hgcmd": b""} def _defaultkwmaps(ui): """Returns default keywordmaps according to keywordset configuration.""" templates = { - "Revision": "{node|short}", - "Author": "{author|user}", + b"Revision": b"{node|short}", + b"Author": b"{author|user}", } kwsets = ( { - "Date": "{date|utcdate}", - "RCSfile": "{file|basename},v", - "RCSFile": "{file|basename},v", # kept for backwards compatibility + b"Date": b"{date|utcdate}", + b"RCSfile": b"{file|basename},v", + b"RCSFile": b"{file|basename},v", # kept for backwards compatibility # with hg-keyword - "Source": "{root}/{file},v", - "Id": "{file|basename},v {node|short} {date|utcdate} {author|user}", - "Header": "{root}/{file},v {node|short} {date|utcdate} {author|user}", + b"Source": b"{root}/{file},v", + b"Id": b"{file|basename},v {node|short} {date|utcdate} {author|user}", + b"Header": b"{root}/{file},v {node|short} {date|utcdate} {author|user}", }, { - "Date": "{date|svnisodate}", - "Id": "{file|basename},v {node|short} {date|svnutcdate} {author|user}", - "LastChangedRevision": "{node|short}", - "LastChangedBy": "{author|user}", - "LastChangedDate": "{date|svnisodate}", + b"Date": b"{date|svnisodate}", + b"Id": b"{file|basename},v {node|short} {date|svnutcdate} {author|user}", + b"LastChangedRevision": b"{node|short}", + b"LastChangedBy": b"{author|user}", + b"LastChangedDate": b"{date|svnisodate}", }, ) - templates.update(kwsets[ui.configbool("keywordset", "svn")]) + templates.update(kwsets[ui.configbool(b"keywordset", b"svn")]) return templates @@ -243,11 +243,11 @@ def __init__(self, ui, repo, inc, exc): self.ui = ui self._repo = weakref.ref(repo) - self.match = match.match(repo.root, "", [], inc, exc) - self.restrict = kwtools["hgcmd"] in restricted.split() + self.match = match.match(repo.root, b"", [], inc, exc) + self.restrict = kwtools[b"hgcmd"] in restricted.split() self.postcommit = False - kwmaps = self.ui.configitems("keywordmaps") + kwmaps = self.ui.configitems(b"keywordmaps") if kwmaps: # override default templates self.templates = dict(kwmaps) else: @@ -260,7 +260,7 @@ @util.propertycache def escape(self): """Returns bar-separated and escaped keywords.""" - return "|".join(map(stringutil.reescape, self.templates.keys())) + return b"|".join(map(stringutil.reescape, self.templates.keys())) @util.propertycache def rekw(self): @@ -283,7 +283,7 @@ self.ui.pushbuffer() ct.show(ctx, root=self.repo.root, file=path) ekw = templatefilters.firstline(self.ui.popbuffer()) - return "$%s: %s $" % (kw, ekw) + return b"$%s: %s $" % (kw, ekw) return subfunc(kwsub, data) @@ -305,7 +305,7 @@ def iskwfile(self, cand, ctx): """Returns subset of candidates which are configured for keyword expansion but are not symbolic links.""" - return [f for f in cand if self.match(f) and "l" not in ctx.flags(f)] + return [f for f in cand if self.match(f) and b"l" not in ctx.flags(f)] def overwrite(self, ctx, candidates, lookup, expand, rekw=False): """Overwrites selected files expanding/shrinking keywords.""" @@ -321,9 +321,9 @@ else: re_kw = self.rekwexp if expand: - msg = _("overwriting %s expanding keywords\n") + msg = _(b"overwriting %s expanding keywords\n") else: - msg = _("overwriting %s shrinking keywords\n") + msg = _(b"overwriting %s shrinking keywords\n") for f in candidates: if self.restrict: data = self.repo.file(f).read(mf[f]) @@ -350,7 +350,7 @@ data, found = _shrinktext(data, re_kw.subn) if found: self.ui.note(msg % f) - fp = self.repo.wvfs(f, "wb", atomictemp=True) + fp = self.repo.wvfs(f, b"wb", atomictemp=True) fp.write(data) fp.close() if kwcmd: @@ -367,7 +367,7 @@ def shrinklines(self, fname, lines): """Returns lines with keyword substitutions removed.""" if self.match(fname): - text = "".join(lines) + text = b"".join(lines) if not stringutil.binary(text): return _shrinktext(text, self.rekwexp.sub).splitlines(True) return lines @@ -417,33 +417,33 @@ return repo.status( match=scmutil.match(wctx, pats, opts), clean=True, - unknown=opts.get("unknown") or opts.get("all"), + unknown=opts.get(b"unknown") or opts.get(b"all"), ) - if ui.configitems("keyword"): - raise error.Abort(_("[keyword] patterns cannot match")) - raise error.Abort(_("no [keyword] patterns configured")) + if ui.configitems(b"keyword"): + raise error.Abort(_(b"[keyword] patterns cannot match")) + raise error.Abort(_(b"no [keyword] patterns configured")) def _kwfwrite(ui, repo, expand, *pats, **opts): """Selects files and passes them to kwtemplater.overwrite.""" wctx = repo[None] if len(wctx.parents()) > 1: - raise error.Abort(_("outstanding uncommitted merge")) + raise error.Abort(_(b"outstanding uncommitted merge")) kwt = getattr(repo, "_keywordkwt", None) with repo.wlock(): status = _status(ui, repo, wctx, kwt, *pats, **opts) if status.modified or status.added or status.removed or status.deleted: - raise error.Abort(_("outstanding uncommitted changes")) + raise error.Abort(_(b"outstanding uncommitted changes")) kwt.overwrite(wctx, status.clean, True, expand) @command( - "kwdemo", + b"kwdemo", [ - ("d", "default", None, _("show default keyword template maps")), - ("f", "rcfile", "", _("read maps from rcfile"), _("FILE")), + (b"d", b"default", None, _(b"show default keyword template maps")), + (b"f", b"rcfile", b"", _(b"read maps from rcfile"), _(b"FILE")), ], - _("hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]..."), + _(b"hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]..."), optionalrepo=True, ) def demo(ui, repo, *args, **opts): @@ -461,55 +461,55 @@ """ def demoitems(section, items): - ui.write("[%s]\n" % section) + ui.write(b"[%s]\n" % section) for k, v in sorted(items): if isinstance(v, bool): v = stringutil.pprint(v) - ui.write("%s = %s\n" % (k, v)) + ui.write(b"%s = %s\n" % (k, v)) - fn = "demo.txt" - tmpdir = pycompat.mkdtemp("", "kwdemo.") - ui.note(_("creating temporary repository at %s\n") % tmpdir) + fn = b"demo.txt" + tmpdir = pycompat.mkdtemp(b"", b"kwdemo.") + ui.note(_(b"creating temporary repository at %s\n") % tmpdir) if repo is None: baseui = ui else: baseui = repo.baseui repo = localrepo.instance(baseui, tmpdir, create=True) - ui.setconfig("keyword", fn, "", "keyword") - svn = ui.configbool("keywordset", "svn") + ui.setconfig(b"keyword", fn, b"", b"keyword") + svn = ui.configbool(b"keywordset", b"svn") # explicitly set keywordset for demo output - ui.setconfig("keywordset", "svn", svn, "keyword") + ui.setconfig(b"keywordset", b"svn", svn, b"keyword") - uikwmaps = ui.configitems("keywordmaps") + uikwmaps = ui.configitems(b"keywordmaps") if args or opts.get(r"rcfile"): - ui.status(_("\n\tconfiguration using custom keyword template maps\n")) + ui.status(_(b"\n\tconfiguration using custom keyword template maps\n")) if uikwmaps: - ui.status(_("\textending current template maps\n")) + ui.status(_(b"\textending current template maps\n")) if opts.get(r"default") or not uikwmaps: if svn: - ui.status(_("\toverriding default svn keywordset\n")) + ui.status(_(b"\toverriding default svn keywordset\n")) else: - ui.status(_("\toverriding default cvs keywordset\n")) + ui.status(_(b"\toverriding default cvs keywordset\n")) if opts.get(r"rcfile"): - ui.readconfig(opts.get("rcfile")) + ui.readconfig(opts.get(b"rcfile")) if args: # simulate hgrc parsing - rcmaps = "[keywordmaps]\n%s\n" % "\n".join(args) - repo.vfs.write("hgrc", rcmaps) - ui.readconfig(repo.vfs.join("hgrc")) - kwmaps = dict(ui.configitems("keywordmaps")) + rcmaps = b"[keywordmaps]\n%s\n" % b"\n".join(args) + repo.vfs.write(b"hgrc", rcmaps) + ui.readconfig(repo.vfs.join(b"hgrc")) + kwmaps = dict(ui.configitems(b"keywordmaps")) elif opts.get(r"default"): if svn: - ui.status(_("\n\tconfiguration using default svn keywordset\n")) + ui.status(_(b"\n\tconfiguration using default svn keywordset\n")) else: - ui.status(_("\n\tconfiguration using default cvs keywordset\n")) + ui.status(_(b"\n\tconfiguration using default cvs keywordset\n")) kwmaps = _defaultkwmaps(ui) if uikwmaps: - ui.status(_("\tdisabling current template maps\n")) + ui.status(_(b"\tdisabling current template maps\n")) for k, v in kwmaps.iteritems(): - ui.setconfig("keywordmaps", k, v, "keyword") + ui.setconfig(b"keywordmaps", k, v, b"keyword") else: - ui.status(_("\n\tconfiguration using current keyword template maps\n")) + ui.status(_(b"\n\tconfiguration using current keyword template maps\n")) if uikwmaps: kwmaps = dict(uikwmaps) else: @@ -517,32 +517,32 @@ uisetup(ui) reposetup(ui, repo) - ui.write("[extensions]\nkeyword =\n") - demoitems("keyword", ui.configitems("keyword")) - demoitems("keywordset", ui.configitems("keywordset")) - demoitems("keywordmaps", kwmaps.iteritems()) - keywords = "$" + "$\n$".join(sorted(kwmaps.keys())) + "$\n" + ui.write(b"[extensions]\nkeyword =\n") + demoitems(b"keyword", ui.configitems(b"keyword")) + demoitems(b"keywordset", ui.configitems(b"keywordset")) + demoitems(b"keywordmaps", kwmaps.iteritems()) + keywords = b"$" + b"$\n$".join(sorted(kwmaps.keys())) + b"$\n" repo.wvfs.write(fn, keywords) repo[None].add([fn]) - ui.note(_("\nkeywords written to %s:\n") % fn) + ui.note(_(b"\nkeywords written to %s:\n") % fn) ui.note(keywords) with repo.wlock(): - repo.dirstate.setbranch("demobranch") - for name, cmd in ui.configitems("hooks"): - if name.split(".", 1)[0].find("commit") > -1: - repo.ui.setconfig("hooks", name, "", "keyword") - msg = _("hg keyword configuration and expansion example") - ui.note(("hg ci -m '%s'\n" % msg)) + repo.dirstate.setbranch(b"demobranch") + for name, cmd in ui.configitems(b"hooks"): + if name.split(b".", 1)[0].find(b"commit") > -1: + repo.ui.setconfig(b"hooks", name, b"", b"keyword") + msg = _(b"hg keyword configuration and expansion example") + ui.note((b"hg ci -m '%s'\n" % msg)) repo.commit(text=msg) - ui.status(_("\n\tkeywords expanded\n")) + ui.status(_(b"\n\tkeywords expanded\n")) ui.write(repo.wread(fn)) repo.wvfs.rmtree(repo.root) @command( - "kwexpand", + b"kwexpand", cmdutil.walkopts, - _("hg kwexpand [OPTION]... [FILE]..."), + _(b"hg kwexpand [OPTION]... [FILE]..."), inferrepo=True, ) def expand(ui, repo, *pats, **opts): @@ -557,14 +557,14 @@ @command( - "kwfiles", + b"kwfiles", [ - ("A", "all", None, _("show keyword status flags of all files")), - ("i", "ignore", None, _("show files excluded from expansion")), - ("u", "unknown", None, _("only show unknown (not tracked) files")), + (b"A", b"all", None, _(b"show keyword status flags of all files")), + (b"i", b"ignore", None, _(b"show files excluded from expansion")), + (b"u", b"unknown", None, _(b"only show unknown (not tracked) files")), ] + cmdutil.walkopts, - _("hg kwfiles [OPTION]... [FILE]..."), + _(b"hg kwfiles [OPTION]... [FILE]..."), inferrepo=True, ) def files(ui, repo, *pats, **opts): @@ -594,31 +594,31 @@ if pats: cwd = repo.getcwd() else: - cwd = "" + cwd = b"" files = [] opts = pycompat.byteskwargs(opts) - if not opts.get("unknown") or opts.get("all"): + if not opts.get(b"unknown") or opts.get(b"all"): files = sorted(status.modified + status.added + status.clean) kwfiles = kwt.iskwfile(files, wctx) kwdeleted = kwt.iskwfile(status.deleted, wctx) kwunknown = kwt.iskwfile(status.unknown, wctx) - if not opts.get("ignore") or opts.get("all"): + if not opts.get(b"ignore") or opts.get(b"all"): showfiles = kwfiles, kwdeleted, kwunknown else: showfiles = [], [], [] - if opts.get("all") or opts.get("ignore"): + if opts.get(b"all") or opts.get(b"ignore"): showfiles += ( [f for f in files if f not in kwfiles], [f for f in status.unknown if f not in kwunknown], ) - kwlabels = "enabled deleted enabledunknown ignored ignoredunknown".split() - kwstates = zip(kwlabels, pycompat.bytestr("K!kIi"), showfiles) - fm = ui.formatter("kwfiles", opts) - fmt = "%.0s%s\n" - if opts.get("all") or ui.verbose: - fmt = "%s %s\n" + kwlabels = b"enabled deleted enabledunknown ignored ignoredunknown".split() + kwstates = zip(kwlabels, pycompat.bytestr(b"K!kIi"), showfiles) + fm = ui.formatter(b"kwfiles", opts) + fmt = b"%.0s%s\n" + if opts.get(b"all") or ui.verbose: + fmt = b"%s %s\n" for kwstate, char, filenames in kwstates: - label = "kwfiles." + kwstate + label = b"kwfiles." + kwstate for f in filenames: fm.startitem() fm.data(kwstatus=char, path=f) @@ -627,9 +627,9 @@ @command( - "kwshrink", + b"kwshrink", cmdutil.walkopts, - _("hg kwshrink [OPTION]... [FILE]..."), + _(b"hg kwshrink [OPTION]... [FILE]..."), inferrepo=True, ) def shrink(ui, repo, *pats, **opts): @@ -715,7 +715,7 @@ return orig(ui, repo, pats, opts, rename) with repo.wlock(): orig(ui, repo, pats, opts, rename) - if opts.get("dry_run"): + if opts.get(b"dry_run"): return wctx = repo[None] cwd = repo.getcwd() @@ -725,7 +725,7 @@ expansion or a symlink which points to a file configured for expansion. """ source = repo.dirstate.copied(dest) - if "l" in wctx.flags(source): + if b"l" in wctx.flags(source): source = pathutil.canonpath( repo.root, cwd, os.path.realpath(source) ) @@ -734,7 +734,7 @@ candidates = [ f for f in repo.dirstate.copies() - if "l" not in wctx.flags(f) and haskwsource(f) + if b"l" not in wctx.flags(f) and haskwsource(f) ] kwt.overwrite(wctx, candidates, False, False) @@ -748,10 +748,10 @@ # record returns 0 even when nothing has changed # therefore compare nodes before and after kwt.postcommit = True - ctx = repo["."] + ctx = repo[b"."] wstatus = ctx.status() ret = orig(ui, repo, commitfunc, *pats, **opts) - recctx = repo["."] + recctx = repo[b"."] if ctx != recctx: modified, added = _preselect(wstatus, recctx.files()) kwt.restrict = False @@ -774,7 +774,7 @@ and ( self._repo._encodefilterpats or kwt.match(fctx.path()) - and "l" not in fctx.flags() + and b"l" not in fctx.flags() or self.size() - 4 == fctx.size() ) or self.size() == fctx.size() @@ -794,17 +794,17 @@ def kwdispatch_parse(orig, ui, args): """Monkeypatch dispatch._parse to obtain running hg command.""" cmd, func, args, options, cmdoptions = orig(ui, args) - kwtools["hgcmd"] = cmd + kwtools[b"hgcmd"] = cmd return cmd, func, args, options, cmdoptions - extensions.wrapfunction(dispatch, "_parse", kwdispatch_parse) + extensions.wrapfunction(dispatch, b"_parse", kwdispatch_parse) - extensions.wrapfunction(context.filectx, "cmp", kwfilectx_cmp) - extensions.wrapfunction(patch.patchfile, "__init__", kwpatchfile_init) - extensions.wrapfunction(patch, "diff", kwdiff) - extensions.wrapfunction(cmdutil, "amend", kw_amend) - extensions.wrapfunction(cmdutil, "copy", kw_copy) - extensions.wrapfunction(cmdutil, "dorecord", kw_dorecord) + extensions.wrapfunction(context.filectx, b"cmp", kwfilectx_cmp) + extensions.wrapfunction(patch.patchfile, b"__init__", kwpatchfile_init) + extensions.wrapfunction(patch, b"diff", kwdiff) + extensions.wrapfunction(cmdutil, b"amend", kw_amend) + extensions.wrapfunction(cmdutil, b"copy", kw_copy) + extensions.wrapfunction(cmdutil, b"dorecord", kw_dorecord) for c in nokwwebcommands.split(): extensions.wrapfunction(webcommands, c, kwweb_skip) @@ -815,17 +815,17 @@ try: if ( not repo.local() - or kwtools["hgcmd"] in nokwcommands.split() - or ".hg" in util.splitpath(repo.root) - or repo._url.startswith("bundle:") + or kwtools[b"hgcmd"] in nokwcommands.split() + or b".hg" in util.splitpath(repo.root) + or repo._url.startswith(b"bundle:") ): return except AttributeError: pass - inc, exc = [], [".hg*"] - for pat, opt in ui.configitems("keyword"): - if opt != "ignore": + inc, exc = [], [b".hg*"] + for pat, opt in ui.configitems(b"keyword"): + if opt != b"ignore": inc.append(pat) else: exc.append(pat) @@ -836,7 +836,7 @@ class kwrepo(repo.__class__): def file(self, f): - if f[0] == "/": + if f[0] == b"/": f = f[1:] return kwfilelog(self.svfs, kwt, f) @@ -870,10 +870,10 @@ origrestrict = kwt.restrict try: if not dryrun: - changed = self["."].files() + changed = self[b"."].files() ret = super(kwrepo, self).rollback(dryrun, force) if not dryrun: - ctx = self["."] + ctx = self[b"."] modified, added = _preselect(ctx.status(), changed) kwt.restrict = False kwt.overwrite(ctx, modified, True, True) diff --git a/hgext/largefiles/__init__.py b/hgext/largefiles/__init__.py --- a/hgext/largefiles/__init__.py +++ b/hgext/largefiles/__init__.py @@ -128,7 +128,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" eh = exthelper.exthelper() eh.merge(lfcommands.eh) @@ -136,13 +136,13 @@ eh.merge(proto.eh) eh.configitem( - "largefiles", "minsize", default=eh.configitem.dynamicdefault, + b"largefiles", b"minsize", default=eh.configitem.dynamicdefault, ) eh.configitem( - "largefiles", "patterns", default=list, + b"largefiles", b"patterns", default=list, ) eh.configitem( - "largefiles", "usercache", default=None, + b"largefiles", b"usercache", default=None, ) cmdtable = eh.cmdtable @@ -154,7 +154,7 @@ def featuresetup(ui, supported): # don't die on seeing a repo with the largefiles requirement - supported |= {"largefiles"} + supported |= {b"largefiles"} @eh.uisetup @@ -162,25 +162,25 @@ localrepo.featuresetupfuncs.add(featuresetup) hg.wirepeersetupfuncs.append(proto.wirereposetup) - cmdutil.outgoinghooks.add("largefiles", overrides.outgoinghook) - cmdutil.summaryremotehooks.add("largefiles", overrides.summaryremotehook) + cmdutil.outgoinghooks.add(b"largefiles", overrides.outgoinghook) + cmdutil.summaryremotehooks.add(b"largefiles", overrides.summaryremotehook) # create the new wireproto commands ... - wireprotov1server.wireprotocommand("putlfile", "sha", permission="push")( + wireprotov1server.wireprotocommand(b"putlfile", b"sha", permission=b"push")( proto.putlfile ) - wireprotov1server.wireprotocommand("getlfile", "sha", permission="pull")( + wireprotov1server.wireprotocommand(b"getlfile", b"sha", permission=b"pull")( proto.getlfile ) - wireprotov1server.wireprotocommand("statlfile", "sha", permission="pull")( - proto.statlfile - ) - wireprotov1server.wireprotocommand("lheads", "", permission="pull")( + wireprotov1server.wireprotocommand( + b"statlfile", b"sha", permission=b"pull" + )(proto.statlfile) + wireprotov1server.wireprotocommand(b"lheads", b"", permission=b"pull")( wireprotov1server.heads ) extensions.wrapfunction( - wireprotov1server.commands["heads"], "func", proto.heads + wireprotov1server.commands[b"heads"], b"func", proto.heads ) # TODO also wrap wireproto.commandsv2 once heads is implemented there. @@ -193,9 +193,9 @@ # override some extensions' stuff as well for name, module in extensions.extensions(): - if name == "rebase": + if name == b"rebase": # TODO: teach exthelper to handle this - extensions.wrapfunction(module, "rebase", overrides.overriderebase) + extensions.wrapfunction(module, b"rebase", overrides.overriderebase) revsetpredicate = eh.revsetpredicate diff --git a/hgext/largefiles/basestore.py b/hgext/largefiles/basestore.py --- a/hgext/largefiles/basestore.py +++ b/hgext/largefiles/basestore.py @@ -27,7 +27,7 @@ self.detail = detail def longmessage(self): - return _("error getting id %s from url %s for file %s: %s\n") % ( + return _(b"error getting id %s from url %s for file %s: %s\n") % ( self.hash, util.hidepassword(self.url), self.filename, @@ -35,7 +35,7 @@ ) def __str__(self): - return "%s: %s" % (util.hidepassword(self.url), self.detail) + return b"%s: %s" % (util.hidepassword(self.url), self.detail) class basestore(object): @@ -46,12 +46,12 @@ def put(self, source, hash): """Put source file into the store so it can be retrieved by hash.""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") def exists(self, hashes): """Check to see if the store contains the given hashes. Given an iterable of hashes it returns a mapping from hash to bool.""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") def get(self, files): """Get the specified largefiles from the store and write to local @@ -69,16 +69,16 @@ at = 0 available = self.exists(set(hash for (_filename, hash) in files)) with ui.makeprogress( - _("getting largefiles"), unit=_("files"), total=len(files) + _(b"getting largefiles"), unit=_(b"files"), total=len(files) ) as progress: for filename, hash in files: progress.update(at) at += 1 - ui.note(_("getting %s:%s\n") % (filename, hash)) + ui.note(_(b"getting %s:%s\n") % (filename, hash)) if not available.get(hash): ui.warn( - _("%s: largefile %s not available from %s\n") + _(b"%s: largefile %s not available from %s\n") % (filename, hash, util.hidepassword(self.url)) ) missing.append(filename) @@ -96,10 +96,10 @@ store and in the usercache. filename is for informational messages only. """ - util.makedirs(lfutil.storepath(self.repo, "")) + util.makedirs(lfutil.storepath(self.repo, b"")) storefilename = lfutil.storepath(self.repo, hash) - tmpname = storefilename + ".tmp" + tmpname = storefilename + b".tmp" with util.atomictempfile( tmpname, createmode=self.repo.store.createmode ) as tmpfile: @@ -107,12 +107,12 @@ gothash = self._getfile(tmpfile, filename, hash) except StoreError as err: self.ui.warn(err.longmessage()) - gothash = "" + gothash = b"" if gothash != hash: - if gothash != "": + if gothash != b"": self.ui.warn( - _("%s: data corruption (expected %s, got %s)\n") + _(b"%s: data corruption (expected %s, got %s)\n") % (filename, hash, gothash) ) util.unlink(tmpname) @@ -128,13 +128,13 @@ Return 0 if all is well, non-zero on any errors.""" self.ui.status( - _("searching %d changesets for largefiles\n") % len(revs) + _(b"searching %d changesets for largefiles\n") % len(revs) ) verified = set() # set of (filename, filenode) tuples filestocheck = [] # list of (cset, filename, expectedhash) for rev in revs: cctx = self.repo[rev] - cset = "%d:%s" % (cctx.rev(), node.short(cctx.node())) + cset = b"%d:%s" % (cctx.rev(), node.short(cctx.node())) for standin in cctx: filename = lfutil.splitstandin(standin) @@ -152,12 +152,12 @@ numlfiles = len({fname for (fname, fnode) in verified}) if contents: self.ui.status( - _("verified contents of %d revisions of %d largefiles\n") + _(b"verified contents of %d revisions of %d largefiles\n") % (numrevs, numlfiles) ) else: self.ui.status( - _("verified existence of %d revisions of %d largefiles\n") + _(b"verified existence of %d revisions of %d largefiles\n") % (numrevs, numlfiles) ) return int(failed) @@ -168,7 +168,7 @@ downloads and return the hash. Close tmpfile. Raise StoreError if unable to download the file (e.g. it does not exist in the store).""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") def _verifyfiles(self, contents, filestocheck): """Perform the actual verification of files in the store. @@ -176,4 +176,4 @@ 'filestocheck' is list of files to check. Returns _true_ if any problems are found! """ - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py --- a/hgext/largefiles/lfcommands.py +++ b/hgext/largefiles/lfcommands.py @@ -45,23 +45,23 @@ @eh.command( - "lfconvert", + b"lfconvert", [ ( - "s", - "size", - "", - _("minimum size (MB) for files to be converted as largefiles"), - "SIZE", + b"s", + b"size", + b"", + _(b"minimum size (MB) for files to be converted as largefiles"), + b"SIZE", ), ( - "", - "to-normal", + b"", + b"to-normal", False, - _("convert from a largefiles repo to a normal repo"), + _(b"convert from a largefiles repo to a normal repo"), ), ], - _("hg lfconvert SOURCE DEST [FILE ...]"), + _(b"hg lfconvert SOURCE DEST [FILE ...]"), norepo=True, inferrepo=True, ) @@ -85,19 +85,19 @@ this, the DEST repository can be used without largefiles at all.""" opts = pycompat.byteskwargs(opts) - if opts["to_normal"]: + if opts[b"to_normal"]: tolfile = False else: tolfile = True - size = lfutil.getminsize(ui, True, opts.get("size"), default=None) + size = lfutil.getminsize(ui, True, opts.get(b"size"), default=None) if not hg.islocal(src): - raise error.Abort(_("%s is not a local Mercurial repo") % src) + raise error.Abort(_(b"%s is not a local Mercurial repo") % src) if not hg.islocal(dest): - raise error.Abort(_("%s is not a local Mercurial repo") % dest) + raise error.Abort(_(b"%s is not a local Mercurial repo") % dest) rsrc = hg.repository(ui, src) - ui.status(_("initializing destination %s\n") % dest) + ui.status(_(b"initializing destination %s\n") % dest) rdst = hg.repository(ui, dest, create=True) success = False @@ -122,17 +122,17 @@ lfiles = set() normalfiles = set() if not pats: - pats = ui.configlist(lfutil.longname, "patterns") + pats = ui.configlist(lfutil.longname, b"patterns") if pats: - matcher = matchmod.match(rsrc.root, "", list(pats)) + matcher = matchmod.match(rsrc.root, b"", list(pats)) else: matcher = None lfiletohash = {} with ui.makeprogress( - _("converting revisions"), - unit=_("revisions"), - total=rsrc["tip"].rev(), + _(b"converting revisions"), + unit=_(b"revisions"), + total=rsrc[b"tip"].rev(), ) as progress: for ctx in ctxs: progress.update(ctx.rev()) @@ -162,14 +162,14 @@ # If there were any files converted to largefiles, add largefiles # to the destination repository's requirements. if lfiles: - rdst.requirements.add("largefiles") + rdst.requirements.add(b"largefiles") rdst._writerequirements() else: class lfsource(filemap.filemap_source): def __init__(self, ui, source): super(lfsource, self).__init__(ui, source, None) - self.filemapper.rename[lfutil.shortname] = "." + self.filemapper.rename[lfutil.shortname] = b"." def getfile(self, name, rev): realname, realrev = rev @@ -187,7 +187,7 @@ if path is None: raise error.Abort( - _("missing largefile for '%s' in %s") + _(b"missing largefile for '%s' in %s") % (realname, realrev) ) return util.readfile(path), f[1] @@ -202,13 +202,15 @@ found, missing = downloadlfiles(ui, rsrc) if missing != 0: - raise error.Abort(_("all largefiles must be present locally")) + raise error.Abort(_(b"all largefiles must be present locally")) orig = convcmd.converter convcmd.converter = converter try: - convcmd.convert(ui, src, dest, source_type="hg", dest_type="hg") + convcmd.convert( + ui, src, dest, source_type=b"hg", dest_type=b"hg" + ) finally: convcmd.converter = orig success = True @@ -245,10 +247,11 @@ renamed = False renamedlfile = renamed and renamed in lfiles islfile |= renamedlfile - if "l" in fctx.flags(): + if b"l" in fctx.flags(): if renamedlfile: raise error.Abort( - _("renamed/copied largefile %s becomes symlink") % f + _(b"renamed/copied largefile %s becomes symlink") + % f ) islfile = False if islfile: @@ -262,18 +265,20 @@ # largefile in manifest if it has not been removed/renamed if f in ctx.manifest(): fctx = ctx.filectx(f) - if "l" in fctx.flags(): + if b"l" in fctx.flags(): renamed = fctx.copysource() if renamed and renamed in lfiles: - raise error.Abort(_("largefile %s becomes symlink") % f) + raise error.Abort( + _(b"largefile %s becomes symlink") % f + ) # largefile was modified, update standins - m = hashlib.sha1("") + m = hashlib.sha1(b"") m.update(ctx[f].data()) hash = node.hex(m.digest()) if f not in lfiletohash or lfiletohash[f] != hash: rdst.wwrite(f, ctx[f].data(), ctx[f].flags()) - executable = "x" in ctx[f].flags() + executable = b"x" in ctx[f].flags() lfutil.writestandin(rdst, fstandin, hash, executable) lfiletohash[f] = hash else: @@ -299,9 +304,9 @@ repo, memctx, f, - lfiletohash[srcfname] + "\n", - "l" in fctx.flags(), - "x" in fctx.flags(), + lfiletohash[srcfname] + b"\n", + b"l" in fctx.flags(), + b"x" in fctx.flags(), renamed, ) else: @@ -358,10 +363,10 @@ renamed = fctx.copysource() data = fctx.data() - if f == ".hgtags": + if f == b".hgtags": data = _converttags(repo.ui, revmap, data) return context.memfilectx( - repo, ctx, f, data, "l" in fctx.flags(), "x" in fctx.flags(), renamed + repo, ctx, f, data, b"l" in fctx.flags(), b"x" in fctx.flags(), renamed ) @@ -370,28 +375,28 @@ newdata = [] for line in data.splitlines(): try: - id, name = line.split(" ", 1) + id, name = line.split(b" ", 1) except ValueError: - ui.warn(_("skipping incorrectly formatted tag %s\n") % line) + ui.warn(_(b"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(_(b"skipping incorrectly formatted id %s\n") % id) continue try: - newdata.append("%s %s\n" % (node.hex(revmap[newid]), name)) + newdata.append(b"%s %s\n" % (node.hex(revmap[newid]), name)) except KeyError: - ui.warn(_("no mapping for id %s\n") % id) + ui.warn(_(b"no mapping for id %s\n") % id) continue - return "".join(newdata) + return b"".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.""" # never store special .hg* files as largefiles - if file == ".hgtags" or file == ".hgignore" or file == ".hgsigs": + if file == b".hgtags" or file == b".hgignore" or file == b".hgsigs": return False if matcher and matcher(file): return True @@ -410,13 +415,13 @@ store = storefactory.openstore(rsrc, rdst, put=True) at = 0 - ui.debug("sending statlfile command for %d largefiles\n" % len(files)) + ui.debug(b"sending statlfile command for %d largefiles\n" % len(files)) retval = store.exists(files) files = [h for h in files if not retval[h]] - ui.debug("%d largefiles need to be uploaded\n" % len(files)) + ui.debug(b"%d largefiles need to be uploaded\n" % len(files)) with ui.makeprogress( - _("uploading largefiles"), unit=_("files"), total=len(files) + _(b"uploading largefiles"), unit=_(b"files"), total=len(files) ) as progress: for hash in files: progress.update(at) @@ -424,8 +429,8 @@ if not source: raise error.Abort( _( - "largefile %s missing from store" - " (needs to be uploaded)" + b"largefile %s missing from store" + b" (needs to be uploaded)" ) % hash ) @@ -441,9 +446,9 @@ matches the revision ID). With --all, check every changeset in this repository.""" if all: - revs = repo.revs("all()") + revs = repo.revs(b"all()") else: - revs = ["."] + revs = [b"."] store = storefactory.openstore(repo) return store.verify(revs, contents=contents) @@ -489,13 +494,13 @@ totalsuccess = 0 totalmissing = 0 if rev != []: # walkchangerevs on empty list would return all revs - for ctx in cmdutil.walkchangerevs(repo, match, {"rev": rev}, prepare): + for ctx in cmdutil.walkchangerevs(repo, match, {b"rev": rev}, prepare): success, missing = cachelfiles(ui, repo, ctx.node()) totalsuccess += len(success) totalmissing += len(missing) - ui.status(_("%d additional largefiles cached\n") % totalsuccess) + ui.status(_(b"%d additional largefiles cached\n") % totalsuccess) if totalmissing > 0: - ui.status(_("%d largefiles failed to download\n") % totalmissing) + ui.status(_(b"%d largefiles failed to download\n") % totalmissing) return totalsuccess, totalmissing @@ -534,9 +539,9 @@ shutil.copyfile(wvfs.join(lfile), wvfs.join(lfileorig)) wvfs.unlinkpath(standinorig) expecthash = lfutil.readasstandin(wctx[standin]) - if expecthash != "": + if expecthash != b"": if lfile not in wctx: # not switched to normal file - if repo.dirstate[standin] != "?": + if repo.dirstate[standin] != b"?": wvfs.unlinkpath(lfile, ignoremissing=True) else: dropped.add(lfile) @@ -571,7 +576,7 @@ # the M state. lfutil.synclfdirstate(repo, lfdirstate, f, normallookup) - statuswriter(_("getting changed largefiles\n")) + statuswriter(_(b"getting changed largefiles\n")) cachelfiles(ui, repo, None, lfiles) for lfile in lfiles: @@ -610,17 +615,17 @@ lfdirstate.write() if lfiles: statuswriter( - _("%d largefiles updated, %d removed\n") % (updated, removed) + _(b"%d largefiles updated, %d removed\n") % (updated, removed) ) @eh.command( - "lfpull", - [("r", "rev", [], _("pull largefiles for these revisions"))] + b"lfpull", + [(b"r", b"rev", [], _(b"pull largefiles for these revisions"))] + cmdutil.remoteopts, - _("-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]"), + _(b"-r REV... [-e CMD] [--remotecmd CMD] [SOURCE]"), ) -def lfpull(ui, repo, source="default", **opts): +def lfpull(ui, repo, source=b"default", **opts): """pull largefiles for the specified revisions from the specified source Pull largefiles that are referenced from local changesets but missing @@ -645,20 +650,20 @@ revs = opts.get(r"rev", []) if not revs: - raise error.Abort(_("no revisions specified")) + raise error.Abort(_(b"no revisions specified")) revs = scmutil.revrange(repo, revs) numcached = 0 for rev in revs: - ui.note(_("pulling largefiles for revision %d\n") % rev) + ui.note(_(b"pulling largefiles for revision %d\n") % rev) (cached, missing) = cachelfiles(ui, repo, rev) numcached += len(cached) - ui.status(_("%d largefiles cached\n") % numcached) + ui.status(_(b"%d largefiles cached\n") % numcached) -@eh.command("debuglfput", [] + cmdutil.remoteopts, _("FILE")) +@eh.command(b"debuglfput", [] + cmdutil.remoteopts, _(b"FILE")) def debuglfput(ui, repo, filepath, **kwargs): hash = lfutil.hashfile(filepath) storefactory.openstore(repo).put(filepath, hash) - ui.write("%s\n" % hash) + ui.write(b"%s\n" % hash) return 0 diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py --- a/hgext/largefiles/lfutil.py +++ b/hgext/largefiles/lfutil.py @@ -31,9 +31,9 @@ vfs as vfsmod, ) -shortname = ".hglf" -shortnameslash = shortname + "/" -longname = "largefiles" +shortname = b".hglf" +shortnameslash = shortname + b"/" +longname = b"largefiles" # -- Private worker functions ------------------------------------------ @@ -41,16 +41,16 @@ def getminsize(ui, assumelfiles, opt, default=10): lfsize = opt if not lfsize and assumelfiles: - lfsize = ui.config(longname, "minsize", default=default) + lfsize = ui.config(longname, b"minsize", default=default) if lfsize: try: lfsize = float(lfsize) except ValueError: raise error.Abort( - _("largefiles: size must be number (not %s)\n") % lfsize + _(b"largefiles: size must be number (not %s)\n") % lfsize ) if lfsize is None: - raise error.Abort(_("minimum size for largefiles must be specified")) + raise error.Abort(_(b"minimum size for largefiles must be specified")) return lfsize @@ -61,7 +61,7 @@ util.oslink(src, dest) except OSError: # if hardlinks fail, fallback on atomic copy - with open(src, "rb") as srcf, util.atomictempfile(dest) as dstf: + with open(src, b"rb") as srcf, util.atomictempfile(dest) as dstf: for chunk in util.filechunkiter(srcf): dstf.write(chunk) os.chmod(dest, os.stat(src).st_mode) @@ -77,29 +77,31 @@ def _usercachedir(ui, name=longname): """Return the location of the "global" largefiles cache.""" - path = ui.configpath(name, "usercache") + path = ui.configpath(name, b"usercache") if path: return path if pycompat.iswindows: appdata = encoding.environ.get( - "LOCALAPPDATA", encoding.environ.get("APPDATA") + b"LOCALAPPDATA", encoding.environ.get(b"APPDATA") ) if appdata: return os.path.join(appdata, name) elif pycompat.isdarwin: - home = encoding.environ.get("HOME") + home = encoding.environ.get(b"HOME") if home: - return os.path.join(home, "Library", "Caches", name) + return os.path.join(home, b"Library", b"Caches", name) elif pycompat.isposix: - path = encoding.environ.get("XDG_CACHE_HOME") + path = encoding.environ.get(b"XDG_CACHE_HOME") if path: return os.path.join(path, name) - home = encoding.environ.get("HOME") + home = encoding.environ.get(b"HOME") if home: - return os.path.join(home, ".cache", name) + return os.path.join(home, b".cache", name) else: - raise error.Abort(_("unknown operating system: %s\n") % pycompat.osname) - raise error.Abort(_("unknown %s usercache location") % name) + raise error.Abort( + _(b"unknown operating system: %s\n") % pycompat.osname + ) + raise error.Abort(_(b"unknown %s usercache location") % name) def inusercache(ui, hash): @@ -113,10 +115,10 @@ Return None if the file can't be found locally.""" path, exists = findstorepath(repo, hash) if exists: - repo.ui.note(_("found %s in store\n") % hash) + repo.ui.note(_(b"found %s in store\n") % hash) return path elif inusercache(repo.ui, hash): - repo.ui.note(_("found %s in system cache\n") % hash) + repo.ui.note(_(b"found %s in system cache\n") % hash) path = storepath(repo, hash) link(usercachepath(repo.ui, hash), path) return path @@ -174,7 +176,7 @@ # If the largefiles dirstate does not exist, populate and create # it. This ensures that we create it on the first meaningful # largefiles operation in a new clone. - if create and not vfs.exists(vfs.join(lfstoredir, "dirstate")): + if create and not vfs.exists(vfs.join(lfstoredir, b"dirstate")): matcher = getstandinmatcher(repo) standins = repo.dirstate.walk( matcher, subrepos=[], unknown=False, ignored=False @@ -190,7 +192,7 @@ def lfdirstatestatus(lfdirstate, repo): - pctx = repo["."] + pctx = repo[b"."] match = matchmod.always() unsure, s = lfdirstate.status( match, subrepos=[], ignored=False, clean=False, unknown=False @@ -220,7 +222,7 @@ return [ splitstandin(f) for f in repo[rev].walk(matcher) - if rev is not None or repo.dirstate[f] != "?" + if rev is not None or repo.dirstate[f] != b"?" ] @@ -268,11 +270,11 @@ wvfs.makedirs(wvfs.dirname(wvfs.join(filename))) # The write may fail before the file is fully written, but we # don't use atomic writes in the working copy. - with open(path, "rb") as srcfd, wvfs(filename, "wb") as destfd: + with open(path, b"rb") as srcfd, wvfs(filename, b"wb") as destfd: gothash = copyandhash(util.filechunkiter(srcfd), destfd) if gothash != hash: repo.ui.warn( - _("%s: data corruption in %s with hash %s\n") + _(b"%s: data corruption in %s with hash %s\n") % (filename, path, gothash) ) wvfs.unlink(filename) @@ -289,7 +291,7 @@ copytostoreabsolute(repo, wvfs.join(file), hash) else: repo.ui.warn( - _("%s: largefile %s not available from local store\n") + _(b"%s: largefile %s not available from local store\n") % (file, hash) ) @@ -309,7 +311,7 @@ link(usercachepath(repo.ui, hash), storepath(repo, hash)) else: util.makedirs(os.path.dirname(storepath(repo, hash))) - with open(file, "rb") as srcf: + with open(file, b"rb") as srcf: with util.atomictempfile( storepath(repo, hash), createmode=repo.store.createmode ) as dstf: @@ -382,7 +384,7 @@ # Split on / because that's what dirstate always uses, even on Windows. # Change local separator to / first just in case we are passed filenames # from an external source (like the command line). - bits = util.pconvert(filename).split("/", 1) + bits = util.pconvert(filename).split(b"/", 1) if len(bits) == 2 and bits[0] == shortname: return bits[1] else: @@ -400,7 +402,7 @@ executable = getexecutable(file) writestandin(repo, standin, hash, executable) else: - raise error.Abort(_("%s: file not found!") % lfile) + raise error.Abort(_(b"%s: file not found!") % lfile) def readasstandin(fctx): @@ -412,13 +414,13 @@ def writestandin(repo, standin, hash, executable): """write hash to /""" - repo.wwrite(standin, hash + "\n", executable and "x" or "") + repo.wwrite(standin, hash + b"\n", executable and b"x" or b"") def copyandhash(instream, outfile): """Read bytes from instream (iterable) and write them to outfile, computing the SHA-1 hash of the data along the way. Return the hash.""" - hasher = hashlib.sha1("") + hasher = hashlib.sha1(b"") for data in instream: hasher.update(data) outfile.write(data) @@ -427,8 +429,8 @@ def hashfile(file): if not os.path.exists(file): - return "" - with open(file, "rb") as fd: + return b"" + with open(file, b"rb") as fd: return hexsha1(fd) @@ -443,9 +445,9 @@ def urljoin(first, second, *arg): def join(left, right): - if not left.endswith("/"): - left += "/" - if right.startswith("/"): + if not left.endswith(b"/"): + left += b"/" + if right.startswith(b"/"): right = right[1:] return left + right @@ -465,7 +467,7 @@ def httpsendfile(ui, filename): - return httpconnection.httpsendfile(ui, filename, "rb") + return httpconnection.httpsendfile(ui, filename, b"rb") def unixpath(path): @@ -475,7 +477,7 @@ def islfilesrepo(repo): """Return true if the repo is a largefile repo.""" - if "largefiles" in repo.requirements and any( + if b"largefiles" in repo.requirements and any( shortnameslash in f[0] for f in repo.store.datafiles() ): return True @@ -510,20 +512,20 @@ stat = repo.dirstate._map[lfstandin] state, mtime = stat[0], stat[3] else: - state, mtime = "?", -1 - if state == "n": + state, mtime = b"?", -1 + if state == b"n": if normallookup or mtime < 0 or not repo.wvfs.exists(lfile): # state 'n' doesn't ensure 'clean' in this case lfdirstate.normallookup(lfile) else: lfdirstate.normal(lfile) - elif state == "m": + elif state == b"m": lfdirstate.normallookup(lfile) - elif state == "r": + elif state == b"r": lfdirstate.remove(lfile) - elif state == "a": + elif state == b"a": lfdirstate.add(lfile) - elif state == "?": + elif state == b"?": lfdirstate.drop(lfile) @@ -569,8 +571,8 @@ def getlfilestoupload(repo, missing, addfunc): makeprogress = repo.ui.makeprogress with makeprogress( - _("finding outgoing largefiles"), - unit=_("revisions"), + _(b"finding outgoing largefiles"), + unit=_(b"revisions"), total=len(missing), ) as progress: for i, n in enumerate(missing): @@ -665,7 +667,7 @@ lfdirstate = openlfdirstate(ui, repo) for fstandin in standins: lfile = splitstandin(fstandin) - if lfdirstate[lfile] != "r": + if lfdirstate[lfile] != b"r": updatestandin(repo, lfile, fstandin) # Cook up a new matcher that only matches regular files or @@ -689,10 +691,10 @@ # standin removal, drop the normal file if it is unknown to dirstate. # Thus, skip plain largefile names but keep the standin. if f in lfiles or fstandin in standins: - if repo.dirstate[fstandin] != "r": - if repo.dirstate[f] != "r": + if repo.dirstate[fstandin] != b"r": + if repo.dirstate[f] != b"r": continue - elif repo.dirstate[f] == "?": + elif repo.dirstate[f] == b"?": continue actualfiles.append(f) @@ -741,7 +743,7 @@ Otherwise, this returns the function to always write out (or ignore if ``not forcibly``) status. """ - if forcibly is None and util.safehasattr(repo, "_largefilesenabled"): + if forcibly is None and util.safehasattr(repo, b"_largefilesenabled"): return repo._lfstatuswriters[-1] else: if forcibly: diff --git a/hgext/largefiles/localstore.py b/hgext/largefiles/localstore.py --- a/hgext/largefiles/localstore.py +++ b/hgext/largefiles/localstore.py @@ -42,9 +42,9 @@ path = lfutil.findfile(self.remote, hash) if not path: raise basestore.StoreError( - filename, hash, self.url, _("can't get file locally") + filename, hash, self.url, _(b"can't get file locally") ) - with open(path, "rb") as fd: + with open(path, b"rb") as fd: return lfutil.copyandhash(util.filechunkiter(fd), tmpfile) def _verifyfiles(self, contents, filestocheck): @@ -57,7 +57,7 @@ ) if not exists: self.ui.warn( - _("changeset %s: %s references missing %s\n") + _(b"changeset %s: %s references missing %s\n") % (cset, filename, storepath) ) failed = True @@ -65,7 +65,7 @@ actualhash = lfutil.hashfile(storepath) if actualhash != expectedhash: self.ui.warn( - _("changeset %s: %s references corrupted %s\n") + _(b"changeset %s: %s references corrupted %s\n") % (cset, filename, storepath) ) failed = True diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py +++ b/hgext/largefiles/overrides.py @@ -88,9 +88,9 @@ lfmatcher = None if lfutil.islfilesrepo(repo): - lfpats = ui.configlist(lfutil.longname, "patterns") + lfpats = ui.configlist(lfutil.longname, b"patterns") if lfpats: - lfmatcher = matchmod.match(repo.root, "", list(lfpats)) + lfmatcher = matchmod.match(repo.root, b"", list(lfpats)) lfnames = [] m = matcher @@ -106,7 +106,7 @@ # The normal add code will do that for us. if exact and exists: if lfile: - ui.warn(_("%s already a largefile\n") % uipathfn(f)) + ui.warn(_(b"%s already a largefile\n") % uipathfn(f)) continue if (exact or not exists) and not lfutil.isstandin(f): @@ -121,7 +121,7 @@ if large or abovemin or (lfmatcher and lfmatcher(f)): lfnames.append(f) if ui.verbose or not exact: - ui.status(_("adding %s as a largefile\n") % uipathfn(f)) + ui.status(_(b"adding %s as a largefile\n") % uipathfn(f)) bad = [] @@ -136,11 +136,11 @@ lfutil.writestandin( repo, standinname, - hash="", + hash=b"", executable=lfutil.getexecutable(repo.wjoin(f)), ) standins.append(standinname) - if lfdirstate[f] == "r": + if lfdirstate[f] == b"r": lfdirstate.normallookup(f) else: lfdirstate.add(f) @@ -177,23 +177,23 @@ if after: remove = deleted result = warn( - modified + added + clean, _("not removing %s: file still exists\n") + modified + added + clean, _(b"not removing %s: file still exists\n") ) else: remove = deleted + clean result = warn( modified, _( - "not removing %s: file is modified (use -f" - " to force removal)\n" + b"not removing %s: file is modified (use -f" + b" to force removal)\n" ), ) result = ( warn( added, _( - "not removing %s: file has been marked for add" - " (use forget to undo)\n" + b"not removing %s: file has been marked for add" + b" (use forget to undo)\n" ), ) or result @@ -205,7 +205,7 @@ lfdirstate = lfutil.openlfdirstate(ui, repo) for f in sorted(remove): if ui.verbose or not m.exact(f): - ui.status(_("removing %s\n") % uipathfn(f)) + ui.status(_(b"removing %s\n") % uipathfn(f)) if not dryrun: if not after: @@ -234,7 +234,7 @@ # For overriding mercurial.hgweb.webcommands so that largefiles will # appear at their right place in the manifests. -@eh.wrapfunction(webcommands, "decodepath") +@eh.wrapfunction(webcommands, b"decodepath") def decodepath(orig, path): return lfutil.splitstandin(path) or path @@ -243,28 +243,28 @@ @eh.wrapcommand( - "add", + b"add", opts=[ - ("", "large", None, _("add as largefile")), - ("", "normal", None, _("add as normal file")), + (b"", b"large", None, _(b"add as largefile")), + (b"", b"normal", None, _(b"add as normal file")), ( - "", - "lfsize", - "", + b"", + b"lfsize", + b"", _( - "add all files above this size (in megabytes) " - "as largefiles (default: 10)" + b"add all files above this size (in megabytes) " + b"as largefiles (default: 10)" ), ), ], ) def overrideadd(orig, ui, repo, *pats, **opts): if opts.get(r"normal") and opts.get(r"large"): - raise error.Abort(_("--normal cannot be used with --large")) + raise error.Abort(_(b"--normal cannot be used with --large")) return orig(ui, repo, *pats, **opts) -@eh.wrapfunction(cmdutil, "add") +@eh.wrapfunction(cmdutil, b"add") def cmdutiladd(orig, ui, repo, matcher, prefix, uipathfn, explicitonly, **opts): # The --normal flag short circuits this override if opts.get(r"normal"): @@ -280,7 +280,7 @@ return bad -@eh.wrapfunction(cmdutil, "remove") +@eh.wrapfunction(cmdutil, b"remove") def cmdutilremove( orig, ui, repo, matcher, prefix, uipathfn, after, force, subrepos, dryrun ): @@ -304,7 +304,7 @@ ) -@eh.wrapfunction(subrepo.hgsubrepo, "status") +@eh.wrapfunction(subrepo.hgsubrepo, b"status") def overridestatusfn(orig, repo, rev2, **opts): try: repo._repo.lfstatus = True @@ -313,7 +313,7 @@ repo._repo.lfstatus = False -@eh.wrapcommand("status") +@eh.wrapcommand(b"status") def overridestatus(orig, ui, repo, *pats, **opts): try: repo.lfstatus = True @@ -322,7 +322,7 @@ repo.lfstatus = False -@eh.wrapfunction(subrepo.hgsubrepo, "dirty") +@eh.wrapfunction(subrepo.hgsubrepo, b"dirty") def overridedirty(orig, repo, ignoreupdate=False, missing=False): try: repo._repo.lfstatus = True @@ -331,7 +331,7 @@ repo._repo.lfstatus = False -@eh.wrapcommand("log") +@eh.wrapcommand(b"log") def overridelog(orig, ui, repo, *pats, **opts): def overridematchandpats( orig, @@ -339,7 +339,7 @@ pats=(), opts=None, globbed=False, - default="relpath", + default=b"relpath", badfn=None, ): """Matcher that merges root directory with .hglf, suitable for log. @@ -360,13 +360,13 @@ pats = set(p) def fixpats(pat, tostandin=lfutil.standin): - if pat.startswith("set:"): + if pat.startswith(b"set:"): return pat kindpat = matchmod._patsplit(pat, None) if kindpat[0] is not None: - return kindpat[0] + ":" + tostandin(kindpat[1]) + return kindpat[0] + b":" + tostandin(kindpat[1]) return tostandin(kindpat[1]) cwd = repo.getcwd() @@ -388,7 +388,7 @@ if os.path.isabs(cwd): f = f[len(back) :] else: - f = cwd + "/" + f + f = cwd + b"/" + f return back + lfutil.standin(f) else: @@ -402,7 +402,7 @@ for i in range(0, len(m._files)): # Don't add '.hglf' to m.files, since that is already covered by '.' - if m._files[i] == ".": + if m._files[i] == b".": continue standin = lfutil.standin(m._files[i]) # If the "standin" is a directory, append instead of replace to @@ -427,7 +427,7 @@ m.matchfn = lfmatchfn - ui.debug("updated patterns: %s\n" % ", ".join(sorted(pats))) + ui.debug(b"updated patterns: %s\n" % b", ".join(sorted(pats))) return m, pats # For hg log --patch, the match object is used in two different senses: @@ -443,35 +443,35 @@ return lambda ctx: match wrappedmatchandpats = extensions.wrappedfunction( - scmutil, "matchandpats", overridematchandpats + scmutil, b"matchandpats", overridematchandpats ) wrappedmakefilematcher = extensions.wrappedfunction( - logcmdutil, "_makenofollowfilematcher", overridemakefilematcher + logcmdutil, b"_makenofollowfilematcher", overridemakefilematcher ) with wrappedmatchandpats, wrappedmakefilematcher: return orig(ui, repo, *pats, **opts) @eh.wrapcommand( - "verify", + b"verify", opts=[ ( - "", - "large", + b"", + b"large", None, - _("verify that all largefiles in current revision exists"), + _(b"verify that all largefiles in current revision exists"), ), ( - "", - "lfa", + b"", + b"lfa", None, - _("verify largefiles in all revisions, not just current"), + _(b"verify largefiles in all revisions, not just current"), ), ( - "", - "lfc", + b"", + b"lfc", None, - _("verify local largefile contents, not just existence"), + _(b"verify local largefile contents, not just existence"), ), ], ) @@ -487,7 +487,8 @@ @eh.wrapcommand( - "debugstate", opts=[("", "large", None, _("display largefiles dirstate"))] + b"debugstate", + opts=[(b"", b"large", None, _(b"display largefiles dirstate"))], ) def overridedebugstate(orig, ui, repo, *pats, **opts): large = opts.pop(r"large", False) @@ -511,7 +512,7 @@ # The overridden function filters the unknown files by removing any # largefiles. This makes the merge proceed and we can then handle this # case further in the overridden calculateupdates function below. -@eh.wrapfunction(merge, "_checkunknownfile") +@eh.wrapfunction(merge, b"_checkunknownfile") def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None): if lfutil.standin(repo.dirstate.normalize(f)) in wctx: return False @@ -544,7 +545,7 @@ # Finally, the merge.applyupdates function will then take care of # writing the files into the working copy and lfcommands.updatelfiles # will update the largefiles. -@eh.wrapfunction(merge, "calculateupdates") +@eh.wrapfunction(merge, b"calculateupdates") def overridecalculateupdates( origfn, repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs ): @@ -569,71 +570,71 @@ standin = lfutil.standin(lfile) (lm, largs, lmsg) = actions.get(lfile, (None, None, None)) (sm, sargs, smsg) = actions.get(standin, (None, None, None)) - if sm in ("g", "dc") and lm != "r": - if sm == "dc": + if sm in (b"g", b"dc") and lm != b"r": + if sm == b"dc": f1, f2, fa, move, anc = sargs sargs = (p2[f2].flags(), False) # Case 1: normal file in the working copy, largefile in # the second parent usermsg = ( _( - "remote turned local normal file %s into a largefile\n" - "use (l)argefile or keep (n)ormal file?" - "$$ &Largefile $$ &Normal file" + b"remote turned local normal file %s into a largefile\n" + b"use (l)argefile or keep (n)ormal file?" + b"$$ &Largefile $$ &Normal file" ) % lfile ) if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile - actions[lfile] = ("r", None, "replaced by standin") - actions[standin] = ("g", sargs, "replaces standin") + actions[lfile] = (b"r", None, b"replaced by standin") + actions[standin] = (b"g", sargs, b"replaces standin") else: # keep local normal file - actions[lfile] = ("k", None, "replaces standin") + actions[lfile] = (b"k", None, b"replaces standin") if branchmerge: - actions[standin] = ("k", None, "replaced by non-standin") + actions[standin] = (b"k", None, b"replaced by non-standin") else: - actions[standin] = ("r", None, "replaced by non-standin") - elif lm in ("g", "dc") and sm != "r": - if lm == "dc": + actions[standin] = (b"r", None, b"replaced by non-standin") + elif lm in (b"g", b"dc") and sm != b"r": + if lm == b"dc": f1, f2, fa, move, anc = largs largs = (p2[f2].flags(), False) # Case 2: largefile in the working copy, normal file in # the second parent usermsg = ( _( - "remote turned local largefile %s into a normal file\n" - "keep (l)argefile or use (n)ormal file?" - "$$ &Largefile $$ &Normal file" + b"remote turned local largefile %s into a normal file\n" + b"keep (l)argefile or use (n)ormal file?" + b"$$ &Largefile $$ &Normal file" ) % lfile ) if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile if branchmerge: # largefile can be restored from standin safely - actions[lfile] = ("k", None, "replaced by standin") - actions[standin] = ("k", None, "replaces standin") + actions[lfile] = (b"k", None, b"replaced by standin") + actions[standin] = (b"k", None, b"replaces standin") else: # "lfile" should be marked as "removed" without # removal of itself actions[lfile] = ( - "lfmr", + b"lfmr", None, - "forget non-standin largefile", + b"forget non-standin largefile", ) # linear-merge should treat this largefile as 're-added' - actions[standin] = ("a", None, "keep standin") + actions[standin] = (b"a", None, b"keep standin") else: # pick remote normal file - actions[lfile] = ("g", largs, "replaces standin") - actions[standin] = ("r", None, "replaced by non-standin") + actions[lfile] = (b"g", largs, b"replaces standin") + actions[standin] = (b"r", None, b"replaced by non-standin") return actions, diverge, renamedelete -@eh.wrapfunction(merge, "recordupdates") +@eh.wrapfunction(merge, b"recordupdates") def mergerecordupdates(orig, repo, actions, branchmerge, getfiledata): - if "lfmr" in actions: + if b"lfmr" in actions: lfdirstate = lfutil.openlfdirstate(repo.ui, repo) - for lfile, args, msg in actions["lfmr"]: + for lfile, args, msg in actions[b"lfmr"]: # this should be executed before 'orig', to execute 'remove' # before all other actions repo.dirstate.remove(lfile) @@ -646,7 +647,7 @@ # Override filemerge to prompt the user about how they wish to merge # largefiles. This will handle identical edits without prompting the user. -@eh.wrapfunction(filemerge, "_filemerge") +@eh.wrapfunction(filemerge, b"_filemerge") def overridefilemerge( origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None ): @@ -665,10 +666,10 @@ dhash == ahash or repo.ui.promptchoice( _( - "largefile %s has a merge conflict\nancestor was %s\n" - "you can keep (l)ocal %s or take (o)ther %s.\n" - "what do you want to do?" - "$$ &Local $$ &Other" + b"largefile %s has a merge conflict\nancestor was %s\n" + b"you can keep (l)ocal %s or take (o)ther %s.\n" + b"what do you want to do?" + b"$$ &Local $$ &Other" ) % (lfutil.splitstandin(orig), ahash, dhash, ohash), 0, @@ -680,7 +681,7 @@ return True, 0, False -@eh.wrapfunction(copiesmod, "pathcopies") +@eh.wrapfunction(copiesmod, b"pathcopies") def copiespathcopies(orig, ctx1, ctx2, match=None): copies = orig(ctx1, ctx2, match=match) updated = {} @@ -696,7 +697,7 @@ # checks if the destination largefile already exists. It also keeps a # list of copied files so that the largefiles can be copied and the # dirstate updated. -@eh.wrapfunction(cmdutil, "copy") +@eh.wrapfunction(cmdutil, b"copy") def overridecopy(orig, ui, repo, pats, opts, rename=False): # doesn't remove largefile on rename if len(pats) < 2: @@ -717,7 +718,7 @@ pats=(), opts=None, globbed=False, - default="relpath", + default=b"relpath", badfn=None, ): if opts is None: @@ -725,11 +726,11 @@ match = orig(ctx, pats, opts, globbed, default, badfn=badfn) return composenormalfilematcher(match, manifest) - with extensions.wrappedfunction(scmutil, "match", normalfilesmatchfn): + with extensions.wrappedfunction(scmutil, b"match", normalfilesmatchfn): try: result = orig(ui, repo, pats, opts, rename) except error.Abort as e: - if pycompat.bytestr(e) != _("no files to copy"): + if pycompat.bytestr(e) != _(b"no files to copy"): raise e else: nonormalfiles = True @@ -766,7 +767,7 @@ pats=(), opts=None, globbed=False, - default="relpath", + default=b"relpath", badfn=None, ): if opts is None: @@ -776,7 +777,7 @@ # directory; we need to remove that now for pat in pats: if matchmod.patkind(pat) is None and lfutil.shortname in pat: - newpats.append(pat.replace(lfutil.shortname, "")) + newpats.append(pat.replace(lfutil.shortname, b"")) else: newpats.append(pat) match = orig(ctx, newpats, opts, globbed, default, badfn=badfn) @@ -811,14 +812,16 @@ if lfutil.shortname in src and dest.startswith( repo.wjoin(lfutil.shortname) ): - destlfile = dest.replace(lfutil.shortname, "") - if not opts["force"] and os.path.exists(destlfile): - raise IOError("", _("destination largefile already exists")) + destlfile = dest.replace(lfutil.shortname, b"") + if not opts[b"force"] and os.path.exists(destlfile): + raise IOError( + b"", _(b"destination largefile already exists") + ) copiedfiles.append((src, dest)) orig(src, dest, *args, **kwargs) - with extensions.wrappedfunction(util, "copyfile", overridecopyfile): - with extensions.wrappedfunction(scmutil, "match", overridematch): + with extensions.wrappedfunction(util, b"copyfile", overridecopyfile): + with extensions.wrappedfunction(scmutil, b"match", overridematch): result += orig(ui, repo, listpats, opts, rename) lfdirstate = lfutil.openlfdirstate(ui, repo) @@ -826,9 +829,9 @@ if lfutil.shortname in src and dest.startswith( repo.wjoin(lfutil.shortname) ): - srclfile = src.replace(repo.wjoin(lfutil.standin("")), "") - destlfile = dest.replace(repo.wjoin(lfutil.standin("")), "") - destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or "." + srclfile = src.replace(repo.wjoin(lfutil.standin(b"")), b"") + destlfile = dest.replace(repo.wjoin(lfutil.standin(b"")), b"") + destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or b"." if not os.path.isdir(destlfiledir): os.makedirs(destlfiledir) if rename: @@ -844,7 +847,7 @@ lfdirstate.add(destlfile) lfdirstate.write() except error.Abort as e: - if pycompat.bytestr(e) != _("no files to copy"): + if pycompat.bytestr(e) != _(b"no files to copy"): raise e else: nolfiles = True @@ -852,7 +855,7 @@ wlock.release() if nolfiles and nonormalfiles: - raise error.Abort(_("no files to copy")) + raise error.Abort(_(b"no files to copy")) return result @@ -866,7 +869,7 @@ # commits. Update the standins then run the original revert, changing # the matcher to hit standins instead of largefiles. Based on the # resulting standins update the largefiles. -@eh.wrapfunction(cmdutil, "revert") +@eh.wrapfunction(cmdutil, b"revert") def overriderevert(orig, ui, repo, ctx, parents, *pats, **opts): # Because we put the standins in a bad state (by updating them) # and then return them to a correct state we need to lock to @@ -890,7 +893,7 @@ pats=(), opts=None, globbed=False, - default="relpath", + default=b"relpath", badfn=None, ): if opts is None: @@ -912,7 +915,7 @@ standin = lfutil.standin(f) if standin in ctx or standin in mctx: matchfiles.append(standin) - elif standin in wctx or lfdirstate[f] == "r": + elif standin in wctx or lfdirstate[f] == b"r": continue else: matchfiles.append(f) @@ -929,7 +932,7 @@ m.matchfn = matchfn return m - with extensions.wrappedfunction(scmutil, "match", overridematch): + with extensions.wrappedfunction(scmutil, b"match", overridematch): orig(ui, repo, ctx, parents, *pats, **opts) newstandins = lfutil.getstandinsstate(repo) @@ -947,51 +950,57 @@ # after pulling changesets, we need to take some extra care to get # largefiles updated remotely @eh.wrapcommand( - "pull", + b"pull", opts=[ ( - "", - "all-largefiles", + b"", + b"all-largefiles", None, - _("download all pulled versions of largefiles (DEPRECATED)"), + _(b"download all pulled versions of largefiles (DEPRECATED)"), ), ( - "", - "lfrev", + b"", + b"lfrev", [], - _("download largefiles for these revisions"), - _("REV"), + _(b"download largefiles for these revisions"), + _(b"REV"), ), ], ) def overridepull(orig, ui, repo, source=None, **opts): revsprepull = len(repo) if not source: - source = "default" + source = b"default" repo.lfpullsource = source result = orig(ui, repo, source, **opts) revspostpull = len(repo) lfrevs = opts.get(r"lfrev", []) if opts.get(r"all_largefiles"): - lfrevs.append("pulled()") + lfrevs.append(b"pulled()") if lfrevs and revspostpull > revsprepull: numcached = 0 repo.firstpulled = revsprepull # for pulled() revset expression try: for rev in scmutil.revrange(repo, lfrevs): - ui.note(_("pulling largefiles for revision %d\n") % rev) + ui.note(_(b"pulling largefiles for revision %d\n") % rev) (cached, missing) = lfcommands.cachelfiles(ui, repo, rev) numcached += len(cached) finally: del repo.firstpulled - ui.status(_("%d largefiles cached\n") % numcached) + ui.status(_(b"%d largefiles cached\n") % numcached) return result @eh.wrapcommand( - "push", + b"push", opts=[ - ("", "lfrev", [], _("upload largefiles for these revisions"), _("REV")) + ( + b"", + b"lfrev", + [], + _(b"upload largefiles for these revisions"), + _(b"REV"), + ) ], ) def overridepush(orig, ui, repo, *args, **kwargs): @@ -999,11 +1008,11 @@ lfrevs = kwargs.pop(r"lfrev", None) if lfrevs: opargs = kwargs.setdefault(r"opargs", {}) - opargs["lfrevs"] = scmutil.revrange(repo, lfrevs) + opargs[b"lfrevs"] = scmutil.revrange(repo, lfrevs) return orig(ui, repo, *args, **kwargs) -@eh.wrapfunction(exchange, "pushoperation") +@eh.wrapfunction(exchange, b"pushoperation") def exchangepushoperation(orig, *args, **kwargs): """Override pushoperation constructor and store lfrevs parameter""" lfrevs = kwargs.pop(r"lfrevs", None) @@ -1012,7 +1021,7 @@ return pushop -@eh.revsetpredicate("pulled()") +@eh.revsetpredicate(b"pulled()") def pulledrevsetsymbol(repo, subset, x): """Changesets that just has been pulled. @@ -1035,18 +1044,18 @@ try: firstpulled = repo.firstpulled except AttributeError: - raise error.Abort(_("pulled() only available in --lfrev")) + raise error.Abort(_(b"pulled() only available in --lfrev")) return smartset.baseset([r for r in subset if r >= firstpulled]) @eh.wrapcommand( - "clone", + b"clone", opts=[ ( - "", - "all-largefiles", + b"", + b"all-largefiles", None, - _("download all versions of all largefiles"), + _(b"download all versions of all largefiles"), ) ], ) @@ -1056,14 +1065,14 @@ d = hg.defaultdest(source) if opts.get(r"all_largefiles") and not hg.islocal(d): raise error.Abort( - _("--all-largefiles is incompatible with non-local destination %s") + _(b"--all-largefiles is incompatible with non-local destination %s") % d ) return orig(ui, source, dest, **opts) -@eh.wrapfunction(hg, "clone") +@eh.wrapfunction(hg, b"clone") def hgclone(orig, ui, opts, *args, **kwargs): result = orig(ui, opts, *args, **kwargs) @@ -1080,7 +1089,7 @@ # Caching is implicitly limited to 'rev' option, since the dest repo was # truncated at that point. The user may expect a download count with # this option, so attempt whether or not this is a largefile repo. - if opts.get("all_largefiles"): + if opts.get(b"all_largefiles"): success, missing = lfcommands.downloadlfiles(ui, repo, None) if missing != 0: @@ -1089,9 +1098,9 @@ return result -@eh.wrapcommand("rebase", extension="rebase") +@eh.wrapcommand(b"rebase", extension=b"rebase") def overriderebase(orig, ui, repo, **opts): - if not util.safehasattr(repo, "_largefilesenabled"): + if not util.safehasattr(repo, b"_largefilesenabled"): return orig(ui, repo, **opts) resuming = opts.get(r"continue") @@ -1104,7 +1113,7 @@ repo._lfcommithooks.pop() -@eh.wrapcommand("archive") +@eh.wrapcommand(b"archive") def overridearchivecmd(orig, ui, repo, dest, **opts): repo.unfiltered().lfstatus = True @@ -1114,7 +1123,7 @@ repo.unfiltered().lfstatus = False -@eh.wrapfunction(webcommands, "archive") +@eh.wrapfunction(webcommands, b"archive") def hgwebarchive(orig, web): web.repo.lfstatus = True @@ -1124,7 +1133,7 @@ web.repo.lfstatus = False -@eh.wrapfunction(archival, "archive") +@eh.wrapfunction(archival, b"archive") def overridearchive( orig, repo, @@ -1133,7 +1142,7 @@ kind, decode=True, match=None, - prefix="", + prefix=b"", mtime=None, subrepos=None, ): @@ -1150,13 +1159,13 @@ lfcommands.cachelfiles(repo.ui, repo, node) if kind not in archival.archivers: - raise error.Abort(_("unknown archive type '%s'") % kind) + raise error.Abort(_(b"unknown archive type '%s'") % kind) ctx = repo[node] - if kind == "files": + if kind == b"files": if prefix: - raise error.Abort(_("cannot give prefix when archiving to files")) + raise error.Abort(_(b"cannot give prefix when archiving to files")) else: prefix = archival.tidyprefix(dest, kind, prefix) @@ -1170,9 +1179,9 @@ archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) - if repo.ui.configbool("ui", "archivemeta"): + if repo.ui.configbool(b"ui", b"archivemeta"): write( - ".hg_archival.txt", + b".hg_archival.txt", 0o644, False, lambda: archival.buildmetadata(ctx), @@ -1189,7 +1198,7 @@ if path is None: raise error.Abort( _( - "largefile %s not found in repo store or system cache" + b"largefile %s not found in repo store or system cache" ) % lfile ) @@ -1199,26 +1208,26 @@ f = lfile getdata = lambda: util.readfile(path) - write(f, "x" in ff and 0o755 or 0o644, "l" in ff, getdata) + write(f, b"x" in ff and 0o755 or 0o644, b"l" in ff, getdata) if subrepos: for subpath in sorted(ctx.substate): sub = ctx.workingsub(subpath) submatch = matchmod.subdirmatcher(subpath, match) - subprefix = prefix + subpath + "/" + subprefix = prefix + subpath + b"/" sub._repo.lfstatus = True sub.archive(archiver, subprefix, submatch) archiver.done() -@eh.wrapfunction(subrepo.hgsubrepo, "archive") +@eh.wrapfunction(subrepo.hgsubrepo, b"archive") def hgsubrepoarchive(orig, repo, archiver, prefix, match=None, decode=True): - lfenabled = util.safehasattr(repo._repo, "_largefilesenabled") + lfenabled = util.safehasattr(repo._repo, b"_largefilesenabled") if not lfenabled or not repo._repo.lfstatus: return orig(repo, archiver, prefix, match, decode) - repo._get(repo._state + ("hg",)) + repo._get(repo._state + (b"hg",)) rev = repo._state[1] ctx = repo._repo[rev] @@ -1247,7 +1256,7 @@ if path is None: raise error.Abort( _( - "largefile %s not found in repo store or system cache" + b"largefile %s not found in repo store or system cache" ) % lfile ) @@ -1258,12 +1267,12 @@ getdata = lambda: util.readfile(os.path.join(prefix, path)) - write(f, "x" in ff and 0o755 or 0o644, "l" in ff, getdata) + write(f, b"x" in ff and 0o755 or 0o644, b"l" in ff, getdata) for subpath in sorted(ctx.substate): sub = ctx.workingsub(subpath) submatch = matchmod.subdirmatcher(subpath, match) - subprefix = prefix + subpath + "/" + subprefix = prefix + subpath + b"/" sub._repo.lfstatus = True sub.archive(archiver, subprefix, submatch, decode) @@ -1272,17 +1281,17 @@ # standin until a commit. cmdutil.bailifchanged() raises an exception # if the repo has uncommitted changes. Wrap it to also check if # largefiles were changed. This is used by bisect, backout and fetch. -@eh.wrapfunction(cmdutil, "bailifchanged") +@eh.wrapfunction(cmdutil, b"bailifchanged") def overridebailifchanged(orig, repo, *args, **kwargs): orig(repo, *args, **kwargs) repo.lfstatus = True s = repo.status() repo.lfstatus = False if s.modified or s.added or s.removed or s.deleted: - raise error.Abort(_("uncommitted changes")) + raise error.Abort(_(b"uncommitted changes")) -@eh.wrapfunction(cmdutil, "postcommitstatus") +@eh.wrapfunction(cmdutil, b"postcommitstatus") def postcommitstatus(orig, repo, *args, **kwargs): repo.lfstatus = True try: @@ -1291,7 +1300,7 @@ repo.lfstatus = False -@eh.wrapfunction(cmdutil, "forget") +@eh.wrapfunction(cmdutil, b"forget") def cmdutilforget( orig, ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive ): @@ -1321,20 +1330,20 @@ fstandin = lfutil.standin(f) if fstandin not in repo.dirstate and not repo.wvfs.isdir(fstandin): ui.warn( - _("not removing %s: file is already untracked\n") % uipathfn(f) + _(b"not removing %s: file is already untracked\n") % uipathfn(f) ) bad.append(f) for f in forget: if ui.verbose or not m.exact(f): - ui.status(_("removing %s\n") % uipathfn(f)) + ui.status(_(b"removing %s\n") % uipathfn(f)) # Need to lock because standin files are deleted then removed from the # repository and we could race in-between. with repo.wlock(): lfdirstate = lfutil.openlfdirstate(ui, repo) for f in forget: - if lfdirstate[f] == "a": + if lfdirstate[f] == b"a": lfdirstate.drop(f) else: lfdirstate.remove(f) @@ -1376,7 +1385,7 @@ def outgoinghook(ui, repo, other, opts, missing): - if opts.pop("large", None): + if opts.pop(b"large", None): lfhashes = set() if ui.debugflag: toupload = {} @@ -1389,7 +1398,7 @@ def showhashes(fn): for lfhash in sorted(toupload[fn]): - ui.debug(" %s\n" % lfhash) + ui.debug(b" %s\n" % lfhash) else: toupload = set() @@ -1404,19 +1413,19 @@ _getoutgoings(repo, other, missing, addfunc) if not toupload: - ui.status(_("largefiles: no files to upload\n")) + ui.status(_(b"largefiles: no files to upload\n")) else: ui.status( - _("largefiles to upload (%d entities):\n") % (len(lfhashes)) + _(b"largefiles to upload (%d entities):\n") % (len(lfhashes)) ) for file in sorted(toupload): - ui.status(lfutil.splitstandin(file) + "\n") + ui.status(lfutil.splitstandin(file) + b"\n") showhashes(file) - ui.status("\n") + ui.status(b"\n") @eh.wrapcommand( - "outgoing", opts=[("", "large", None, _("display outgoing largefiles"))] + b"outgoing", opts=[(b"", b"large", None, _(b"display outgoing largefiles"))] ) def _outgoingcmd(orig, *args, **kwargs): # Nothing to do here other than add the extra help option- the hook above @@ -1425,7 +1434,7 @@ def summaryremotehook(ui, repo, opts, changes): - largeopt = opts.get("large", False) + largeopt = opts.get(b"large", False) if changes is None: if largeopt: return (False, True) # only outgoing check is needed @@ -1435,7 +1444,7 @@ url, branch, peer, outgoing = changes[1] if peer is None: # i18n: column positioning for "hg summary" - ui.status(_("largefiles: (no remote repo)\n")) + ui.status(_(b"largefiles: (no remote repo)\n")) return toupload = set() @@ -1449,17 +1458,17 @@ if not toupload: # i18n: column positioning for "hg summary" - ui.status(_("largefiles: (no files to upload)\n")) + ui.status(_(b"largefiles: (no files to upload)\n")) else: # i18n: column positioning for "hg summary" ui.status( - _("largefiles: %d entities for %d files to upload\n") + _(b"largefiles: %d entities for %d files to upload\n") % (len(lfhashes), len(toupload)) ) @eh.wrapcommand( - "summary", opts=[("", "large", None, _("display outgoing largefiles"))] + b"summary", opts=[(b"", b"large", None, _(b"display outgoing largefiles"))] ) def overridesummary(orig, ui, repo, *pats, **opts): try: @@ -1469,7 +1478,7 @@ repo.lfstatus = False -@eh.wrapfunction(scmutil, "addremove") +@eh.wrapfunction(scmutil, b"addremove") def scmutiladdremove(orig, repo, matcher, prefix, uipathfn, opts=None): if opts is None: opts = {} @@ -1505,7 +1514,7 @@ True, m, uipathfn, - opts.get("dry_run"), + opts.get(b"dry_run"), **pycompat.strkwargs(opts) ) # Call into the normal add code, and any files that *should* be added as @@ -1522,7 +1531,7 @@ # Calling purge with --all will cause the largefiles to be deleted. # Override repo.status to prevent this from happening. -@eh.wrapcommand("purge", extension="purge") +@eh.wrapcommand(b"purge", extension=b"purge") def overridepurge(orig, ui, repo, *dirs, **opts): # XXX Monkey patching a repoview will not work. The assigned attribute will # be set on the unfiltered repo, but we will only lookup attributes in the @@ -1537,7 +1546,7 @@ oldstatus = repo.status def overridestatus( - node1=".", + node1=b".", node2=None, match=None, ignored=False, @@ -1549,8 +1558,8 @@ node1, node2, match, ignored, clean, unknown, listsubrepos ) lfdirstate = lfutil.openlfdirstate(ui, repo) - unknown = [f for f in r.unknown if lfdirstate[f] == "?"] - ignored = [f for f in r.ignored if lfdirstate[f] == "?"] + unknown = [f for f in r.unknown if lfdirstate[f] == b"?"] + ignored = [f for f in r.ignored if lfdirstate[f] == b"?"] return scmutil.status( r.modified, r.added, r.removed, r.deleted, unknown, ignored, r.clean ) @@ -1560,25 +1569,25 @@ repo.status = oldstatus -@eh.wrapcommand("rollback") +@eh.wrapcommand(b"rollback") def overriderollback(orig, ui, repo, **opts): with repo.wlock(): before = repo.dirstate.parents() orphans = set( f for f in repo.dirstate - if lfutil.isstandin(f) and repo.dirstate[f] != "r" + if lfutil.isstandin(f) and repo.dirstate[f] != b"r" ) result = orig(ui, repo, **opts) after = repo.dirstate.parents() if before == after: return result # no need to restore standins - pctx = repo["."] + pctx = repo[b"."] for f in repo.dirstate: if lfutil.isstandin(f): orphans.discard(f) - if repo.dirstate[f] == "r": + if repo.dirstate[f] == b"r": repo.wvfs.unlinkpath(f, ignoremissing=True) elif f in pctx: fctx = pctx[f] @@ -1586,7 +1595,7 @@ else: # content of standin is not so important in 'a', # 'm' or 'n' (coming from the 2nd parent) cases - lfutil.writestandin(repo, f, "", False) + lfutil.writestandin(repo, f, b"", False) for standin in orphans: repo.wvfs.unlinkpath(standin, ignoremissing=True) @@ -1602,7 +1611,7 @@ return result -@eh.wrapcommand("transplant", extension="transplant") +@eh.wrapcommand(b"transplant", extension=b"transplant") def overridetransplant(orig, ui, repo, *revs, **opts): resuming = opts.get(r"continue") repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) @@ -1615,10 +1624,10 @@ return result -@eh.wrapcommand("cat") +@eh.wrapcommand(b"cat") def overridecat(orig, ui, repo, file1, *pats, **opts): opts = pycompat.byteskwargs(opts) - ctx = scmutil.revsingle(repo, opts.get("rev")) + ctx = scmutil.revsingle(repo, opts.get(b"rev")) err = 1 notbad = set() m = scmutil.match(ctx, (file1,) + pats, opts) @@ -1658,12 +1667,12 @@ m.visitdir = lfvisitdirfn for f in ctx.walk(m): - with cmdutil.makefileobj(ctx, opts.get("output"), pathname=f) as fp: + with cmdutil.makefileobj(ctx, opts.get(b"output"), pathname=f) as fp: lf = lfutil.splitstandin(f) if lf is None or origmatchfn(f): # duplicating unreachable code from commands.cat data = ctx[f].data() - if opts.get("decode"): + if opts.get(b"decode"): data = repo.wwritedata(f, data) fp.write(data) else: @@ -1674,20 +1683,20 @@ if len(success) != 1: raise error.Abort( _( - "largefile %s is not in cache and could not be " - "downloaded" + b"largefile %s is not in cache and could not be " + b"downloaded" ) % lf ) path = lfutil.usercachepath(repo.ui, hash) - with open(path, "rb") as fpin: + with open(path, b"rb") as fpin: for chunk in util.filechunkiter(fpin): fp.write(chunk) err = 0 return err -@eh.wrapfunction(merge, "update") +@eh.wrapfunction(merge, b"update") def mergeupdate(orig, repo, node, branchmerge, force, *args, **kwargs): matcher = kwargs.get(r"matcher", None) # note if this is a partial update @@ -1717,7 +1726,7 @@ unknown=False, ) oldclean = set(s.clean) - pctx = repo["."] + pctx = repo[b"."] dctx = repo[node] for lfile in unsure + s.modified: lfileabs = repo.wvfs.join(lfile) @@ -1771,7 +1780,7 @@ return result -@eh.wrapfunction(scmutil, "marktouched") +@eh.wrapfunction(scmutil, b"marktouched") def scmutilmarktouched(orig, repo, files, *args, **kwargs): result = orig(repo, files, *args, **kwargs) @@ -1792,23 +1801,23 @@ return result -@eh.wrapfunction(upgrade, "preservedrequirements") -@eh.wrapfunction(upgrade, "supporteddestrequirements") +@eh.wrapfunction(upgrade, b"preservedrequirements") +@eh.wrapfunction(upgrade, b"supporteddestrequirements") def upgraderequirements(orig, repo): reqs = orig(repo) - if "largefiles" in repo.requirements: - reqs.add("largefiles") + if b"largefiles" in repo.requirements: + reqs.add(b"largefiles") return reqs -_lfscheme = "largefile://" +_lfscheme = b"largefile://" -@eh.wrapfunction(urlmod, "open") +@eh.wrapfunction(urlmod, b"open") def openlargefile(orig, ui, url_, data=None): if url_.startswith(_lfscheme): if data: - msg = "cannot use data on a 'largefile://' url" + msg = b"cannot use data on a 'largefile://' url" raise error.ProgrammingError(msg) lfid = url_[len(_lfscheme) :] return storefactory.getlfile(ui, lfid) diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py --- a/hgext/largefiles/proto.py +++ b/hgext/largefiles/proto.py @@ -25,9 +25,9 @@ urlreq = util.urlreq LARGEFILES_REQUIRED_MSG = ( - "\nThis repository uses the largefiles extension." - "\n\nPlease enable it in your Mercurial config " - "file.\n" + b"\nThis repository uses the largefiles extension." + b"\n\nPlease enable it in your Mercurial config " + b"file.\n" ) eh = exthelper.exthelper() @@ -50,21 +50,21 @@ tmpfp.write(p) tmpfp._fp.seek(0) if sha != lfutil.hexsha1(tmpfp._fp): - raise IOError(0, _("largefile contents do not match hash")) + raise IOError(0, _(b"largefile contents do not match hash")) tmpfp.close() lfutil.linktousercache(repo, sha) except IOError as e: repo.ui.warn( - _("largefiles: failed to put %s into store: %s\n") + _(b"largefiles: failed to put %s into store: %s\n") % (sha, e.strerror) ) return wireprototypes.pushres( - 1, output.getvalue() if output else "" + 1, output.getvalue() if output else b"" ) finally: tmpfp.discard() - return wireprototypes.pushres(0, output.getvalue() if output else "") + return wireprototypes.pushres(0, output.getvalue() if output else b"") def getlfile(repo, proto, sha): @@ -73,9 +73,9 @@ filename = lfutil.findfile(repo, sha) if not filename: raise error.Abort( - _("requested largefile %s not present in cache") % sha + _(b"requested largefile %s not present in cache") % sha ) - f = open(filename, "rb") + f = open(filename, b"rb") length = os.fstat(f.fileno())[6] # Since we can't set an HTTP content-length header here, and @@ -84,7 +84,7 @@ # just send the length on the first line of the response, like the # ssh proto does for string responses. def generator(): - yield "%d\n" % length + yield b"%d\n" % length for chunk in util.filechunkiter(f): yield chunk @@ -100,8 +100,8 @@ server side.""" filename = lfutil.findfile(repo, sha) if not filename: - return wireprototypes.bytesresponse("2\n") - return wireprototypes.bytesresponse("0\n") + return wireprototypes.bytesresponse(b"2\n") + return wireprototypes.bytesresponse(b"0\n") def wirereposetup(ui, repo): @@ -112,44 +112,46 @@ # it ... if issubclass(self.__class__, httppeer.httppeer): res = self._call( - "putlfile", + b"putlfile", data=fd, sha=sha, headers={r"content-type": r"application/mercurial-0.1"}, ) try: - d, output = res.split("\n", 1) + d, output = res.split(b"\n", 1) for l in output.splitlines(True): - self.ui.warn(_("remote: "), l) # assume l ends with \n + self.ui.warn(_(b"remote: "), l) # assume l ends with \n return int(d) except ValueError: - self.ui.warn(_("unexpected putlfile response: %r\n") % res) + self.ui.warn(_(b"unexpected putlfile response: %r\n") % res) return 1 # ... but we can't use sshrepository._call because the data= # argument won't get sent, and _callpush does exactly what we want # in this case: send the data straight through else: try: - ret, output = self._callpush("putlfile", fd, sha=sha) - if ret == "": - raise error.ResponseError(_("putlfile failed:"), output) + ret, output = self._callpush(b"putlfile", fd, sha=sha) + if ret == b"": + raise error.ResponseError( + _(b"putlfile failed:"), output + ) return int(ret) except IOError: return 1 except ValueError: raise error.ResponseError( - _("putlfile failed (unexpected response):"), ret + _(b"putlfile failed (unexpected response):"), ret ) def getlfile(self, sha): """returns an iterable with the chunks of the file with sha sha""" - stream = self._callstream("getlfile", sha=sha) + stream = self._callstream(b"getlfile", sha=sha) length = stream.readline() try: length = int(length) except ValueError: self._abort( - error.ResponseError(_("unexpected response:"), length) + error.ResponseError(_(b"unexpected response:"), length) ) # SSH streams will block if reading more than length @@ -161,13 +163,13 @@ chunk = stream.read(1) if chunk: self._abort( - error.ResponseError(_("unexpected response:"), chunk) + error.ResponseError(_(b"unexpected response:"), chunk) ) @wireprotov1peer.batchable def statlfile(self, sha): f = wireprotov1peer.future() - result = {"sha": sha} + result = {b"sha": sha} yield result, f try: yield int(f.value) @@ -182,11 +184,11 @@ # advertise the largefiles=serve capability -@eh.wrapfunction(wireprotov1server, "_capabilities") +@eh.wrapfunction(wireprotov1server, b"_capabilities") def _capabilities(orig, repo, proto): """announce largefile server capability""" caps = orig(repo, proto) - caps.append("largefiles=serve") + caps.append(b"largefiles=serve") return caps @@ -200,10 +202,10 @@ def sshrepocallstream(self, cmd, **args): - if cmd == "heads" and self.capable("largefiles"): - cmd = "lheads" - if cmd == "batch" and self.capable("largefiles"): - args[r"cmds"] = args[r"cmds"].replace("heads ", "lheads ") + if cmd == b"heads" and self.capable(b"largefiles"): + cmd = b"lheads" + if cmd == b"batch" and self.capable(b"largefiles"): + args[r"cmds"] = args[r"cmds"].replace(b"heads ", b"lheads ") return ssholdcallstream(self, cmd, **args) @@ -211,8 +213,8 @@ def httprepocallstream(self, cmd, **args): - if cmd == "heads" and self.capable("largefiles"): - cmd = "lheads" - if cmd == "batch" and self.capable("largefiles"): - args[r"cmds"] = headsre.sub("lheads", args[r"cmds"]) + if cmd == b"heads" and self.capable(b"largefiles"): + cmd = b"lheads" + if cmd == b"batch" and self.capable(b"largefiles"): + args[r"cmds"] = headsre.sub(b"lheads", args[r"cmds"]) return httpoldcallstream(self, cmd, **args) diff --git a/hgext/largefiles/remotestore.py b/hgext/largefiles/remotestore.py --- a/hgext/largefiles/remotestore.py +++ b/hgext/largefiles/remotestore.py @@ -38,11 +38,11 @@ def put(self, source, hash): if self.sendfile(source, hash): raise error.Abort( - _("remotestore: could not put %s to remote store %s") + _(b"remotestore: could not put %s to remote store %s") % (source, util.hidepassword(self.url)) ) self.ui.debug( - _("remotestore: put %s to remote store %s\n") + _(b"remotestore: put %s to remote store %s\n") % (source, util.hidepassword(self.url)) ) @@ -53,13 +53,13 @@ ) def sendfile(self, filename, hash): - self.ui.debug("remotestore: sendfile(%s, %s)\n" % (filename, hash)) + self.ui.debug(b"remotestore: sendfile(%s, %s)\n" % (filename, hash)) try: with lfutil.httpsendfile(self.ui, filename) as fd: return self._put(hash, fd) except IOError as e: raise error.Abort( - _("remotestore: could not open file %s: %s") + _(b"remotestore: could not open file %s: %s") % (filename, stringutil.forcebytestr(e)) ) @@ -77,7 +77,7 @@ # keep trying with the other files... they will probably # all fail too. raise error.Abort( - "%s: %s" % (util.hidepassword(self.url), e.reason) + b"%s: %s" % (util.hidepassword(self.url), e.reason) ) except IOError as e: raise basestore.StoreError( @@ -118,33 +118,33 @@ if stat: if stat == 1: self.ui.warn( - _("changeset %s: %s: contents differ\n") + _(b"changeset %s: %s: contents differ\n") % (cset, filename) ) failed = True elif stat == 2: self.ui.warn( - _("changeset %s: %s missing\n") % (cset, filename) + _(b"changeset %s: %s missing\n") % (cset, filename) ) failed = True else: raise RuntimeError( - "verify failed: unexpected response " - "from statlfile (%r)" % stat + b"verify failed: unexpected response " + b"from statlfile (%r)" % stat ) return failed def _put(self, hash, fd): """Put file with the given hash in the remote store.""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") def _get(self, hash): """Get a iterator for content with the given hash.""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") def _stat(self, hashes): """Get information about availability of files specified by hashes in the remote store. Return dictionary mapping hashes to return code where 0 means that file is available, other values if not.""" - raise NotImplementedError("abstract method") + raise NotImplementedError(b"abstract method") diff --git a/hgext/largefiles/reposetup.py b/hgext/largefiles/reposetup.py --- a/hgext/largefiles/reposetup.py +++ b/hgext/largefiles/reposetup.py @@ -84,7 +84,7 @@ else: result = orig(lfutil.standin(path), fileid) olddata = result.data - result.data = lambda: olddata() + "\0" + result.data = lambda: olddata() + b"\0" return result ctx.__class__ = lfilesctx @@ -99,7 +99,7 @@ @localrepo.unfilteredmethod def status( self, - node1=".", + node1=b".", node2=None, match=None, ignored=False, @@ -125,7 +125,7 @@ ctx1 = self[node1] ctx2 = self[node2] working = ctx2.rev() is None - parentworking = working and ctx1 == self["."] + parentworking = working and ctx1 == self[b"."] if match is None: match = matchmod.always() @@ -236,7 +236,7 @@ != lfutil.hashfile(abslfile) ) or ( checkexec - and ("x" in ctx1.flags(standin)) + and (b"x" in ctx1.flags(standin)) != bool(lfutil.getexecutable(abslfile)) ): modified.append(lfile) @@ -334,7 +334,7 @@ # Do that here. def commit( self, - text="", + text=b"", user=None, date=None, match=None, @@ -365,10 +365,10 @@ missing = set(self.requirements) - remote.local().supported if missing: msg = _( - "required features are not" - " supported in the destination:" - " %s" - ) % (", ".join(sorted(missing))) + b"required features are not" + b" supported in the destination:" + b" %s" + ) % (b", ".join(sorted(missing))) raise error.Abort(msg) return super(lfilesrepo, self).push( remote, force=force, revs=revs, newbranch=newbranch @@ -393,10 +393,10 @@ regulars = [] for f in files: - if lfutil.isstandin(f + "/"): + if lfutil.isstandin(f + b"/"): raise error.Abort( - _('file "%s" is a largefile standin') % f, - hint="commit the largefile itself instead", + _(b'file "%s" is a largefile standin') % f, + hint=b"commit the largefile itself instead", ) # Scan directories if self.wvfs.isdir(f): @@ -406,7 +406,7 @@ for f in dirs: matcheddir = False - d = self.dirstate.normalize(f) + "/" + d = self.dirstate.normalize(f) + b"/" # Check for matched normal files for mf in regulars: if self.dirstate.normalize(mf).startswith(d): @@ -425,7 +425,7 @@ # forces status/dirstate to walk all files and # call the match function on the matcher, even # on case sensitive filesystems. - actualfiles.append(".") + actualfiles.append(b".") matcheddir = True # Nothing in dir, so readd it # and let commit reject it @@ -458,16 +458,16 @@ lfutil.getlfilestoupload(pushop.repo, lfrevs, addfunc) lfcommands.uploadlfiles(ui, pushop.repo, pushop.remote, toupload) - repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook) + repo.prepushoutgoinghooks.add(b"largefiles", prepushoutgoinghook) def checkrequireslfiles(ui, repo, **kwargs): - if "largefiles" not in repo.requirements and any( - lfutil.shortname + "/" in f[0] for f in repo.store.datafiles() + if b"largefiles" not in repo.requirements and any( + lfutil.shortname + b"/" in f[0] for f in repo.store.datafiles() ): - repo.requirements.add("largefiles") + repo.requirements.add(b"largefiles") repo._writerequirements() ui.setconfig( - "hooks", "changegroup.lfiles", checkrequireslfiles, "largefiles" + b"hooks", b"changegroup.lfiles", checkrequireslfiles, b"largefiles" ) - ui.setconfig("hooks", "commit.lfiles", checkrequireslfiles, "largefiles") + ui.setconfig(b"hooks", b"commit.lfiles", checkrequireslfiles, b"largefiles") diff --git a/hgext/largefiles/storefactory.py b/hgext/largefiles/storefactory.py --- a/hgext/largefiles/storefactory.py +++ b/hgext/largefiles/storefactory.py @@ -31,18 +31,18 @@ if lfpullsource: path = ui.expandpath(lfpullsource) elif put: - path = ui.expandpath("default-push", "default") + path = ui.expandpath(b"default-push", b"default") else: - path = ui.expandpath("default") + path = ui.expandpath(b"default") # ui.expandpath() leaves 'default-push' and 'default' alone if # they cannot be expanded: fallback to the empty string, # meaning the current directory. if repo is None: - path = ui.expandpath("default") + path = ui.expandpath(b"default") path, _branches = hg.parseurl(path) remote = hg.peer(repo or ui, {}, path) - elif path == "default-push" or path == "default": + elif path == b"default-push" or path == b"default": remote = repo else: path, _branches = hg.parseurl(path) @@ -50,18 +50,18 @@ # The path could be a scheme so use Mercurial's normal functionality # to resolve the scheme to a repository and use its path - path = util.safehasattr(remote, "url") and remote.url() or remote.path + path = util.safehasattr(remote, b"url") and remote.url() or remote.path match = _scheme_re.match(path) if not match: # regular filesystem path - scheme = "file" + scheme = b"file" else: scheme = match.group(1) try: storeproviders = _storeprovider[scheme] except KeyError: - raise error.Abort(_("unsupported URL scheme %r") % scheme) + raise error.Abort(_(b"unsupported URL scheme %r") % scheme) for classobj in storeproviders: try: @@ -70,16 +70,16 @@ pass raise error.Abort( - _("%s does not appear to be a largefile store") + _(b"%s does not appear to be a largefile store") % util.hidepassword(path) ) _storeprovider = { - "file": [localstore.localstore], - "http": [wirestore.wirestore], - "https": [wirestore.wirestore], - "ssh": [wirestore.wirestore], + b"file": [localstore.localstore], + b"http": [wirestore.wirestore], + b"https": [wirestore.wirestore], + b"ssh": [wirestore.wirestore], } _scheme_re = re.compile(br"^([a-zA-Z0-9+-.]+)://") diff --git a/hgext/largefiles/wirestore.py b/hgext/largefiles/wirestore.py --- a/hgext/largefiles/wirestore.py +++ b/hgext/largefiles/wirestore.py @@ -14,11 +14,11 @@ class wirestore(remotestore.remotestore): def __init__(self, ui, repo, remote): - cap = remote.capable("largefiles") + cap = remote.capable(b"largefiles") if not cap: raise lfutil.storeprotonotcapable([]) - storetypes = cap.split(",") - if "serve" not in storetypes: + storetypes = cap.split(b",") + if b"serve" not in storetypes: raise lfutil.storeprotonotcapable(storetypes) self.remote = remote super(wirestore, self).__init__(ui, repo, remote.url()) @@ -37,6 +37,6 @@ with self.remote.commandexecutor() as e: fs = [] for hash in hashes: - fs.append((hash, e.callcommand("statlfile", {"sha": hash,}))) + fs.append((hash, e.callcommand(b"statlfile", {b"sha": hash,}))) return {hash: f.result() for hash, f in fs} diff --git a/hgext/lfs/__init__.py b/hgext/lfs/__init__.py --- a/hgext/lfs/__init__.py +++ b/hgext/lfs/__init__.py @@ -159,7 +159,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" eh = exthelper.exthelper() eh.merge(wrapper.eh) @@ -174,33 +174,33 @@ templatekeyword = eh.templatekeyword eh.configitem( - "experimental", "lfs.serve", default=True, + b"experimental", b"lfs.serve", default=True, ) eh.configitem( - "experimental", "lfs.user-agent", default=None, + b"experimental", b"lfs.user-agent", default=None, ) eh.configitem( - "experimental", "lfs.disableusercache", default=False, + b"experimental", b"lfs.disableusercache", default=False, ) eh.configitem( - "experimental", "lfs.worker-enable", default=False, + b"experimental", b"lfs.worker-enable", default=False, ) eh.configitem( - "lfs", "url", default=None, + b"lfs", b"url", default=None, ) eh.configitem( - "lfs", "usercache", default=None, + b"lfs", b"usercache", default=None, ) # Deprecated eh.configitem( - "lfs", "threshold", default=None, + b"lfs", b"threshold", default=None, ) eh.configitem( - "lfs", "track", default="none()", + b"lfs", b"track", default=b"none()", ) eh.configitem( - "lfs", "retry", default=5, + b"lfs", b"retry", default=5, ) lfsprocessor = ( @@ -212,7 +212,7 @@ def featuresetup(ui, supported): # don't die on seeing a repo with the lfs requirement - supported |= {"lfs"} + supported |= {b"lfs"} @eh.uisetup @@ -232,76 +232,78 @@ class lfsrepo(repo.__class__): @localrepo.unfilteredmethod def commitctx(self, ctx, error=False, origctx=None): - repo.svfs.options["lfstrack"] = _trackedmatcher(self) + repo.svfs.options[b"lfstrack"] = _trackedmatcher(self) return super(lfsrepo, self).commitctx(ctx, error, origctx=origctx) repo.__class__ = lfsrepo - if "lfs" not in repo.requirements: + if b"lfs" not in repo.requirements: def checkrequireslfs(ui, repo, **kwargs): - if "lfs" in repo.requirements: + if b"lfs" in repo.requirements: return 0 last = kwargs.get(r"node_last") _bin = node.bin if last: - s = repo.set("%n:%n", _bin(kwargs[r"node"]), _bin(last)) + s = repo.set(b"%n:%n", _bin(kwargs[r"node"]), _bin(last)) else: - s = repo.set("%n", _bin(kwargs[r"node"])) + s = repo.set(b"%n", _bin(kwargs[r"node"])) match = repo._storenarrowmatch for ctx in s: # TODO: is there a way to just walk the files in the commit? if any( ctx[f].islfs() for f in ctx.files() if f in ctx and match(f) ): - repo.requirements.add("lfs") + repo.requirements.add(b"lfs") repo.features.add(repository.REPO_FEATURE_LFS) repo._writerequirements() - repo.prepushoutgoinghooks.add("lfs", wrapper.prepush) + repo.prepushoutgoinghooks.add(b"lfs", wrapper.prepush) break - ui.setconfig("hooks", "commit.lfs", checkrequireslfs, "lfs") - ui.setconfig("hooks", "pretxnchangegroup.lfs", checkrequireslfs, "lfs") + ui.setconfig(b"hooks", b"commit.lfs", checkrequireslfs, b"lfs") + ui.setconfig( + b"hooks", b"pretxnchangegroup.lfs", checkrequireslfs, b"lfs" + ) else: - repo.prepushoutgoinghooks.add("lfs", wrapper.prepush) + repo.prepushoutgoinghooks.add(b"lfs", wrapper.prepush) def _trackedmatcher(repo): """Return a function (path, size) -> bool indicating whether or not to track a given file with lfs.""" - if not repo.wvfs.exists(".hglfs"): + if not repo.wvfs.exists(b".hglfs"): # No '.hglfs' in wdir. Fallback to config for now. - trackspec = repo.ui.config("lfs", "track") + trackspec = repo.ui.config(b"lfs", b"track") # deprecated config: lfs.threshold - threshold = repo.ui.configbytes("lfs", "threshold") + threshold = repo.ui.configbytes(b"lfs", b"threshold") if threshold: filesetlang.parse(trackspec) # make sure syntax errors are confined - trackspec = "(%s) | size('>%d')" % (trackspec, threshold) + trackspec = b"(%s) | size('>%d')" % (trackspec, threshold) return minifileset.compile(trackspec) - data = repo.wvfs.tryread(".hglfs") + data = repo.wvfs.tryread(b".hglfs") if not data: return lambda p, s: False # Parse errors here will abort with a message that points to the .hglfs file # and line number. cfg = config.config() - cfg.parse(".hglfs", data) + cfg.parse(b".hglfs", data) try: rules = [ (minifileset.compile(pattern), minifileset.compile(rule)) - for pattern, rule in cfg.items("track") + for pattern, rule in cfg.items(b"track") ] except error.ParseError as e: # The original exception gives no indicator that the error is in the # .hglfs file, so add that. # TODO: See if the line number of the file can be made available. - raise error.Abort(_("parse error in .hglfs: %s") % e) + raise error.Abort(_(b"parse error in .hglfs: %s") % e) def _match(path, size): for pat, rule in rules: @@ -322,7 +324,7 @@ wrapfunction(filelog, "size", wrapper.filelogsize) -@eh.wrapfunction(localrepo, "resolverevlogstorevfsoptions") +@eh.wrapfunction(localrepo, b"resolverevlogstorevfsoptions") def _resolverevlogstorevfsoptions(orig, ui, requirements, features): opts = orig(ui, requirements, features) for name, module in extensions.extensions(ui): @@ -346,56 +348,56 @@ context.basefilectx.islfs = wrapper.filectxislfs - scmutil.fileprefetchhooks.add("lfs", wrapper._prefetchfiles) + scmutil.fileprefetchhooks.add(b"lfs", wrapper._prefetchfiles) # Make bundle choose changegroup3 instead of changegroup2. This affects # "hg bundle" command. Note: it does not cover all bundle formats like # "packed1". Using "packed1" with lfs will likely cause trouble. - exchange._bundlespeccontentopts["v2"]["cg.version"] = "03" + exchange._bundlespeccontentopts[b"v2"][b"cg.version"] = b"03" -@eh.filesetpredicate("lfs()") +@eh.filesetpredicate(b"lfs()") def lfsfileset(mctx, x): """File that uses LFS storage.""" # i18n: "lfs" is a keyword - filesetlang.getargs(x, 0, 0, _("lfs takes no arguments")) + filesetlang.getargs(x, 0, 0, _(b"lfs takes no arguments")) ctx = mctx.ctx def lfsfilep(f): return wrapper.pointerfromctx(ctx, f, removed=True) is not None - return mctx.predicate(lfsfilep, predrepr="") + return mctx.predicate(lfsfilep, predrepr=b"") -@eh.templatekeyword("lfs_files", requires={"ctx"}) +@eh.templatekeyword(b"lfs_files", requires={b"ctx"}) def lfsfiles(context, mapping): """List of strings. All files modified, added, or removed by this changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") pointers = wrapper.pointersfromctx(ctx, removed=True) # {path: pointer} files = sorted(pointers.keys()) def pointer(v): # In the file spec, version is first and the other keys are sorted. - sortkeyfunc = lambda x: (x[0] != "version", x) + sortkeyfunc = lambda x: (x[0] != b"version", x) items = sorted(pointers[v].iteritems(), key=sortkeyfunc) return util.sortdict(items) makemap = lambda v: { - "file": v, - "lfsoid": pointers[v].oid() if pointers[v] else None, - "lfspointer": templateutil.hybriddict(pointer(v)), + b"file": v, + b"lfsoid": pointers[v].oid() if pointers[v] else None, + b"lfspointer": templateutil.hybriddict(pointer(v)), } # TODO: make the separator ', '? - f = templateutil._showcompatlist(context, mapping, "lfs_file", files) + f = templateutil._showcompatlist(context, mapping, b"lfs_file", files) return templateutil.hybrid(f, files, makemap, pycompat.identity) @eh.command( - "debuglfsupload", - [("r", "rev", [], _("upload large files introduced by REV"))], + b"debuglfsupload", + [(b"r", b"rev", [], _(b"upload large files introduced by REV"))], ) def debuglfsupload(ui, repo, **opts): """upload lfs blobs added by the working copy parent or given revisions""" diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py --- a/hgext/lfs/blobstore.py +++ b/hgext/lfs/blobstore.py @@ -66,7 +66,7 @@ [dirpath + f for f in files if _lfsre.match(dirpath + f)] ) - yield ("", [], oids) + yield (b"", [], oids) class nullvfs(lfsvfs): @@ -256,7 +256,7 @@ if isinstance(urlerror.reason, Exception): inst = urlerror.reason - if util.safehasattr(inst, "reason"): + if util.safehasattr(inst, b"reason"): try: # usually it is in the form (errno, strerror) reason = inst.reason.args[1] except (AttributeError, IndexError): @@ -703,11 +703,11 @@ https://github.com/git-lfs/git-lfs/blob/master/docs/api/server-discovery.md """ lfsurl = repo.ui.config(b"lfs", b"url") - url = util.url(lfsurl or "") + url = util.url(lfsurl or b"") if lfsurl is None: if remote: path = remote - elif util.safehasattr(repo, "_subtoppath"): + elif util.safehasattr(repo, b"_subtoppath"): # The pull command sets this during the optional update phase, which # tells exactly where the pull originated, whether 'paths.default' # or explicit. diff --git a/hgext/lfs/pointer.py b/hgext/lfs/pointer.py --- a/hgext/lfs/pointer.py +++ b/hgext/lfs/pointer.py @@ -23,41 +23,41 @@ class gitlfspointer(dict): - VERSION = "https://git-lfs.github.com/spec/v1" + VERSION = b"https://git-lfs.github.com/spec/v1" def __init__(self, *args, **kwargs): - self["version"] = self.VERSION + self[b"version"] = self.VERSION super(gitlfspointer, self).__init__(*args) self.update(pycompat.byteskwargs(kwargs)) @classmethod def deserialize(cls, text): try: - return cls(l.split(" ", 1) for l in text.splitlines()).validate() + return cls(l.split(b" ", 1) for l in text.splitlines()).validate() except ValueError: # l.split returns 1 item instead of 2 raise InvalidPointer( - _("cannot parse git-lfs text: %s") % stringutil.pprint(text) + _(b"cannot parse git-lfs text: %s") % stringutil.pprint(text) ) def serialize(self): - sortkeyfunc = lambda x: (x[0] != "version", x) + sortkeyfunc = lambda x: (x[0] != b"version", x) items = sorted(self.validate().iteritems(), key=sortkeyfunc) - return "".join("%s %s\n" % (k, v) for k, v in items) + return b"".join(b"%s %s\n" % (k, v) for k, v in items) def oid(self): - return self["oid"].split(":")[-1] + return self[b"oid"].split(b":")[-1] def size(self): - return int(self["size"]) + return int(self[b"size"]) # regular expressions used by _validate # see https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md _keyre = re.compile(br"\A[a-z0-9.-]+\Z") _valuere = re.compile(br"\A[^\n]*\Z") _requiredre = { - "size": re.compile(br"\A[0-9]+\Z"), - "oid": re.compile(br"\Asha256:[0-9a-f]{64}\Z"), - "version": re.compile(br"\A%s\Z" % stringutil.reescape(VERSION)), + b"size": re.compile(br"\A[0-9]+\Z"), + b"oid": re.compile(br"\Asha256:[0-9a-f]{64}\Z"), + b"version": re.compile(br"\A%s\Z" % stringutil.reescape(VERSION)), } def validate(self): @@ -67,21 +67,21 @@ if k in self._requiredre: if not self._requiredre[k].match(v): raise InvalidPointer( - _("unexpected lfs pointer value: %s=%s") + _(b"unexpected lfs pointer value: %s=%s") % (k, stringutil.pprint(v)) ) requiredcount += 1 elif not self._keyre.match(k): - raise InvalidPointer(_("unexpected lfs pointer key: %s") % k) + raise InvalidPointer(_(b"unexpected lfs pointer key: %s") % k) if not self._valuere.match(v): raise InvalidPointer( - _("unexpected lfs pointer value: %s=%s") + _(b"unexpected lfs pointer value: %s=%s") % (k, stringutil.pprint(v)) ) if len(self._requiredre) != requiredcount: miss = sorted(set(self._requiredre.keys()).difference(self.keys())) raise InvalidPointer( - _("missing lfs pointer keys: %s") % ", ".join(miss) + _(b"missing lfs pointer keys: %s") % b", ".join(miss) ) return self diff --git a/hgext/lfs/wireprotolfsserver.py b/hgext/lfs/wireprotolfsserver.py --- a/hgext/lfs/wireprotolfsserver.py +++ b/hgext/lfs/wireprotolfsserver.py @@ -34,7 +34,7 @@ eh = exthelper.exthelper() -@eh.wrapfunction(wireprotoserver, "handlewsgirequest") +@eh.wrapfunction(wireprotoserver, b"handlewsgirequest") def handlewsgirequest(orig, rctx, req, res, checkperm): """Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS request if it is left unprocessed by the wrapped method. @@ -45,7 +45,7 @@ if not rctx.repo.ui.configbool(b"experimental", b"lfs.serve"): return False - if not util.safehasattr(rctx.repo.svfs, "lfslocalblobstore"): + if not util.safehasattr(rctx.repo.svfs, b"lfslocalblobstore"): return False if not req.dispatchpath: diff --git a/hgext/lfs/wrapper.py b/hgext/lfs/wrapper.py --- a/hgext/lfs/wrapper.py +++ b/hgext/lfs/wrapper.py @@ -46,7 +46,7 @@ eh = exthelper.exthelper() -@eh.wrapfunction(localrepo, "makefilestorage") +@eh.wrapfunction(localrepo, b"makefilestorage") def localrepomakefilestorage(orig, requirements, features, **kwargs): if b"lfs" in requirements: features.add(repository.REPO_FEATURE_LFS) @@ -54,26 +54,26 @@ return orig(requirements=requirements, features=features, **kwargs) -@eh.wrapfunction(changegroup, "allsupportedversions") +@eh.wrapfunction(changegroup, b"allsupportedversions") def allsupportedversions(orig, ui): versions = orig(ui) - versions.add("03") + versions.add(b"03") return versions -@eh.wrapfunction(wireprotov1server, "_capabilities") +@eh.wrapfunction(wireprotov1server, b"_capabilities") def _capabilities(orig, repo, proto): """Wrap server command to announce lfs server capability""" caps = orig(repo, proto) - if util.safehasattr(repo.svfs, "lfslocalblobstore"): + if util.safehasattr(repo.svfs, b"lfslocalblobstore"): # Advertise a slightly different capability when lfs is *required*, so # that the client knows it MUST load the extension. If lfs is not # required on the server, there's no reason to autoload the extension # on the client. if b"lfs" in repo.requirements: - caps.append("lfs-serve") + caps.append(b"lfs-serve") - caps.append("lfs") + caps.append(b"lfs") return caps @@ -101,10 +101,10 @@ # pack hg filelog metadata hgmeta = {} for k in p.keys(): - if k.startswith("x-hg-"): - name = k[len("x-hg-") :] + if k.startswith(b"x-hg-"): + name = k[len(b"x-hg-") :] hgmeta[name] = p[k] - if hgmeta or text.startswith("\1\n"): + if hgmeta or text.startswith(b"\1\n"): text = storageutil.packmeta(hgmeta, text) return (text, True, {}) @@ -122,20 +122,20 @@ self.opener.lfslocalblobstore.write(oid, text) # replace contents with metadata - longoid = "sha256:%s" % oid - metadata = pointer.gitlfspointer(oid=longoid, size="%d" % len(text)) + longoid = b"sha256:%s" % oid + metadata = pointer.gitlfspointer(oid=longoid, size=b"%d" % len(text)) # by default, we expect the content to be binary. however, LFS could also # be used for non-binary content. add a special entry for non-binary data. # this will be used by filectx.isbinary(). if not stringutil.binary(text): # not hg filelog metadata (affecting commit hash), no "x-hg-" prefix - metadata["x-is-binary"] = "0" + metadata[b"x-is-binary"] = b"0" # translate hg filelog metadata to lfs metadata with "x-hg-" prefix if hgmeta is not None: for k, v in hgmeta.iteritems(): - metadata["x-hg-%s" % k] = v + metadata[b"x-hg-%s" % k] = v rawtext = metadata.serialize() return (rawtext, False) @@ -170,7 +170,7 @@ **kwds ): # The matcher isn't available if reposetup() wasn't called. - lfstrack = self._revlog.opener.options.get("lfstrack") + lfstrack = self._revlog.opener.options.get(b"lfstrack") if lfstrack: textlen = len(text) @@ -203,8 +203,8 @@ if not rawtext: return False metadata = pointer.deserialize(rawtext) - if "x-hg-copy" in metadata and "x-hg-copyrev" in metadata: - return metadata["x-hg-copy"], bin(metadata["x-hg-copyrev"]) + if b"x-hg-copy" in metadata and b"x-hg-copyrev" in metadata: + return metadata[b"x-hg-copy"], bin(metadata[b"x-hg-copyrev"]) else: return False return orig(self, node) @@ -216,11 +216,11 @@ # fast path: use lfs metadata to answer size rawtext = self._revlog.rawdata(rev) metadata = pointer.deserialize(rawtext) - return int(metadata["size"]) + return int(metadata[b"size"]) return orig(self, rev) -@eh.wrapfunction(context.basefilectx, "cmp") +@eh.wrapfunction(context.basefilectx, b"cmp") def filectxcmp(orig, self, fctx): """returns True if text is different than fctx""" # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs @@ -232,13 +232,13 @@ return orig(self, fctx) -@eh.wrapfunction(context.basefilectx, "isbinary") +@eh.wrapfunction(context.basefilectx, b"isbinary") def filectxisbinary(orig, self): if self.islfs(): # fast path: use lfs metadata to answer isbinary metadata = pointer.deserialize(self.rawdata()) # if lfs metadata says nothing, assume it's binary by default - return bool(int(metadata.get("x-is-binary", 1))) + return bool(int(metadata.get(b"x-is-binary", 1))) return orig(self) @@ -246,16 +246,16 @@ return _islfs(self.filelog(), self.filenode()) -@eh.wrapfunction(cmdutil, "_updatecatformatter") +@eh.wrapfunction(cmdutil, b"_updatecatformatter") def _updatecatformatter(orig, fm, ctx, matcher, path, decode): orig(fm, ctx, matcher, path, decode) fm.data(rawdata=ctx[path].rawdata()) -@eh.wrapfunction(scmutil, "wrapconvertsink") +@eh.wrapfunction(scmutil, b"wrapconvertsink") def convertsink(orig, sink): sink = orig(sink) - if sink.repotype == "hg": + if sink.repotype == b"hg": class lfssink(sink.__class__): def putcommit( @@ -281,13 +281,13 @@ cleanp2, ) - if "lfs" not in self.repo.requirements: + if b"lfs" not in self.repo.requirements: ctx = self.repo[node] # The file list may contain removed files, so check for # membership before assuming it is in the context. if any(f in ctx and ctx[f].islfs() for f, n in files): - self.repo.requirements.add("lfs") + self.repo.requirements.add(b"lfs") self.repo._writerequirements() return node @@ -299,16 +299,16 @@ # bundlerepo uses "vfsmod.readonlyvfs(othervfs)", we need to make sure lfs # options and blob stores are passed from othervfs to the new readonlyvfs. -@eh.wrapfunction(vfsmod.readonlyvfs, "__init__") +@eh.wrapfunction(vfsmod.readonlyvfs, b"__init__") def vfsinit(orig, self, othervfs): orig(self, othervfs) # copy lfs related options for k, v in othervfs.options.items(): - if k.startswith("lfs"): + if k.startswith(b"lfs"): self.options[k] = v # also copy lfs blobstores. note: this can run before reposetup, so lfs # blobstore attributes are not always ready at this time. - for name in ["lfslocalblobstore", "lfsremoteblobstore"]: + for name in [b"lfslocalblobstore", b"lfsremoteblobstore"]: if util.safehasattr(othervfs, name): setattr(self, name, getattr(othervfs, name)) @@ -316,7 +316,7 @@ def _prefetchfiles(repo, revs, match): """Ensure that required LFS blobs are present, fetching them as a group if needed.""" - if not util.safehasattr(repo.svfs, "lfslocalblobstore"): + if not util.safehasattr(repo.svfs, b"lfslocalblobstore"): return pointers = [] @@ -340,7 +340,7 @@ def _canskipupload(repo): # Skip if this hasn't been passed to reposetup() - if not util.safehasattr(repo.svfs, "lfsremoteblobstore"): + if not util.safehasattr(repo.svfs, b"lfsremoteblobstore"): return True # if remotestore is a null store, upload is a no-op and can be skipped @@ -349,7 +349,7 @@ def candownload(repo): # Skip if this hasn't been passed to reposetup() - if not util.safehasattr(repo.svfs, "lfsremoteblobstore"): + if not util.safehasattr(repo.svfs, b"lfsremoteblobstore"): return False # if remotestore is a null store, downloads will lead to nothing @@ -377,20 +377,20 @@ return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing) -@eh.wrapfunction(exchange, "push") +@eh.wrapfunction(exchange, b"push") def push(orig, repo, remote, *args, **kwargs): """bail on push if the extension isn't enabled on remote when needed, and update the remote store based on the destination path.""" - if "lfs" in repo.requirements: + if b"lfs" in repo.requirements: # If the remote peer is for a local repo, the requirement tests in the # base class method enforce lfs support. Otherwise, some revisions in # this repo use lfs, and the remote repo needs the extension loaded. - if not remote.local() and not remote.capable("lfs"): + if not remote.local() and not remote.capable(b"lfs"): # This is a copy of the message in exchange.push() when requirements # are missing between local repos. - m = _("required features are not supported in the destination: %s") + m = _(b"required features are not supported in the destination: %s") raise error.Abort( - m % "lfs", hint=_("enable the lfs extension on the server") + m % b"lfs", hint=_(b"enable the lfs extension on the server") ) # Repositories where this extension is disabled won't have the field. @@ -407,7 +407,7 @@ # when writing a bundle via "hg bundle" command, upload related LFS blobs -@eh.wrapfunction(bundle2, "writenewbundle") +@eh.wrapfunction(bundle2, b"writenewbundle") def writenewbundle( orig, ui, repo, source, filename, bundletype, outgoing, *args, **kwargs ): @@ -420,11 +420,13 @@ def extractpointers(repo, revs): """return a list of lfs pointers added by given revs""" - repo.ui.debug("lfs: computing set of blobs to upload\n") + repo.ui.debug(b"lfs: computing set of blobs to upload\n") pointers = {} makeprogress = repo.ui.makeprogress - with makeprogress(_("lfs search"), _("changesets"), len(revs)) as progress: + with makeprogress( + _(b"lfs search"), _(b"changesets"), len(revs) + ) as progress: for r in revs: ctx = repo[r] for p in pointersfromctx(ctx).values(): @@ -461,7 +463,7 @@ return {} except pointer.InvalidPointer as ex: raise error.Abort( - _("lfs: corrupted pointer (%s@%s): %s\n") + _(b"lfs: corrupted pointer (%s@%s): %s\n") % (f, short(_ctx.node()), ex) ) @@ -494,27 +496,27 @@ remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore) -@eh.wrapfunction(upgrade, "_finishdatamigration") +@eh.wrapfunction(upgrade, b"_finishdatamigration") def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements): orig(ui, srcrepo, dstrepo, requirements) # Skip if this hasn't been passed to reposetup() - if util.safehasattr(srcrepo.svfs, "lfslocalblobstore") and util.safehasattr( - dstrepo.svfs, "lfslocalblobstore" - ): + if util.safehasattr( + srcrepo.svfs, b"lfslocalblobstore" + ) and util.safehasattr(dstrepo.svfs, b"lfslocalblobstore"): srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs for dirpath, dirs, files in srclfsvfs.walk(): for oid in files: - ui.write(_("copying lfs blob %s\n") % oid) + ui.write(_(b"copying lfs blob %s\n") % oid) lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid)) -@eh.wrapfunction(upgrade, "preservedrequirements") -@eh.wrapfunction(upgrade, "supporteddestrequirements") +@eh.wrapfunction(upgrade, b"preservedrequirements") +@eh.wrapfunction(upgrade, b"supporteddestrequirements") def upgraderequirements(orig, repo): reqs = orig(repo) - if "lfs" in repo.requirements: - reqs.add("lfs") + if b"lfs" in repo.requirements: + reqs.add(b"lfs") return reqs diff --git a/hgext/logtoprocess.py b/hgext/logtoprocess.py --- a/hgext/logtoprocess.py +++ b/hgext/logtoprocess.py @@ -42,7 +42,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" class processlogger(object): diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -104,7 +104,7 @@ ) release = lockmod.release -seriesopts = [("s", "summary", None, _("print first line of patch header"))] +seriesopts = [(b"s", b"summary", None, _(b"print first line of patch header"))] cmdtable = {} command = registrar.command(cmdtable) @@ -112,27 +112,27 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "mq", "git", default="auto", + b"mq", b"git", default=b"auto", ) configitem( - "mq", "keepchanges", default=False, + b"mq", b"keepchanges", default=False, ) configitem( - "mq", "plain", default=False, + b"mq", b"plain", default=False, ) configitem( - "mq", "secret", default=False, + b"mq", b"secret", default=False, ) # force load strip extension formerly included in mq and import some utility try: - stripext = extensions.find("strip") + stripext = extensions.find(b"strip") except KeyError: # note: load is lazy so we could avoid the try-except, # but I (marmoute) prefer this explicit code. @@ -143,7 +143,7 @@ def log(self, event, msgfmt, *msgargs, **opts): pass - stripext = extensions.load(dummyui(), "strip", "") + stripext = extensions.load(dummyui(), b"strip", b"") strip = stripext.strip @@ -174,7 +174,7 @@ self.node, self.name = node, name def __bytes__(self): - return hex(self.node) + ":" + self.name + return hex(self.node) + b":" + self.name __str__ = encoding.strmethod(__bytes__) __repr__ = encoding.strmethod(__bytes__) @@ -183,18 +183,18 @@ # The order of the headers in 'hg export' HG patches: HGHEADERS = [ # '# HG changeset patch', - "# User ", - "# Date ", - "# ", - "# Branch ", - "# Node ID ", - "# Parent ", # can occur twice for merges - but that is not relevant for mq + b"# User ", + b"# Date ", + b"# ", + b"# Branch ", + b"# Node ID ", + b"# Parent ", # can occur twice for merges - but that is not relevant for mq ] # The order of headers in plain 'mail style' patches: PLAINHEADERS = { - "from": 0, - "date": 1, - "subject": 2, + b"from": 0, + b"date": 1, + b"subject": 2, } @@ -221,12 +221,12 @@ ... b'# Date ', b'z') ['# HG changeset patch', '# Date z', '# Parent y'] """ - start = lines.index("# HG changeset patch") + 1 + start = lines.index(b"# HG changeset patch") + 1 newindex = HGHEADERS.index(header) bestpos = len(lines) for i in range(start, len(lines)): line = lines[i] - if not line.startswith("# "): + if not line.startswith(b"# "): bestpos = min(bestpos, i) break for lineindex, h in enumerate(HGHEADERS): @@ -261,21 +261,21 @@ newprio = PLAINHEADERS[header.lower()] bestpos = len(lines) for i, line in enumerate(lines): - if ":" in line: - lheader = line.split(":", 1)[0].strip().lower() + if b":" in line: + lheader = line.split(b":", 1)[0].strip().lower() lprio = PLAINHEADERS.get(lheader, newprio + 1) if lprio == newprio: - lines[i] = "%s: %s" % (header, value) + lines[i] = b"%s: %s" % (header, value) return lines if lprio > newprio and i < bestpos: bestpos = i else: if line: - lines.insert(i, "") + lines.insert(i, b"") if i < bestpos: bestpos = i break - lines.insert(bestpos, "%s: %s" % (header, value)) + lines.insert(bestpos, b"%s: %s" % (header, value)) return lines @@ -285,9 +285,9 @@ while lines: l = lines[-1] if ( - l.startswith("diff -") - or l.startswith("Index:") - or l.startswith("===========") + l.startswith(b"diff -") + or l.startswith(b"Index:") + or l.startswith(b"===========") ): del lines[-1] else: @@ -311,54 +311,54 @@ nodeid = None diffstart = 0 - for line in open(pf, "rb"): + for line in open(pf, b"rb"): line = line.rstrip() - if line.startswith("diff --git") or ( - diffstart and line.startswith("+++ ") + if line.startswith(b"diff --git") or ( + diffstart and line.startswith(b"+++ ") ): diffstart = 2 break diffstart = 0 # reset - if line.startswith("--- "): + if line.startswith(b"--- "): diffstart = 1 continue - elif format == "hgpatch": + elif format == b"hgpatch": # parse values when importing the result of an hg export - if line.startswith("# User "): + if line.startswith(b"# User "): user = line[7:] - elif line.startswith("# Date "): + elif line.startswith(b"# Date "): date = line[7:] - elif line.startswith("# Parent "): + elif line.startswith(b"# Parent "): parent = line[9:].lstrip() # handle double trailing space - elif line.startswith("# Branch "): + elif line.startswith(b"# Branch "): branch = line[9:] - elif line.startswith("# Node ID "): + elif line.startswith(b"# Node ID "): nodeid = line[10:] - elif not line.startswith("# ") and line: + elif not line.startswith(b"# ") and line: message.append(line) format = None - elif line == "# HG changeset patch": + elif line == b"# HG changeset patch": message = [] - format = "hgpatch" - elif format != "tagdone" and ( - line.startswith("Subject: ") or line.startswith("subject: ") + format = b"hgpatch" + elif format != b"tagdone" and ( + line.startswith(b"Subject: ") or line.startswith(b"subject: ") ): subject = line[9:] - format = "tag" - elif format != "tagdone" and ( - line.startswith("From: ") or line.startswith("from: ") + format = b"tag" + elif format != b"tagdone" and ( + line.startswith(b"From: ") or line.startswith(b"from: ") ): user = line[6:] - format = "tag" - elif format != "tagdone" and ( - line.startswith("Date: ") or line.startswith("date: ") + format = b"tag" + elif format != b"tagdone" and ( + line.startswith(b"Date: ") or line.startswith(b"date: ") ): date = line[6:] - format = "tag" - elif format == "tag" and line == "": + format = b"tag" + elif format == b"tag" and line == b"": # when looking for tags (subject: from: etc) they # end once you find a blank line in the source - format = "tagdone" + format = b"tagdone" elif message or line: message.append(line) comments.append(line) @@ -372,7 +372,7 @@ eatempty(comments) # make sure message isn't empty - if format and format.startswith("tag") and subject: + if format and format.startswith(b"tag") and subject: message.insert(0, subject) self.message = message @@ -386,41 +386,41 @@ self.haspatch = diffstart > 1 self.plainmode = ( plainmode - or "# HG changeset patch" not in self.comments + or b"# HG changeset patch" not in self.comments and any( - c.startswith("Date: ") or c.startswith("From: ") + c.startswith(b"Date: ") or c.startswith(b"From: ") for c in self.comments ) ) def setuser(self, user): try: - inserthgheader(self.comments, "# User ", user) + inserthgheader(self.comments, b"# User ", user) except ValueError: if self.plainmode: - insertplainheader(self.comments, "From", user) + insertplainheader(self.comments, b"From", user) else: - tmp = ["# HG changeset patch", "# User " + user] + tmp = [b"# HG changeset patch", b"# User " + user] self.comments = tmp + self.comments self.user = user def setdate(self, date): try: - inserthgheader(self.comments, "# Date ", date) + inserthgheader(self.comments, b"# Date ", date) except ValueError: if self.plainmode: - insertplainheader(self.comments, "Date", date) + insertplainheader(self.comments, b"Date", date) else: - tmp = ["# HG changeset patch", "# Date " + date] + tmp = [b"# HG changeset patch", b"# Date " + date] self.comments = tmp + self.comments self.date = date def setparent(self, parent): try: - inserthgheader(self.comments, "# Parent ", parent) + inserthgheader(self.comments, b"# Parent ", parent) except ValueError: if not self.plainmode: - tmp = ["# HG changeset patch", "# Parent " + parent] + tmp = [b"# HG changeset patch", b"# Parent " + parent] self.comments = tmp + self.comments self.parent = parent @@ -430,14 +430,14 @@ self.message = [message] if message: if self.plainmode and self.comments and self.comments[-1]: - self.comments.append("") + self.comments.append(b"") self.comments.append(message) def __bytes__(self): - s = "\n".join(self.comments).rstrip() + s = b"\n".join(self.comments).rstrip() if not s: - return "" - return s + "\n\n" + return b"" + return s + b"\n\n" __str__ = encoding.strmethod(__bytes__) @@ -446,7 +446,7 @@ If comments contains 'subject: ', message will prepend the field and a blank line.""" if self.message: - subj = "subject: " + self.message[0].lower() + subj = b"subject: " + self.message[0].lower() for i in pycompat.xrange(len(self.comments)): if subj == self.comments[i].lower(): del self.comments[i] @@ -467,13 +467,13 @@ """ repo = repo.unfiltered() if phase is None: - if repo.ui.configbool("mq", "secret"): + if repo.ui.configbool(b"mq", b"secret"): phase = phases.secret - overrides = {("ui", "allowemptycommit"): True} + overrides = {(b"ui", b"allowemptycommit"): True} if phase is not None: - overrides[("phases", "new-commit")] = phase - with repo.ui.configoverride(overrides, "mq"): - repo.ui.setconfig("ui", "allowemptycommit", True) + overrides[(b"phases", b"new-commit")] = phase + with repo.ui.configoverride(overrides, b"mq"): + repo.ui.setconfig(b"ui", b"allowemptycommit", True) return repo.commit(*args, **kwargs) @@ -485,15 +485,15 @@ def __init__(self, ui, baseui, path, patchdir=None): self.basepath = path try: - with open(os.path.join(path, "patches.queue"), r"rb") as fh: + with open(os.path.join(path, b"patches.queue"), r"rb") as fh: cur = fh.read().rstrip() if not cur: - curpath = os.path.join(path, "patches") + curpath = os.path.join(path, b"patches") else: - curpath = os.path.join(path, "patches-" + cur) + curpath = os.path.join(path, b"patches-" + cur) except IOError: - curpath = os.path.join(path, "patches") + curpath = os.path.join(path, b"patches") self.path = patchdir or curpath self.opener = vfsmod.vfs(self.path) self.ui = ui @@ -501,35 +501,35 @@ self.applieddirty = False self.seriesdirty = False self.added = [] - self.seriespath = "series" - self.statuspath = "status" - self.guardspath = "guards" + self.seriespath = b"series" + self.statuspath = b"status" + self.guardspath = b"guards" self.activeguards = None self.guardsdirty = False # Handle mq.git as a bool with extended values - gitmode = ui.config("mq", "git").lower() + gitmode = ui.config(b"mq", b"git").lower() boolmode = stringutil.parsebool(gitmode) if boolmode is not None: if boolmode: - gitmode = "yes" + gitmode = b"yes" else: - gitmode = "no" + gitmode = b"no" self.gitmode = gitmode # deprecated config: mq.plain - self.plainmode = ui.configbool("mq", "plain") + self.plainmode = ui.configbool(b"mq", b"plain") self.checkapplied = True @util.propertycache def applied(self): def parselines(lines): for l in lines: - entry = l.split(":", 1) + entry = l.split(b":", 1) if len(entry) > 1: n, name = entry yield statusentry(bin(n), name) elif l.strip(): self.ui.warn( - _("malformated mq status line: %s\n") + _(b"malformated mq status line: %s\n") % stringutil.pprint(entry) ) # else we ignore empty lines @@ -562,7 +562,7 @@ return self.seriesguards def invalidate(self): - for a in "applied fullseries series seriesguards".split(): + for a in b"applied fullseries series seriesguards".split(): if a in self.__dict__: delattr(self, a) self.applieddirty = False @@ -580,15 +580,15 @@ whitespace=not plain, formatchanging=not plain, ) - if self.gitmode == "auto": + if self.gitmode == b"auto": diffopts.upgrade = True - elif self.gitmode == "keep": + elif self.gitmode == b"keep": pass - elif self.gitmode in ("yes", "no"): - diffopts.git = self.gitmode == "yes" + elif self.gitmode in (b"yes", b"no"): + diffopts.git = self.gitmode == b"yes" else: raise error.Abort( - _("mq.git option can be auto/keep/yes/no" " got %s") + _(b"mq.git option can be auto/keep/yes/no" b" got %s") % self.gitmode ) if patchfn: @@ -600,12 +600,12 @@ referenced patch is a git patch and should be preserved as such. """ diffopts = diffopts.copy() - if not diffopts.git and self.gitmode == "keep": + if not diffopts.git and self.gitmode == b"keep": for patchfn in patches: - patchf = self.opener(patchfn, "r") + patchf = self.opener(patchfn, b"r") # if the patch was a git patch, refresh it as a git patch diffopts.git = any( - line.startswith("diff --git") for line in patchf + line.startswith(b"diff --git") for line in patchf ) patchf.close() return diffopts @@ -615,7 +615,7 @@ def findseries(self, patch): def matchpatch(l): - l = l.split("#", 1)[0] + l = l.split(b"#", 1)[0] return l.strip() == patch for index, l in enumerate(self.fullseries): @@ -629,10 +629,10 @@ self.series = [] self.seriesguards = [] for l in self.fullseries: - h = l.find("#") + h = l.find(b"#") if h == -1: patch = l - comment = "" + comment = b"" elif h == 0: continue else: @@ -642,7 +642,7 @@ if patch: if patch in self.series: raise error.Abort( - _("%s appears more than once in %s") + _(b"%s appears more than once in %s") % (patch, self.join(self.seriespath)) ) self.series.append(patch) @@ -650,17 +650,17 @@ def checkguard(self, guard): if not guard: - return _("guard cannot be an empty string") - bad_chars = "# \t\r\n\f" + return _(b"guard cannot be an empty string") + bad_chars = b"# \t\r\n\f" first = guard[0] - if first in "-+": - return _("guard %r starts with invalid character: %r") % ( + if first in b"-+": + return _(b"guard %r starts with invalid character: %r") % ( guard, first, ) for c in bad_chars: if c in guard: - return _("invalid character in guard %r: %r") % (guard, c) + return _(b"invalid character in guard %r: %r") % (guard, c) def setactive(self, guards): for guard in guards: @@ -668,7 +668,7 @@ if bad: raise error.Abort(bad) guards = sorted(set(guards)) - self.ui.debug("active guards: %s\n" % " ".join(guards)) + self.ui.debug(b"active guards: %s\n" % b" ".join(guards)) self.activeguards = guards self.guardsdirty = True @@ -685,7 +685,8 @@ bad = self.checkguard(guard) if bad: self.ui.warn( - "%s:%d: %s\n" % (self.join(self.guardspath), i + 1, bad) + b"%s:%d: %s\n" + % (self.join(self.guardspath), i + 1, bad) ) else: self.activeguards.append(guard) @@ -694,14 +695,14 @@ def setguards(self, idx, guards): for g in guards: if len(g) < 2: - raise error.Abort(_("guard %r too short") % g) - if g[0] not in "-+": - raise error.Abort(_("guard %r starts with invalid char") % g) + raise error.Abort(_(b"guard %r too short") % g) + if g[0] not in b"-+": + raise error.Abort(_(b"guard %r starts with invalid char") % g) bad = self.checkguard(g[1:]) if bad: raise error.Abort(bad) - drop = self.guard_re.sub("", self.fullseries[idx]) - self.fullseries[idx] = drop + "".join([" #" + g for g in guards]) + drop = self.guard_re.sub(b"", self.fullseries[idx]) + self.fullseries[idx] = drop + b"".join([b" #" + g for g in guards]) self.parseseries() self.seriesdirty = True @@ -713,17 +714,17 @@ return True, None guards = self.active() exactneg = [ - g for g in patchguards if g.startswith("-") and g[1:] in guards + g for g in patchguards if g.startswith(b"-") and g[1:] in guards ] if exactneg: return False, stringutil.pprint(exactneg[0]) - pos = [g for g in patchguards if g.startswith("+")] + pos = [g for g in patchguards if g.startswith(b"+")] exactpos = [g for g in pos if g[1:] in guards] if pos: if exactpos: return True, stringutil.pprint(exactpos[0]) - return False, " ".join([stringutil.pprint(p) for p in pos]) - return True, "" + return False, b" ".join([stringutil.pprint(p) for p in pos]) + return True, b"" def explainpushable(self, idx, all_patches=False): if all_patches: @@ -738,37 +739,37 @@ if all_patches and pushable: if why is None: write( - _("allowing %s - no guards in effect\n") + _(b"allowing %s - no guards in effect\n") % self.series[idx] ) else: if not why: write( - _("allowing %s - no matching negative guards\n") + _(b"allowing %s - no matching negative guards\n") % self.series[idx] ) else: write( - _("allowing %s - guarded by %s\n") + _(b"allowing %s - guarded by %s\n") % (self.series[idx], why) ) if not pushable: if why: write( - _("skipping %s - guarded by %s\n") + _(b"skipping %s - guarded by %s\n") % (self.series[idx], why) ) else: write( - _("skipping %s - no matching guards\n") + _(b"skipping %s - no matching guards\n") % self.series[idx] ) def savedirty(self): def writelist(items, path): - fp = self.opener(path, "wb") + fp = self.opener(path, b"wb") for i in items: - fp.write("%s\n" % i) + fp.write(b"%s\n" % i) fp.close() if self.applieddirty: @@ -787,14 +788,14 @@ self.added = [] def removeundo(self, repo): - undo = repo.sjoin("undo") + undo = repo.sjoin(b"undo") if not os.path.exists(undo): return try: os.unlink(undo) except OSError as inst: self.ui.warn( - _("error removing undo: %s\n") % stringutil.forcebytestr(inst) + _(b"error removing undo: %s\n") % stringutil.forcebytestr(inst) ) def backup(self, repo, files, copy=False): @@ -804,7 +805,7 @@ if os.path.lexists(absf): absorig = scmutil.backuppath(self.ui, repo, f) self.ui.note( - _("saving current version of %s as %s\n") + _(b"saving current version of %s as %s\n") % (f, os.path.relpath(absorig)) ) @@ -826,7 +827,7 @@ ): if opts is None: opts = {} - stat = opts.get("stat") + stat = opts.get(b"stat") m = scmutil.match(repo[node1], files, opts) logcmdutil.diffordiffstat( self.ui, repo, diffopts, node1, node2, m, changes, stat, fp @@ -842,9 +843,9 @@ return (err, n) if n is None: - raise error.Abort(_("apply failed for patch %s") % patch) - - self.ui.warn(_("patch didn't work out, merging %s\n") % patch) + raise error.Abort(_(b"apply failed for patch %s") % patch) + + self.ui.warn(_(b"patch didn't work out, merging %s\n") % patch) # apply failed, strip away that rev and merge. hg.clean(repo, head) @@ -853,17 +854,17 @@ ctx = repo[rev] ret = hg.merge(repo, rev) if ret: - raise error.Abort(_("update returned %d") % ret) + raise error.Abort(_(b"update returned %d") % ret) n = newcommit(repo, None, ctx.description(), ctx.user(), force=True) if n is None: - raise error.Abort(_("repo commit failed")) + raise error.Abort(_(b"repo commit failed")) try: ph = patchheader(mergeq.join(patch), self.plainmode) except Exception: - raise error.Abort(_("unable to read %s") % patch) + raise error.Abort(_(b"unable to read %s") % patch) diffopts = self.patchopts(diffopts, patch) - patchf = self.opener(patch, "w") + patchf = self.opener(patch, b"w") comments = bytes(ph) if comments: patchf.write(comments) @@ -901,8 +902,8 @@ # so, we insert a merge marker with only one parent. This way # the first patch in the queue is never a merge patch # - pname = ".hg.patches.merge.marker" - n = newcommit(repo, None, "[mq]: merge marker", force=True) + pname = b".hg.patches.merge.marker" + n = newcommit(repo, None, b"[mq]: merge marker", force=True) self.removeundo(repo) self.applied.append(statusentry(n, pname)) self.applieddirty = True @@ -912,7 +913,7 @@ for patch in series: patch = mergeq.lookup(patch, strict=True) if not patch: - self.ui.warn(_("patch %s does not exist\n") % patch) + self.ui.warn(_(b"patch %s does not exist\n") % patch) return (1, None) pushable, reason = self.pushable(patch) if not pushable: @@ -920,7 +921,7 @@ continue info = mergeq.isapplied(patch) if not info: - self.ui.warn(_("patch %s is not applied\n") % patch) + self.ui.warn(_(b"patch %s is not applied\n") % patch) return (1, None) rev = info[1] err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts) @@ -942,9 +943,9 @@ ) return (True, list(files), fuzz) except Exception as inst: - self.ui.note(stringutil.forcebytestr(inst) + "\n") + self.ui.note(stringutil.forcebytestr(inst) + b"\n") if not self.ui.verbose: - self.ui.warn(_("patch failed, unable to continue (try -v)\n")) + self.ui.warn(_(b"patch failed, unable to continue (try -v)\n")) self.ui.traceback() return (False, list(files), False) @@ -965,7 +966,7 @@ try: wlock = repo.wlock() lock = repo.lock() - tr = repo.transaction("qpush") + tr = repo.transaction(b"qpush") try: ret = self._apply( repo, @@ -1025,25 +1026,25 @@ if not pushable: self.explainpushable(patchname, all_patches=True) continue - self.ui.status(_("applying %s\n") % patchname) + self.ui.status(_(b"applying %s\n") % patchname) pf = os.path.join(patchdir, patchname) try: ph = patchheader(self.join(patchname), self.plainmode) except IOError: - self.ui.warn(_("unable to read %s\n") % patchname) + self.ui.warn(_(b"unable to read %s\n") % patchname) err = 1 break message = ph.message if not message: # The commit message should not be translated - message = "imported patch %s\n" % patchname + message = b"imported patch %s\n" % patchname else: if list: # The commit message should not be translated - message.append("\nimported patch %s" % patchname) - message = "\n".join(message) + message.append(b"\nimported patch %s" % patchname) + message = b"\n".join(message) if ph.haspatch: if tobackup: @@ -1051,8 +1052,8 @@ touched = set(touched) & tobackup if touched and keepchanges: raise AbortNoCleanup( - _("conflicting local changes found"), - hint=_("did you forget to qrefresh?"), + _(b"conflicting local changes found"), + hint=_(b"did you forget to qrefresh?"), ) self.backup(repo, touched, copy=True) tobackup = tobackup - touched @@ -1061,7 +1062,7 @@ all_files.update(files) patcherr = not patcherr else: - self.ui.warn(_("patch %s is empty\n") % patchname) + self.ui.warn(_(b"patch %s is empty\n") % patchname) patcherr, files, fuzz = 0, [], 0 if merge and files: @@ -1081,9 +1082,9 @@ p1 = repo.dirstate.p1() repo.setparents(p1, merge) - if all_files and ".hgsubstate" in all_files: + if all_files and b".hgsubstate" in all_files: wctx = repo[None] - pctx = repo["."] + pctx = repo[b"."] overwrite = False mergedsubstate = subrepoutil.submerge( repo, pctx, wctx, wctx, overwrite @@ -1096,22 +1097,24 @@ repo, None, message, ph.user, ph.date, match=match, force=True ) if repo.changelog.tip() == oldtip: - raise error.Abort(_("qpush exactly duplicates child changeset")) + raise error.Abort( + _(b"qpush exactly duplicates child changeset") + ) if n is None: - raise error.Abort(_("repository commit failed")) + raise error.Abort(_(b"repository commit failed")) if update_status: self.applied.append(statusentry(n, patchname)) if patcherr: self.ui.warn( - _("patch failed, rejects left in working " "directory\n") + _(b"patch failed, rejects left in working " b"directory\n") ) err = 2 break if fuzz and strict: - self.ui.warn(_("fuzz found when applying patch, stopping\n")) + self.ui.warn(_(b"fuzz found when applying patch, stopping\n")) err = 3 break return (err, n) @@ -1155,11 +1158,11 @@ if numrevs: rev = dict((entry.name, entry.node) for entry in qfinished) for p in unknown: - msg = _("revision %s refers to unknown patches: %s\n") + msg = _(b"revision %s refers to unknown patches: %s\n") self.ui.warn(msg % (short(rev[p]), p)) else: - msg = _("unknown patches: %s\n") - raise error.Abort("".join(msg % p for p in unknown)) + msg = _(b"unknown patches: %s\n") + raise error.Abort(b"".join(msg % p for p in unknown)) self.parseseries() self.seriesdirty = True @@ -1171,18 +1174,18 @@ for i, rev in enumerate(revs): if rev < firstrev: - raise error.Abort(_("revision %d is not managed") % rev) + raise error.Abort(_(b"revision %d is not managed") % rev) ctx = repo[rev] base = self.applied[i].node if ctx.node() != base: - msg = _("cannot delete revision %d above applied patches") + msg = _(b"cannot delete revision %d above applied patches") raise error.Abort(msg % rev) patch = self.applied[i].name - for fmt in ("[mq]: %s", "imported patch %s"): + for fmt in (b"[mq]: %s", b"imported patch %s"): if ctx.description() == fmt % patch: - msg = _("patch %s finalized without changeset message\n") + msg = _(b"patch %s finalized without changeset message\n") repo.ui.status(msg % patch) break @@ -1195,18 +1198,18 @@ repo._phasecache patches = self._revpatches(repo, sorted(revs)) qfinished = self._cleanup(patches, len(patches)) - if qfinished and repo.ui.configbool("mq", "secret"): + if qfinished and repo.ui.configbool(b"mq", b"secret"): # only use this logic when the secret option is added oldqbase = repo[qfinished[0]] tphase = phases.newcommitphase(repo.ui) if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase: - with repo.transaction("qfinish") as tr: + with repo.transaction(b"qfinish") as tr: phases.advanceboundary(repo, tr, tphase, qfinished) def delete(self, repo, patches, opts): - if not patches and not opts.get("rev"): + if not patches and not opts.get(b"rev"): raise error.Abort( - _("qdelete requires at least one revision or " "patch name") + _(b"qdelete requires at least one revision or " b"patch name") ) realpatches = [] @@ -1214,23 +1217,23 @@ patch = self.lookup(patch, strict=True) info = self.isapplied(patch) if info: - raise error.Abort(_("cannot delete applied patch %s") % patch) + raise error.Abort(_(b"cannot delete applied patch %s") % patch) if patch not in self.series: - raise error.Abort(_("patch %s not in series file") % patch) + raise error.Abort(_(b"patch %s not in series file") % patch) if patch not in realpatches: realpatches.append(patch) numrevs = 0 - if opts.get("rev"): + if opts.get(b"rev"): if not self.applied: - raise error.Abort(_("no patches applied")) - revs = scmutil.revrange(repo, opts.get("rev")) + raise error.Abort(_(b"no patches applied")) + revs = scmutil.revrange(repo, opts.get(b"rev")) revs.sort() revpatches = self._revpatches(repo, revs) realpatches += revpatches numrevs = len(revpatches) - self._cleanup(realpatches, numrevs, opts.get("keep")) + self._cleanup(realpatches, numrevs, opts.get(b"keep")) def checktoppatch(self, repo): """check that working directory is at qtip""" @@ -1238,64 +1241,66 @@ top = self.applied[-1].node patch = self.applied[-1].name if repo.dirstate.p1() != top: - raise error.Abort(_("working directory revision is not qtip")) + raise error.Abort(_(b"working directory revision is not qtip")) return top, patch return None, None def putsubstate2changes(self, substatestate, changes): for files in changes[:3]: - if ".hgsubstate" in files: + if b".hgsubstate" in files: return # already listed up # not yet listed up - if substatestate in "a?": - changes[1].append(".hgsubstate") - elif substatestate in "r": - changes[2].append(".hgsubstate") + if substatestate in b"a?": + changes[1].append(b".hgsubstate") + elif substatestate in b"r": + changes[2].append(b".hgsubstate") else: # modified - changes[0].append(".hgsubstate") + changes[0].append(b".hgsubstate") def checklocalchanges(self, repo, force=False, refresh=True): - excsuffix = "" + excsuffix = b"" if refresh: - excsuffix = ", qrefresh first" + excsuffix = b", qrefresh first" # plain versions for i18n tool to detect them - _("local changes found, qrefresh first") - _("local changed subrepos found, qrefresh first") + _(b"local changes found, qrefresh first") + _(b"local changed subrepos found, qrefresh first") s = repo.status() if not force: cmdutil.checkunfinished(repo) if s.modified or s.added or s.removed or s.deleted: - _("local changes found") # i18n tool detection - raise error.Abort(_("local changes found" + excsuffix)) + _(b"local changes found") # i18n tool detection + raise error.Abort(_(b"local changes found" + excsuffix)) if checksubstate(repo): - _("local changed subrepos found") # i18n tool detection - raise error.Abort(_("local changed subrepos found" + excsuffix)) + _(b"local changed subrepos found") # i18n tool detection + raise error.Abort( + _(b"local changed subrepos found" + excsuffix) + ) else: cmdutil.checkunfinished(repo, skipmerge=True) return s - _reserved = ("series", "status", "guards", ".", "..") + _reserved = (b"series", b"status", b"guards", b".", b"..") def checkreservedname(self, name): if name in self._reserved: raise error.Abort( - _('"%s" cannot be used as the name of a patch') % name + _(b'"%s" cannot be used as the name of a patch') % name ) if name != name.strip(): # whitespace is stripped by parseseries() raise error.Abort( - _("patch name cannot begin or end with " "whitespace") + _(b"patch name cannot begin or end with " b"whitespace") ) - for prefix in (".hg", ".mq"): + for prefix in (b".hg", b".mq"): if name.startswith(prefix): raise error.Abort( - _('patch name cannot begin with "%s"') % prefix + _(b'patch name cannot begin with "%s"') % prefix ) - for c in ("#", ":", "\r", "\n"): + for c in (b"#", b":", b"\r", b"\n"): if c in name: raise error.Abort( - _("%r cannot be used in the name of a patch") + _(b"%r cannot be used in the name of a patch") % pycompat.bytestr(c) ) @@ -1304,10 +1309,10 @@ if not force and os.path.exists(self.join(name)): if os.path.isdir(self.join(name)): raise error.Abort( - _('"%s" already exists as a directory') % name + _(b'"%s" already exists as a directory') % name ) else: - raise error.Abort(_('patch "%s" already exists') % name) + raise error.Abort(_(b'patch "%s" already exists') % name) def makepatchname(self, title, fallbackname): """Return a suitable filename for title, adding a suffix to make @@ -1331,36 +1336,36 @@ except error.Abort: pass i += 1 - name = "%s__%d" % (namebase, i) + name = b"%s__%d" % (namebase, i) return name def checkkeepchanges(self, keepchanges, force): if force and keepchanges: - raise error.Abort(_("cannot use both --force and --keep-changes")) + raise error.Abort(_(b"cannot use both --force and --keep-changes")) def new(self, repo, patchfn, *pats, **opts): """options: msg: a string or a no-argument function returning a string """ opts = pycompat.byteskwargs(opts) - msg = opts.get("msg") - edit = opts.get("edit") - editform = opts.get("editform", "mq.qnew") - user = opts.get("user") - date = opts.get("date") + msg = opts.get(b"msg") + edit = opts.get(b"edit") + editform = opts.get(b"editform", b"mq.qnew") + user = opts.get(b"user") + date = opts.get(b"date") if date: date = dateutil.parsedate(date) - diffopts = self.diffopts({"git": opts.get("git")}, plain=True) - if opts.get("checkname", True): + diffopts = self.diffopts({b"git": opts.get(b"git")}, plain=True) + if opts.get(b"checkname", True): self.checkpatchname(patchfn) inclsubs = checksubstate(repo) if inclsubs: - substatestate = repo.dirstate[".hgsubstate"] - if opts.get("include") or opts.get("exclude") or pats: + substatestate = repo.dirstate[b".hgsubstate"] + if opts.get(b"include") or opts.get(b"exclude") or pats: # detect missing files in pats def badfn(f, msg): - if f != ".hgsubstate": # .hgsubstate is auto-created - raise error.Abort("%s: %s" % (f, msg)) + if f != b".hgsubstate": # .hgsubstate is auto-created + raise error.Abort(b"%s: %s" % (f, msg)) match = scmutil.match(repo[None], pats, opts, badfn=badfn) changes = repo.status(match=match) @@ -1371,20 +1376,20 @@ commitfiles.extend(files) match = scmutil.matchfiles(repo, commitfiles) if len(repo[None].parents()) > 1: - raise error.Abort(_("cannot manage merge changesets")) + raise error.Abort(_(b"cannot manage merge changesets")) self.checktoppatch(repo) insert = self.fullseriesend() with repo.wlock(): try: # if patch file write fails, abort early - p = self.opener(patchfn, "w") + p = self.opener(patchfn, b"w") except IOError as e: raise error.Abort( - _('cannot write patch "%s": %s') + _(b'cannot write patch "%s": %s') % (patchfn, encoding.strtolocal(e.strerror)) ) try: - defaultmsg = "[mq]: %s" % patchfn + defaultmsg = b"[mq]: %s" % patchfn editor = cmdutil.getcommiteditor(editform=editform) if edit: @@ -1395,7 +1400,7 @@ return defaultmsg # i18n: this message is shown in editor with "HG: " prefix - extramsg = _("Leave message empty to use default message.") + extramsg = _(b"Leave message empty to use default message.") editor = cmdutil.getcommiteditor( finishdesc=finishdesc, extramsg=extramsg, @@ -1416,7 +1421,7 @@ editor=editor, ) if n is None: - raise error.Abort(_("repo commit failed")) + raise error.Abort(_(b"repo commit failed")) try: self.fullseries[insert:insert] = [patchfn] self.applied.append(statusentry(n, patchfn)) @@ -1428,11 +1433,11 @@ if user: ph.setuser(user) if date: - ph.setdate("%d %d" % date) + ph.setdate(b"%d %d" % date) ph.setparent(hex(nctx.p1().node())) msg = nctx.description().strip() if msg == defaultmsg.strip(): - msg = "" + msg = b"" ph.setmessage(msg) p.write(bytes(ph)) if commitfiles: @@ -1460,7 +1465,7 @@ try: os.unlink(patchpath) except OSError: - self.ui.warn(_("error unlinking %s\n") % patchpath) + self.ui.warn(_(b"error unlinking %s\n") % patchpath) raise self.removeundo(repo) @@ -1483,16 +1488,16 @@ return s matches = [x for x in self.series if s in x] if len(matches) > 1: - self.ui.warn(_('patch name "%s" is ambiguous:\n') % s) + self.ui.warn(_(b'patch name "%s" is ambiguous:\n') % s) for m in matches: - self.ui.warn(" %s\n" % m) + self.ui.warn(b" %s\n" % m) return None if matches: return matches[0] if self.series and self.applied: - if s == "qtip": + if s == b"qtip": return self.series[self.seriesend(True) - 1] - if s == "qbase": + if s == b"qbase": return self.series[0] return None @@ -1512,7 +1517,7 @@ res = partialname(patch) if res: return res - minus = patch.rfind("-") + minus = patch.rfind(b"-") if minus >= 0: res = partialname(patch[:minus]) if res: @@ -1524,7 +1529,7 @@ else: if i - off >= 0: return self.series[i - off] - plus = patch.rfind("+") + plus = patch.rfind(b"+") if plus >= 0: res = partialname(patch[:plus]) if res: @@ -1536,7 +1541,7 @@ else: if i + off < len(self.series): return self.series[i + off] - raise error.Abort(_("patch %s not in series") % patch) + raise error.Abort(_(b"patch %s not in series") % patch) def push( self, @@ -1560,10 +1565,10 @@ if not heads: heads = [nullid] if repo.dirstate.p1() not in heads and not exact: - self.ui.status(_("(working directory not at a head)\n")) + self.ui.status(_(b"(working directory not at a head)\n")) if not self.series: - self.ui.warn(_("no patches in series\n")) + self.ui.warn(_(b"no patches in series\n")) return 0 # Suppose our series file is: A B C and the current 'top' @@ -1574,26 +1579,30 @@ patch = self.lookup(patch) info = self.isapplied(patch) if info and info[0] >= len(self.applied) - 1: - self.ui.warn(_("qpush: %s is already at the top\n") % patch) + self.ui.warn( + _(b"qpush: %s is already at the top\n") % patch + ) return 0 pushable, reason = self.pushable(patch) if pushable: if self.series.index(patch) < self.seriesend(): raise error.Abort( - _("cannot push to a previous patch: %s") % patch + _(b"cannot push to a previous patch: %s") % patch ) else: if reason: - reason = _("guarded by %s") % reason + reason = _(b"guarded by %s") % reason else: - reason = _("no matching guards") - self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason)) + reason = _(b"no matching guards") + self.ui.warn( + _(b"cannot push '%s' - %s\n") % (patch, reason) + ) return 1 elif all: patch = self.series[-1] if self.isapplied(patch): - self.ui.warn(_("all patches are currently applied\n")) + self.ui.warn(_(b"all patches are currently applied\n")) return 0 # Following the above example, starting at 'top' of B: @@ -1603,7 +1612,7 @@ # work as it detects an error when done start = self.seriesend() if start == len(self.series): - self.ui.warn(_("patch series already fully applied\n")) + self.ui.warn(_(b"patch series already fully applied\n")) return 1 if not force and not keepchanges: self.checklocalchanges(repo, refresh=self.applied) @@ -1611,28 +1620,28 @@ if exact: if keepchanges: raise error.Abort( - _("cannot use --exact and --keep-changes together") + _(b"cannot use --exact and --keep-changes together") ) if move: raise error.Abort( - _("cannot use --exact and --move " "together") + _(b"cannot use --exact and --move " b"together") ) if self.applied: raise error.Abort( - _("cannot push --exact with applied " "patches") + _(b"cannot push --exact with applied " b"patches") ) root = self.series[start] target = patchheader(self.join(root), self.plainmode).parent if not target: raise error.Abort( - _("%s does not have a parent recorded") % root + _(b"%s does not have a parent recorded") % root ) - if not repo[target] == repo["."]: + if not repo[target] == repo[b"."]: hg.update(repo, target) if move: if not patch: - raise error.Abort(_("please specify the patch to move")) + raise error.Abort(_(b"please specify the patch to move")) for fullstart, rpn in enumerate(self.fullseries): # strip markers for patch guards if self.guard_re.split(rpn, 1)[0] == self.series[start]: @@ -1688,11 +1697,11 @@ except AbortNoCleanup: raise except: # re-raises - self.ui.warn(_("cleaning up working directory...\n")) + self.ui.warn(_(b"cleaning up working directory...\n")) cmdutil.revert( self.ui, repo, - repo["."], + repo[b"."], repo.dirstate.parents(), no_backup=True, ) @@ -1701,17 +1710,17 @@ for f in all_files: if f not in repo.dirstate: repo.wvfs.unlinkpath(f, ignoremissing=True) - self.ui.warn(_("done\n")) + self.ui.warn(_(b"done\n")) raise if not self.applied: return ret[0] top = self.applied[-1].name if ret[0] and ret[0] > 1: - msg = _("errors during apply, please fix and qrefresh %s\n") + msg = _(b"errors during apply, please fix and qrefresh %s\n") self.ui.write(msg % top) else: - self.ui.write(_("now at: %s\n") % top) + self.ui.write(_(b"now at: %s\n") % top) return ret[0] def pop( @@ -1733,12 +1742,12 @@ patch = self.lookup(patch) info = self.isapplied(patch) if not info: - raise error.Abort(_("patch %s is not applied") % patch) + raise error.Abort(_(b"patch %s is not applied") % patch) if not self.applied: # Allow qpop -a to work repeatedly, # but not qpop without an argument - self.ui.warn(_("no patches applied\n")) + self.ui.warn(_(b"no patches applied\n")) return not all if all: @@ -1749,7 +1758,7 @@ start = len(self.applied) - 1 if start >= len(self.applied): - self.ui.warn(_("qpop: %s is already at the top\n") % patch) + self.ui.warn(_(b"qpop: %s is already at the top\n") % patch) return if not update: @@ -1757,7 +1766,7 @@ rr = [x.node for x in self.applied] for p in parents: if p in rr: - self.ui.warn(_("qpop: forcing dirstate update\n")) + self.ui.warn(_(b"qpop: forcing dirstate update\n")) update = True else: parents = [p.node() for p in repo[None].parents()] @@ -1784,19 +1793,19 @@ heads = repo.changelog.heads(rev) except error.LookupError: node = short(rev) - raise error.Abort(_("trying to pop unknown node %s") % node) + raise error.Abort(_(b"trying to pop unknown node %s") % node) if heads != [self.applied[-1].node]: raise error.Abort( _( - "popping would remove a revision not " - "managed by this patch queue" + b"popping would remove a revision not " + b"managed by this patch queue" ) ) if not repo[self.applied[-1].node].mutable(): raise error.Abort( - _("popping would remove a public revision"), - hint=_("see 'hg help phases' for details"), + _(b"popping would remove a public revision"), + hint=_(b"see 'hg help phases' for details"), ) # we know there are no local changes, so we can make a simplified @@ -1804,13 +1813,13 @@ if update: qp = self.qparents(repo, rev) ctx = repo[qp] - m, a, r, d = repo.status(qp, ".")[:4] + m, a, r, d = repo.status(qp, b".")[:4] if d: - raise error.Abort(_("deletions found between repo revs")) + raise error.Abort(_(b"deletions found between repo revs")) tobackup = set(a + m + r) & tobackup if keepchanges and tobackup: - raise error.Abort(_("local changes found, qrefresh first")) + raise error.Abort(_(b"local changes found, qrefresh first")) self.backup(repo, tobackup) with repo.dirstate.parentchange(): for f in a: @@ -1822,23 +1831,23 @@ repo.dirstate.normal(f) repo.setparents(qp, nullid) for patch in reversed(self.applied[start:end]): - self.ui.status(_("popping %s\n") % patch.name) + self.ui.status(_(b"popping %s\n") % patch.name) del self.applied[start:end] strip(self.ui, repo, [rev], update=False, backup=False) - for s, state in repo["."].substate.items(): - repo["."].sub(s).get(state) + for s, state in repo[b"."].substate.items(): + repo[b"."].sub(s).get(state) if self.applied: - self.ui.write(_("now at: %s\n") % self.applied[-1].name) + self.ui.write(_(b"now at: %s\n") % self.applied[-1].name) else: - self.ui.write(_("patch queue now empty\n")) + self.ui.write(_(b"patch queue now empty\n")) def diff(self, repo, pats, opts): top, patch = self.checktoppatch(repo) if not top: - self.ui.write(_("no patches applied\n")) + self.ui.write(_(b"no patches applied\n")) return qp = self.qparents(repo, top) - if opts.get("reverse"): + if opts.get(b"reverse"): node1, node2 = None, qp else: node1, node2 = qp, None @@ -1848,26 +1857,28 @@ def refresh(self, repo, pats=None, **opts): opts = pycompat.byteskwargs(opts) if not self.applied: - self.ui.write(_("no patches applied\n")) + self.ui.write(_(b"no patches applied\n")) return 1 - msg = opts.get("msg", "").rstrip() - edit = opts.get("edit") - editform = opts.get("editform", "mq.qrefresh") - newuser = opts.get("user") - newdate = opts.get("date") + msg = opts.get(b"msg", b"").rstrip() + edit = opts.get(b"edit") + editform = opts.get(b"editform", b"mq.qrefresh") + newuser = opts.get(b"user") + newdate = opts.get(b"date") if newdate: - newdate = "%d %d" % dateutil.parsedate(newdate) + newdate = b"%d %d" % dateutil.parsedate(newdate) wlock = repo.wlock() try: self.checktoppatch(repo) (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) if repo.changelog.heads(top) != [top]: - raise error.Abort(_("cannot qrefresh a revision with children")) + raise error.Abort( + _(b"cannot qrefresh a revision with children") + ) if not repo[top].mutable(): raise error.Abort( - _("cannot qrefresh public revision"), - hint=_("see 'hg help phases' for details"), + _(b"cannot qrefresh public revision"), + hint=_(b"see 'hg help phases' for details"), ) cparents = repo.changelog.parents(top) @@ -1875,11 +1886,11 @@ inclsubs = checksubstate(repo, patchparent) if inclsubs: - substatestate = repo.dirstate[".hgsubstate"] + substatestate = repo.dirstate[b".hgsubstate"] ph = patchheader(self.join(patchfn), self.plainmode) diffopts = self.diffopts( - {"git": opts.get("git")}, patchfn, plain=True + {b"git": opts.get(b"git")}, patchfn, plain=True ) if newuser: ph.setuser(newuser) @@ -1888,7 +1899,7 @@ ph.setparent(hex(patchparent)) # only commit new patch when write is complete - patchf = self.opener(patchfn, "w", atomictemp=True) + patchf = self.opener(patchfn, b"w", atomictemp=True) # update the dirstate in place, strip off the qtip commit # and then commit. @@ -1903,7 +1914,7 @@ match1 = scmutil.match(repo[None], pats, opts) # in short mode, we only diff the files included in the # patch already plus specified files - if opts.get("short"): + if opts.get(b"short"): # if amending a patch, we start with existing # files plus specified files - unfiltered match = scmutil.matchfiles(repo, mm + aa + dd + match1.files()) @@ -1963,7 +1974,7 @@ dsguard = None try: - dsguard = dirstateguard.dirstateguard(repo, "mq.refresh") + dsguard = dirstateguard.dirstateguard(repo, b"mq.refresh") if diffopts.git or diffopts.upgrade: copies = {} for dst in a: @@ -2026,7 +2037,7 @@ try: # might be nice to attempt to roll back strip after this - defaultmsg = "[mq]: %s" % patchfn + defaultmsg = b"[mq]: %s" % patchfn editor = cmdutil.getcommiteditor(editform=editform) if edit: @@ -2037,18 +2048,18 @@ return defaultmsg # i18n: this message is shown in editor with "HG: " prefix - extramsg = _("Leave message empty to use default message.") + extramsg = _(b"Leave message empty to use default message.") editor = cmdutil.getcommiteditor( finishdesc=finishdesc, extramsg=extramsg, editform=editform, ) - message = msg or "\n".join(ph.message) + message = msg or b"\n".join(ph.message) elif not msg: if not ph.message: message = defaultmsg else: - message = "\n".join(ph.message) + message = b"\n".join(ph.message) else: message = msg ph.setmessage(msg) @@ -2058,7 +2069,7 @@ lock = tr = None try: lock = repo.lock() - tr = repo.transaction("mq") + tr = repo.transaction(b"mq") n = newcommit( repo, oldphase, @@ -2096,8 +2107,8 @@ self.savedirty() self.ui.warn( _( - "qrefresh interrupted while patch was popped! " - "(revert --all, qpush to recover)\n" + b"qrefresh interrupted while patch was popped! " + b"(revert --all, qpush to recover)\n" ) ) raise @@ -2107,7 +2118,7 @@ def init(self, repo, create=False): if not create and os.path.isdir(self.path): - raise error.Abort(_("patch queue directory already exists")) + raise error.Abort(_(b"patch queue directory already exists")) try: os.mkdir(self.path) except OSError as inst: @@ -2118,7 +2129,7 @@ def unapplied(self, repo, patch=None): if patch and patch not in self.series: - raise error.Abort(_("patch %s is not in series file") % patch) + raise error.Abort(_(b"patch %s is not in series file") % patch) if not patch: start = self.seriesend() else: @@ -2148,38 +2159,38 @@ if ph.message: msg = ph.message[0] else: - msg = "" + msg = b"" if self.ui.formatted(): width = self.ui.termwidth() - len(pfx) - len(patchname) - 2 if width > 0: msg = stringutil.ellipsis(msg, width) else: - msg = "" - self.ui.write(patchname, label="qseries." + state) - self.ui.write(": ") - self.ui.write(msg, label="qseries.message." + state) + msg = b"" + self.ui.write(patchname, label=b"qseries." + state) + self.ui.write(b": ") + self.ui.write(msg, label=b"qseries.message." + state) else: - self.ui.write(patchname, label="qseries." + state) - self.ui.write("\n") + self.ui.write(patchname, label=b"qseries." + state) + self.ui.write(b"\n") applied = {p.name for p in self.applied} if length is None: length = len(self.series) - start if not missing: if self.ui.verbose: - idxwidth = len("%d" % (start + length - 1)) + idxwidth = len(b"%d" % (start + length - 1)) for i in pycompat.xrange(start, start + length): patch = self.series[i] if patch in applied: - char, state = "A", "applied" + char, state = b"A", b"applied" elif self.pushable(i)[0]: - char, state = "U", "unapplied" + char, state = b"U", b"unapplied" else: - char, state = "G", "guarded" - pfx = "" + char, state = b"G", b"guarded" + pfx = b"" if self.ui.verbose: - pfx = "%*d %s " % (idxwidth, i, char) + pfx = b"%*d %s " % (idxwidth, i, char) elif status and status != char: continue displayname(pfx, patch, state) @@ -2197,15 +2208,15 @@ self.seriespath, self.guardspath, ) - and not fl.startswith(".") + and not fl.startswith(b".") ): msng_list.append(fl) for x in sorted(msng_list): - pfx = self.ui.verbose and "D " or "" - displayname(pfx, x, "missing") + pfx = self.ui.verbose and b"D " or b"" + displayname(pfx, x, b"missing") def issaveline(self, l): - if l.name == ".hg.patches.save.line": + if l.name == b".hg.patches.save.line": return True def qrepo(self, create=False): @@ -2215,15 +2226,18 @@ ui.pageractive = self.ui.pageractive # internal config: ui.formatted ui.setconfig( - "ui", "formatted", self.ui.config("ui", "formatted"), "mqpager" + b"ui", + b"formatted", + self.ui.config(b"ui", b"formatted"), + b"mqpager", ) ui.setconfig( - "ui", - "interactive", - self.ui.config("ui", "interactive"), - "mqpager", + b"ui", + b"interactive", + self.ui.config(b"ui", b"interactive"), + b"mqpager", ) - if create or os.path.isdir(self.join(".hg")): + if create or os.path.isdir(self.join(b".hg")): return hg.repository(ui, path=self.path, create=create) def restore(self, repo, rev, delete=None, qupdate=None): @@ -2235,23 +2249,23 @@ applied = [] qpp = None for i, line in enumerate(lines): - if line == "Patch Data:": + if line == b"Patch Data:": datastart = i + 1 - elif line.startswith("Dirstate:"): + elif line.startswith(b"Dirstate:"): l = line.rstrip() - l = l[10:].split(" ") + l = l[10:].split(b" ") qpp = [bin(x) for x in l] elif datastart is not None: l = line.rstrip() - n, name = l.split(":", 1) + n, name = l.split(b":", 1) if n: applied.append(statusentry(bin(n), name)) else: series.append(l) if datastart is None: - self.ui.warn(_("no saved patch data found\n")) + self.ui.warn(_(b"no saved patch data found\n")) return 1 - self.ui.warn(_("restoring status: %s\n") % lines[0]) + self.ui.warn(_(b"restoring status: %s\n") % lines[0]) self.fullseries = series self.applied = applied self.parseseries() @@ -2260,9 +2274,9 @@ heads = repo.changelog.heads() if delete: if rev not in heads: - self.ui.warn(_("save entry has children, leaving it alone\n")) + self.ui.warn(_(b"save entry has children, leaving it alone\n")) else: - self.ui.warn(_("removing save entry %s\n") % short(rev)) + self.ui.warn(_(b"removing save entry %s\n") % short(rev)) pp = repo.dirstate.parents() if rev in pp: update = True @@ -2271,41 +2285,41 @@ strip(self.ui, repo, [rev], update=update, backup=False) if qpp: self.ui.warn( - _("saved queue repository parents: %s %s\n") + _(b"saved queue repository parents: %s %s\n") % (short(qpp[0]), short(qpp[1])) ) if qupdate: - self.ui.status(_("updating queue directory\n")) + self.ui.status(_(b"updating queue directory\n")) r = self.qrepo() if not r: - self.ui.warn(_("unable to load queue repository\n")) + self.ui.warn(_(b"unable to load queue repository\n")) return 1 hg.clean(r, qpp[0]) def save(self, repo, msg=None): if not self.applied: - self.ui.warn(_("save: no patches applied, exiting\n")) + self.ui.warn(_(b"save: no patches applied, exiting\n")) return 1 if self.issaveline(self.applied[-1]): - self.ui.warn(_("status is already saved\n")) + self.ui.warn(_(b"status is already saved\n")) return 1 if not msg: - msg = _("hg patches saved state") + msg = _(b"hg patches saved state") else: - msg = "hg patches: " + msg.rstrip("\r\n") + msg = b"hg patches: " + msg.rstrip(b"\r\n") r = self.qrepo() if r: pp = r.dirstate.parents() - msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1])) - msg += "\n\nPatch Data:\n" - msg += "".join("%s\n" % x for x in self.applied) - msg += "".join(":%s\n" % x for x in self.fullseries) + msg += b"\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1])) + msg += b"\n\nPatch Data:\n" + msg += b"".join(b"%s\n" % x for x in self.applied) + msg += b"".join(b":%s\n" % x for x in self.fullseries) n = repo.commit(msg, force=True) if not n: - self.ui.warn(_("repo commit failed\n")) + self.ui.warn(_(b"repo commit failed\n")) return 1 - self.applied.append(statusentry(n, ".hg.patches.save.line")) + self.applied.append(statusentry(n, b".hg.patches.save.line")) self.applieddirty = True self.removeundo(repo) @@ -2349,7 +2363,7 @@ if not self.ui.verbose: p = pname else: - p = ("%d" % self.series.index(pname)) + " " + pname + p = (b"%d" % self.series.index(pname)) + b" " + pname return p def qimport( @@ -2365,21 +2379,21 @@ def checkseries(patchname): if patchname in self.series: raise error.Abort( - _("patch %s is already in the series file") % patchname + _(b"patch %s is already in the series file") % patchname ) if rev: if files: raise error.Abort( - _('option "-r" not valid when importing ' "files") + _(b'option "-r" not valid when importing ' b"files") ) rev = scmutil.revrange(repo, rev) rev.sort(reverse=True) elif not files: - raise error.Abort(_("no files or revisions specified")) + raise error.Abort(_(b"no files or revisions specified")) if (len(files) > 1 or len(rev) > 1) and patchname: raise error.Abort( - _('option "-n" not valid when importing multiple ' "patches") + _(b'option "-n" not valid when importing multiple ' b"patches") ) imported = [] if rev: @@ -2389,18 +2403,18 @@ heads = repo.changelog.heads(repo.changelog.node(rev.first())) if len(heads) > 1: raise error.Abort( - _("revision %d is the root of more than one " "branch") + _(b"revision %d is the root of more than one " b"branch") % rev.last() ) if self.applied: base = repo.changelog.node(rev.first()) if base in [n.node for n in self.applied]: raise error.Abort( - _("revision %d is already managed") % rev.first() + _(b"revision %d is already managed") % rev.first() ) if heads != [self.applied[-1].node]: raise error.Abort( - _("revision %d is not the parent of " "the queue") + _(b"revision %d is not the parent of " b"the queue") % rev.first() ) base = repo.changelog.rev(self.applied[0].node) @@ -2408,41 +2422,41 @@ else: if heads != [repo.changelog.node(rev.first())]: raise error.Abort( - _("revision %d has unmanaged children") % rev.first() + _(b"revision %d has unmanaged children") % rev.first() ) lastparent = None - diffopts = self.diffopts({"git": git}) - with repo.transaction("qimport") as tr: + diffopts = self.diffopts({b"git": git}) + with repo.transaction(b"qimport") as tr: for r in rev: if not repo[r].mutable(): raise error.Abort( - _("revision %d is not mutable") % r, - hint=_("see 'hg help phases' " "for details"), + _(b"revision %d is not mutable") % r, + hint=_(b"see 'hg help phases' " b"for details"), ) p1, p2 = repo.changelog.parentrevs(r) n = repo.changelog.node(r) if p2 != nullrev: raise error.Abort( - _("cannot import merge revision %d") % r + _(b"cannot import merge revision %d") % r ) if lastparent and lastparent != r: raise error.Abort( - _("revision %d is not the parent of " "%d") + _(b"revision %d is not the parent of " b"%d") % (r, lastparent) ) lastparent = p1 if not patchname: patchname = self.makepatchname( - repo[r].description().split("\n", 1)[0], - "%d.diff" % r, + repo[r].description().split(b"\n", 1)[0], + b"%d.diff" % r, ) checkseries(patchname) self.checkpatchname(patchname, force) self.fullseries.insert(0, patchname) - with self.opener(patchname, "w") as fp: + with self.opener(patchname, b"w") as fp: cmdutil.exportfile(repo, [n], fp, opts=diffopts) se = statusentry(n, patchname) @@ -2451,7 +2465,7 @@ self.added.append(patchname) imported.append(patchname) patchname = None - if rev and repo.ui.configbool("mq", "secret"): + if rev and repo.ui.configbool(b"mq", b"secret"): # if we added anything with --rev, move the secret root phases.retractboundary(repo, tr, phases.secret, [n]) self.parseseries() @@ -2460,9 +2474,9 @@ for i, filename in enumerate(files): if existing: - if filename == "-": + if filename == b"-": raise error.Abort( - _("-e is incompatible with import from -") + _(b"-e is incompatible with import from -") ) filename = normname(filename) self.checkreservedname(filename) @@ -2470,35 +2484,39 @@ originpath = self.join(filename) if not os.path.isfile(originpath): raise error.Abort( - _("patch %s does not exist") % filename + _(b"patch %s does not exist") % filename ) if patchname: self.checkpatchname(patchname, force) self.ui.write( - _("renaming %s to %s\n") % (filename, patchname) + _(b"renaming %s to %s\n") % (filename, patchname) ) util.rename(originpath, self.join(patchname)) else: patchname = filename else: - if filename == "-" and not patchname: - raise error.Abort(_("need --name to import a patch from -")) + if filename == b"-" and not patchname: + raise error.Abort( + _(b"need --name to import a patch from -") + ) elif not patchname: - patchname = normname(os.path.basename(filename.rstrip("/"))) + patchname = normname( + os.path.basename(filename.rstrip(b"/")) + ) self.checkpatchname(patchname, force) try: - if filename == "-": + if filename == b"-": text = self.ui.fin.read() else: fp = hg.openpath(self.ui, filename) text = fp.read() fp.close() except (OSError, IOError): - raise error.Abort(_("unable to read file %s") % filename) - patchf = self.opener(patchname, "w") + raise error.Abort(_(b"unable to read file %s") % filename) + patchf = self.opener(patchname, b"w") patchf.write(text) patchf.close() if not force: @@ -2508,7 +2526,7 @@ self.fullseries[index:index] = [patchname] self.parseseries() self.seriesdirty = True - self.ui.warn(_("adding %s to series file\n") % patchname) + self.ui.warn(_(b"adding %s to series file\n") % patchname) self.added.append(patchname) imported.append(patchname) patchname = None @@ -2519,23 +2537,29 @@ def fixkeepchangesopts(ui, opts): if ( - not ui.configbool("mq", "keepchanges") - or opts.get("force") - or opts.get("exact") + not ui.configbool(b"mq", b"keepchanges") + or opts.get(b"force") + or opts.get(b"exact") ): return opts opts = dict(opts) - opts["keep_changes"] = True + opts[b"keep_changes"] = True return opts @command( - "qdelete|qremove|qrm", + b"qdelete|qremove|qrm", [ - ("k", "keep", None, _("keep patch file")), - ("r", "rev", [], _("stop managing a revision (DEPRECATED)"), _("REV")), + (b"k", b"keep", None, _(b"keep patch file")), + ( + b"r", + b"rev", + [], + _(b"stop managing a revision (DEPRECATED)"), + _(b"REV"), + ), ], - _("hg qdelete [-k] [PATCH]..."), + _(b"hg qdelete [-k] [PATCH]..."), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def delete(ui, repo, *patches, **opts): @@ -2554,10 +2578,10 @@ @command( - "qapplied", - [("1", "last", None, _("show only the preceding applied patch"))] + b"qapplied", + [(b"1", b"last", None, _(b"show only the preceding applied patch"))] + seriesopts, - _("hg qapplied [-1] [-s] [PATCH]"), + _(b"hg qapplied [-1] [-s] [PATCH]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def applied(ui, repo, patch=None, **opts): @@ -2570,32 +2594,32 @@ if patch: if patch not in q.series: - raise error.Abort(_("patch %s is not in series file") % patch) + raise error.Abort(_(b"patch %s is not in series file") % patch) end = q.series.index(patch) + 1 else: end = q.seriesend(True) - if opts.get("last") and not end: - ui.write(_("no patches applied\n")) + if opts.get(b"last") and not end: + ui.write(_(b"no patches applied\n")) return 1 - elif opts.get("last") and end == 1: - ui.write(_("only one patch applied\n")) + elif opts.get(b"last") and end == 1: + ui.write(_(b"only one patch applied\n")) return 1 - elif opts.get("last"): + elif opts.get(b"last"): start = end - 2 end = 1 else: start = 0 q.qseries( - repo, length=end, start=start, status="A", summary=opts.get("summary") + repo, length=end, start=start, status=b"A", summary=opts.get(b"summary") ) @command( - "qunapplied", - [("1", "first", None, _("show only the first patch"))] + seriesopts, - _("hg qunapplied [-1] [-s] [PATCH]"), + b"qunapplied", + [(b"1", b"first", None, _(b"show only the first patch"))] + seriesopts, + _(b"hg qunapplied [-1] [-s] [PATCH]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def unapplied(ui, repo, patch=None, **opts): @@ -2607,16 +2631,16 @@ opts = pycompat.byteskwargs(opts) if patch: if patch not in q.series: - raise error.Abort(_("patch %s is not in series file") % patch) + raise error.Abort(_(b"patch %s is not in series file") % patch) start = q.series.index(patch) + 1 else: start = q.seriesend(True) - if start == len(q.series) and opts.get("first"): - ui.write(_("all patches applied\n")) + if start == len(q.series) and opts.get(b"first"): + ui.write(_(b"all patches applied\n")) return 1 - if opts.get("first"): + if opts.get(b"first"): length = 1 else: length = None @@ -2624,28 +2648,28 @@ repo, start=start, length=length, - status="U", - summary=opts.get("summary"), + status=b"U", + summary=opts.get(b"summary"), ) @command( - "qimport", + b"qimport", [ - ("e", "existing", None, _("import file in patch directory")), - ("n", "name", "", _("name of patch file"), _("NAME")), - ("f", "force", None, _("overwrite existing files")), + (b"e", b"existing", None, _(b"import file in patch directory")), + (b"n", b"name", b"", _(b"name of patch file"), _(b"NAME")), + (b"f", b"force", None, _(b"overwrite existing files")), ( - "r", - "rev", + b"r", + b"rev", [], - _("place existing revisions under mq control"), - _("REV"), + _(b"place existing revisions under mq control"), + _(b"REV"), ), - ("g", "git", None, _("use git extended diff format")), - ("P", "push", None, _("qpush after importing")), + (b"g", b"git", None, _(b"use git extended diff format")), + (b"P", b"push", None, _(b"qpush after importing")), ], - _("hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]..."), + _(b"hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]..."), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def qimport(ui, repo, *filename, **opts): @@ -2689,16 +2713,16 @@ imported = q.qimport( repo, filename, - patchname=opts.get("name"), - existing=opts.get("existing"), - force=opts.get("force"), - rev=opts.get("rev"), - git=opts.get("git"), + patchname=opts.get(b"name"), + existing=opts.get(b"existing"), + force=opts.get(b"force"), + rev=opts.get(b"rev"), + git=opts.get(b"git"), ) finally: q.savedirty() - if imported and opts.get("push") and not opts.get("rev"): + if imported and opts.get(b"push") and not opts.get(b"rev"): return q.push(repo, imported[-1]) return 0 @@ -2715,25 +2739,25 @@ r = q.init(repo, create) q.savedirty() if r: - if not os.path.exists(r.wjoin(".hgignore")): - fp = r.wvfs(".hgignore", "w") - fp.write("^\\.hg\n") - fp.write("^\\.mq\n") - fp.write("syntax: glob\n") - fp.write("status\n") - fp.write("guards\n") + if not os.path.exists(r.wjoin(b".hgignore")): + fp = r.wvfs(b".hgignore", b"w") + fp.write(b"^\\.hg\n") + fp.write(b"^\\.mq\n") + fp.write(b"syntax: glob\n") + fp.write(b"status\n") + fp.write(b"guards\n") fp.close() - if not os.path.exists(r.wjoin("series")): - r.wvfs("series", "w").close() - r[None].add([".hgignore", "series"]) + if not os.path.exists(r.wjoin(b"series")): + r.wvfs(b"series", b"w").close() + r[None].add([b".hgignore", b"series"]) commands.add(ui, r) return 0 @command( - "qinit", - [("c", "create-repo", None, _("create queue repository"))], - _("hg qinit [-c]"), + b"qinit", + [(b"c", b"create-repo", None, _(b"create queue repository"))], + _(b"hg qinit [-c]"), helpcategory=command.CATEGORY_REPO_CREATION, helpbasic=True, ) @@ -2752,26 +2776,31 @@ @command( - "qclone", + b"qclone", [ - ("", "pull", None, _("use pull protocol to copy metadata")), - ("U", "noupdate", None, _("do not update the new working directories")), + (b"", b"pull", None, _(b"use pull protocol to copy metadata")), ( - "", - "uncompressed", + b"U", + b"noupdate", None, - _("use uncompressed transfer (fast over LAN)"), + _(b"do not update the new working directories"), ), ( - "p", - "patches", - "", - _("location of source patch repository"), - _("REPO"), + b"", + b"uncompressed", + None, + _(b"use uncompressed transfer (fast over LAN)"), + ), + ( + b"p", + b"patches", + b"", + _(b"location of source patch repository"), + _(b"REPO"), ), ] + cmdutil.remoteopts, - _("hg qclone [OPTION]... SOURCE [DEST]"), + _(b"hg qclone [OPTION]... SOURCE [DEST]"), helpcategory=command.CATEGORY_REPO_CREATION, norepo=True, ) @@ -2797,9 +2826,9 @@ def patchdir(repo): """compute a patch repo url from a repo object""" url = repo.url() - if url.endswith("/"): + if url.endswith(b"/"): url = url[:-1] - return url + "/.hg/patches" + return url + b"/.hg/patches" # main repo (destination and sources) if dest is None: @@ -2807,15 +2836,15 @@ sr = hg.peer(ui, opts, ui.expandpath(source)) # patches repo (source only) - if opts.get("patches"): - patchespath = ui.expandpath(opts.get("patches")) + if opts.get(b"patches"): + patchespath = ui.expandpath(opts.get(b"patches")) else: patchespath = patchdir(sr) try: hg.peer(ui, opts, patchespath) except error.RepoError: raise error.Abort( - _("versioned patch repository not found" " (see init --mq)") + _(b"versioned patch repository not found" b" (see init --mq)") ) qbase, destrev = None, None if sr.local(): @@ -2826,51 +2855,54 @@ heads = set(repo.heads()) destrev = list(heads.difference(repo.heads(qbase))) destrev.append(repo.changelog.parents(qbase)[0]) - elif sr.capable("lookup"): + elif sr.capable(b"lookup"): try: - qbase = sr.lookup("qbase") + qbase = sr.lookup(b"qbase") except error.RepoError: pass - ui.note(_("cloning main repository\n")) + ui.note(_(b"cloning main repository\n")) sr, dr = hg.clone( ui, opts, sr.url(), dest, - pull=opts.get("pull"), + pull=opts.get(b"pull"), revs=destrev, update=False, - stream=opts.get("uncompressed"), + stream=opts.get(b"uncompressed"), ) - ui.note(_("cloning patch repository\n")) + ui.note(_(b"cloning patch repository\n")) hg.clone( ui, opts, - opts.get("patches") or patchdir(sr), + opts.get(b"patches") or patchdir(sr), patchdir(dr), - pull=opts.get("pull"), - update=not opts.get("noupdate"), - stream=opts.get("uncompressed"), + pull=opts.get(b"pull"), + update=not opts.get(b"noupdate"), + stream=opts.get(b"uncompressed"), ) if dr.local(): repo = dr.local() if qbase: ui.note( - _("stripping applied patches from destination " "repository\n") + _( + b"stripping applied patches from destination " + b"repository\n" + ) ) strip(ui, repo, [qbase], update=False, backup=None) - if not opts.get("noupdate"): - ui.note(_("updating destination repository\n")) + if not opts.get(b"noupdate"): + ui.note(_(b"updating destination repository\n")) hg.update(repo, repo.changelog.tip()) @command( - "qcommit|qci", - commands.table["commit|ci"][1], - _("hg qcommit [OPTION]... [FILE]..."), + b"qcommit|qci", + commands.table[b"commit|ci"][1], + _(b"hg qcommit [OPTION]... [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, inferrepo=True, ) @@ -2881,14 +2913,14 @@ q = repo.mq r = q.qrepo() if not r: - raise error.Abort("no queue repository") + raise error.Abort(b"no queue repository") commands.commit(r.ui, r, *pats, **opts) @command( - "qseries", - [("m", "missing", None, _("print patches not in series")),] + seriesopts, - _("hg qseries [-ms]"), + b"qseries", + [(b"m", b"missing", None, _(b"print patches not in series")),] + seriesopts, + _(b"hg qseries [-ms]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def series(ui, repo, **opts): @@ -2902,9 +2934,9 @@ @command( - "qtop", + b"qtop", seriesopts, - _("hg qtop [-s]"), + _(b"hg qtop [-s]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def top(ui, repo, **opts): @@ -2922,18 +2954,18 @@ repo, start=t - 1, length=1, - status="A", + status=b"A", summary=opts.get(r"summary"), ) else: - ui.write(_("no patches applied\n")) + ui.write(_(b"no patches applied\n")) return 1 @command( - "qnext", + b"qnext", seriesopts, - _("hg qnext [-s]"), + _(b"hg qnext [-s]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def next(ui, repo, **opts): @@ -2943,15 +2975,15 @@ q = repo.mq end = q.seriesend() if end == len(q.series): - ui.write(_("all patches applied\n")) + ui.write(_(b"all patches applied\n")) return 1 q.qseries(repo, start=end, length=1, summary=opts.get(r"summary")) @command( - "qprev", + b"qprev", seriesopts, - _("hg qprev [-s]"), + _(b"hg qprev [-s]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def prev(ui, repo, **opts): @@ -2961,38 +2993,38 @@ q = repo.mq l = len(q.applied) if l == 1: - ui.write(_("only one patch applied\n")) + ui.write(_(b"only one patch applied\n")) return 1 if not l: - ui.write(_("no patches applied\n")) + ui.write(_(b"no patches applied\n")) return 1 idx = q.series.index(q.applied[-2].name) q.qseries( - repo, start=idx, length=1, status="A", summary=opts.get(r"summary") + repo, start=idx, length=1, status=b"A", summary=opts.get(r"summary") ) def setupheaderopts(ui, opts): - if not opts.get("user") and opts.get("currentuser"): - opts["user"] = ui.username() - if not opts.get("date") and opts.get("currentdate"): - opts["date"] = "%d %d" % dateutil.makedate() + if not opts.get(b"user") and opts.get(b"currentuser"): + opts[b"user"] = ui.username() + if not opts.get(b"date") and opts.get(b"currentdate"): + opts[b"date"] = b"%d %d" % dateutil.makedate() @command( - "qnew", + b"qnew", [ - ("e", "edit", None, _("invoke editor on commit messages")), - ("f", "force", None, _("import uncommitted changes (DEPRECATED)")), - ("g", "git", None, _("use git extended diff format")), - ("U", "currentuser", None, _('add "From: " to patch')), - ("u", "user", "", _('add "From: " to patch'), _("USER")), - ("D", "currentdate", None, _('add "Date: " to patch')), - ("d", "date", "", _('add "Date: " to patch'), _("DATE")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), + (b"f", b"force", None, _(b"import uncommitted changes (DEPRECATED)")), + (b"g", b"git", None, _(b"use git extended diff format")), + (b"U", b"currentuser", None, _(b'add "From: " to patch')), + (b"u", b"user", b"", _(b'add "From: " to patch'), _(b"USER")), + (b"D", b"currentdate", None, _(b'add "Date: " to patch')), + (b"d", b"date", b"", _(b'add "Date: " to patch'), _(b"DATE")), ] + cmdutil.walkopts + cmdutil.commitopts, - _("hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]..."), + _(b"hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, inferrepo=True, @@ -3025,7 +3057,7 @@ opts = pycompat.byteskwargs(opts) msg = cmdutil.logmessage(ui, opts) q = repo.mq - opts["msg"] = msg + opts[b"msg"] = msg setupheaderopts(ui, opts) q.new(repo, patch, *args, **pycompat.strkwargs(opts)) q.savedirty() @@ -3033,46 +3065,46 @@ @command( - "qrefresh", + b"qrefresh", [ - ("e", "edit", None, _("invoke editor on commit messages")), - ("g", "git", None, _("use git extended diff format")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), + (b"g", b"git", None, _(b"use git extended diff format")), ( - "s", - "short", + b"s", + b"short", None, - _("refresh only files already in the patch and specified files"), + _(b"refresh only files already in the patch and specified files"), ), ( - "U", - "currentuser", + b"U", + b"currentuser", None, - _("add/update author field in patch with current user"), + _(b"add/update author field in patch with current user"), ), ( - "u", - "user", - "", - _("add/update author field in patch with given user"), - _("USER"), + b"u", + b"user", + b"", + _(b"add/update author field in patch with given user"), + _(b"USER"), ), ( - "D", - "currentdate", + b"D", + b"currentdate", None, - _("add/update date field in patch with current date"), + _(b"add/update date field in patch with current date"), ), ( - "d", - "date", - "", - _("add/update date field in patch with given date"), - _("DATE"), + b"d", + b"date", + b"", + _(b"add/update date field in patch with given date"), + _(b"DATE"), ), ] + cmdutil.walkopts + cmdutil.commitopts, - _("hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]..."), + _(b"hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, inferrepo=True, @@ -3109,9 +3141,9 @@ @command( - "qdiff", + b"qdiff", cmdutil.diffopts + cmdutil.diffopts2 + cmdutil.walkopts, - _("hg qdiff [OPTION]... [FILE]..."), + _(b"hg qdiff [OPTION]... [FILE]..."), helpcategory=command.CATEGORY_FILE_CONTENTS, helpbasic=True, inferrepo=True, @@ -3131,19 +3163,19 @@ Returns 0 on success. """ - ui.pager("qdiff") + ui.pager(b"qdiff") repo.mq.diff(repo, pats, pycompat.byteskwargs(opts)) return 0 @command( - "qfold", + b"qfold", [ - ("e", "edit", None, _("invoke editor on commit messages")), - ("k", "keep", None, _("keep folded patch files")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), + (b"k", b"keep", None, _(b"keep folded patch files")), ] + cmdutil.commitopts, - _("hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH..."), + _(b"hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH..."), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def fold(ui, repo, *files, **opts): @@ -3163,23 +3195,23 @@ opts = pycompat.byteskwargs(opts) q = repo.mq if not files: - raise error.Abort(_("qfold requires at least one patch name")) + raise error.Abort(_(b"qfold requires at least one patch name")) if not q.checktoppatch(repo)[0]: - raise error.Abort(_("no patches applied")) + raise error.Abort(_(b"no patches applied")) q.checklocalchanges(repo) message = cmdutil.logmessage(ui, opts) - parent = q.lookup("qtip") + parent = q.lookup(b"qtip") patches = [] messages = [] for f in files: p = q.lookup(f) if p in patches or p == parent: - ui.warn(_("skipping already folded patch %s\n") % p) + ui.warn(_(b"skipping already folded patch %s\n") % p) if q.isapplied(p): raise error.Abort( - _("qfold cannot fold already applied patch %s") % p + _(b"qfold cannot fold already applied patch %s") % p ) patches.append(p) @@ -3191,7 +3223,7 @@ pf = q.join(p) (patchsuccess, files, fuzz) = q.patch(repo, pf) if not patchsuccess: - raise error.Abort(_("error folding patch %s") % p) + raise error.Abort(_(b"error folding patch %s") % p) if not message: ph = patchheader(q.join(parent), q.plainmode) @@ -3199,9 +3231,9 @@ for msg in messages: if msg: if message: - message.append("* * *") + message.append(b"* * *") message.extend(msg) - message = "\n".join(message) + message = b"\n".join(message) diffopts = q.patchopts(q.diffopts(), *patches) with repo.wlock(): @@ -3209,21 +3241,26 @@ repo, msg=message, git=diffopts.git, - edit=opts.get("edit"), - editform="mq.qfold", + edit=opts.get(b"edit"), + editform=b"mq.qfold", ) q.delete(repo, patches, opts) q.savedirty() @command( - "qgoto", + b"qgoto", [ - ("", "keep-changes", None, _("tolerate non-conflicting local changes")), - ("f", "force", None, _("overwrite any local changes")), - ("", "no-backup", None, _("do not save backup copies of files")), + ( + b"", + b"keep-changes", + None, + _(b"tolerate non-conflicting local changes"), + ), + (b"f", b"force", None, _(b"overwrite any local changes")), + (b"", b"no-backup", None, _(b"do not save backup copies of files")), ], - _("hg qgoto [OPTION]... PATCH"), + _(b"hg qgoto [OPTION]... PATCH"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def goto(ui, repo, patch, **opts): @@ -3234,13 +3271,13 @@ opts = fixkeepchangesopts(ui, opts) q = repo.mq patch = q.lookup(patch) - nobackup = opts.get("no_backup") - keepchanges = opts.get("keep_changes") + nobackup = opts.get(b"no_backup") + keepchanges = opts.get(b"keep_changes") if q.isapplied(patch): ret = q.pop( repo, patch, - force=opts.get("force"), + force=opts.get(b"force"), nobackup=nobackup, keepchanges=keepchanges, ) @@ -3248,7 +3285,7 @@ ret = q.push( repo, patch, - force=opts.get("force"), + force=opts.get(b"force"), nobackup=nobackup, keepchanges=keepchanges, ) @@ -3257,12 +3294,12 @@ @command( - "qguard", + b"qguard", [ - ("l", "list", None, _("list all patches and guards")), - ("n", "none", None, _("drop all guards")), + (b"l", b"list", None, _(b"list all patches and guards")), + (b"n", b"none", None, _(b"drop all guards")), ], - _("hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]"), + _(b"hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def guard(ui, repo, *args, **opts): @@ -3289,26 +3326,26 @@ """ def status(idx): - guards = q.seriesguards[idx] or ["unguarded"] + guards = q.seriesguards[idx] or [b"unguarded"] if q.series[idx] in applied: - state = "applied" + state = b"applied" elif q.pushable(idx)[0]: - state = "unapplied" + state = b"unapplied" else: - state = "guarded" - label = "qguard.patch qguard.%s qseries.%s" % (state, state) - ui.write("%s: " % ui.label(q.series[idx], label)) + state = b"guarded" + label = b"qguard.patch qguard.%s qseries.%s" % (state, state) + ui.write(b"%s: " % ui.label(q.series[idx], label)) for i, guard in enumerate(guards): - if guard.startswith("+"): - ui.write(guard, label="qguard.positive") - elif guard.startswith("-"): - ui.write(guard, label="qguard.negative") + if guard.startswith(b"+"): + ui.write(guard, label=b"qguard.positive") + elif guard.startswith(b"-"): + ui.write(guard, label=b"qguard.negative") else: - ui.write(guard, label="qguard.unguarded") + ui.write(guard, label=b"qguard.unguarded") if i != len(guards) - 1: - ui.write(" ") - ui.write("\n") + ui.write(b" ") + ui.write(b"\n") q = repo.mq applied = set(p.name for p in q.applied) @@ -3317,23 +3354,23 @@ if opts.get(r"list"): if args or opts.get(r"none"): raise error.Abort( - _("cannot mix -l/--list with options or " "arguments") + _(b"cannot mix -l/--list with options or " b"arguments") ) for i in pycompat.xrange(len(q.series)): status(i) return - if not args or args[0][0:1] in "-+": + if not args or args[0][0:1] in b"-+": if not q.applied: - raise error.Abort(_("no patches applied")) + raise error.Abort(_(b"no patches applied")) patch = q.applied[-1].name - if patch is None and args[0][0:1] not in "-+": + if patch is None and args[0][0:1] not in b"-+": patch = args.pop(0) if patch is None: - raise error.Abort(_("no patch to work with")) + raise error.Abort(_(b"no patch to work with")) if args or opts.get(r"none"): idx = q.findseries(patch) if idx is None: - raise error.Abort(_("no patch named %s") % patch) + raise error.Abort(_(b"no patch named %s") % patch) q.setguards(idx, args) q.savedirty() else: @@ -3341,9 +3378,9 @@ @command( - "qheader", + b"qheader", [], - _("hg qheader [PATCH]"), + _(b"hg qheader [PATCH]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def header(ui, repo, patch=None): @@ -3356,18 +3393,18 @@ patch = q.lookup(patch) else: if not q.applied: - ui.write(_("no patches applied\n")) + ui.write(_(b"no patches applied\n")) return 1 - patch = q.lookup("qtip") + patch = q.lookup(b"qtip") ph = patchheader(q.join(patch), q.plainmode) - ui.write("\n".join(ph.message) + "\n") + ui.write(b"\n".join(ph.message) + b"\n") def lastsavename(path): (directory, base) = os.path.split(path) names = os.listdir(directory) - namere = re.compile("%s.([0-9]+)" % base) + namere = re.compile(b"%s.([0-9]+)" % base) maxindex = None maxname = None for f in names: @@ -3386,29 +3423,39 @@ (last, index) = lastsavename(path) if last is None: index = 0 - newpath = path + ".%d" % (index + 1) + newpath = path + b".%d" % (index + 1) return newpath @command( - "qpush", + b"qpush", [ - ("", "keep-changes", None, _("tolerate non-conflicting local changes")), - ("f", "force", None, _("apply on top of local changes")), ( - "e", - "exact", + b"", + b"keep-changes", + None, + _(b"tolerate non-conflicting local changes"), + ), + (b"f", b"force", None, _(b"apply on top of local changes")), + ( + b"e", + b"exact", None, - _("apply the target patch to its recorded parent"), + _(b"apply the target patch to its recorded parent"), ), - ("l", "list", None, _("list patch name in commit text")), - ("a", "all", None, _("apply all patches")), - ("m", "merge", None, _("merge from another queue (DEPRECATED)")), - ("n", "name", "", _("merge queue name (DEPRECATED)"), _("NAME")), - ("", "move", None, _("reorder patch series and apply only the patch")), - ("", "no-backup", None, _("do not save backup copies of files")), + (b"l", b"list", None, _(b"list patch name in commit text")), + (b"a", b"all", None, _(b"apply all patches")), + (b"m", b"merge", None, _(b"merge from another queue (DEPRECATED)")), + (b"n", b"name", b"", _(b"merge queue name (DEPRECATED)"), _(b"NAME")), + ( + b"", + b"move", + None, + _(b"reorder patch series and apply only the patch"), + ), + (b"", b"no-backup", None, _(b"do not save backup copies of files")), ], - _("hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]"), + _(b"hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, helpbasic=True, ) @@ -3427,41 +3474,46 @@ opts = pycompat.byteskwargs(opts) opts = fixkeepchangesopts(ui, opts) - if opts.get("merge"): - if opts.get("name"): - newpath = repo.vfs.join(opts.get("name")) + if opts.get(b"merge"): + if opts.get(b"name"): + newpath = repo.vfs.join(opts.get(b"name")) else: newpath, i = lastsavename(q.path) if not newpath: - ui.warn(_("no saved queues found, please use -n\n")) + ui.warn(_(b"no saved queues found, please use -n\n")) return 1 mergeq = queue(ui, repo.baseui, repo.path, newpath) - ui.warn(_("merging with queue at: %s\n") % mergeq.path) + ui.warn(_(b"merging with queue at: %s\n") % mergeq.path) ret = q.push( repo, patch, - force=opts.get("force"), - list=opts.get("list"), + force=opts.get(b"force"), + list=opts.get(b"list"), mergeq=mergeq, - all=opts.get("all"), - move=opts.get("move"), - exact=opts.get("exact"), - nobackup=opts.get("no_backup"), - keepchanges=opts.get("keep_changes"), + all=opts.get(b"all"), + move=opts.get(b"move"), + exact=opts.get(b"exact"), + nobackup=opts.get(b"no_backup"), + keepchanges=opts.get(b"keep_changes"), ) return ret @command( - "qpop", + b"qpop", [ - ("a", "all", None, _("pop all patches")), - ("n", "name", "", _("queue name to pop (DEPRECATED)"), _("NAME")), - ("", "keep-changes", None, _("tolerate non-conflicting local changes")), - ("f", "force", None, _("forget any local changes to patched files")), - ("", "no-backup", None, _("do not save backup copies of files")), + (b"a", b"all", None, _(b"pop all patches")), + (b"n", b"name", b"", _(b"queue name to pop (DEPRECATED)"), _(b"NAME")), + ( + b"", + b"keep-changes", + None, + _(b"tolerate non-conflicting local changes"), + ), + (b"f", b"force", None, _(b"forget any local changes to patched files")), + (b"", b"no-backup", None, _(b"do not save backup copies of files")), ], - _("hg qpop [-a] [-f] [PATCH | INDEX]"), + _(b"hg qpop [-a] [-f] [PATCH | INDEX]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, helpbasic=True, ) @@ -3482,29 +3534,29 @@ opts = pycompat.byteskwargs(opts) opts = fixkeepchangesopts(ui, opts) localupdate = True - if opts.get("name"): - q = queue(ui, repo.baseui, repo.path, repo.vfs.join(opts.get("name"))) - ui.warn(_("using patch queue: %s\n") % q.path) + if opts.get(b"name"): + q = queue(ui, repo.baseui, repo.path, repo.vfs.join(opts.get(b"name"))) + ui.warn(_(b"using patch queue: %s\n") % q.path) localupdate = False else: q = repo.mq ret = q.pop( repo, patch, - force=opts.get("force"), + force=opts.get(b"force"), update=localupdate, - all=opts.get("all"), - nobackup=opts.get("no_backup"), - keepchanges=opts.get("keep_changes"), + all=opts.get(b"all"), + nobackup=opts.get(b"no_backup"), + keepchanges=opts.get(b"keep_changes"), ) q.savedirty() return ret @command( - "qrename|qmv", + b"qrename|qmv", [], - _("hg qrename PATCH1 [PATCH2]"), + _(b"hg qrename PATCH1 [PATCH2]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def rename(ui, repo, patch, name=None, **opts): @@ -3523,19 +3575,19 @@ patch = q.lookup(patch) else: if not q.applied: - ui.write(_("no patches applied\n")) + ui.write(_(b"no patches applied\n")) return - patch = q.lookup("qtip") + patch = q.lookup(b"qtip") absdest = q.join(name) if os.path.isdir(absdest): name = normname(os.path.join(name, os.path.basename(patch))) absdest = q.join(name) q.checkpatchname(name) - ui.note(_("renaming %s to %s\n") % (patch, name)) + ui.note(_(b"renaming %s to %s\n") % (patch, name)) i = q.findseries(patch) guards = q.guard_re.findall(q.fullseries[i]) - q.fullseries[i] = name + "".join([" #" + g for g in guards]) + q.fullseries[i] = name + b"".join([b" #" + g for g in guards]) q.parseseries() q.seriesdirty = True @@ -3552,7 +3604,7 @@ if r and patch in r.dirstate: wctx = r[None] with r.wlock(): - if r.dirstate[patch] == "a": + if r.dirstate[patch] == b"a": r.dirstate.drop(patch) r.dirstate.add(name) else: @@ -3563,12 +3615,12 @@ @command( - "qrestore", + b"qrestore", [ - ("d", "delete", None, _("delete save entry")), - ("u", "update", None, _("update queue working directory")), + (b"d", b"delete", None, _(b"delete save entry")), + (b"u", b"update", None, _(b"update queue working directory")), ], - _("hg qrestore [-d] [-u] REV"), + _(b"hg qrestore [-d] [-u] REV"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def restore(ui, repo, rev, **opts): @@ -3585,15 +3637,15 @@ @command( - "qsave", + b"qsave", [ - ("c", "copy", None, _("copy patch directory")), - ("n", "name", "", _("copy directory name"), _("NAME")), - ("e", "empty", None, _("clear queue status file")), - ("f", "force", None, _("force copy")), + (b"c", b"copy", None, _(b"copy patch directory")), + (b"n", b"name", b"", _(b"copy directory name"), _(b"NAME")), + (b"e", b"empty", None, _(b"clear queue status file")), + (b"f", b"force", None, _(b"force copy")), ] + cmdutil.commitopts, - _("hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]"), + _(b"hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def save(ui, repo, **opts): @@ -3607,25 +3659,26 @@ if ret: return ret q.savedirty() # save to .hg/patches before copying - if opts.get("copy"): + if opts.get(b"copy"): path = q.path - if opts.get("name"): - newpath = os.path.join(q.basepath, opts.get("name")) + if opts.get(b"name"): + newpath = os.path.join(q.basepath, opts.get(b"name")) if os.path.exists(newpath): if not os.path.isdir(newpath): raise error.Abort( - _("destination %s exists and is not " "a directory") + _(b"destination %s exists and is not " b"a directory") % newpath ) - if not opts.get("force"): + if not opts.get(b"force"): raise error.Abort( - _("destination %s exists, " "use -f to force") % newpath + _(b"destination %s exists, " b"use -f to force") + % newpath ) else: newpath = savename(path) - ui.warn(_("copy %s to %s\n") % (path, newpath)) + ui.warn(_(b"copy %s to %s\n") % (path, newpath)) util.copyfiles(path, newpath) - if opts.get("empty"): + if opts.get(b"empty"): del q.applied[:] q.applieddirty = True q.savedirty() @@ -3633,14 +3686,14 @@ @command( - "qselect", + b"qselect", [ - ("n", "none", None, _("disable all guards")), - ("s", "series", None, _("list all guards in series file")), - ("", "pop", None, _("pop to before first guarded applied patch")), - ("", "reapply", None, _("pop, then reapply patches")), + (b"n", b"none", None, _(b"disable all guards")), + (b"s", b"series", None, _(b"list all guards in series file")), + (b"", b"pop", None, _(b"pop to before first guarded applied patch")), + (b"", b"reapply", None, _(b"pop, then reapply patches")), ], - _("hg qselect [OPTION]... [GUARD]..."), + _(b"hg qselect [OPTION]... [GUARD]..."), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def select(ui, repo, *args, **opts): @@ -3682,7 +3735,7 @@ opts = pycompat.byteskwargs(opts) guards = q.active() pushable = lambda i: q.pushable(q.applied[i].name)[0] - if args or opts.get("none"): + if args or opts.get(b"none"): old_unapplied = q.unapplied(repo) old_guarded = [ i for i in pycompat.xrange(len(q.applied)) if not pushable(i) @@ -3690,8 +3743,8 @@ q.setactive(args) q.savedirty() if not args: - ui.status(_("guards deactivated\n")) - if not opts.get("pop") and not opts.get("reapply"): + ui.status(_(b"guards deactivated\n")) + if not opts.get(b"pop") and not opts.get(b"reapply"): unapplied = q.unapplied(repo) guarded = [ i for i in pycompat.xrange(len(q.applied)) if not pushable(i) @@ -3699,20 +3752,20 @@ if len(unapplied) != len(old_unapplied): ui.status( _( - "number of unguarded, unapplied patches has " - "changed from %d to %d\n" + b"number of unguarded, unapplied patches has " + b"changed from %d to %d\n" ) % (len(old_unapplied), len(unapplied)) ) if len(guarded) != len(old_guarded): ui.status( _( - "number of guarded, applied patches has changed " - "from %d to %d\n" + b"number of guarded, applied patches has changed " + b"from %d to %d\n" ) % (len(old_guarded), len(guarded)) ) - elif opts.get("series"): + elif opts.get(b"series"): guards = {} noguards = 0 for gs in q.seriesguards: @@ -3722,29 +3775,29 @@ guards.setdefault(g, 0) guards[g] += 1 if ui.verbose: - guards["NONE"] = noguards + guards[b"NONE"] = noguards guards = list(guards.items()) guards.sort(key=lambda x: x[0][1:]) if guards: - ui.note(_("guards in series file:\n")) + ui.note(_(b"guards in series file:\n")) for guard, count in guards: - ui.note("%2d " % count) - ui.write(guard, "\n") + ui.note(b"%2d " % count) + ui.write(guard, b"\n") else: - ui.note(_("no guards in series file\n")) + ui.note(_(b"no guards in series file\n")) else: if guards: - ui.note(_("active guards:\n")) + ui.note(_(b"active guards:\n")) for g in guards: - ui.write(g, "\n") + ui.write(g, b"\n") else: - ui.write(_("no active guards\n")) - reapply = opts.get("reapply") and q.applied and q.applied[-1].name + ui.write(_(b"no active guards\n")) + reapply = opts.get(b"reapply") and q.applied and q.applied[-1].name popped = False - if opts.get("pop") or opts.get("reapply"): + if opts.get(b"pop") or opts.get(b"reapply"): for i in pycompat.xrange(len(q.applied)): if not pushable(i): - ui.status(_("popping guarded patches\n")) + ui.status(_(b"popping guarded patches\n")) popped = True if i == 0: q.pop(repo, all=True) @@ -3754,16 +3807,16 @@ if popped: try: if reapply: - ui.status(_("reapplying unguarded patches\n")) + ui.status(_(b"reapplying unguarded patches\n")) q.push(repo, reapply) finally: q.savedirty() @command( - "qfinish", - [("a", "applied", None, _("finish all applied changesets"))], - _("hg qfinish [-a] [REV]..."), + b"qfinish", + [(b"a", b"applied", None, _(b"finish all applied changesets"))], + _(b"hg qfinish [-a] [REV]..."), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def finish(ui, repo, *revrange, **opts): @@ -3785,18 +3838,18 @@ Returns 0 on success. """ if not opts.get(r"applied") and not revrange: - raise error.Abort(_("no revisions specified")) + raise error.Abort(_(b"no revisions specified")) elif opts.get(r"applied"): - revrange = ("qbase::qtip",) + revrange + revrange = (b"qbase::qtip",) + revrange q = repo.mq if not q.applied: - ui.status(_("no patches applied\n")) + ui.status(_(b"no patches applied\n")) return 0 revs = scmutil.revrange(repo, revrange) - if repo["."].rev() in revs and repo[None].files(): - ui.warn(_("warning: uncommitted changes in the working directory\n")) + if repo[b"."].rev() in revs and repo[None].files(): + ui.warn(_(b"warning: uncommitted changes in the working directory\n")) # queue.finish may changes phases but leave the responsibility to lock the # repo to the caller to avoid deadlock with wlock. This command code is # responsibility for this locking. @@ -3807,16 +3860,16 @@ @command( - "qqueue", + b"qqueue", [ - ("l", "list", False, _("list all available queues")), - ("", "active", False, _("print name of active queue")), - ("c", "create", False, _("create new queue")), - ("", "rename", False, _("rename active queue")), - ("", "delete", False, _("delete reference to queue")), - ("", "purge", False, _("delete queue, and remove patch dir")), + (b"l", b"list", False, _(b"list all available queues")), + (b"", b"active", False, _(b"print name of active queue")), + (b"c", b"create", False, _(b"create new queue")), + (b"", b"rename", False, _(b"rename active queue")), + (b"", b"delete", False, _(b"delete reference to queue")), + (b"", b"purge", False, _(b"delete queue, and remove patch dir")), ], - _("[OPTION] [QUEUE]"), + _(b"[OPTION] [QUEUE]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def qqueue(ui, repo, name=None, **opts): @@ -3841,19 +3894,19 @@ Returns 0 on success. """ q = repo.mq - _defaultqueue = "patches" - _allqueues = "patches.queues" - _activequeue = "patches.queue" + _defaultqueue = b"patches" + _allqueues = b"patches.queues" + _activequeue = b"patches.queue" def _getcurrent(): cur = os.path.basename(q.path) - if cur.startswith("patches-"): + if cur.startswith(b"patches-"): cur = cur[8:] return cur def _noqueues(): try: - fh = repo.vfs(_allqueues, "r") + fh = repo.vfs(_allqueues, b"r") fh.close() except IOError: return True @@ -3864,7 +3917,7 @@ current = _getcurrent() try: - fh = repo.vfs(_allqueues, "r") + fh = repo.vfs(_allqueues, b"r") queues = [queue.strip() for queue in fh if queue.strip()] fh.close() if current not in queues: @@ -3878,112 +3931,112 @@ if q.applied: raise error.Abort( _( - "new queue created, but cannot make active " - "as patches are applied" + b"new queue created, but cannot make active " + b"as patches are applied" ) ) _setactivenocheck(name) def _setactivenocheck(name): - fh = repo.vfs(_activequeue, "w") - if name != "patches": + fh = repo.vfs(_activequeue, b"w") + if name != b"patches": fh.write(name) fh.close() def _addqueue(name): - fh = repo.vfs(_allqueues, "a") - fh.write("%s\n" % (name,)) + fh = repo.vfs(_allqueues, b"a") + fh.write(b"%s\n" % (name,)) fh.close() def _queuedir(name): - if name == "patches": - return repo.vfs.join("patches") + if name == b"patches": + return repo.vfs.join(b"patches") else: - return repo.vfs.join("patches-" + name) + return repo.vfs.join(b"patches-" + name) def _validname(name): for n in name: - if n in ":\\/.": + if n in b":\\/.": return False return True def _delete(name): if name not in existing: - raise error.Abort(_("cannot delete queue that does not exist")) + raise error.Abort(_(b"cannot delete queue that does not exist")) current = _getcurrent() if name == current: - raise error.Abort(_("cannot delete currently active queue")) - - fh = repo.vfs("patches.queues.new", "w") + raise error.Abort(_(b"cannot delete currently active queue")) + + fh = repo.vfs(b"patches.queues.new", b"w") for queue in existing: if queue == name: continue - fh.write("%s\n" % (queue,)) + fh.write(b"%s\n" % (queue,)) fh.close() - repo.vfs.rename("patches.queues.new", _allqueues) + repo.vfs.rename(b"patches.queues.new", _allqueues) opts = pycompat.byteskwargs(opts) - if not name or opts.get("list") or opts.get("active"): + if not name or opts.get(b"list") or opts.get(b"active"): current = _getcurrent() - if opts.get("active"): - ui.write("%s\n" % (current,)) + if opts.get(b"active"): + ui.write(b"%s\n" % (current,)) return for queue in _getqueues(): - ui.write("%s" % (queue,)) + ui.write(b"%s" % (queue,)) if queue == current and not ui.quiet: - ui.write(_(" (active)\n")) + ui.write(_(b" (active)\n")) else: - ui.write("\n") + ui.write(b"\n") return if not _validname(name): raise error.Abort( - _('invalid queue name, may not contain the characters ":\\/."') + _(b'invalid queue name, may not contain the characters ":\\/."') ) with repo.wlock(): existing = _getqueues() - if opts.get("create"): + if opts.get(b"create"): if name in existing: - raise error.Abort(_('queue "%s" already exists') % name) + raise error.Abort(_(b'queue "%s" already exists') % name) if _noqueues(): _addqueue(_defaultqueue) _addqueue(name) _setactive(name) - elif opts.get("rename"): + elif opts.get(b"rename"): current = _getcurrent() if name == current: raise error.Abort( - _('can\'t rename "%s" to its current name') % name + _(b'can\'t rename "%s" to its current name') % name ) if name in existing: - raise error.Abort(_('queue "%s" already exists') % name) + raise error.Abort(_(b'queue "%s" already exists') % name) olddir = _queuedir(current) newdir = _queuedir(name) if os.path.exists(newdir): raise error.Abort( - _('non-queue directory "%s" already exists') % newdir + _(b'non-queue directory "%s" already exists') % newdir ) - fh = repo.vfs("patches.queues.new", "w") + fh = repo.vfs(b"patches.queues.new", b"w") for queue in existing: if queue == current: - fh.write("%s\n" % (name,)) + fh.write(b"%s\n" % (name,)) if os.path.exists(olddir): util.rename(olddir, newdir) else: - fh.write("%s\n" % (queue,)) + fh.write(b"%s\n" % (queue,)) fh.close() - repo.vfs.rename("patches.queues.new", _allqueues) + repo.vfs.rename(b"patches.queues.new", _allqueues) _setactivenocheck(name) - elif opts.get("delete"): + elif opts.get(b"delete"): _delete(name) - elif opts.get("purge"): + elif opts.get(b"purge"): if name in existing: _delete(name) qdir = _queuedir(name) @@ -3991,14 +4044,14 @@ shutil.rmtree(qdir) else: if name not in existing: - raise error.Abort(_("use --create to create a new queue")) + raise error.Abort(_(b"use --create to create a new queue")) _setactive(name) def mqphasedefaults(repo, roots): """callback used to set mq changeset as secret when no phase data exists""" if repo.mq.applied: - if repo.ui.configbool("mq", "secret"): + if repo.ui.configbool(b"mq", b"secret"): mqphase = phases.secret else: mqphase = phases.draft @@ -4028,7 +4081,7 @@ def commit( self, - text="", + text=b"", user=None, date=None, match=None, @@ -4039,7 +4092,7 @@ if extra is None: extra = {} self.abortifwdirpatched( - _("cannot commit over an applied mq patch"), force + _(b"cannot commit over an applied mq patch"), force ) return super(mqrepo, self).commit( @@ -4062,7 +4115,7 @@ # looking for pushed and shared changeset for node in outapplied: if self[node].phase() < phases.secret: - raise error.Abort(_("source has mq patches applied")) + raise error.Abort(_(b"source has mq patches applied")) # no non-secret patches pushed super(mqrepo, self).checkpush(pushop) @@ -4081,7 +4134,7 @@ self.unfiltered().changelog.rev(mqtags[-1][0]) except error.LookupError: self.ui.warn( - _("mq status file refers to unknown node %s\n") + _(b"mq status file refers to unknown node %s\n") % short(mqtags[-1][0]) ) return result @@ -4092,14 +4145,14 @@ if not mqtags: return result - mqtags.append((mqtags[-1][0], "qtip")) - mqtags.append((mqtags[0][0], "qbase")) - mqtags.append((self.changelog.parents(mqtags[0][0])[0], "qparent")) + mqtags.append((mqtags[-1][0], b"qtip")) + mqtags.append((mqtags[0][0], b"qbase")) + mqtags.append((self.changelog.parents(mqtags[0][0])[0], b"qparent")) tags = result[0] for patch in mqtags: if patch[1] in tags: self.ui.warn( - _("tag %s overrides mq patch of the same " "name\n") + _(b"tag %s overrides mq patch of the same " b"name\n") % patch[1] ) else: @@ -4114,11 +4167,11 @@ def mqimport(orig, ui, repo, *args, **kwargs): - if util.safehasattr(repo, "abortifwdirpatched") and not kwargs.get( + if util.safehasattr(repo, b"abortifwdirpatched") and not kwargs.get( r"no_commit", False ): repo.abortifwdirpatched( - _("cannot import over an applied patch"), kwargs.get(r"force") + _(b"cannot import over an applied patch"), kwargs.get(r"force") ) return orig(ui, repo, *args, **kwargs) @@ -4133,13 +4186,13 @@ repopath = args[0] if not hg.islocal(repopath): raise error.Abort( - _("only a local queue repository " "may be initialized") + _(b"only a local queue repository " b"may be initialized") ) else: repopath = cmdutil.findrepo(encoding.getcwd()) if not repopath: raise error.Abort( - _("there is no Mercurial repository here " "(.hg not found)") + _(b"there is no Mercurial repository here " b"(.hg not found)") ) repo = hg.repository(ui, repopath) return qinit(ui, repo, True) @@ -4157,7 +4210,7 @@ q = repo.mq r = q.qrepo() if not r: - raise error.Abort(_("no queue repository")) + raise error.Abort(_(b"no queue repository")) return orig(r.ui, r, *args, **kwargs) @@ -4166,25 +4219,25 @@ m = [] a, u = len(q.applied), len(q.unapplied(repo)) if a: - m.append(ui.label(_("%d applied"), "qseries.applied") % a) + m.append(ui.label(_(b"%d applied"), b"qseries.applied") % a) if u: - m.append(ui.label(_("%d unapplied"), "qseries.unapplied") % u) + m.append(ui.label(_(b"%d unapplied"), b"qseries.unapplied") % u) if m: # i18n: column positioning for "hg summary" - ui.write(_("mq: %s\n") % ", ".join(m)) + ui.write(_(b"mq: %s\n") % b", ".join(m)) else: # i18n: column positioning for "hg summary" - ui.note(_("mq: (empty queue)\n")) + ui.note(_(b"mq: (empty queue)\n")) revsetpredicate = registrar.revsetpredicate() -@revsetpredicate("mq()") +@revsetpredicate(b"mq()") def revsetmq(repo, subset, x): """Changesets managed by MQ. """ - revsetlang.getargs(x, 0, 0, _("mq takes no arguments")) + revsetlang.getargs(x, 0, 0, _(b"mq takes no arguments")) applied = {repo[r.node].rev() for r in repo.mq.applied} return smartset.baseset([r for r in subset if r in applied]) @@ -4196,12 +4249,12 @@ def extsetup(ui): # Ensure mq wrappers are called first, regardless of extension load order by # NOT wrapping in uisetup() and instead deferring to init stage two here. - mqopt = [("", "mq", None, _("operate on patch repository"))] - - extensions.wrapcommand(commands.table, "import", mqimport) - cmdutil.summaryhooks.add("mq", summaryhook) - - entry = extensions.wrapcommand(commands.table, "init", mqinit) + mqopt = [(b"", b"mq", None, _(b"operate on patch repository"))] + + extensions.wrapcommand(commands.table, b"import", mqimport) + cmdutil.summaryhooks.add(b"mq", summaryhook) + + entry = extensions.wrapcommand(commands.table, b"init", mqinit) entry[1].extend(mqopt) def dotable(cmdtable): @@ -4221,11 +4274,11 @@ colortable = { - "qguard.negative": "red", - "qguard.positive": "yellow", - "qguard.unguarded": "green", - "qseries.applied": "blue bold underline", - "qseries.guarded": "black bold", - "qseries.missing": "red bold", - "qseries.unapplied": "black bold", + b"qguard.negative": b"red", + b"qguard.positive": b"yellow", + b"qguard.unguarded": b"green", + b"qseries.applied": b"blue bold underline", + b"qseries.guarded": b"black bold", + b"qseries.missing": b"red bold", + b"qseries.unapplied": b"black bold", } diff --git a/hgext/narrow/__init__.py b/hgext/narrow/__init__.py --- a/hgext/narrow/__init__.py +++ b/hgext/narrow/__init__.py @@ -12,7 +12,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" from mercurial import ( localrepo, @@ -41,10 +41,10 @@ # ellipsis nodes to be a hard requirement also enforce strictly linear # history for other scaling reasons. configitem( - "experimental", - "narrowservebrokenellipses", + b"experimental", + b"narrowservebrokenellipses", default=False, - alias=[("narrow", "serveellipses")], + alias=[(b"narrow", b"serveellipses")], ) # Export the commands table for Mercurial to see. @@ -68,7 +68,7 @@ if not repo.local(): return - repo.ui.setconfig("experimental", "narrow", True, "narrow-ext") + repo.ui.setconfig(b"experimental", b"narrow", True, b"narrow-ext") if repository.NARROW_REQUIREMENT in repo.requirements: narrowrepo.wraprepo(repo) narrowwirepeer.reposetup(repo) diff --git a/hgext/narrow/narrowbundle2.py b/hgext/narrow/narrowbundle2.py --- a/hgext/narrow/narrowbundle2.py +++ b/hgext/narrow/narrowbundle2.py @@ -29,16 +29,16 @@ from mercurial.interfaces import repository from mercurial.utils import stringutil -_NARROWACL_SECTION = "narrowacl" -_CHANGESPECPART = "narrow:changespec" -_RESSPECS = "narrow:responsespec" -_SPECPART = "narrow:spec" -_SPECPART_INCLUDE = "include" -_SPECPART_EXCLUDE = "exclude" -_KILLNODESIGNAL = "KILL" -_DONESIGNAL = "DONE" -_ELIDEDCSHEADER = ">20s20s20sl" # cset id, p1, p2, len(text) -_ELIDEDMFHEADER = ">20s20s20s20sl" # manifest id, p1, p2, link id, len(text) +_NARROWACL_SECTION = b"narrowacl" +_CHANGESPECPART = b"narrow:changespec" +_RESSPECS = b"narrow:responsespec" +_SPECPART = b"narrow:spec" +_SPECPART_INCLUDE = b"include" +_SPECPART_EXCLUDE = b"exclude" +_KILLNODESIGNAL = b"KILL" +_DONESIGNAL = b"DONE" +_ELIDEDCSHEADER = b">20s20s20sl" # cset id, p1, p2, len(text) +_ELIDEDMFHEADER = b">20s20s20s20sl" # manifest id, p1, p2, link id, len(text) _CSHEADERSIZE = struct.calcsize(_ELIDEDCSHEADER) _MFHEADERSIZE = struct.calcsize(_ELIDEDMFHEADER) @@ -53,16 +53,16 @@ common=None, **kwargs ): - assert repo.ui.configbool("experimental", "narrowservebrokenellipses") + assert repo.ui.configbool(b"experimental", b"narrowservebrokenellipses") - cgversions = b2caps.get("changegroup") + cgversions = b2caps.get(b"changegroup") cgversions = [ v for v in cgversions if v in changegroup.supportedoutgoingversions(repo) ] if not cgversions: - raise ValueError(_("no common changegroup version")) + raise ValueError(_(b"no common changegroup version")) version = max(cgversions) oldinclude = sorted(filter(bool, kwargs.get(r"oldincludepats", []))) @@ -104,7 +104,7 @@ if depth is not None: depth = int(depth) if depth < 1: - raise error.Abort(_("depth must be positive, got %d") % depth) + raise error.Abort(_(b"depth must be positive, got %d") % depth) heads = set(heads or repo.heads()) common = set(common or [nullid]) @@ -127,7 +127,7 @@ # until they've built up the full new state. # Convert to revnums and intersect with "common". The client should # have made it a subset of "common" already, but let's be safe. - known = set(repo.revs("%ln & ::%ln", known, common)) + known = set(repo.revs(b"%ln & ::%ln", known, common)) # TODO: we could send only roots() of this set, and the # list of nodes in common, and the client could work out # what to strip, instead of us explicitly sending every @@ -154,18 +154,18 @@ ellipsisroots=newellipsis, fullnodes=newfull, ) - cgdata = packer.generate(common, newvisit, False, "narrow_widen") + cgdata = packer.generate(common, newvisit, False, b"narrow_widen") - part = bundler.newpart("changegroup", data=cgdata) - part.addparam("version", version) - if "treemanifest" in repo.requirements: - part.addparam("treemanifest", "1") + part = bundler.newpart(b"changegroup", data=cgdata) + part.addparam(b"version", version) + if b"treemanifest" in repo.requirements: + part.addparam(b"treemanifest", b"1") visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis( repo, common, heads, set(), newmatch, depth=depth ) - repo.ui.debug("Found %d relevant revs\n" % len(relevant_nodes)) + repo.ui.debug(b"Found %d relevant revs\n" % len(relevant_nodes)) if visitnodes: packer = changegroup.getbundler( version, @@ -176,12 +176,12 @@ ellipsisroots=ellipsisroots, fullnodes=relevant_nodes, ) - cgdata = packer.generate(common, visitnodes, False, "narrow_widen") + cgdata = packer.generate(common, visitnodes, False, b"narrow_widen") - part = bundler.newpart("changegroup", data=cgdata) - part.addparam("version", version) - if "treemanifest" in repo.requirements: - part.addparam("treemanifest", "1") + part = bundler.newpart(b"changegroup", data=cgdata) + part.addparam(b"version", version) + if b"treemanifest" in repo.requirements: + part.addparam(b"treemanifest", b"1") @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE)) @@ -190,8 +190,8 @@ # released. New servers will send a mandatory bundle2 part named # 'Narrowspec' and will send specs as data instead of params. # Refer to issue5952 and 6019 - includepats = set(inpart.params.get(_SPECPART_INCLUDE, "").splitlines()) - excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, "").splitlines()) + includepats = set(inpart.params.get(_SPECPART_INCLUDE, b"").splitlines()) + excludepats = set(inpart.params.get(_SPECPART_EXCLUDE, b"").splitlines()) narrowspec.validatepatterns(includepats) narrowspec.validatepatterns(excludepats) @@ -205,7 +205,7 @@ @bundle2.parthandler(_RESSPECS) def _handlenarrowspecs(op, inpart): data = inpart.read() - inc, exc = data.split("\0") + inc, exc = data.split(b"\0") includepats = set(inc.splitlines()) excludepats = set(exc.splitlines()) narrowspec.validatepatterns(includepats) @@ -241,7 +241,7 @@ clkills.add(ck) else: raise error.Abort( - _("unexpected changespec node chunk type: %s") % chunksignal + _(b"unexpected changespec node chunk type: %s") % chunksignal ) chunksignal = changegroup.readexactly(inpart, 4) @@ -255,7 +255,7 @@ localrepo.localrepository._bookmarks.set(repo, dummybmstore()) chgrpfile = repair.strip( - op.ui, repo, list(clkills), backup=True, topic="widen" + op.ui, repo, list(clkills), backup=True, topic=b"widen" ) if chgrpfile: op._widen_uninterr = repo.ui.uninterruptible() @@ -266,7 +266,7 @@ # will currently always be there when using the core+narrowhg server, but # other servers may include a changespec part even when not widening (e.g. # because we're deepening a shallow repo). - if util.safehasattr(repo, "setnewnarrowpats"): + if util.safehasattr(repo, b"setnewnarrowpats"): repo.setnewnarrowpats() @@ -281,20 +281,22 @@ del op._widen_bundle vfs = repo.vfs - ui.note(_("adding branch\n")) - f = vfs.open(chgrpfile, "rb") + ui.note(_(b"adding branch\n")) + f = vfs.open(chgrpfile, b"rb") try: gen = exchange.readbundle(ui, f, chgrpfile, vfs) # silence internal shuffling chatter - override = {("ui", "quiet"): True} + override = {(b"ui", b"quiet"): True} if ui.verbose: override = {} with ui.configoverride(override): if isinstance(gen, bundle2.unbundle20): - with repo.transaction("strip") as tr: + with repo.transaction(b"strip") as tr: bundle2.processbundle(repo, gen, lambda: tr) else: - gen.apply(repo, "strip", "bundle:" + vfs.join(chgrpfile), True) + gen.apply( + repo, b"strip", b"bundle:" + vfs.join(chgrpfile), True + ) finally: f.close() @@ -305,7 +307,7 @@ except OSError as e: if e.errno != errno.ENOENT: ui.warn( - _("error removing %s: %s\n") + _(b"error removing %s: %s\n") % (undovfs.join(undofile), stringutil.forcebytestr(e)) ) @@ -318,14 +320,14 @@ """Enable narrow repo support in bundle2-related extension points.""" getbundleargs = wireprototypes.GETBUNDLE_ARGUMENTS - getbundleargs["narrow"] = "boolean" - getbundleargs["depth"] = "plain" - getbundleargs["oldincludepats"] = "csv" - getbundleargs["oldexcludepats"] = "csv" - getbundleargs["known"] = "csv" + getbundleargs[b"narrow"] = b"boolean" + getbundleargs[b"depth"] = b"plain" + getbundleargs[b"oldincludepats"] = b"csv" + getbundleargs[b"oldexcludepats"] = b"csv" + getbundleargs[b"known"] = b"csv" # Extend changegroup serving to handle requests from narrow clients. - origcgfn = exchange.getbundle2partsmapping["changegroup"] + origcgfn = exchange.getbundle2partsmapping[b"changegroup"] def wrappedcgfn(*args, **kwargs): repo = args[1] @@ -333,26 +335,26 @@ kwargs = exchange.applynarrowacl(repo, kwargs) if kwargs.get(r"narrow", False) and repo.ui.configbool( - "experimental", "narrowservebrokenellipses" + b"experimental", b"narrowservebrokenellipses" ): getbundlechangegrouppart_narrow(*args, **kwargs) else: origcgfn(*args, **kwargs) - exchange.getbundle2partsmapping["changegroup"] = wrappedcgfn + exchange.getbundle2partsmapping[b"changegroup"] = wrappedcgfn # Extend changegroup receiver so client can fixup after widen requests. - origcghandler = bundle2.parthandlermapping["changegroup"] + origcghandler = bundle2.parthandlermapping[b"changegroup"] def wrappedcghandler(op, inpart): origcghandler(op, inpart) - if util.safehasattr(op, "_widen_bundle"): + if util.safehasattr(op, b"_widen_bundle"): handlechangegroup_widen(op, inpart) - if util.safehasattr(op, "_bookmarksbackup"): + if util.safehasattr(op, b"_bookmarksbackup"): localrepo.localrepository._bookmarks.set( op.repo, op._bookmarksbackup ) del op._bookmarksbackup wrappedcghandler.params = origcghandler.params - bundle2.parthandlermapping["changegroup"] = wrappedcghandler + bundle2.parthandlermapping[b"changegroup"] = wrappedcghandler diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py --- a/hgext/narrow/narrowcommands.py +++ b/hgext/narrow/narrowcommands.py @@ -39,59 +39,69 @@ def setup(): """Wraps user-facing mercurial commands with narrow-aware versions.""" - entry = extensions.wrapcommand(commands.table, "clone", clonenarrowcmd) + entry = extensions.wrapcommand(commands.table, b"clone", clonenarrowcmd) entry[1].append( - ("", "narrow", None, _("create a narrow clone of select files")) + (b"", b"narrow", None, _(b"create a narrow clone of select files")) ) entry[1].append( - ("", "depth", "", _("limit the history fetched by distance from heads")) + ( + b"", + b"depth", + b"", + _(b"limit the history fetched by distance from heads"), + ) ) - entry[1].append(("", "narrowspec", "", _("read narrowspecs from file"))) + entry[1].append((b"", b"narrowspec", b"", _(b"read narrowspecs from file"))) # TODO(durin42): unify sparse/narrow --include/--exclude logic a bit - if "sparse" not in extensions.enabled(): + if b"sparse" not in extensions.enabled(): entry[1].append( - ("", "include", [], _("specifically fetch this file/directory")) + (b"", b"include", [], _(b"specifically fetch this file/directory")) ) entry[1].append( ( - "", - "exclude", + b"", + b"exclude", [], - _("do not fetch this file/directory, even if included"), + _(b"do not fetch this file/directory, even if included"), ) ) - entry = extensions.wrapcommand(commands.table, "pull", pullnarrowcmd) + entry = extensions.wrapcommand(commands.table, b"pull", pullnarrowcmd) entry[1].append( - ("", "depth", "", _("limit the history fetched by distance from heads")) + ( + b"", + b"depth", + b"", + _(b"limit the history fetched by distance from heads"), + ) ) - extensions.wrapcommand(commands.table, "archive", archivenarrowcmd) + extensions.wrapcommand(commands.table, b"archive", archivenarrowcmd) def clonenarrowcmd(orig, ui, repo, *args, **opts): """Wraps clone command, so 'hg clone' first wraps localrepo.clone().""" opts = pycompat.byteskwargs(opts) wrappedextraprepare = util.nullcontextmanager() - narrowspecfile = opts["narrowspec"] + narrowspecfile = opts[b"narrowspec"] if narrowspecfile: filepath = os.path.join(encoding.getcwd(), narrowspecfile) - ui.status(_("reading narrowspec from '%s'\n") % filepath) + ui.status(_(b"reading narrowspec from '%s'\n") % filepath) try: fdata = util.readfile(filepath) except IOError as inst: raise error.Abort( - _("cannot read narrowspecs from '%s': %s") + _(b"cannot read narrowspecs from '%s': %s") % (filepath, encoding.strtolocal(inst.strerror)) ) - includes, excludes, profiles = sparse.parseconfig(ui, fdata, "narrow") + includes, excludes, profiles = sparse.parseconfig(ui, fdata, b"narrow") if profiles: raise error.Abort( _( - "cannot specify other files using '%include' in" - " narrowspec" + b"cannot specify other files using '%include' in" + b" narrowspec" ) ) @@ -99,20 +109,20 @@ narrowspec.validatepatterns(excludes) # narrowspec is passed so we should assume that user wants narrow clone - opts["narrow"] = True - opts["include"].extend(includes) - opts["exclude"].extend(excludes) + opts[b"narrow"] = True + opts[b"include"].extend(includes) + opts[b"exclude"].extend(excludes) - if opts["narrow"]: + if opts[b"narrow"]: def pullbundle2extraprepare_widen(orig, pullop, kwargs): orig(pullop, kwargs) - if opts.get("depth"): - kwargs["depth"] = opts["depth"] + if opts.get(b"depth"): + kwargs[b"depth"] = opts[b"depth"] wrappedextraprepare = extensions.wrappedfunction( - exchange, "_pullbundle2extraprepare", pullbundle2extraprepare_widen + exchange, b"_pullbundle2extraprepare", pullbundle2extraprepare_widen ) with wrappedextraprepare: @@ -127,10 +137,10 @@ def pullbundle2extraprepare_widen(orig, pullop, kwargs): orig(pullop, kwargs) if opts.get(r"depth"): - kwargs["depth"] = opts[r"depth"] + kwargs[b"depth"] = opts[r"depth"] wrappedextraprepare = extensions.wrappedfunction( - exchange, "_pullbundle2extraprepare", pullbundle2extraprepare_widen + exchange, b"_pullbundle2extraprepare", pullbundle2extraprepare_widen ) with wrappedextraprepare: @@ -159,33 +169,33 @@ return orig(pullop, kwargs) if wireprototypes.NARROWCAP not in pullop.remote.capabilities(): - raise error.Abort(_("server does not support narrow clones")) + raise error.Abort(_(b"server does not support narrow clones")) orig(pullop, kwargs) - kwargs["narrow"] = True + kwargs[b"narrow"] = True include, exclude = repo.narrowpats - kwargs["oldincludepats"] = include - kwargs["oldexcludepats"] = exclude + kwargs[b"oldincludepats"] = include + kwargs[b"oldexcludepats"] = exclude if include: - kwargs["includepats"] = include + kwargs[b"includepats"] = include if exclude: - kwargs["excludepats"] = exclude + kwargs[b"excludepats"] = exclude # calculate known nodes only in ellipses cases because in non-ellipses cases # we have all the nodes if wireprototypes.ELLIPSESCAP1 in pullop.remote.capabilities(): - kwargs["known"] = [ + kwargs[b"known"] = [ node.hex(ctx.node()) - for ctx in repo.set("::%ln", pullop.common) + for ctx in repo.set(b"::%ln", pullop.common) if ctx.node() != node.nullid ] - if not kwargs["known"]: + if not kwargs[b"known"]: # Mercurial serializes an empty list as '' and deserializes it as # [''], so delete it instead to avoid handling the empty string on # the server. - del kwargs["known"] + del kwargs[b"known"] extensions.wrapfunction( - exchange, "_pullbundle2extraprepare", pullbundle2extraprepare + exchange, b"_pullbundle2extraprepare", pullbundle2extraprepare ) @@ -208,62 +218,64 @@ # have any changes to files that will be untracked. unfi = repo.unfiltered() outgoing = discovery.findcommonoutgoing(unfi, remote, commoninc=commoninc) - ui.status(_("looking for local changes to affected paths\n")) + ui.status(_(b"looking for local changes to affected paths\n")) localnodes = [] for n in itertools.chain(outgoing.missing, outgoing.excluded): if any(oldmatch(f) and not newmatch(f) for f in unfi[n].files()): localnodes.append(n) - revstostrip = unfi.revs("descendants(%ln)", localnodes) - hiddenrevs = repoview.filterrevs(repo, "visible") + revstostrip = unfi.revs(b"descendants(%ln)", localnodes) + hiddenrevs = repoview.filterrevs(repo, b"visible") visibletostrip = list( repo.changelog.node(r) for r in (revstostrip - hiddenrevs) ) if visibletostrip: ui.status( _( - "The following changeset(s) or their ancestors have " - "local changes not on the remote:\n" + b"The following changeset(s) or their ancestors have " + b"local changes not on the remote:\n" ) ) maxnodes = 10 if ui.verbose or len(visibletostrip) <= maxnodes: for n in visibletostrip: - ui.status("%s\n" % node.short(n)) + ui.status(b"%s\n" % node.short(n)) else: for n in visibletostrip[:maxnodes]: - ui.status("%s\n" % node.short(n)) + ui.status(b"%s\n" % node.short(n)) ui.status( - _("...and %d more, use --verbose to list all\n") + _(b"...and %d more, use --verbose to list all\n") % (len(visibletostrip) - maxnodes) ) if not force: raise error.Abort( - _("local changes found"), - hint=_("use --force-delete-local-changes to " "ignore"), + _(b"local changes found"), + hint=_(b"use --force-delete-local-changes to " b"ignore"), ) with ui.uninterruptible(): if revstostrip: tostrip = [unfi.changelog.node(r) for r in revstostrip] - if repo["."].node() in tostrip: + if repo[b"."].node() in tostrip: # stripping working copy, so move to a different commit first urev = max( repo.revs( - "(::%n) - %ln + null", repo["."].node(), visibletostrip + b"(::%n) - %ln + null", + repo[b"."].node(), + visibletostrip, ) ) hg.clean(repo, urev) - overrides = {("devel", "strip-obsmarkers"): False} - with ui.configoverride(overrides, "narrow"): - repair.strip(ui, unfi, tostrip, topic="narrow") + overrides = {(b"devel", b"strip-obsmarkers"): False} + with ui.configoverride(overrides, b"narrow"): + repair.strip(ui, unfi, tostrip, topic=b"narrow") todelete = [] for f, f2, size in repo.store.datafiles(): - if f.startswith("data/"): + if f.startswith(b"data/"): file = f[5:-2] if not newmatch(file): todelete.append(f) - elif f.startswith("meta/"): + elif f.startswith(b"meta/"): dir = f[5:-13] dirs = sorted(util.dirs({dir})) + [dir] include = True @@ -272,20 +284,20 @@ if not visit: include = False break - if visit == "all": + if visit == b"all": break if not include: todelete.append(f) repo.destroying() - with repo.transaction("narrowing"): + with repo.transaction(b"narrowing"): # Update narrowspec before removing revlogs, so repo won't be # corrupt in case of crash repo.setnarrowpats(newincludes, newexcludes) for f in todelete: - ui.status(_("deleting %s\n") % f) + ui.status(_(b"deleting %s\n") % f) util.unlinkpath(repo.svfs.join(f)) repo.store.markremoved(f) @@ -327,11 +339,11 @@ def pullbundle2extraprepare_widen(orig, pullop, kwargs): orig(pullop, kwargs) # The old{in,ex}cludepats have already been set by orig() - kwargs["includepats"] = newincludes - kwargs["excludepats"] = newexcludes + kwargs[b"includepats"] = newincludes + kwargs[b"excludepats"] = newexcludes wrappedextraprepare = extensions.wrappedfunction( - exchange, "_pullbundle2extraprepare", pullbundle2extraprepare_widen + exchange, b"_pullbundle2extraprepare", pullbundle2extraprepare_widen ) # define a function that narrowbundle2 can call after creating the @@ -341,7 +353,7 @@ repo.setnewnarrowpats = setnewnarrowpats # silence the devel-warning of applying an empty changegroup - overrides = {("devel", "all-warnings"): False} + overrides = {(b"devel", b"all-warnings"): False} common = commoninc[0] with ui.uninterruptible(): @@ -358,28 +370,30 @@ if ellipsesremote: known = [ ctx.node() - for ctx in repo.set("::%ln", common) + for ctx in repo.set(b"::%ln", common) if ctx.node() != node.nullid ] with remote.commandexecutor() as e: bundle = e.callcommand( - "narrow_widen", + b"narrow_widen", { - "oldincludes": oldincludes, - "oldexcludes": oldexcludes, - "newincludes": newincludes, - "newexcludes": newexcludes, - "cgversion": "03", - "commonheads": common, - "known": known, - "ellipses": ellipsesremote, + b"oldincludes": oldincludes, + b"oldexcludes": oldexcludes, + b"newincludes": newincludes, + b"newexcludes": newexcludes, + b"cgversion": b"03", + b"commonheads": common, + b"known": known, + b"ellipses": ellipsesremote, }, ).result() - trmanager = exchange.transactionmanager(repo, "widen", remote.url()) - with trmanager, repo.ui.configoverride(overrides, "widen"): + trmanager = exchange.transactionmanager( + repo, b"widen", remote.url() + ) + with trmanager, repo.ui.configoverride(overrides, b"widen"): op = bundle2.bundleoperation( - repo, trmanager.transaction, source="widen" + repo, trmanager.transaction, source=b"widen" ) # TODO: we should catch error.Abort here bundle2.processbundle(repo, bundle, op=op) @@ -388,7 +402,7 @@ with ds.parentchange(): ds.setparents(p1, p2) - with repo.transaction("widening"): + with repo.transaction(b"widening"): repo.setnewnarrowpats() narrowspec.updateworkingcopy(repo) narrowspec.copytoworkingcopy(repo) @@ -396,35 +410,40 @@ # TODO(rdamazio): Make new matcher format and update description @command( - "tracked", + b"tracked", [ - ("", "addinclude", [], _("new paths to include")), - ("", "removeinclude", [], _("old paths to no longer include")), + (b"", b"addinclude", [], _(b"new paths to include")), + (b"", b"removeinclude", [], _(b"old paths to no longer include")), ( - "", - "auto-remove-includes", + b"", + b"auto-remove-includes", False, - _("automatically choose unused includes to remove"), + _(b"automatically choose unused includes to remove"), ), - ("", "addexclude", [], _("new paths to exclude")), - ("", "import-rules", "", _("import narrowspecs from a file")), - ("", "removeexclude", [], _("old paths to no longer exclude")), - ("", "clear", False, _("whether to replace the existing narrowspec")), + (b"", b"addexclude", [], _(b"new paths to exclude")), + (b"", b"import-rules", b"", _(b"import narrowspecs from a file")), + (b"", b"removeexclude", [], _(b"old paths to no longer exclude")), ( - "", - "force-delete-local-changes", + b"", + b"clear", False, - _("forces deletion of local changes when narrowing"), + _(b"whether to replace the existing narrowspec"), ), ( - "", - "update-working-copy", + b"", + b"force-delete-local-changes", False, - _("update working copy when the store has changed"), + _(b"forces deletion of local changes when narrowing"), + ), + ( + b"", + b"update-working-copy", + False, + _(b"update working copy when the store has changed"), ), ] + commands.remoteopts, - _("[OPTIONS]... [REMOTE]"), + _(b"[OPTIONS]... [REMOTE]"), inferrepo=True, ) def trackedcmd(ui, repo, remotepath=None, *pats, **opts): @@ -464,47 +483,47 @@ if repository.NARROW_REQUIREMENT not in repo.requirements: raise error.Abort( _( - "the tracked command is only supported on " - "repositories cloned with --narrow" + b"the tracked command is only supported on " + b"repositories cloned with --narrow" ) ) # Before supporting, decide whether it "hg tracked --clear" should mean # tracking no paths or all paths. - if opts["clear"]: - raise error.Abort(_("the --clear option is not yet supported")) + if opts[b"clear"]: + raise error.Abort(_(b"the --clear option is not yet supported")) # import rules from a file - newrules = opts.get("import_rules") + newrules = opts.get(b"import_rules") if newrules: try: filepath = os.path.join(encoding.getcwd(), newrules) fdata = util.readfile(filepath) except IOError as inst: raise error.Abort( - _("cannot read narrowspecs from '%s': %s") + _(b"cannot read narrowspecs from '%s': %s") % (filepath, encoding.strtolocal(inst.strerror)) ) includepats, excludepats, profiles = sparse.parseconfig( - ui, fdata, "narrow" + ui, fdata, b"narrow" ) if profiles: raise error.Abort( _( - "including other spec files using '%include' " - "is not supported in narrowspec" + b"including other spec files using '%include' " + b"is not supported in narrowspec" ) ) - opts["addinclude"].extend(includepats) - opts["addexclude"].extend(excludepats) + opts[b"addinclude"].extend(includepats) + opts[b"addexclude"].extend(excludepats) - addedincludes = narrowspec.parsepatterns(opts["addinclude"]) - removedincludes = narrowspec.parsepatterns(opts["removeinclude"]) - addedexcludes = narrowspec.parsepatterns(opts["addexclude"]) - removedexcludes = narrowspec.parsepatterns(opts["removeexclude"]) - autoremoveincludes = opts["auto_remove_includes"] + addedincludes = narrowspec.parsepatterns(opts[b"addinclude"]) + removedincludes = narrowspec.parsepatterns(opts[b"removeinclude"]) + addedexcludes = narrowspec.parsepatterns(opts[b"addexclude"]) + removedexcludes = narrowspec.parsepatterns(opts[b"removeexclude"]) + autoremoveincludes = opts[b"auto_remove_includes"] - update_working_copy = opts["update_working_copy"] + update_working_copy = opts[b"update_working_copy"] only_show = not ( addedincludes or removedincludes @@ -529,27 +548,27 @@ # Only print the current narrowspec. if only_show: - ui.pager("tracked") - fm = ui.formatter("narrow", opts) + ui.pager(b"tracked") + fm = ui.formatter(b"narrow", opts) for i in sorted(oldincludes): fm.startitem() - fm.write("status", "%s ", "I", label="narrow.included") - fm.write("pat", "%s\n", i, label="narrow.included") + fm.write(b"status", b"%s ", b"I", label=b"narrow.included") + fm.write(b"pat", b"%s\n", i, label=b"narrow.included") for i in sorted(oldexcludes): fm.startitem() - fm.write("status", "%s ", "X", label="narrow.excluded") - fm.write("pat", "%s\n", i, label="narrow.excluded") + fm.write(b"status", b"%s ", b"X", label=b"narrow.excluded") + fm.write(b"pat", b"%s\n", i, label=b"narrow.excluded") fm.end() return 0 if update_working_copy: - with repo.wlock(), repo.lock(), repo.transaction("narrow-wc"): + with repo.wlock(), repo.lock(), repo.transaction(b"narrow-wc"): narrowspec.updateworkingcopy(repo) narrowspec.copytoworkingcopy(repo) return 0 if not (widening or narrowing or autoremoveincludes): - ui.status(_("nothing to widen or narrow\n")) + ui.status(_(b"nothing to widen or narrow\n")) return 0 with repo.wlock(), repo.lock(): @@ -558,16 +577,16 @@ # Find the revisions we have in common with the remote. These will # be used for finding local-only changes for narrowing. They will # also define the set of revisions to update for widening. - remotepath = ui.expandpath(remotepath or "default") + remotepath = ui.expandpath(remotepath or b"default") url, branches = hg.parseurl(remotepath) - ui.status(_("comparing with %s\n") % util.hidepassword(url)) + ui.status(_(b"comparing with %s\n") % util.hidepassword(url)) remote = hg.peer(repo, opts, url) # check narrow support before doing anything if widening needs to be # performed. In future we should also abort if client is ellipses and # server does not support ellipses if widening and wireprototypes.NARROWCAP not in remote.capabilities(): - raise error.Abort(_("server does not support narrow clones")) + raise error.Abort(_(b"server does not support narrow clones")) commoninc = discovery.findcommonincoming(repo, remote) @@ -575,7 +594,7 @@ outgoing = discovery.findcommonoutgoing( repo, remote, commoninc=commoninc ) - ui.status(_("looking for unused includes to remove\n")) + ui.status(_(b"looking for unused includes to remove\n")) localfiles = set() for n in itertools.chain(outgoing.missing, outgoing.excluded): localfiles.update(repo[n].files()) @@ -586,17 +605,20 @@ suggestedremovals.append(include) if suggestedremovals: for s in suggestedremovals: - ui.status("%s\n" % s) + ui.status(b"%s\n" % s) if ( ui.promptchoice( - _("remove these unused includes (yn)?" "$$ &Yes $$ &No") + _( + b"remove these unused includes (yn)?" + b"$$ &Yes $$ &No" + ) ) == 0 ): removedincludes.update(suggestedremovals) narrowing = True else: - ui.status(_("found no unused includes\n")) + ui.status(_(b"found no unused includes\n")) if narrowing: newincludes = oldincludes - removedincludes @@ -610,7 +632,7 @@ oldexcludes, newincludes, newexcludes, - opts["force_delete_local_changes"], + opts[b"force_delete_local_changes"], ) # _narrow() updated the narrowspec and _widen() below needs to # use the updated values as its base (otherwise removed includes diff --git a/hgext/narrow/narrowdirstate.py b/hgext/narrow/narrowdirstate.py --- a/hgext/narrow/narrowdirstate.py +++ b/hgext/narrow/narrowdirstate.py @@ -21,8 +21,8 @@ if f is not None and not narrowmatch(f) and f not in self: raise error.Abort( _( - "cannot track '%s' - it is outside " - + "the narrow clone" + b"cannot track '%s' - it is outside " + + b"the narrow clone" ) % f ) diff --git a/hgext/narrow/narrowtemplates.py b/hgext/narrow/narrowtemplates.py --- a/hgext/narrow/narrowtemplates.py +++ b/hgext/narrow/narrowtemplates.py @@ -23,30 +23,30 @@ return False -@templatekeyword("ellipsis", requires={"repo", "ctx"}) +@templatekeyword(b"ellipsis", requires={b"repo", b"ctx"}) def ellipsis(context, mapping): """String. 'ellipsis' if the change is an ellipsis node, else ''.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") if _isellipsis(repo, ctx.rev()): - return "ellipsis" - return "" + return b"ellipsis" + return b"" -@templatekeyword("outsidenarrow", requires={"repo", "ctx"}) +@templatekeyword(b"outsidenarrow", requires={b"repo", b"ctx"}) def outsidenarrow(context, mapping): """String. 'outsidenarrow' if the change affects no tracked files, else ''.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") m = repo.narrowmatch() if ctx.files() and not m.always(): if not any(m(f) for f in ctx.files()): - return "outsidenarrow" - return "" + return b"outsidenarrow" + return b"" -@revsetpredicate("ellipsis()") +@revsetpredicate(b"ellipsis()") def ellipsisrevset(repo, subset, x): """Changesets that are ellipsis nodes.""" return subset.filter(lambda r: _isellipsis(repo, r)) diff --git a/hgext/narrow/narrowwirepeer.py b/hgext/narrow/narrowwirepeer.py --- a/hgext/narrow/narrowwirepeer.py +++ b/hgext/narrow/narrowwirepeer.py @@ -29,26 +29,26 @@ def reposetup(repo): def wirereposetup(ui, peer): def wrapped(orig, cmd, *args, **kwargs): - if cmd == "unbundle": + if cmd == b"unbundle": # TODO: don't blindly add include/exclude wireproto # arguments to unbundle. include, exclude = repo.narrowpats - kwargs[r"includepats"] = ",".join(include) - kwargs[r"excludepats"] = ",".join(exclude) + kwargs[r"includepats"] = b",".join(include) + kwargs[r"excludepats"] = b",".join(exclude) return orig(cmd, *args, **kwargs) - extensions.wrapfunction(peer, "_calltwowaystream", wrapped) + extensions.wrapfunction(peer, b"_calltwowaystream", wrapped) hg.wirepeersetupfuncs.append(wirereposetup) @wireprotov1server.wireprotocommand( - "narrow_widen", - "oldincludes oldexcludes" - " newincludes newexcludes" - " commonheads cgversion" - " known ellipses", - permission="pull", + b"narrow_widen", + b"oldincludes oldexcludes" + b" newincludes newexcludes" + b" commonheads cgversion" + b" known ellipses", + permission=b"pull", ) def narrow_widen( repo, @@ -95,7 +95,7 @@ common = wireprototypes.decodelist(commonheads) known = wireprototypes.decodelist(known) - if ellipses == "0": + if ellipses == b"0": ellipses = False else: ellipses = bool(ellipses) @@ -135,11 +135,11 @@ ) except error.Abort as exc: bundler = bundle2.bundle20(repo.ui) - manargs = [("message", pycompat.bytestr(exc))] + manargs = [(b"message", pycompat.bytestr(exc))] advargs = [] if exc.hint is not None: - advargs.append(("hint", exc.hint)) - bundler.addpart(bundle2.bundlepart("error:abort", manargs, advargs)) + advargs.append((b"hint", exc.hint)) + bundler.addpart(bundle2.bundlepart(b"error:abort", manargs, advargs)) preferuncompressed = True chunks = bundler.getchunks() @@ -155,6 +155,6 @@ for ch in (r"oldincludes", r"newincludes", r"oldexcludes", r"newexcludes"): kwargs[ch] = b",".join(kwargs[ch]) - kwargs[r"ellipses"] = "%i" % bool(kwargs[r"ellipses"]) - f = remote._callcompressable("narrow_widen", **kwargs) + kwargs[r"ellipses"] = b"%i" % bool(kwargs[r"ellipses"]) + f = remote._callcompressable(b"narrow_widen", **kwargs) return bundle2.getunbundler(remote.ui, f) diff --git a/hgext/notify.py b/hgext/notify.py --- a/hgext/notify.py +++ b/hgext/notify.py @@ -173,67 +173,67 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "notify", "changegroup", default=None, + b"notify", b"changegroup", default=None, ) configitem( - "notify", "config", default=None, + b"notify", b"config", default=None, ) configitem( - "notify", "diffstat", default=True, + b"notify", b"diffstat", default=True, ) configitem( - "notify", "domain", default=None, + b"notify", b"domain", default=None, ) configitem( - "notify", "messageidseed", default=None, + b"notify", b"messageidseed", default=None, ) configitem( - "notify", "fromauthor", default=None, + b"notify", b"fromauthor", default=None, ) configitem( - "notify", "incoming", default=None, + b"notify", b"incoming", default=None, ) configitem( - "notify", "maxdiff", default=300, + b"notify", b"maxdiff", default=300, ) configitem( - "notify", "maxdiffstat", default=-1, + b"notify", b"maxdiffstat", default=-1, ) configitem( - "notify", "maxsubject", default=67, + b"notify", b"maxsubject", default=67, ) configitem( - "notify", "mbox", default=None, + b"notify", b"mbox", default=None, ) configitem( - "notify", "merge", default=True, + b"notify", b"merge", default=True, ) configitem( - "notify", "outgoing", default=None, + b"notify", b"outgoing", default=None, ) configitem( - "notify", "sources", default="serve", + b"notify", b"sources", default=b"serve", ) configitem( - "notify", "showfunc", default=None, + b"notify", b"showfunc", default=None, ) configitem( - "notify", "strip", default=0, + b"notify", b"strip", default=0, ) configitem( - "notify", "style", default=None, + b"notify", b"style", default=None, ) configitem( - "notify", "template", default=None, + b"notify", b"template", default=None, ) configitem( - "notify", "test", default=True, + b"notify", b"test", default=True, ) # template for single changeset can include email headers. @@ -257,7 +257,7 @@ """ deftemplates = { - "changegroup": multiple_template, + b"changegroup": multiple_template, } @@ -266,29 +266,29 @@ def __init__(self, ui, repo, hooktype): self.ui = ui - cfg = self.ui.config("notify", "config") + cfg = self.ui.config(b"notify", b"config") if cfg: - self.ui.readconfig(cfg, sections=["usersubs", "reposubs"]) + self.ui.readconfig(cfg, sections=[b"usersubs", b"reposubs"]) self.repo = repo - self.stripcount = int(self.ui.config("notify", "strip")) + self.stripcount = int(self.ui.config(b"notify", b"strip")) self.root = self.strip(self.repo.root) - self.domain = self.ui.config("notify", "domain") - self.mbox = self.ui.config("notify", "mbox") - self.test = self.ui.configbool("notify", "test") + self.domain = self.ui.config(b"notify", b"domain") + self.mbox = self.ui.config(b"notify", b"mbox") + self.test = self.ui.configbool(b"notify", b"test") self.charsets = mail._charsets(self.ui) self.subs = self.subscribers() - self.merge = self.ui.configbool("notify", "merge") - self.showfunc = self.ui.configbool("notify", "showfunc") - self.messageidseed = self.ui.config("notify", "messageidseed") + self.merge = self.ui.configbool(b"notify", b"merge") + self.showfunc = self.ui.configbool(b"notify", b"showfunc") + self.messageidseed = self.ui.config(b"notify", b"messageidseed") if self.showfunc is None: - self.showfunc = self.ui.configbool("diff", "showfunc") + self.showfunc = self.ui.configbool(b"diff", b"showfunc") mapfile = None - template = self.ui.config("notify", hooktype) or self.ui.config( - "notify", "template" + template = self.ui.config(b"notify", hooktype) or self.ui.config( + b"notify", b"template" ) if not template: - mapfile = self.ui.config("notify", "style") + mapfile = self.ui.config(b"notify", b"style") if not mapfile and not template: template = deftemplates.get(hooktype) or single_template spec = logcmdutil.templatespec(template, mapfile) @@ -300,7 +300,7 @@ path = util.pconvert(path) count = self.stripcount while count > 0: - c = path.find("/") + c = path.find(b"/") if c == -1: break path = path[c + 1 :] @@ -312,31 +312,31 @@ addr = stringutil.email(addr.strip()) if self.domain: - a = addr.find("@localhost") + a = addr.find(b"@localhost") if a != -1: addr = addr[:a] - if "@" not in addr: - return addr + "@" + self.domain + if b"@" not in addr: + return addr + b"@" + self.domain return addr def subscribers(self): """return list of email addresses of subscribers to this repo.""" subs = set() - for user, pats in self.ui.configitems("usersubs"): - for pat in pats.split(","): - if "#" in pat: - pat, revs = pat.split("#", 1) + for user, pats in self.ui.configitems(b"usersubs"): + for pat in pats.split(b","): + if b"#" in pat: + pat, revs = pat.split(b"#", 1) else: revs = None if fnmatch.fnmatch(self.repo.root, pat.strip()): subs.add((self.fixmail(user), revs)) - for pat, users in self.ui.configitems("reposubs"): - if "#" in pat: - pat, revs = pat.split("#", 1) + for pat, users in self.ui.configitems(b"reposubs"): + if b"#" in pat: + pat, revs = pat.split(b"#", 1) else: revs = None if fnmatch.fnmatch(self.repo.root, pat): - for user in users.split(","): + for user in users.split(b","): subs.add((self.fixmail(user), revs)) return [ (mail.addressencode(self.ui, s, self.charsets, self.test), r) @@ -350,7 +350,7 @@ self.t.show( ctx, changes=ctx.changeset(), - baseurl=self.ui.config("web", "baseurl"), + baseurl=self.ui.config(b"web", b"baseurl"), root=self.repo.root, webroot=self.root, **props @@ -359,7 +359,7 @@ def skipsource(self, source): """true if incoming changes from this source should be skipped.""" - ok_sources = self.ui.config("notify", "sources").split() + ok_sources = self.ui.config(b"notify", b"sources").split() return source not in ok_sources def send(self, ctx, count, data): @@ -371,13 +371,13 @@ if spec is None: subs.add(sub) continue - revs = self.repo.revs("%r and %d:", spec, ctx.rev()) + revs = self.repo.revs(b"%r and %d:", spec, ctx.rev()) if len(revs): subs.add(sub) continue if len(subs) == 0: self.ui.debug( - "notify: no subscribers to selected repo " "and revset\n" + b"notify: no subscribers to selected repo " b"and revset\n" ) return @@ -408,17 +408,17 @@ msg[k] = v msg[r"Date"] = encoding.strfromlocal( - dateutil.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") + dateutil.datestr(format=b"%a, %d %b %Y %H:%M:%S %1%2") ) # try to make subject line exist and be useful if not subject: if count > 1: - subject = _("%s: %d new changesets") % (self.root, count) + subject = _(b"%s: %d new changesets") % (self.root, count) else: - s = ctx.description().lstrip().split("\n", 1)[0].rstrip() - subject = "%s: %s" % (self.root, s) - maxsubject = int(self.ui.config("notify", "maxsubject")) + s = ctx.description().lstrip().split(b"\n", 1)[0].rstrip() + subject = b"%s: %s" % (self.root, s) + maxsubject = int(self.ui.config(b"notify", b"maxsubject")) if maxsubject: subject = stringutil.ellipsis(subject, maxsubject) msg[r"Subject"] = encoding.strfromlocal( @@ -427,8 +427,8 @@ # try to make message have proper sender if not sender: - sender = self.ui.config("email", "from") or self.ui.username() - if "@" not in sender or "@localhost" in sender: + sender = self.ui.config(b"email", b"from") or self.ui.username() + if b"@" not in sender or b"@localhost" in sender: sender = self.fixmail(sender) msg[r"From"] = encoding.strfromlocal( mail.addressencode(self.ui, sender, self.charsets, self.test) @@ -437,16 +437,16 @@ msg[r"X-Hg-Notification"] = r"changeset %s" % ctx if not msg[r"Message-Id"]: msg[r"Message-Id"] = messageid(ctx, self.domain, self.messageidseed) - msg[r"To"] = encoding.strfromlocal(", ".join(sorted(subs))) + msg[r"To"] = encoding.strfromlocal(b", ".join(sorted(subs))) msgtext = encoding.strtolocal(msg.as_string()) if self.test: self.ui.write(msgtext) - if not msgtext.endswith("\n"): - self.ui.write("\n") + if not msgtext.endswith(b"\n"): + self.ui.write(b"\n") else: self.ui.status( - _("notify: sending %d subscribers %d changes\n") + _(b"notify: sending %d subscribers %d changes\n") % (len(subs), count) ) mail.sendmail( @@ -459,7 +459,7 @@ def diff(self, ctx, ref=None): - maxdiff = int(self.ui.config("notify", "maxdiff")) + maxdiff = int(self.ui.config(b"notify", b"maxdiff")) prev = ctx.p1().node() if ref: ref = ref.node() @@ -468,31 +468,31 @@ diffopts = patch.diffallopts(self.ui) diffopts.showfunc = self.showfunc chunks = patch.diff(self.repo, prev, ref, opts=diffopts) - difflines = "".join(chunks).splitlines() + difflines = b"".join(chunks).splitlines() - if self.ui.configbool("notify", "diffstat"): - maxdiffstat = int(self.ui.config("notify", "maxdiffstat")) + if self.ui.configbool(b"notify", b"diffstat"): + maxdiffstat = int(self.ui.config(b"notify", b"maxdiffstat")) s = patch.diffstat(difflines) # s may be nil, don't include the header if it is if s: - if maxdiffstat >= 0 and s.count("\n") > maxdiffstat + 1: - s = s.split("\n") - msg = _("\ndiffstat (truncated from %d to %d lines):\n\n") + if maxdiffstat >= 0 and s.count(b"\n") > maxdiffstat + 1: + s = s.split(b"\n") + msg = _(b"\ndiffstat (truncated from %d to %d lines):\n\n") self.ui.write(msg % (len(s) - 2, maxdiffstat)) - self.ui.write("\n".join(s[:maxdiffstat] + s[-2:])) + self.ui.write(b"\n".join(s[:maxdiffstat] + s[-2:])) else: - self.ui.write(_("\ndiffstat:\n\n%s") % s) + self.ui.write(_(b"\ndiffstat:\n\n%s") % s) if maxdiff == 0: return elif maxdiff > 0 and len(difflines) > maxdiff: - msg = _("\ndiffs (truncated from %d to %d lines):\n\n") + msg = _(b"\ndiffs (truncated from %d to %d lines):\n\n") self.ui.write(msg % (len(difflines), maxdiff)) difflines = difflines[:maxdiff] elif difflines: - self.ui.write(_("\ndiffs (%d lines):\n\n") % len(difflines)) + self.ui.write(_(b"\ndiffs (%d lines):\n\n") % len(difflines)) - self.ui.write("\n".join(difflines)) + self.ui.write(b"\n".join(difflines)) def hook(ui, repo, hooktype, node=None, source=None, **kwargs): @@ -505,17 +505,17 @@ ctx = repo.unfiltered()[node] if not n.subs: - ui.debug("notify: no subscribers to repository %s\n" % n.root) + ui.debug(b"notify: no subscribers to repository %s\n" % n.root) return if n.skipsource(source): - ui.debug('notify: changes have source "%s" - skipping\n' % source) + ui.debug(b'notify: changes have source "%s" - skipping\n' % source) return ui.pushbuffer() - data = "" + data = b"" count = 0 - author = "" - if hooktype == "changegroup" or hooktype == "outgoing": + author = b"" + if hooktype == b"changegroup" or hooktype == b"outgoing": for rev in repo.changelog.revs(start=ctx.rev()): if n.node(repo[rev]): count += 1 @@ -524,17 +524,17 @@ else: data += ui.popbuffer() ui.note( - _("notify: suppressing notification for merge %d:%s\n") + _(b"notify: suppressing notification for merge %d:%s\n") % (rev, repo[rev].hex()[:12]) ) ui.pushbuffer() if count: - n.diff(ctx, repo["tip"]) + n.diff(ctx, repo[b"tip"]) elif ctx.rev() in repo: if not n.node(ctx): ui.popbuffer() ui.note( - _("notify: suppressing notification for merge %d:%s\n") + _(b"notify: suppressing notification for merge %d:%s\n") % (ctx.rev(), ctx.hex()[:12]) ) return @@ -544,9 +544,9 @@ author = ctx.user() data += ui.popbuffer() - fromauthor = ui.config("notify", "fromauthor") + fromauthor = ui.config(b"notify", b"fromauthor") if author and fromauthor: - data = "\n".join(["From: %s" % author, data]) + data = b"\n".join([b"From: %s" % author, data]) if count: n.send(ctx, count, data) @@ -559,9 +559,9 @@ host = encoding.strtolocal(socket.getfqdn()) if messageidseed: messagehash = hashlib.sha512(ctx.hex() + messageidseed) - messageid = "" % (messagehash.hexdigest()[:64], host) + messageid = b"" % (messagehash.hexdigest()[:64], host) else: - messageid = "" % ( + messageid = b"" % ( ctx, int(time.time()), hash(ctx.repo().root), diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py @@ -35,29 +35,29 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "pager", "attend", default=lambda: attended, + b"pager", b"attend", default=lambda: attended, ) def uisetup(ui): def pagecmd(orig, ui, options, cmd, cmdfunc): - auto = options["pager"] == "auto" + auto = options[b"pager"] == b"auto" if auto and not ui.pageractive: usepager = False - attend = ui.configlist("pager", "attend") - ignore = ui.configlist("pager", "ignore") + attend = ui.configlist(b"pager", b"attend") + ignore = ui.configlist(b"pager", b"ignore") cmds, _ = cmdutil.findcmd(cmd, commands.table) for cmd in cmds: - var = "attend-%s" % cmd - if ui.config("pager", var, None): - usepager = ui.configbool("pager", var, True) + var = b"attend-%s" % cmd + if ui.config(b"pager", var, None): + usepager = ui.configbool(b"pager", var, True) break if cmd in attend or (cmd not in ignore and not attend): usepager = True @@ -69,13 +69,13 @@ # core code doesn't know about attend, so we have to # lobotomize the ignore list so that the extension's # behavior is preserved. - ui.setconfig("pager", "ignore", "", "pager") - ui.pager("extension-via-attend-" + cmd) + ui.setconfig(b"pager", b"ignore", b"", b"pager") + ui.pager(b"extension-via-attend-" + cmd) else: ui.disablepager() return orig(ui, options, cmd, cmdfunc) - extensions.wrapfunction(dispatch, "_runcommand", pagecmd) + extensions.wrapfunction(dispatch, b"_runcommand", pagecmd) -attended = ["annotate", "cat", "diff", "export", "glog", "log", "qdiff"] +attended = [b"annotate", b"cat", b"diff", b"export", b"glog", b"log", b"qdiff"] diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py --- a/hgext/patchbomb.py +++ b/hgext/patchbomb.py @@ -110,34 +110,34 @@ configitem = registrar.configitem(configtable) configitem( - "patchbomb", "bundletype", default=None, + b"patchbomb", b"bundletype", default=None, ) configitem( - "patchbomb", "bcc", default=None, + b"patchbomb", b"bcc", default=None, ) configitem( - "patchbomb", "cc", default=None, + b"patchbomb", b"cc", default=None, ) configitem( - "patchbomb", "confirm", default=False, + b"patchbomb", b"confirm", default=False, ) configitem( - "patchbomb", "flagtemplate", default=None, + b"patchbomb", b"flagtemplate", default=None, ) configitem( - "patchbomb", "from", default=None, + b"patchbomb", b"from", default=None, ) configitem( - "patchbomb", "intro", default="auto", + b"patchbomb", b"intro", default=b"auto", ) configitem( - "patchbomb", "publicurl", default=None, + b"patchbomb", b"publicurl", default=None, ) configitem( - "patchbomb", "reply-to", default=None, + b"patchbomb", b"reply-to", default=None, ) configitem( - "patchbomb", "to", default=None, + b"patchbomb", b"to", default=None, ) if pycompat.ispy3: @@ -149,7 +149,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def _addpullheader(seq, ctx): @@ -159,9 +159,9 @@ # experimental config: patchbomb.publicurl # waiting for some logic that check that the changeset are available on the # destination before patchbombing anything. - publicurl = repo.ui.config("patchbomb", "publicurl") + publicurl = repo.ui.config(b"patchbomb", b"publicurl") if publicurl: - return "Available At %s\n" "# hg pull %s -r %s" % ( + return b"Available At %s\n" b"# hg pull %s -r %s" % ( publicurl, publicurl, ctx, @@ -170,53 +170,53 @@ def uisetup(ui): - cmdutil.extraexport.append("pullurl") - cmdutil.extraexportmap["pullurl"] = _addpullheader + cmdutil.extraexport.append(b"pullurl") + cmdutil.extraexportmap[b"pullurl"] = _addpullheader def reposetup(ui, repo): if not repo.local(): return - repo._wlockfreeprefix.add("last-email.txt") + repo._wlockfreeprefix.add(b"last-email.txt") -def prompt(ui, prompt, default=None, rest=":"): +def prompt(ui, prompt, default=None, rest=b":"): if default: - prompt += " [%s]" % default + prompt += b" [%s]" % default return ui.prompt(prompt + rest, default) def introwanted(ui, opts, number): """is an introductory message apparently wanted?""" - introconfig = ui.config("patchbomb", "intro") - if opts.get("intro") or opts.get("desc"): + introconfig = ui.config(b"patchbomb", b"intro") + if opts.get(b"intro") or opts.get(b"desc"): intro = True - elif introconfig == "always": + elif introconfig == b"always": intro = True - elif introconfig == "never": + elif introconfig == b"never": intro = False - elif introconfig == "auto": + elif introconfig == b"auto": intro = number > 1 else: ui.write_err( - _('warning: invalid patchbomb.intro value "%s"\n') % introconfig + _(b'warning: invalid patchbomb.intro value "%s"\n') % introconfig ) - ui.write_err(_("(should be one of always, never, auto)\n")) + ui.write_err(_(b"(should be one of always, never, auto)\n")) intro = number > 1 return intro def _formatflags(ui, repo, rev, flags): """build flag string optionally by template""" - tmpl = ui.config("patchbomb", "flagtemplate") + tmpl = ui.config(b"patchbomb", b"flagtemplate") if not tmpl: - return " ".join(flags) + return b" ".join(flags) out = util.stringio() - opts = {"template": templater.unquotestring(tmpl)} - with formatter.templateformatter(ui, out, "patchbombflag", opts) as fm: + opts = {b"template": templater.unquotestring(tmpl)} + with formatter.templateformatter(ui, out, b"patchbombflag", opts) as fm: fm.startitem() fm.context(ctx=repo[rev]) - fm.write("flags", "%s", fm.formatlist(flags, name="flag")) + fm.write(b"flags", b"%s", fm.formatlist(flags, name=b"flag")) return out.getvalue() @@ -224,13 +224,13 @@ """build prefix to patch subject""" flag = _formatflags(ui, repo, rev, flags) if flag: - flag = " " + flag + flag = b" " + flag if not numbered: - return "[PATCH%s]" % flag + return b"[PATCH%s]" % flag else: - tlen = len("%d" % total) - return "[PATCH %0*d of %d%s]" % (tlen, idx, total, flag) + tlen = len(b"%d" % total) + return b"[PATCH %0*d of %d%s]" % (tlen, idx, total, flag) def makepatch( @@ -248,28 +248,29 @@ desc = [] node = None - body = "" + body = b"" for line in patchlines: - if line.startswith("#"): - if line.startswith("# Node ID"): + if line.startswith(b"#"): + if line.startswith(b"# Node ID"): node = line.split()[-1] continue - if line.startswith("diff -r") or line.startswith("diff --git"): + if line.startswith(b"diff -r") or line.startswith(b"diff --git"): break desc.append(line) if not patchname and not node: raise ValueError - if opts.get("attach") and not opts.get("body"): + if opts.get(b"attach") and not opts.get(b"body"): body = ( - "\n".join(desc[1:]).strip() or "Patch subject is complete summary." + b"\n".join(desc[1:]).strip() + or b"Patch subject is complete summary." ) - body += "\n\n\n" + body += b"\n\n\n" - if opts.get("plain"): - while patchlines and patchlines[0].startswith("# "): + if opts.get(b"plain"): + while patchlines and patchlines[0].startswith(b"# "): patchlines.pop(0) if patchlines: patchlines.pop(0) @@ -277,19 +278,19 @@ patchlines.pop(0) ds = patch.diffstat(patchlines) - if opts.get("diffstat"): - body += ds + "\n\n" + if opts.get(b"diffstat"): + body += ds + b"\n\n" - addattachment = opts.get("attach") or opts.get("inline") - if not addattachment or opts.get("body"): - body += "\n".join(patchlines) + addattachment = opts.get(b"attach") or opts.get(b"inline") + if not addattachment or opts.get(b"body"): + body += b"\n".join(patchlines) if addattachment: msg = emimemultipart.MIMEMultipart() if body: - msg.attach(mail.mimeencode(ui, body, _charsets, opts.get("test"))) + msg.attach(mail.mimeencode(ui, body, _charsets, opts.get(b"test"))) p = mail.mimetextpatch( - "\n".join(patchlines), "x-patch", opts.get("test") + b"\n".join(patchlines), b"x-patch", opts.get(b"test") ) binnode = nodemod.bin(node) # if node is mq patch, it will have the patch file's name as a tag @@ -297,38 +298,38 @@ patchtags = [ t for t in repo.nodetags(binnode) - if t.endswith(".patch") or t.endswith(".diff") + if t.endswith(b".patch") or t.endswith(b".diff") ] if patchtags: patchname = patchtags[0] elif total > 1: patchname = cmdutil.makefilename( - repo[node], "%b-%n.patch", seqno=idx, total=total + repo[node], b"%b-%n.patch", seqno=idx, total=total ) else: - patchname = cmdutil.makefilename(repo[node], "%b.patch") + patchname = cmdutil.makefilename(repo[node], b"%b.patch") disposition = r"inline" - if opts.get("attach"): + if opts.get(b"attach"): disposition = r"attachment" p[r"Content-Disposition"] = ( disposition + r"; filename=" + encoding.strfromlocal(patchname) ) msg.attach(p) else: - msg = mail.mimetextpatch(body, display=opts.get("test")) + msg = mail.mimetextpatch(body, display=opts.get(b"test")) prefix = _formatprefix( - ui, repo, rev, opts.get("flag"), idx, total, numbered + ui, repo, rev, opts.get(b"flag"), idx, total, numbered ) - subj = desc[0].strip().rstrip(". ") + subj = desc[0].strip().rstrip(b". ") if not numbered: - subj = " ".join([prefix, opts.get("subject") or subj]) + subj = b" ".join([prefix, opts.get(b"subject") or subj]) else: - subj = " ".join([prefix, subj]) - msg["Subject"] = mail.headencode(ui, subj, _charsets, opts.get("test")) - msg["X-Mercurial-Node"] = node - msg["X-Mercurial-Series-Index"] = "%i" % idx - msg["X-Mercurial-Series-Total"] = "%i" % total + subj = b" ".join([prefix, subj]) + msg[b"Subject"] = mail.headencode(ui, subj, _charsets, opts.get(b"test")) + msg[b"X-Mercurial-Node"] = node + msg[b"X-Mercurial-Series-Index"] = b"%i" % idx + msg[b"X-Mercurial-Series-Total"] = b"%i" % total return msg, subj, ds @@ -338,17 +339,17 @@ Each patch in the list is itself a list of lines. """ ui = repo.ui - prev = repo["."].rev() + prev = repo[b"."].rev() for r in revs: if r == prev and (repo[None].files() or repo[None].deleted()): ui.warn( - _("warning: working directory has " "uncommitted changes\n") + _(b"warning: working directory has " b"uncommitted changes\n") ) output = stringio() cmdutil.exportfile( repo, [r], output, opts=patch.difffeatureopts(ui, opts, git=True) ) - yield output.getvalue().split("\n") + yield output.getvalue().split(b"\n") def _getbundle(repo, dest, **opts): @@ -360,9 +361,9 @@ The bundle is a returned as a single in-memory binary blob. """ ui = repo.ui - tmpdir = pycompat.mkdtemp(prefix="hg-email-bundle-") - tmpfn = os.path.join(tmpdir, "bundle") - btype = ui.config("patchbomb", "bundletype") + tmpdir = pycompat.mkdtemp(prefix=b"hg-email-bundle-") + tmpfn = os.path.join(tmpdir, b"bundle") + btype = ui.config(b"patchbomb", b"bundletype") if btype: opts[r"type"] = btype try: @@ -389,13 +390,13 @@ body = open(opts.get(r"desc")).read() else: ui.write( - _("\nWrite the introductory message for the " "patch series.\n\n") + _(b"\nWrite the introductory message for the " b"patch series.\n\n") ) body = ui.edit( - defaultbody, sender, repopath=repo.path, action="patchbombbody" + defaultbody, sender, repopath=repo.path, action=b"patchbombbody" ) # Save series description in case sendmail fails - msgfile = repo.vfs("last-email.txt", "wb") + msgfile = repo.vfs(b"last-email.txt", b"wb") msgfile.write(body) msgfile.close() return body @@ -410,16 +411,16 @@ ui = repo.ui _charsets = mail._charsets(ui) subj = opts.get(r"subject") or prompt( - ui, "Subject:", "A bundle for your repository" + ui, b"Subject:", b"A bundle for your repository" ) - body = _getdescription(repo, "", sender, **opts) + body = _getdescription(repo, b"", sender, **opts) msg = emimemultipart.MIMEMultipart() if body: msg.attach(mail.mimeencode(ui, body, _charsets, opts.get(r"test"))) datapart = emimebase.MIMEBase(r"application", r"x-mercurial-bundle") datapart.set_payload(bundle) - bundlename = "%s.hg" % opts.get(r"bundlename", "bundle") + bundlename = b"%s.hg" % opts.get(r"bundlename", b"bundle") datapart.add_header( r"Content-Disposition", r"attachment", @@ -427,7 +428,7 @@ ) emailencoders.encode_base64(datapart) msg.attach(datapart) - msg["Subject"] = mail.headencode(ui, subj, _charsets, opts.get(r"test")) + msg[b"Subject"] = mail.headencode(ui, subj, _charsets, opts.get(r"test")) return [(msg, subj, None)] @@ -443,24 +444,24 @@ ui, repo, revs.last(), opts.get(r"flag"), 0, len(patches), numbered=True ) subj = opts.get(r"subject") or prompt( - ui, "(optional) Subject: ", rest=prefix, default="" + ui, b"(optional) Subject: ", rest=prefix, default=b"" ) if not subj: return None # skip intro if the user doesn't bother - subj = prefix + " " + subj + subj = prefix + b" " + subj - body = "" + body = b"" if opts.get(r"diffstat"): # generate a cumulative diffstat of the whole patch series diffstat = patch.diffstat(sum(patches, [])) - body = "\n" + diffstat + body = b"\n" + diffstat else: diffstat = None body = _getdescription(repo, body, sender, **opts) msg = mail.mimeencode(ui, body, _charsets, opts.get(r"test")) - msg["Subject"] = mail.headencode(ui, subj, _charsets, opts.get(r"test")) + msg[b"Subject"] = mail.headencode(ui, subj, _charsets, opts.get(r"test")) return (msg, subj, diffstat) @@ -477,7 +478,7 @@ patches = list(_getpatches(repo, revs, **opts)) msgs = [] - ui.write(_("this patch series consists of %d patches.\n\n") % len(patches)) + ui.write(_(b"this patch series consists of %d patches.\n\n") % len(patches)) # build the intro message, or skip it if the user declines if introwanted(ui, bytesopts, len(patches)): @@ -514,132 +515,149 @@ def _getoutgoing(repo, dest, revs): """Return the revisions present locally but not in dest""" ui = repo.ui - url = ui.expandpath(dest or "default-push", dest or "default") + url = ui.expandpath(dest or b"default-push", dest or b"default") url = hg.parseurl(url)[0] - ui.status(_("comparing with %s\n") % util.hidepassword(url)) + ui.status(_(b"comparing with %s\n") % util.hidepassword(url)) revs = [r for r in revs if r >= 0] if not revs: revs = [repo.changelog.tiprev()] - revs = repo.revs("outgoing(%s) and ::%ld", dest or "", revs) + revs = repo.revs(b"outgoing(%s) and ::%ld", dest or b"", revs) if not revs: - ui.status(_("no changes found\n")) + ui.status(_(b"no changes found\n")) return revs def _msgid(node, timestamp): hostname = encoding.strtolocal(socket.getfqdn()) - hostname = encoding.environ.get("HGHOSTNAME", hostname) - return "<%s.%d@%s>" % (node, timestamp, hostname) + hostname = encoding.environ.get(b"HGHOSTNAME", hostname) + return b"<%s.%d@%s>" % (node, timestamp, hostname) emailopts = [ - ("", "body", None, _("send patches as inline message text (default)")), - ("a", "attach", None, _("send patches as attachments")), - ("i", "inline", None, _("send patches as inline attachments")), - ( - "", - "bcc", - [], - _("email addresses of blind carbon copy recipients"), - _("EMAIL"), - ), - ("c", "cc", [], _("email addresses of copy recipients"), _("EMAIL")), - ("", "confirm", None, _("ask for confirmation before sending")), - ("d", "diffstat", None, _("add diffstat output to messages")), - ("", "date", "", _("use the given date as the sending date"), _("DATE")), + (b"", b"body", None, _(b"send patches as inline message text (default)")), + (b"a", b"attach", None, _(b"send patches as attachments")), + (b"i", b"inline", None, _(b"send patches as inline attachments")), ( - "", - "desc", - "", - _("use the given file as the series description"), - _("FILE"), + b"", + b"bcc", + [], + _(b"email addresses of blind carbon copy recipients"), + _(b"EMAIL"), ), - ("f", "from", "", _("email address of sender"), _("EMAIL")), - ("n", "test", None, _("print messages that would be sent")), + (b"c", b"cc", [], _(b"email addresses of copy recipients"), _(b"EMAIL")), + (b"", b"confirm", None, _(b"ask for confirmation before sending")), + (b"d", b"diffstat", None, _(b"add diffstat output to messages")), ( - "m", - "mbox", - "", - _("write messages to mbox file instead of sending them"), - _("FILE"), + b"", + b"date", + b"", + _(b"use the given date as the sending date"), + _(b"DATE"), ), ( - "", - "reply-to", - [], - _("email addresses replies should be sent to"), - _("EMAIL"), + b"", + b"desc", + b"", + _(b"use the given file as the series description"), + _(b"FILE"), + ), + (b"f", b"from", b"", _(b"email address of sender"), _(b"EMAIL")), + (b"n", b"test", None, _(b"print messages that would be sent")), + ( + b"m", + b"mbox", + b"", + _(b"write messages to mbox file instead of sending them"), + _(b"FILE"), ), ( - "s", - "subject", - "", - _("subject of first message (intro or single patch)"), - _("TEXT"), + b"", + b"reply-to", + [], + _(b"email addresses replies should be sent to"), + _(b"EMAIL"), ), - ("", "in-reply-to", "", _("message identifier to reply to"), _("MSGID")), - ("", "flag", [], _("flags to add in subject prefixes"), _("FLAG")), - ("t", "to", [], _("email addresses of recipients"), _("EMAIL")), + ( + b"s", + b"subject", + b"", + _(b"subject of first message (intro or single patch)"), + _(b"TEXT"), + ), + ( + b"", + b"in-reply-to", + b"", + _(b"message identifier to reply to"), + _(b"MSGID"), + ), + (b"", b"flag", [], _(b"flags to add in subject prefixes"), _(b"FLAG")), + (b"t", b"to", [], _(b"email addresses of recipients"), _(b"EMAIL")), ] @command( - "email", + b"email", [ - ("g", "git", None, _("use git extended diff format")), - ("", "plain", None, _("omit hg patch header")), + (b"g", b"git", None, _(b"use git extended diff format")), + (b"", b"plain", None, _(b"omit hg patch header")), ( - "o", - "outgoing", + b"o", + b"outgoing", None, - _("send changes not found in the target repository"), + _(b"send changes not found in the target repository"), ), ( - "b", - "bundle", + b"b", + b"bundle", None, - _("send changes not in target as a binary bundle"), + _(b"send changes not in target as a binary bundle"), ), ( - "B", - "bookmark", - "", - _("send changes only reachable by given bookmark"), - _("BOOKMARK"), + b"B", + b"bookmark", + b"", + _(b"send changes only reachable by given bookmark"), + _(b"BOOKMARK"), ), ( - "", - "bundlename", - "bundle", - _("name of the bundle attachment file"), - _("NAME"), + b"", + b"bundlename", + b"bundle", + _(b"name of the bundle attachment file"), + _(b"NAME"), ), - ("r", "rev", [], _("a revision to send"), _("REV")), + (b"r", b"rev", [], _(b"a revision to send"), _(b"REV")), ( - "", - "force", + b"", + b"force", None, _( - "run even when remote repository is unrelated " - "(with -b/--bundle)" + b"run even when remote repository is unrelated " + b"(with -b/--bundle)" ), ), ( - "", - "base", + b"", + b"base", [], _( - "a base changeset to specify instead of a destination " - "(with -b/--bundle)" + b"a base changeset to specify instead of a destination " + b"(with -b/--bundle)" ), - _("REV"), + _(b"REV"), ), - ("", "intro", None, _("send an introduction email for a single patch")), + ( + b"", + b"intro", + None, + _(b"send an introduction email for a single patch"), + ), ] + emailopts + cmdutil.remoteopts, - _("hg email [OPTION]... [DEST]..."), + _(b"hg email [OPTION]... [DEST]..."), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def email(ui, repo, *revs, **opts): @@ -731,33 +749,35 @@ _charsets = mail._charsets(ui) - bundle = opts.get("bundle") - date = opts.get("date") - mbox = opts.get("mbox") - outgoing = opts.get("outgoing") - rev = opts.get("rev") - bookmark = opts.get("bookmark") + bundle = opts.get(b"bundle") + date = opts.get(b"date") + mbox = opts.get(b"mbox") + outgoing = opts.get(b"outgoing") + rev = opts.get(b"rev") + bookmark = opts.get(b"bookmark") - if not (opts.get("test") or mbox): + if not (opts.get(b"test") or mbox): # really sending mail.validateconfig(ui) if not (revs or rev or outgoing or bundle or bookmark): - raise error.Abort(_("specify at least one changeset with -B, -r or -o")) + raise error.Abort( + _(b"specify at least one changeset with -B, -r or -o") + ) if outgoing and bundle: raise error.Abort( _( - "--outgoing mode always on with --bundle;" - " do not re-specify --outgoing" + b"--outgoing mode always on with --bundle;" + b" do not re-specify --outgoing" ) ) if rev and bookmark: - raise error.Abort(_("-r and -B are mutually exclusive")) + raise error.Abort(_(b"-r and -B are mutually exclusive")) if outgoing or bundle: if len(revs) > 1: - raise error.Abort(_("too many destinations")) + raise error.Abort(_(b"too many destinations")) if revs: dest = revs[0] else: @@ -766,32 +786,32 @@ if rev: if revs: - raise error.Abort(_("use only one form to specify the revision")) + raise error.Abort(_(b"use only one form to specify the revision")) revs = rev elif bookmark: if bookmark not in repo._bookmarks: - raise error.Abort(_("bookmark '%s' not found") % bookmark) + raise error.Abort(_(b"bookmark '%s' not found") % bookmark) revs = scmutil.bookmarkrevs(repo, bookmark) revs = scmutil.revrange(repo, revs) if outgoing: revs = _getoutgoing(repo, dest, revs) if bundle: - opts["revs"] = ["%d" % r for r in revs] + opts[b"revs"] = [b"%d" % r for r in revs] # check if revision exist on the public destination - publicurl = repo.ui.config("patchbomb", "publicurl") + publicurl = repo.ui.config(b"patchbomb", b"publicurl") if publicurl: - repo.ui.debug("checking that revision exist in the public repo\n") + repo.ui.debug(b"checking that revision exist in the public repo\n") try: publicpeer = hg.peer(repo, {}, publicurl) except error.RepoError: repo.ui.write_err( - _("unable to access public repo: %s\n") % publicurl + _(b"unable to access public repo: %s\n") % publicurl ) raise - if not publicpeer.capable("known"): - repo.ui.debug("skipping existence checks: public repo too old\n") + if not publicpeer.capable(b"known"): + repo.ui.debug(b"skipping existence checks: public repo too old\n") else: out = [repo[r] for r in revs] known = publicpeer.known(h.node() for h in out) @@ -801,16 +821,16 @@ missing.append(h) if missing: if len(missing) > 1: - msg = _('public "%s" is missing %s and %i others') + msg = _(b'public "%s" is missing %s and %i others') msg %= (publicurl, missing[0], len(missing) - 1) else: - msg = _("public url %s is missing %s") + msg = _(b"public url %s is missing %s") msg %= (publicurl, missing[0]) missingrevs = [ctx.rev() for ctx in missing] - revhint = " ".join( - "-r %s" % h for h in repo.set("heads(%ld)", missingrevs) + revhint = b" ".join( + b"-r %s" % h for h in repo.set(b"heads(%ld)", missingrevs) ) - hint = _("use 'hg push %s %s'") % (publicurl, revhint) + hint = _(b"use 'hg push %s %s'") % (publicurl, revhint) raise error.Abort(msg, hint=hint) # start @@ -824,10 +844,10 @@ # deprecated config: patchbomb.from sender = ( - opts.get("from") - or ui.config("email", "from") - or ui.config("patchbomb", "from") - or prompt(ui, "From", ui.username()) + opts.get(b"from") + or ui.config(b"email", b"from") + or ui.config(b"patchbomb", b"from") + or prompt(ui, b"From", ui.username()) ) if bundle: @@ -843,98 +863,100 @@ def getaddrs(header, ask=False, default=None): configkey = header.lower() - opt = header.replace("-", "_").lower() + opt = header.replace(b"-", b"_").lower() addrs = opts.get(opt) if addrs: - showaddrs.append("%s: %s" % (header, ", ".join(addrs))) - return mail.addrlistencode(ui, addrs, _charsets, opts.get("test")) + showaddrs.append(b"%s: %s" % (header, b", ".join(addrs))) + return mail.addrlistencode(ui, addrs, _charsets, opts.get(b"test")) # not on the command line: fallback to config and then maybe ask - addr = ui.config("email", configkey) or ui.config( - "patchbomb", configkey + addr = ui.config(b"email", configkey) or ui.config( + b"patchbomb", configkey ) if not addr: - specified = ui.hasconfig("email", configkey) or ui.hasconfig( - "patchbomb", configkey + specified = ui.hasconfig(b"email", configkey) or ui.hasconfig( + b"patchbomb", configkey ) if not specified and ask: addr = prompt(ui, header, default=default) if addr: - showaddrs.append("%s: %s" % (header, addr)) - return mail.addrlistencode(ui, [addr], _charsets, opts.get("test")) + showaddrs.append(b"%s: %s" % (header, addr)) + return mail.addrlistencode(ui, [addr], _charsets, opts.get(b"test")) elif default: return mail.addrlistencode( - ui, [default], _charsets, opts.get("test") + ui, [default], _charsets, opts.get(b"test") ) return [] - to = getaddrs("To", ask=True) + to = getaddrs(b"To", ask=True) if not to: # we can get here in non-interactive mode - raise error.Abort(_("no recipient addresses provided")) - cc = getaddrs("Cc", ask=True, default="") - bcc = getaddrs("Bcc") - replyto = getaddrs("Reply-To") + raise error.Abort(_(b"no recipient addresses provided")) + cc = getaddrs(b"Cc", ask=True, default=b"") + bcc = getaddrs(b"Bcc") + replyto = getaddrs(b"Reply-To") - confirm = ui.configbool("patchbomb", "confirm") - confirm |= bool(opts.get("diffstat") or opts.get("confirm")) + confirm = ui.configbool(b"patchbomb", b"confirm") + confirm |= bool(opts.get(b"diffstat") or opts.get(b"confirm")) if confirm: - ui.write(_("\nFinal summary:\n\n"), label="patchbomb.finalsummary") - ui.write(("From: %s\n" % sender), label="patchbomb.from") + ui.write(_(b"\nFinal summary:\n\n"), label=b"patchbomb.finalsummary") + ui.write((b"From: %s\n" % sender), label=b"patchbomb.from") for addr in showaddrs: - ui.write("%s\n" % addr, label="patchbomb.to") + ui.write(b"%s\n" % addr, label=b"patchbomb.to") for m, subj, ds in msgs: - ui.write(("Subject: %s\n" % subj), label="patchbomb.subject") + ui.write((b"Subject: %s\n" % subj), label=b"patchbomb.subject") if ds: - ui.write(ds, label="patchbomb.diffstats") - ui.write("\n") + ui.write(ds, label=b"patchbomb.diffstats") + ui.write(b"\n") if ui.promptchoice( - _("are you sure you want to send (yn)?" "$$ &Yes $$ &No") + _(b"are you sure you want to send (yn)?" b"$$ &Yes $$ &No") ): - raise error.Abort(_("patchbomb canceled")) + raise error.Abort(_(b"patchbomb canceled")) - ui.write("\n") + ui.write(b"\n") - parent = opts.get("in_reply_to") or None + parent = opts.get(b"in_reply_to") or None # angle brackets may be omitted, they're not semantically part of the msg-id if parent is not None: - if not parent.startswith("<"): - parent = "<" + parent - if not parent.endswith(">"): - parent += ">" + if not parent.startswith(b"<"): + parent = b"<" + parent + if not parent.endswith(b">"): + parent += b">" sender_addr = eutil.parseaddr(encoding.strfromlocal(sender))[1] - sender = mail.addressencode(ui, sender, _charsets, opts.get("test")) + sender = mail.addressencode(ui, sender, _charsets, opts.get(b"test")) sendmail = None firstpatch = None - progress = ui.makeprogress(_("sending"), unit=_("emails"), total=len(msgs)) + progress = ui.makeprogress( + _(b"sending"), unit=_(b"emails"), total=len(msgs) + ) for i, (m, subj, ds) in enumerate(msgs): try: - m["Message-Id"] = genmsgid(m["X-Mercurial-Node"]) + m[b"Message-Id"] = genmsgid(m[b"X-Mercurial-Node"]) if not firstpatch: - firstpatch = m["Message-Id"] - m["X-Mercurial-Series-Id"] = firstpatch + firstpatch = m[b"Message-Id"] + m[b"X-Mercurial-Series-Id"] = firstpatch except TypeError: - m["Message-Id"] = genmsgid("patchbomb") + m[b"Message-Id"] = genmsgid(b"patchbomb") if parent: - m["In-Reply-To"] = parent - m["References"] = parent - if not parent or "X-Mercurial-Node" not in m: - parent = m["Message-Id"] + m[b"In-Reply-To"] = parent + m[b"References"] = parent + if not parent or b"X-Mercurial-Node" not in m: + parent = m[b"Message-Id"] - m["User-Agent"] = "Mercurial-patchbomb/%s" % util.version() - m["Date"] = eutil.formatdate(start_time[0], localtime=True) + m[b"User-Agent"] = b"Mercurial-patchbomb/%s" % util.version() + m[b"Date"] = eutil.formatdate(start_time[0], localtime=True) start_time = (start_time[0] + 1, start_time[1]) - m["From"] = sender - m["To"] = ", ".join(to) + m[b"From"] = sender + m[b"To"] = b", ".join(to) if cc: - m["Cc"] = ", ".join(cc) + m[b"Cc"] = b", ".join(cc) if bcc: - m["Bcc"] = ", ".join(bcc) + m[b"Bcc"] = b", ".join(bcc) if replyto: - m["Reply-To"] = ", ".join(replyto) + m[b"Reply-To"] = b", ".join(replyto) # Fix up all headers to be native strings. # TODO(durin42): this should probably be cleaned up above in the future. if pycompat.ispy3: @@ -952,24 +974,24 @@ change = True if change: m[hdr] = val - if opts.get("test"): - ui.status(_("displaying "), subj, " ...\n") - ui.pager("email") + if opts.get(b"test"): + ui.status(_(b"displaying "), subj, b" ...\n") + ui.pager(b"email") generator = _bytesgenerator(ui, mangle_from_=False) try: generator.flatten(m, 0) - ui.write("\n") + ui.write(b"\n") except IOError as inst: if inst.errno != errno.EPIPE: raise else: if not sendmail: sendmail = mail.connect(ui, mbox=mbox) - ui.status(_("sending "), subj, " ...\n") + ui.status(_(b"sending "), subj, b" ...\n") progress.update(i, item=subj) if not mbox: # Exim does not remove the Bcc field - del m["Bcc"] + del m[b"Bcc"] fp = stringio() generator = _bytesgenerator(fp, mangle_from_=False) generator.flatten(m, 0) diff --git a/hgext/phabricator.py b/hgext/phabricator.py --- a/hgext/phabricator.py +++ b/hgext/phabricator.py @@ -79,7 +79,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" eh = exthelper.exthelper() @@ -747,7 +747,7 @@ if old.description() != newdesc: if old.phase() == phases.public: ui.warn( - _("warning: not updating public commit %s\n") + _(b"warning: not updating public commit %s\n") % scmutil.formatchangeid(old) ) continue diff --git a/hgext/purge.py b/hgext/purge.py --- a/hgext/purge.py +++ b/hgext/purge.py @@ -40,29 +40,29 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "purge|clean", + b"purge|clean", [ - ("a", "abort-on-err", None, _("abort if an error occurs")), - ("", "all", None, _("purge ignored files too")), - ("", "dirs", None, _("purge empty directories")), - ("", "files", None, _("purge files")), - ("p", "print", None, _("print filenames instead of deleting them")), + (b"a", b"abort-on-err", None, _(b"abort if an error occurs")), + (b"", b"all", None, _(b"purge ignored files too")), + (b"", b"dirs", None, _(b"purge empty directories")), + (b"", b"files", None, _(b"purge files")), + (b"p", b"print", None, _(b"print filenames instead of deleting them")), ( - "0", - "print0", + b"0", + b"print0", None, _( - "end filenames with NUL, for use with xargs" - " (implies -p/--print)" + b"end filenames with NUL, for use with xargs" + b" (implies -p/--print)" ), ), ] + cmdutil.walkopts, - _("hg purge [OPTION]... [DIR]..."), + _(b"hg purge [OPTION]... [DIR]..."), helpcategory=command.CATEGORY_MAINTENANCE, ) def purge(ui, repo, *dirs, **opts): @@ -97,14 +97,14 @@ """ opts = pycompat.byteskwargs(opts) - act = not opts.get("print") - eol = "\n" - if opts.get("print0"): - eol = "\0" + act = not opts.get(b"print") + eol = b"\n" + if opts.get(b"print0"): + eol = b"\0" act = False # --print0 implies --print - removefiles = opts.get("files") - removedirs = opts.get("dirs") + removefiles = opts.get(b"files") + removedirs = opts.get(b"dirs") if not removefiles and not removedirs: removefiles = True @@ -115,13 +115,13 @@ paths = mergemod.purge( repo, match, - ignored=opts.get("all", False), + ignored=opts.get(b"all", False), removeemptydirs=removedirs, removefiles=removefiles, - abortonerror=opts.get("abort_on_err"), + abortonerror=opts.get(b"abort_on_err"), noop=not act, ) for path in paths: if not act: - ui.write("%s%s" % (path, eol)) + ui.write(b"%s%s" % (path, eol)) diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -56,11 +56,11 @@ # Indicates that a revision needs to be rebased revtodo = -1 -revtodostr = "-1" +revtodostr = b"-1" # legacy revstates no longer needed in current code # -2: nullmerge, -3: revignored, -4: revprecursor, -5: revpruned -legacystates = {"-2", "-3", "-4", "-5"} +legacystates = {b"-2", b"-3", b"-4", b"-5"} cmdtable = {} command = registrar.command(cmdtable) @@ -68,7 +68,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def _nothingtorebase(): @@ -76,16 +76,16 @@ def _savegraft(ctx, extra): - s = ctx.extra().get("source", None) + s = ctx.extra().get(b"source", None) if s is not None: - extra["source"] = s - s = ctx.extra().get("intermediate-source", None) + extra[b"source"] = s + s = ctx.extra().get(b"intermediate-source", None) if s is not None: - extra["intermediate-source"] = s + extra[b"intermediate-source"] = s def _savebranch(ctx, extra): - extra["branch"] = ctx.branch() + extra[b"branch"] = ctx.branch() def _destrebase(repo, sourceset, destspace=None): @@ -94,7 +94,7 @@ Please wrap destutil.destmerge instead.""" return destutil.destmerge( repo, - action="rebase", + action=b"rebase", sourceset=sourceset, onheadcheck=False, destspace=destspace, @@ -104,7 +104,7 @@ revsetpredicate = registrar.revsetpredicate() -@revsetpredicate("_destrebase") +@revsetpredicate(b"_destrebase") def _revsetdestrebase(repo, subset, x): # ``_rebasedefaultdest()`` @@ -118,13 +118,13 @@ return subset & smartset.baseset([_destrebase(repo, sourceset)]) -@revsetpredicate("_destautoorphanrebase") +@revsetpredicate(b"_destautoorphanrebase") def _revsetdestautoorphanrebase(repo, subset, x): # ``_destautoorphanrebase()`` # automatic rebase destination for a single orphan revision. unfi = repo.unfiltered() - obsoleted = unfi.revs("obsolete()") + obsoleted = unfi.revs(b"obsolete()") src = revset.getset(repo, subset, x).first() @@ -134,7 +134,7 @@ dests = destutil.orphanpossibledestination(repo, src) if len(dests) > 1: raise error.Abort( - _("ambiguous automatic rebase: %r could end up on any of %r") + _(b"ambiguous automatic rebase: %r could end up on any of %r") % (src, dests) ) # We have zero or one destination, so we can just return here. @@ -143,15 +143,19 @@ def _ctxdesc(ctx): """short description for a context""" - desc = '%d:%s "%s"' % (ctx.rev(), ctx, ctx.description().split("\n", 1)[0]) + desc = b'%d:%s "%s"' % ( + ctx.rev(), + ctx, + ctx.description().split(b"\n", 1)[0], + ) repo = ctx.repo() names = [] for nsname, ns in repo.names.iteritems(): - if nsname == "branches": + if nsname == b"branches": continue names.extend(ns.names(repo, ctx.node())) if names: - desc += " (%s)" % " ".join(names) + desc += b" (%s)" % b" ".join(names) return desc @@ -185,22 +189,22 @@ self.destmap = {} self.skipped = set() - self.collapsef = opts.get("collapse", False) + self.collapsef = opts.get(b"collapse", False) self.collapsemsg = cmdutil.logmessage(ui, opts) - self.date = opts.get("date", None) + self.date = opts.get(b"date", None) - e = opts.get("extrafn") # internal, used by e.g. hgsubversion + e = opts.get(b"extrafn") # internal, used by e.g. hgsubversion self.extrafns = [_savegraft] if e: self.extrafns = [e] - self.backupf = ui.configbool("rewrite", "backup-bundle") - self.keepf = opts.get("keep", False) - self.keepbranchesf = opts.get("keepbranches", False) + self.backupf = ui.configbool(b"rewrite", b"backup-bundle") + self.keepf = opts.get(b"keep", False) + self.keepbranchesf = opts.get(b"keepbranches", False) self.obsoletenotrebased = {} self.obsoletewithoutsuccessorindestination = set() self.inmemory = inmemory - self.stateobj = statemod.cmdstate(repo, "rebasestate") + self.stateobj = statemod.cmdstate(repo, b"rebasestate") @property def repo(self): @@ -213,96 +217,96 @@ """Store the current status to allow recovery""" if tr: tr.addfilegenerator( - "rebasestate", - ("rebasestate",), + b"rebasestate", + (b"rebasestate",), self._writestatus, - location="plain", + location=b"plain", ) else: - with self.repo.vfs("rebasestate", "w") as f: + with self.repo.vfs(b"rebasestate", b"w") as f: self._writestatus(f) def _writestatus(self, f): repo = self.repo assert repo.filtername is None - f.write(repo[self.originalwd].hex() + "\n") + f.write(repo[self.originalwd].hex() + b"\n") # was "dest". we now write dest per src root below. - f.write("\n") - f.write(repo[self.external].hex() + "\n") - f.write("%d\n" % int(self.collapsef)) - f.write("%d\n" % int(self.keepf)) - f.write("%d\n" % int(self.keepbranchesf)) - f.write("%s\n" % (self.activebookmark or "")) + f.write(b"\n") + f.write(repo[self.external].hex() + b"\n") + f.write(b"%d\n" % int(self.collapsef)) + f.write(b"%d\n" % int(self.keepf)) + f.write(b"%d\n" % int(self.keepbranchesf)) + f.write(b"%s\n" % (self.activebookmark or b"")) destmap = self.destmap for d, v in self.state.iteritems(): oldrev = repo[d].hex() if v >= 0: newrev = repo[v].hex() else: - newrev = "%d" % v + newrev = b"%d" % v destnode = repo[destmap[d]].hex() - f.write("%s:%s:%s\n" % (oldrev, newrev, destnode)) - repo.ui.debug("rebase status stored\n") + f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode)) + repo.ui.debug(b"rebase status stored\n") def restorestatus(self): """Restore a previously stored status""" if not self.stateobj.exists(): - cmdutil.wrongtooltocontinue(self.repo, _("rebase")) + cmdutil.wrongtooltocontinue(self.repo, _(b"rebase")) data = self._read() - self.repo.ui.debug("rebase status resumed\n") + self.repo.ui.debug(b"rebase status resumed\n") - self.originalwd = data["originalwd"] - self.destmap = data["destmap"] - self.state = data["state"] - self.skipped = data["skipped"] - self.collapsef = data["collapse"] - self.keepf = data["keep"] - self.keepbranchesf = data["keepbranches"] - self.external = data["external"] - self.activebookmark = data["activebookmark"] + self.originalwd = data[b"originalwd"] + self.destmap = data[b"destmap"] + self.state = data[b"state"] + self.skipped = data[b"skipped"] + self.collapsef = data[b"collapse"] + self.keepf = data[b"keep"] + self.keepbranchesf = data[b"keepbranches"] + self.external = data[b"external"] + self.activebookmark = data[b"activebookmark"] def _read(self): self.prepared = True repo = self.repo assert repo.filtername is None data = { - "keepbranches": None, - "collapse": None, - "activebookmark": None, - "external": nullrev, - "keep": None, - "originalwd": None, + b"keepbranches": None, + b"collapse": None, + b"activebookmark": None, + b"external": nullrev, + b"keep": None, + b"originalwd": None, } legacydest = None state = {} destmap = {} if True: - f = repo.vfs("rebasestate") + f = repo.vfs(b"rebasestate") for i, l in enumerate(f.read().splitlines()): if i == 0: - data["originalwd"] = repo[l].rev() + data[b"originalwd"] = repo[l].rev() elif i == 1: # this line should be empty in newer version. but legacy # clients may still use it if l: legacydest = repo[l].rev() elif i == 2: - data["external"] = repo[l].rev() + data[b"external"] = repo[l].rev() elif i == 3: - data["collapse"] = bool(int(l)) + data[b"collapse"] = bool(int(l)) elif i == 4: - data["keep"] = bool(int(l)) + data[b"keep"] = bool(int(l)) elif i == 5: - data["keepbranches"] = bool(int(l)) - elif i == 6 and not (len(l) == 81 and ":" in l): + data[b"keepbranches"] = bool(int(l)) + elif i == 6 and not (len(l) == 81 and b":" in l): # line 6 is a recent addition, so for backwards # compatibility check that the line doesn't look like the # oldrev:newrev lines - data["activebookmark"] = l + data[b"activebookmark"] = l else: - args = l.split(":") + args = l.split(b":") oldrev = repo[args[0]].rev() newrev = args[1] if newrev in legacystates: @@ -318,23 +322,23 @@ else: state[oldrev] = repo[newrev].rev() - if data["keepbranches"] is None: - raise error.Abort(_(".hg/rebasestate is incomplete")) + if data[b"keepbranches"] is None: + raise error.Abort(_(b".hg/rebasestate is incomplete")) - data["destmap"] = destmap - data["state"] = state + data[b"destmap"] = destmap + data[b"state"] = state skipped = set() # recompute the set of skipped revs - if not data["collapse"]: + if not data[b"collapse"]: seen = set(destmap.values()) for old, new in sorted(state.items()): if new != revtodo and new in seen: skipped.add(old) seen.add(new) - data["skipped"] = skipped + data[b"skipped"] = skipped repo.ui.debug( - "computed skipped revs: %s\n" - % (" ".join("%d" % r for r in sorted(skipped)) or "") + b"computed skipped revs: %s\n" + % (b" ".join(b"%d" % r for r in sorted(skipped)) or b"") ) return data @@ -346,7 +350,7 @@ destmap: {srcrev: destrev} destination revisions """ self.obsoletenotrebased = {} - if not self.ui.configbool("experimental", "rebaseskipobsolete"): + if not self.ui.configbool(b"experimental", b"rebaseskipobsolete"): return obsoleteset = set(obsoleterevs) ( @@ -369,14 +373,14 @@ clearcollapsemsg(self.repo) self.repo.ui.warn( _( - "rebase aborted (no revision is removed," - " only broken state is cleared)\n" + b"rebase aborted (no revision is removed," + b" only broken state is cleared)\n" ) ) return 0 else: - msg = _("cannot continue inconsistent rebase") - hint = _('use "hg rebase --abort" to clear broken state') + msg = _(b"cannot continue inconsistent rebase") + hint = _(b'use "hg rebase --abort" to clear broken state') raise error.Abort(msg, hint=hint) if isabort: @@ -390,28 +394,28 @@ rebaseset = destmap.keys() allowunstable = obsolete.isenabled(self.repo, obsolete.allowunstableopt) if not (self.keepf or allowunstable) and self.repo.revs( - "first(children(%ld) - %ld)", rebaseset, rebaseset + b"first(children(%ld) - %ld)", rebaseset, rebaseset ): raise error.Abort( _( - "can't remove original changesets with" - " unrebased descendants" + b"can't remove original changesets with" + b" unrebased descendants" ), - hint=_("use --keep to keep original changesets"), + hint=_(b"use --keep to keep original changesets"), ) result = buildstate(self.repo, destmap, self.collapsef) if not result: # Empty state built, nothing to rebase - self.ui.status(_("nothing to rebase\n")) + self.ui.status(_(b"nothing to rebase\n")) return _nothingtorebase() - for root in self.repo.set("roots(%ld)", rebaseset): + for root in self.repo.set(b"roots(%ld)", rebaseset): if not self.keepf and not root.mutable(): raise error.Abort( - _("can't rebase public changeset %s") % root, - hint=_("see 'hg help phases' for details"), + _(b"can't rebase public changeset %s") % root, + hint=_(b"see 'hg help phases' for details"), ) (self.originalwd, self.destmap, self.state) = result @@ -419,7 +423,7 @@ dests = set(self.destmap.values()) if len(dests) != 1: raise error.Abort( - _("--collapse does not work with multiple destinations") + _(b"--collapse does not work with multiple destinations") ) destrev = next(iter(dests)) destancestors = self.repo.changelog.ancestors( @@ -430,7 +434,7 @@ for destrev in sorted(set(destmap.values())): dest = self.repo[destrev] if dest.closesbranch() and not self.keepbranchesf: - self.ui.status(_("reopening closed branch head %s\n") % dest) + self.ui.status(_(b"reopening closed branch head %s\n") % dest) self.prepared = True @@ -439,13 +443,13 @@ from mercurial.context import overlayworkingctx self.wctx = overlayworkingctx(self.repo) - self.repo.ui.debug("rebasing in-memory\n") + self.repo.ui.debug(b"rebasing in-memory\n") else: self.wctx = self.repo[None] - self.repo.ui.debug("rebasing on disk\n") + self.repo.ui.debug(b"rebasing on disk\n") self.repo.ui.log( - "rebase", - "using in-memory rebase: %r\n", + b"rebase", + b"using in-memory rebase: %r\n", self.inmemory, rebase_imm_used=self.inmemory, ) @@ -464,7 +468,7 @@ branches.add(repo[rev].branch()) if len(branches) > 1: raise error.Abort( - _("cannot collapse multiple named " "branches") + _(b"cannot collapse multiple named " b"branches") ) # Calculate self.obsoletenotrebased @@ -486,27 +490,27 @@ cands = [k for k, v in self.state.iteritems() if v == revtodo] p = repo.ui.makeprogress( - _("rebasing"), unit=_("changesets"), total=len(cands) + _(b"rebasing"), unit=_(b"changesets"), total=len(cands) ) def progress(ctx): - p.increment(item=("%d:%s" % (ctx.rev(), ctx))) + p.increment(item=(b"%d:%s" % (ctx.rev(), ctx))) allowdivergence = self.ui.configbool( - "experimental", "evolution.allowdivergence" + b"experimental", b"evolution.allowdivergence" ) for subset in sortsource(self.destmap): - sortedrevs = self.repo.revs("sort(%ld, -topo)", subset) + sortedrevs = self.repo.revs(b"sort(%ld, -topo)", subset) if not allowdivergence: sortedrevs -= self.repo.revs( - "descendants(%ld) and not %ld", + b"descendants(%ld) and not %ld", self.obsoletewithoutsuccessorindestination, self.obsoletewithoutsuccessorindestination, ) for rev in sortedrevs: self._rebasenode(tr, rev, allowdivergence, progress) p.complete() - ui.note(_("rebase merging completed\n")) + ui.note(_(b"rebase merging completed\n")) def _concludenode(self, rev, p1, p2, editor, commitmsg=None): """Commit the wd changes with parents p1 and p2. @@ -520,15 +524,15 @@ date = self.date if date is None: date = ctx.date() - extra = {"rebase_source": ctx.hex()} + extra = {b"rebase_source": ctx.hex()} for c in self.extrafns: c(ctx, extra) keepbranch = self.keepbranchesf and repo[p1].branch() != ctx.branch() destphase = max(ctx.phase(), phases.draft) - overrides = {("phases", "new-commit"): destphase} + overrides = {(b"phases", b"new-commit"): destphase} if keepbranch: - overrides[("ui", "allowemptycommit")] = True - with repo.ui.configoverride(overrides, "rebase"): + overrides[(b"ui", b"allowemptycommit")] = True + with repo.ui.configoverride(overrides, b"rebase"): if self.inmemory: newnode = commitmemorynode( repo, @@ -567,15 +571,15 @@ ctx = repo[rev] desc = _ctxdesc(ctx) if self.state[rev] == rev: - ui.status(_("already rebased %s\n") % desc) + ui.status(_(b"already rebased %s\n") % desc) elif ( not allowdivergence and rev in self.obsoletewithoutsuccessorindestination ): msg = ( _( - "note: not rebasing %s and its descendants as " - "this would cause divergence\n" + b"note: not rebasing %s and its descendants as " + b"this would cause divergence\n" ) % desc ) @@ -585,12 +589,13 @@ succ = self.obsoletenotrebased[rev] if succ is None: msg = ( - _("note: not rebasing %s, it has no " "successor\n") % desc + _(b"note: not rebasing %s, it has no " b"successor\n") + % desc ) else: succdesc = _ctxdesc(repo[succ]) msg = _( - "note: not rebasing %s, already in " "destination as %s\n" + b"note: not rebasing %s, already in " b"destination as %s\n" ) % (desc, succdesc) repo.ui.status(msg) # Make clearrebased aware state[rev] is not a true successor @@ -602,7 +607,7 @@ ) self.state[rev] = dest elif self.state[rev] == revtodo: - ui.status(_("rebasing %s\n") % desc) + ui.status(_(b"rebasing %s\n") % desc) progressfn(ctx) p1, p2, base = defineparents( repo, @@ -613,10 +618,10 @@ self.obsoletenotrebased, ) if not self.inmemory and len(repo[None].parents()) == 2: - repo.ui.debug("resuming interrupted rebase\n") + repo.ui.debug(b"resuming interrupted rebase\n") else: - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "rebase"): + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"rebase"): stats = rebasenode( repo, rev, @@ -632,13 +637,13 @@ else: raise error.InterventionRequired( _( - "unresolved conflicts (see hg " - "resolve, then hg rebase --continue)" + b"unresolved conflicts (see hg " + b"resolve, then hg rebase --continue)" ) ) if not self.collapsef: merging = p2 != nullrev - editform = cmdutil.mergeeditform(merging, "rebase") + editform = cmdutil.mergeeditform(merging, b"rebase") editor = cmdutil.getcommiteditor( editform=editform, **pycompat.strkwargs(opts) ) @@ -653,22 +658,22 @@ # Update the state if newnode is not None: self.state[rev] = repo[newnode].rev() - ui.debug("rebased as %s\n" % short(newnode)) + ui.debug(b"rebased as %s\n" % short(newnode)) else: if not self.collapsef: ui.warn( _( - "note: not rebasing %s, its destination already " - "has all its changes\n" + b"note: not rebasing %s, its destination already " + b"has all its changes\n" ) % desc ) self.skipped.add(rev) self.state[rev] = p1 - ui.debug("next revision set to %d\n" % p1) + ui.debug(b"next revision set to %d\n" % p1) else: ui.status( - _("already rebased %s as %s\n") % (desc, repo[self.state[rev]]) + _(b"already rebased %s as %s\n") % (desc, repo[self.state[rev]]) ) if not tr: # When not using single transaction, store state after each @@ -679,7 +684,7 @@ def _finishrebase(self): repo, ui, opts = self.repo, self.ui, self.opts - fm = ui.formatter("rebase", opts) + fm = ui.formatter(b"rebase", opts) fm.startitem() if self.collapsef: p1, p2, _base = defineparents( @@ -690,15 +695,15 @@ self.skipped, self.obsoletenotrebased, ) - editopt = opts.get("edit") - editform = "rebase.collapse" + editopt = opts.get(b"edit") + editform = b"rebase.collapse" if self.collapsemsg: commitmsg = self.collapsemsg else: - commitmsg = "Collapsed revision" + commitmsg = b"Collapsed revision" for rebased in sorted(self.state): if rebased not in self.skipped: - commitmsg += "\n* %s" % repo[rebased].description() + commitmsg += b"\n* %s" % repo[rebased].description() editopt = True editor = cmdutil.getcommiteditor(edit=editopt, editform=editform) revtoreuse = max(self.state) @@ -712,7 +717,7 @@ for oldrev in self.state: self.state[oldrev] = newrev - if "qtip" in repo.tags(): + if b"qtip" in repo.tags(): updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts)) # restore original working directory @@ -722,7 +727,7 @@ # original directory is a parent of rebase set root or ignored newwd = self.originalwd if newwd not in [c.rev() for c in repo[None].parents()]: - ui.note(_("update back to initial working directory parent\n")) + ui.note(_(b"update back to initial working directory parent\n")) hg.updaterepo(repo, newwd, overwrite=False) collapsedas = None @@ -743,17 +748,17 @@ clearstatus(repo) clearcollapsemsg(repo) - ui.note(_("rebase completed\n")) - util.unlinkpath(repo.sjoin("undo"), ignoremissing=True) + ui.note(_(b"rebase completed\n")) + util.unlinkpath(repo.sjoin(b"undo"), ignoremissing=True) if self.skipped: skippedlen = len(self.skipped) - ui.note(_("%d revisions have been skipped\n") % skippedlen) + ui.note(_(b"%d revisions have been skipped\n") % skippedlen) fm.end() if ( self.activebookmark and self.activebookmark in repo._bookmarks - and repo["."].node() == repo._bookmarks[self.activebookmark] + and repo[b"."].node() == repo._bookmarks[self.activebookmark] ): bookmarks.activate(repo, self.activebookmark) @@ -775,9 +780,9 @@ cleanup = True if immutable: repo.ui.warn( - _("warning: can't clean up public changesets %s\n") - % ", ".join(bytes(repo[r]) for r in immutable), - hint=_("see 'hg help phases' for details"), + _(b"warning: can't clean up public changesets %s\n") + % b", ".join(bytes(repo[r]) for r in immutable), + hint=_(b"see 'hg help phases' for details"), ) cleanup = False @@ -787,8 +792,8 @@ if descendants - set(rebased): repo.ui.warn( _( - "warning: new changesets detected on " - "destination branch, can't strip\n" + b"warning: new changesets detected on " + b"destination branch, can't strip\n" ) ) cleanup = False @@ -797,13 +802,13 @@ shouldupdate = False if rebased: strippoints = [ - c.node() for c in repo.set("roots(%ld)", rebased) + c.node() for c in repo.set(b"roots(%ld)", rebased) ] updateifonnodes = set(rebased) updateifonnodes.update(self.destmap.values()) updateifonnodes.add(self.originalwd) - shouldupdate = repo["."].rev() in updateifonnodes + shouldupdate = repo[b"."].rev() in updateifonnodes # Update away from the rebase if necessary if shouldupdate or needupdate(repo, self.state): @@ -822,67 +827,73 @@ clearstatus(repo) clearcollapsemsg(repo) if not suppwarns: - repo.ui.warn(_("rebase aborted\n")) + repo.ui.warn(_(b"rebase aborted\n")) return 0 @command( - "rebase", + b"rebase", [ ( - "s", - "source", - "", - _("rebase the specified changeset and descendants"), - _("REV"), + b"s", + b"source", + b"", + _(b"rebase the specified changeset and descendants"), + _(b"REV"), ), ( - "b", - "base", - "", - _("rebase everything from branching point of specified changeset"), - _("REV"), + b"b", + b"base", + b"", + _(b"rebase everything from branching point of specified changeset"), + _(b"REV"), ), - ("r", "rev", [], _("rebase these revisions"), _("REV")), - ("d", "dest", "", _("rebase onto the specified changeset"), _("REV")), - ("", "collapse", False, _("collapse the rebased changesets")), + (b"r", b"rev", [], _(b"rebase these revisions"), _(b"REV")), ( - "m", - "message", - "", - _("use text as collapse commit message"), - _("TEXT"), + b"d", + b"dest", + b"", + _(b"rebase onto the specified changeset"), + _(b"REV"), ), - ("e", "edit", False, _("invoke editor on commit messages")), + (b"", b"collapse", False, _(b"collapse the rebased changesets")), ( - "l", - "logfile", - "", - _("read collapse commit message from file"), - _("FILE"), + b"m", + b"message", + b"", + _(b"use text as collapse commit message"), + _(b"TEXT"), + ), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), + ( + b"l", + b"logfile", + b"", + _(b"read collapse commit message from file"), + _(b"FILE"), ), - ("k", "keep", False, _("keep original changesets")), - ("", "keepbranches", False, _("keep original branch names")), - ("D", "detach", False, _("(DEPRECATED)")), - ("i", "interactive", False, _("(DEPRECATED)")), - ("t", "tool", "", _("specify merge tool")), - ("", "stop", False, _("stop interrupted rebase")), - ("c", "continue", False, _("continue an interrupted rebase")), - ("a", "abort", False, _("abort an interrupted rebase")), + (b"k", b"keep", False, _(b"keep original changesets")), + (b"", b"keepbranches", False, _(b"keep original branch names")), + (b"D", b"detach", False, _(b"(DEPRECATED)")), + (b"i", b"interactive", False, _(b"(DEPRECATED)")), + (b"t", b"tool", b"", _(b"specify merge tool")), + (b"", b"stop", False, _(b"stop interrupted rebase")), + (b"c", b"continue", False, _(b"continue an interrupted rebase")), + (b"a", b"abort", False, _(b"abort an interrupted rebase")), ( - "", - "auto-orphans", - "", + b"", + b"auto-orphans", + b"", _( - "automatically rebase orphan revisions " - "in the specified revset (EXPERIMENTAL)" + b"automatically rebase orphan revisions " + b"in the specified revset (EXPERIMENTAL)" ), ), ] + cmdutil.dryrunopts + cmdutil.formatteropts + cmdutil.confirmopts, - _("[-s REV | -b REV] [-d REV] [OPTION]"), + _(b"[-s REV | -b REV] [-d REV] [OPTION]"), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def rebase(ui, repo, **opts): @@ -1009,21 +1020,21 @@ """ opts = pycompat.byteskwargs(opts) - inmemory = ui.configbool("rebase", "experimental.inmemory") - dryrun = opts.get("dry_run") - confirm = opts.get("confirm") - selactions = [k for k in ["abort", "stop", "continue"] if opts.get(k)] + inmemory = ui.configbool(b"rebase", b"experimental.inmemory") + dryrun = opts.get(b"dry_run") + confirm = opts.get(b"confirm") + selactions = [k for k in [b"abort", b"stop", b"continue"] if opts.get(k)] if len(selactions) > 1: raise error.Abort( - _("cannot use --%s with --%s") % tuple(selactions[:2]) + _(b"cannot use --%s with --%s") % tuple(selactions[:2]) ) action = selactions[0] if selactions else None if dryrun and action: - raise error.Abort(_("cannot specify both --dry-run and --%s") % action) + raise error.Abort(_(b"cannot specify both --dry-run and --%s") % action) if confirm and action: - raise error.Abort(_("cannot specify both --confirm and --%s") % action) + raise error.Abort(_(b"cannot specify both --confirm and --%s") % action) if dryrun and confirm: - raise error.Abort(_("cannot specify both --confirm and --dry-run")) + raise error.Abort(_(b"cannot specify both --confirm and --dry-run")) if action or repo.currenttransaction() is not None: # in-memory rebase is not compatible with resuming rebases. @@ -1031,35 +1042,35 @@ # fail the entire transaction.) inmemory = False - if opts.get("auto_orphans"): + if opts.get(b"auto_orphans"): for key in opts: - if key != "auto_orphans" and opts.get(key): + if key != b"auto_orphans" and opts.get(key): raise error.Abort( - _("--auto-orphans is incompatible with %s") % ("--" + key) + _(b"--auto-orphans is incompatible with %s") % (b"--" + key) ) - userrevs = list(repo.revs(opts.get("auto_orphans"))) - opts["rev"] = [revsetlang.formatspec("%ld and orphan()", userrevs)] - opts["dest"] = "_destautoorphanrebase(SRC)" + userrevs = list(repo.revs(opts.get(b"auto_orphans"))) + opts[b"rev"] = [revsetlang.formatspec(b"%ld and orphan()", userrevs)] + opts[b"dest"] = b"_destautoorphanrebase(SRC)" if dryrun or confirm: return _dryrunrebase(ui, repo, action, opts) - elif action == "stop": + elif action == b"stop": rbsrt = rebaseruntime(repo, ui) with repo.wlock(), repo.lock(): rbsrt.restorestatus() if rbsrt.collapsef: - raise error.Abort(_("cannot stop in --collapse session")) + raise error.Abort(_(b"cannot stop in --collapse session")) allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt) if not (rbsrt.keepf or allowunstable): raise error.Abort( _( - "cannot remove original changesets with" - " unrebased descendants" + b"cannot remove original changesets with" + b" unrebased descendants" ), hint=_( - "either enable obsmarkers to allow unstable " - "revisions or use --keep to keep original " - "changesets" + b"either enable obsmarkers to allow unstable " + b"revisions or use --keep to keep original " + b"changesets" ), ) if needupdate(repo, rbsrt.state): @@ -1072,14 +1083,14 @@ try: # in-memory merge doesn't support conflicts, so if we hit any, abort # and re-run as an on-disk merge. - overrides = {("rebase", "singletransaction"): True} - with ui.configoverride(overrides, "rebase"): + overrides = {(b"rebase", b"singletransaction"): True} + with ui.configoverride(overrides, b"rebase"): return _dorebase(ui, repo, action, opts, inmemory=inmemory) except error.InMemoryMergeConflictsError: ui.warn( _( - "hit merge conflicts; re-running rebase without in-memory" - " merge\n" + b"hit merge conflicts; re-running rebase without in-memory" + b" merge\n" ) ) # TODO: Make in-memory merge not use the on-disk merge state, so @@ -1094,18 +1105,18 @@ def _dryrunrebase(ui, repo, action, opts): rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts) - confirm = opts.get("confirm") + confirm = opts.get(b"confirm") if confirm: - ui.status(_("starting in-memory rebase\n")) + ui.status(_(b"starting in-memory rebase\n")) else: ui.status( - _("starting dry-run rebase; repository will not be " "changed\n") + _(b"starting dry-run rebase; repository will not be " b"changed\n") ) with repo.wlock(), repo.lock(): needsabort = True try: - overrides = {("rebase", "singletransaction"): True} - with ui.configoverride(overrides, "rebase"): + overrides = {(b"rebase", b"singletransaction"): True} + with ui.configoverride(overrides, b"rebase"): _origrebase( ui, repo, @@ -1116,14 +1127,14 @@ leaveunfinished=True, ) except error.InMemoryMergeConflictsError: - ui.status(_("hit a merge conflict\n")) + ui.status(_(b"hit a merge conflict\n")) return 1 except error.Abort: needsabort = False raise else: if confirm: - ui.status(_("rebase completed successfully\n")) + ui.status(_(b"rebase completed successfully\n")) if not ui.promptchoice( _(b"apply changes (yn)?" b"$$ &Yes $$ &No") ): @@ -1137,8 +1148,8 @@ else: ui.status( _( - "dry-run rebase completed successfully; run without" - " -n/--dry-run to perform this rebase\n" + b"dry-run rebase completed successfully; run without" + b" -n/--dry-run to perform this rebase\n" ) ) return 0 @@ -1158,51 +1169,53 @@ def _origrebase( ui, repo, action, opts, rbsrt, inmemory=False, leaveunfinished=False ): - assert action != "stop" + assert action != b"stop" with repo.wlock(), repo.lock(): # Validate input and define rebasing points - destf = opts.get("dest", None) - srcf = opts.get("source", None) - basef = opts.get("base", None) - revf = opts.get("rev", []) + destf = opts.get(b"dest", None) + srcf = opts.get(b"source", None) + basef = opts.get(b"base", None) + revf = opts.get(b"rev", []) # search default destination in this space # used in the 'hg pull --rebase' case, see issue 5214. - destspace = opts.get("_destspace") - if opts.get("interactive"): + destspace = opts.get(b"_destspace") + if opts.get(b"interactive"): try: - if extensions.find("histedit"): - enablehistedit = "" + if extensions.find(b"histedit"): + enablehistedit = b"" except KeyError: - enablehistedit = " --config extensions.histedit=" - help = "hg%s help -e histedit" % enablehistedit + enablehistedit = b" --config extensions.histedit=" + help = b"hg%s help -e histedit" % enablehistedit msg = ( _( - "interactive history editing is supported by the " - "'histedit' extension (see \"%s\")" + b"interactive history editing is supported by the " + b"'histedit' extension (see \"%s\")" ) % help ) raise error.Abort(msg) if rbsrt.collapsemsg and not rbsrt.collapsef: - raise error.Abort(_("message can only be specified with collapse")) + raise error.Abort(_(b"message can only be specified with collapse")) if action: if rbsrt.collapsef: raise error.Abort( - _("cannot use collapse with continue or abort") + _(b"cannot use collapse with continue or abort") ) if srcf or basef or destf: raise error.Abort( - _("abort and continue do not allow specifying revisions") + _(b"abort and continue do not allow specifying revisions") ) - if action == "abort" and opts.get("tool", False): - ui.warn(_("tool option will be ignored\n")) - if action == "continue": + if action == b"abort" and opts.get(b"tool", False): + ui.warn(_(b"tool option will be ignored\n")) + if action == b"continue": ms = mergemod.mergestate.read(repo) mergeutil.checkunresolved(ms) - retcode = rbsrt._prepareabortorcontinue(isabort=(action == "abort")) + retcode = rbsrt._prepareabortorcontinue( + isabort=(action == b"abort") + ) if retcode is not None: return retcode else: @@ -1223,9 +1236,9 @@ tr = None - singletr = ui.configbool("rebase", "singletransaction") + singletr = ui.configbool(b"rebase", b"singletransaction") if singletr: - tr = repo.transaction("rebase") + tr = repo.transaction(b"rebase") # If `rebase.singletransaction` is enabled, wrap the entire operation in # one transaction here. Otherwise, transactions are obtained when @@ -1235,7 +1248,7 @@ # rebasing in-memory (it's not needed). dsguard = None if singletr and not inmemory: - dsguard = dirstateguard.dirstateguard(repo, "rebase") + dsguard = dirstateguard.dirstateguard(repo, b"rebase") with util.acceptintervention(dsguard): rbsrt._performrebase(tr) if not leaveunfinished: @@ -1259,19 +1272,20 @@ # destspace is here to work around issues with `hg pull --rebase` see # issue5214 for details if srcf and basef: - raise error.Abort(_("cannot specify both a source and a base")) + raise error.Abort(_(b"cannot specify both a source and a base")) if revf and basef: - raise error.Abort(_("cannot specify both a revision and a base")) + raise error.Abort(_(b"cannot specify both a revision and a base")) if revf and srcf: - raise error.Abort(_("cannot specify both a revision and a source")) + raise error.Abort(_(b"cannot specify both a revision and a source")) if not inmemory: cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) - if ui.configbool("commands", "rebase.requiredest") and not destf: + if ui.configbool(b"commands", b"rebase.requiredest") and not destf: raise error.Abort( - _("you must specify a destination"), hint=_("use: hg rebase -d REV") + _(b"you must specify a destination"), + hint=_(b"use: hg rebase -d REV"), ) dest = None @@ -1279,20 +1293,20 @@ if revf: rebaseset = scmutil.revrange(repo, revf) if not rebaseset: - ui.status(_('empty "rev" revision set - nothing to rebase\n')) + ui.status(_(b'empty "rev" revision set - nothing to rebase\n')) return None elif srcf: src = scmutil.revrange(repo, [srcf]) if not src: - ui.status(_('empty "source" revision set - nothing to rebase\n')) + ui.status(_(b'empty "source" revision set - nothing to rebase\n')) return None - rebaseset = repo.revs("(%ld)::", src) + rebaseset = repo.revs(b"(%ld)::", src) assert rebaseset else: - base = scmutil.revrange(repo, [basef or "."]) + base = scmutil.revrange(repo, [basef or b"."]) if not base: ui.status( - _('empty "base" revision set - ' "can't compute rebase set\n") + _(b'empty "base" revision set - ' b"can't compute rebase set\n") ) return None if destf: @@ -1305,16 +1319,16 @@ roots = [] # selected children of branching points bpbase = {} # {branchingpoint: [origbase]} for b in base: # group bases by branching points - bp = repo.revs("ancestor(%d, %d)", b, dest.rev()).first() + bp = repo.revs(b"ancestor(%d, %d)", b, dest.rev()).first() bpbase[bp] = bpbase.get(bp, []) + [b] if None in bpbase: # emulate the old behavior, showing "nothing to rebase" (a better # behavior may be abort with "cannot find branching point" error) bpbase.clear() for bp, bs in bpbase.iteritems(): # calculate roots - roots += list(repo.revs("children(%d) & ancestors(%ld)", bp, bs)) + roots += list(repo.revs(b"children(%d) & ancestors(%ld)", bp, bs)) - rebaseset = repo.revs("%ld::", roots) + rebaseset = repo.revs(b"%ld::", roots) if not rebaseset: # transform to list because smartsets are not comparable to @@ -1324,48 +1338,48 @@ if basef: ui.status( _( - 'nothing to rebase - %s is both "base"' - " and destination\n" + b'nothing to rebase - %s is both "base"' + b" and destination\n" ) % dest ) else: ui.status( _( - "nothing to rebase - working directory " - "parent is also destination\n" + b"nothing to rebase - working directory " + b"parent is also destination\n" ) ) - elif not repo.revs("%ld - ::%d", base, dest.rev()): + elif not repo.revs(b"%ld - ::%d", base, dest.rev()): if basef: ui.status( _( - 'nothing to rebase - "base" %s is ' - "already an ancestor of destination " - "%s\n" + b'nothing to rebase - "base" %s is ' + b"already an ancestor of destination " + b"%s\n" ) - % ("+".join(bytes(repo[r]) for r in base), dest) + % (b"+".join(bytes(repo[r]) for r in base), dest) ) else: ui.status( _( - "nothing to rebase - working " - "directory parent is already an " - "ancestor of destination %s\n" + b"nothing to rebase - working " + b"directory parent is already an " + b"ancestor of destination %s\n" ) % dest ) else: # can it happen? ui.status( - _("nothing to rebase from %s to %s\n") - % ("+".join(bytes(repo[r]) for r in base), dest) + _(b"nothing to rebase from %s to %s\n") + % (b"+".join(bytes(repo[r]) for r in base), dest) ) return None - rebasingwcp = repo["."].rev() in rebaseset + rebasingwcp = repo[b"."].rev() in rebaseset ui.log( - "rebase", - "rebasing working copy parent: %r\n", + b"rebase", + b"rebasing working copy parent: %r\n", rebasingwcp, rebase_rebasing_wcp=rebasingwcp, ) @@ -1378,8 +1392,8 @@ dest = repo[_destrebase(repo, rebaseset, destspace=destspace)] destf = bytes(dest) - allsrc = revsetlang.formatspec("%ld", rebaseset) - alias = {"ALLSRC": allsrc} + allsrc = revsetlang.formatspec(b"%ld", rebaseset) + alias = {b"ALLSRC": allsrc} if dest is None: try: @@ -1389,7 +1403,7 @@ # multi-dest path: resolve dest for each SRC separately destmap = {} for r in rebaseset: - alias["SRC"] = revsetlang.formatspec("%d", r) + alias[b"SRC"] = revsetlang.formatspec(b"%d", r) # use repo.anyrevs instead of scmutil.revsingle because we # don't want to abort if destset is empty. destset = repo.anyrevs([destf], user=True, localalias=alias) @@ -1397,10 +1411,10 @@ if size == 1: destmap[r] = destset.first() elif size == 0: - ui.note(_("skipping %s - empty destination\n") % repo[r]) + ui.note(_(b"skipping %s - empty destination\n") % repo[r]) else: raise error.Abort( - _("rebase destination for %s is not " "unique") + _(b"rebase destination for %s is not " b"unique") % repo[r] ) @@ -1410,7 +1424,7 @@ destmap = {r: destrev for r in rebaseset} # {srcrev: destrev} if not destmap: - ui.status(_("nothing to rebase - empty destination\n")) + ui.status(_(b"nothing to rebase - empty destination\n")) return None return destmap @@ -1435,10 +1449,10 @@ return parents.pop() raise error.Abort( _( - "unable to collapse on top of %d, there is more " - "than one external parent: %s" + b"unable to collapse on top of %d, there is more " + b"than one external parent: %s" ) - % (max(destancestors), ", ".join("%d" % p for p in sorted(parents))) + % (max(destancestors), b", ".join(b"%d" % p for p in sorted(parents))) ) @@ -1446,14 +1460,14 @@ """Commit the memory changes with parents p1 and p2. Return node of committed revision.""" # Replicates the empty check in ``repo.commit``. - if wctx.isempty() and not repo.ui.configbool("ui", "allowemptycommit"): + if wctx.isempty() and not repo.ui.configbool(b"ui", b"allowemptycommit"): return None # By convention, ``extra['branch']`` (set by extrafn) clobbers # ``branch`` (used when passing ``--keepbranches``). branch = repo[p1].branch() - if "branch" in extra: - branch = extra["branch"] + if b"branch" in extra: + branch = extra[b"branch"] memctx = wctx.tomemctx( commitmsg, @@ -1473,8 +1487,8 @@ """Commit the wd changes with parents p1 and p2. Return node of committed revision.""" dsguard = util.nullcontextmanager() - if not repo.ui.configbool("rebase", "singletransaction"): - dsguard = dirstateguard.dirstateguard(repo, "rebase") + if not repo.ui.configbool(b"rebase", b"singletransaction"): + dsguard = dirstateguard.dirstateguard(repo, b"rebase") with dsguard: repo.setparents(repo[p1].node(), repo[p2].node()) @@ -1488,24 +1502,24 @@ def rebasenode(repo, rev, p1, base, collapse, dest, wctx): - "Rebase a single revision rev on top of p1 using base as merge ancestor" + b"Rebase a single revision rev on top of p1 using base as merge ancestor" # Merge phase # Update to destination and merge it with local if wctx.isinmemory(): wctx.setbase(repo[p1]) else: - if repo["."].rev() != p1: - repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1])) + if repo[b"."].rev() != p1: + repo.ui.debug(b" update to %d:%s\n" % (p1, repo[p1])) mergemod.update(repo, p1, branchmerge=False, force=True) else: - repo.ui.debug(" already in destination\n") + repo.ui.debug(b" already in destination\n") # This is, alas, necessary to invalidate workingctx's manifest cache, # as well as other data we litter on it in other places. wctx = repo[None] repo.dirstate.write(repo.currenttransaction()) - repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev])) + repo.ui.debug(b" merge against %d:%s\n" % (rev, repo[rev])) if base is not None: - repo.ui.debug(" detach base %d:%s\n" % (base, repo[base])) + repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base])) # When collapsing in-place, the parent is the common ancestor, we # have to allow merging with it. stats = mergemod.update( @@ -1515,7 +1529,7 @@ force=True, ancestor=base, mergeancestor=collapse, - labels=["dest", "source"], + labels=[b"dest", b"source"], wc=wctx, ) if collapse: @@ -1595,7 +1609,7 @@ for prev in repo.changelog.parentrevs(rev): adjusted = dest if prev != nullrev: - candidate = repo.revs("max(%ld and (::%d))", source, prev).first() + candidate = repo.revs(b"max(%ld and (::%d))", source, prev).first() if candidate is not None: adjusted = state[candidate] if adjusted == dest and dest in state: @@ -1603,7 +1617,7 @@ if adjusted == revtodo: # sortsource should produce an order that makes this impossible raise error.ProgrammingError( - "rev %d should be rebased already at this time" % dest + b"rev %d should be rebased already at this time" % dest ) result.append(adjusted) return result @@ -1618,17 +1632,17 @@ successors in destination or no non-obsolete successor. """ # Obsolete node with successors not in dest leads to divergence - divergenceok = ui.configbool("experimental", "evolution.allowdivergence") + divergenceok = ui.configbool(b"experimental", b"evolution.allowdivergence") divergencebasecandidates = rebaseobsrevs - rebaseobsskipped if divergencebasecandidates and not divergenceok: divhashes = (bytes(repo[r]) for r in divergencebasecandidates) - msg = _("this rebase will cause " "divergences from: %s") + msg = _(b"this rebase will cause " b"divergences from: %s") h = _( - "to force the rebase please set " - "experimental.evolution.allowdivergence=True" + b"to force the rebase please set " + b"experimental.evolution.allowdivergence=True" ) - raise error.Abort(msg % (",".join(divhashes),), hint=h) + raise error.Abort(msg % (b",".join(divhashes),), hint=h) def successorrevs(unfi, rev): @@ -1748,8 +1762,8 @@ if set(newps) == set(oldps) and dest not in newps: raise error.Abort( _( - "cannot rebase %d:%s without " - "moving at least one of its parents" + b"cannot rebase %d:%s without " + b"moving at least one of its parents" ) % (rev, repo[rev]) ) @@ -1758,7 +1772,7 @@ # impossible. With multi-dest, the initial check does not cover complex # cases since we don't have abstractions to dry-run rebase cheaply. if any(p != nullrev and isancestor(rev, p) for p in newps): - raise error.Abort(_("source is ancestor of destination")) + raise error.Abort(_(b"source is ancestor of destination")) # "rebasenode" updates to new p1, use the corresponding merge base. if bases[0] != nullrev: @@ -1789,7 +1803,7 @@ # Revisions in the side (not chosen as merge base) branch that # might contain "surprising" contents siderevs = list( - repo.revs("((%ld-%d) %% (%d+%d))", bases, base, base, dest) + repo.revs(b"((%ld-%d) %% (%d+%d))", bases, base, base, dest) ) # If those revisions are covered by rebaseset, the result is good. @@ -1803,7 +1817,7 @@ ] unwanted[i] = list( repo.revs( - "%ld - (::%ld) - %ld", siderevs, merges, rebaseset + b"%ld - (::%ld) - %ld", siderevs, merges, rebaseset ) ) @@ -1825,34 +1839,34 @@ # The merge will include unwanted revisions. Abort now. Revisit this if # we have a more advanced merge algorithm that handles multiple bases. if l > 0: - unwanteddesc = _(" or ").join( + unwanteddesc = _(b" or ").join( ( - ", ".join("%d:%s" % (r, repo[r]) for r in revs) + b", ".join(b"%d:%s" % (r, repo[r]) for r in revs) for revs in unwanted if revs is not None ) ) raise error.Abort( - _("rebasing %d:%s will include unwanted changes from %s") + _(b"rebasing %d:%s will include unwanted changes from %s") % (rev, repo[rev], unwanteddesc) ) - repo.ui.debug(" future parents are %d and %d\n" % tuple(newps)) + repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps)) return newps[0], newps[1], base def isagitpatch(repo, patchname): - "Return true if the given patch is in git format" + b"Return true if the given patch is in git format" mqpatch = os.path.join(repo.mq.path, patchname) - for line in patch.linereader(open(mqpatch, "rb")): - if line.startswith("diff --git"): + for line in patch.linereader(open(mqpatch, b"rb")): + if line.startswith(b"diff --git"): return True return False def updatemq(repo, state, skipped, **opts): - "Update rebased mq patches - finalize and then import them" + b"Update rebased mq patches - finalize and then import them" mqrebase = {} mq = repo.mq original_series = mq.fullseries[:] @@ -1862,7 +1876,7 @@ rev = repo[p.node].rev() if rev in state: repo.ui.debug( - "revision %d is an mq patch (%s), finalize it.\n" + b"revision %d is an mq patch (%s), finalize it.\n" % (rev, p.name) ) mqrebase[rev] = (p.name, isagitpatch(repo, p.name)) @@ -1878,11 +1892,15 @@ if rev not in skipped: name, isgit = mqrebase[rev] repo.ui.note( - _("updating mq patch %s to %d:%s\n") + _(b"updating mq patch %s to %d:%s\n") % (name, state[rev], repo[state[rev]]) ) mq.qimport( - repo, (), patchname=name, git=isgit, rev=["%d" % state[rev]] + repo, + (), + patchname=name, + git=isgit, + rev=[b"%d" % state[rev]], ) else: # Rebased and skipped @@ -1902,22 +1920,22 @@ def storecollapsemsg(repo, collapsemsg): - "Store the collapse message to allow recovery" - collapsemsg = collapsemsg or "" - f = repo.vfs("last-message.txt", "w") - f.write("%s\n" % collapsemsg) + b"Store the collapse message to allow recovery" + collapsemsg = collapsemsg or b"" + f = repo.vfs(b"last-message.txt", b"w") + f.write(b"%s\n" % collapsemsg) f.close() def clearcollapsemsg(repo): - "Remove collapse message file" - repo.vfs.unlinkpath("last-message.txt", ignoremissing=True) + b"Remove collapse message file" + repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True) def restorecollapsemsg(repo, isabort): - "Restore previously stored collapse message" + b"Restore previously stored collapse message" try: - f = repo.vfs("last-message.txt") + f = repo.vfs(b"last-message.txt") collapsemsg = f.readline().strip() f.close() except IOError as err: @@ -1925,19 +1943,19 @@ raise if isabort: # Oh well, just abort like normal - collapsemsg = "" + collapsemsg = b"" else: - raise error.Abort(_("missing .hg/last-message.txt for rebase")) + raise error.Abort(_(b"missing .hg/last-message.txt for rebase")) return collapsemsg def clearstatus(repo): - "Remove the status files" + b"Remove the status files" # Make sure the active transaction won't write the state file tr = repo.currenttransaction() if tr: - tr.removefilegenerator("rebasestate") - repo.vfs.unlinkpath("rebasestate", ignoremissing=True) + tr.removefilegenerator(b"rebasestate") + repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True) def needupdate(repo, state): @@ -1980,7 +1998,7 @@ if destmap[r] not in srcset: result.append(r) if not result: - raise error.Abort(_("source and destination form a cycle")) + raise error.Abort(_(b"source and destination form a cycle")) srcset -= set(result) yield result @@ -1992,28 +2010,28 @@ destmap: {srcrev: destrev} """ rebaseset = destmap.keys() - originalwd = repo["."].rev() + originalwd = repo[b"."].rev() # This check isn't strictly necessary, since mq detects commits over an # applied patch. But it prevents messing up the working directory when # a partially completed rebase is blocked by mq. - if "qtip" in repo.tags(): + if b"qtip" in repo.tags(): mqapplied = set(repo[s.node].rev() for s in repo.mq.applied) if set(destmap.values()) & mqapplied: - raise error.Abort(_("cannot rebase onto an applied mq patch")) + raise error.Abort(_(b"cannot rebase onto an applied mq patch")) # Get "cycle" error early by exhausting the generator. sortedsrc = list(sortsource(destmap)) # a list of sorted revs if not sortedsrc: - raise error.Abort(_("no matching revisions")) + raise error.Abort(_(b"no matching revisions")) # Only check the first batch of revisions to rebase not depending on other # rebaseset. This means "source is ancestor of destination" for the second # (and following) batches of revisions are not checked here. We rely on # "defineparents" to do that check. - roots = list(repo.set("roots(%ld)", sortedsrc[0])) + roots = list(repo.set(b"roots(%ld)", sortedsrc[0])) if not roots: - raise error.Abort(_("no matching revisions")) + raise error.Abort(_(b"no matching revisions")) def revof(r): return r.rev() @@ -2025,7 +2043,7 @@ dest = repo[destmap[root.rev()]] commonbase = root.ancestor(dest) if commonbase == root: - raise error.Abort(_("source is ancestor of destination")) + raise error.Abort(_(b"source is ancestor of destination")) if commonbase == dest: wctx = repo[None] if dest == wctx.p1(): @@ -2037,11 +2055,11 @@ # mark the revision as done by setting its new revision # equal to its old (current) revisions state[root.rev()] = root.rev() - repo.ui.debug("source is a child of destination\n") + repo.ui.debug(b"source is a child of destination\n") continue emptyrebase = False - repo.ui.debug("rebase onto %s starting from %s\n" % (dest, root)) + repo.ui.debug(b"rebase onto %s starting from %s\n" % (dest, root)) if emptyrebase: return None for rev in sorted(state): @@ -2104,36 +2122,36 @@ changes = {} for oldns, newn in replacements.iteritems(): for oldn in oldns: - changes[hf(oldn)] = fl([hf(n) for n in newn], name="node") - nodechanges = fd(changes, key="oldnode", value="newnodes") + changes[hf(oldn)] = fl([hf(n) for n in newn], name=b"node") + nodechanges = fd(changes, key=b"oldnode", value=b"newnodes") fm.data(nodechanges=nodechanges) if keepf: replacements = {} - scmutil.cleanupnodes(repo, replacements, "rebase", moves, backup=backup) + scmutil.cleanupnodes(repo, replacements, b"rebase", moves, backup=backup) def pullrebase(orig, ui, repo, *args, **opts): - "Call rebase after pull if the latter has been invoked with --rebase" + b"Call rebase after pull if the latter has been invoked with --rebase" if opts.get(r"rebase"): - if ui.configbool("commands", "rebase.requiredest"): - msg = _("rebase destination required by configuration") - hint = _("use hg pull followed by hg rebase -d DEST") + if ui.configbool(b"commands", b"rebase.requiredest"): + msg = _(b"rebase destination required by configuration") + hint = _(b"use hg pull followed by hg rebase -d DEST") raise error.Abort(msg, hint=hint) with repo.wlock(), repo.lock(): if opts.get(r"update"): del opts[r"update"] ui.debug( - "--update and --rebase are not compatible, ignoring " - "the update flag\n" + b"--update and --rebase are not compatible, ignoring " + b"the update flag\n" ) cmdutil.checkunfinished(repo, skipmerge=True) cmdutil.bailifchanged( repo, hint=_( - "cannot pull with rebase: " - "please commit or shelve your changes first" + b"cannot pull with rebase: " + b"please commit or shelve your changes first" ), ) @@ -2166,16 +2184,16 @@ except error.NoMergeDestAbort: # we can maybe update instead rev, _a, _b = destutil.destupdate(repo) - if rev == repo["."].rev(): - ui.status(_("nothing to rebase\n")) + if rev == repo[b"."].rev(): + ui.status(_(b"nothing to rebase\n")) else: - ui.status(_("nothing to rebase - updating instead\n")) + ui.status(_(b"nothing to rebase - updating instead\n")) # not passing argument to get the bare update behavior # with warning and trumpets commands.update(ui, repo) else: if opts.get(r"tool"): - raise error.Abort(_("--tool can only be used with --rebase")) + raise error.Abort(_(b"--tool can only be used with --rebase")) ret = orig(ui, repo, *args, **opts) return ret @@ -2205,7 +2223,7 @@ assert repo.filtername is None cl = repo.changelog nodemap = cl.nodemap - extinctrevs = set(repo.revs("extinct()")) + extinctrevs = set(repo.revs(b"extinct()")) for srcrev in rebaseobsrevs: srcnode = cl.node(srcrev) # XXX: more advanced APIs are required to handle split correctly @@ -2258,7 +2276,7 @@ def summaryhook(ui, repo): - if not repo.vfs.exists("rebasestate"): + if not repo.vfs.exists(b"rebasestate"): return try: rbsrt = rebaseruntime(repo, ui, {}) @@ -2266,16 +2284,16 @@ state = rbsrt.state except error.RepoLookupError: # i18n: column positioning for "hg summary" - msg = _('rebase: (use "hg rebase --abort" to clear broken state)\n') + msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n') ui.write(msg) return numrebased = len([i for i in state.itervalues() if i >= 0]) # i18n: column positioning for "hg summary" ui.write( - _("rebase: %s, %s (rebase --continue)\n") + _(b"rebase: %s, %s (rebase --continue)\n") % ( - ui.label(_("%d rebased"), "rebase.rebased") % numrebased, - ui.label(_("%d remaining"), "rebase.remaining") + ui.label(_(b"%d rebased"), b"rebase.rebased") % numrebased, + ui.label(_(b"%d remaining"), b"rebase.remaining") % (len(state) - numrebased), ) ) @@ -2283,15 +2301,15 @@ def uisetup(ui): # Replace pull with a decorator to provide --rebase option - entry = extensions.wrapcommand(commands.table, "pull", pullrebase) + entry = extensions.wrapcommand(commands.table, b"pull", pullrebase) entry[1].append( - ("", "rebase", None, _("rebase working directory to branch head")) + (b"", b"rebase", None, _(b"rebase working directory to branch head")) ) - entry[1].append(("t", "tool", "", _("specify merge tool for rebase"))) - cmdutil.summaryhooks.add("rebase", summaryhook) + entry[1].append((b"t", b"tool", b"", _(b"specify merge tool for rebase"))) + cmdutil.summaryhooks.add(b"rebase", summaryhook) statemod.addunfinished( - "rebase", - fname="rebasestate", + b"rebase", + fname=b"rebasestate", stopflag=True, continueflag=True, abortfunc=abortrebase, diff --git a/hgext/record.py b/hgext/record.py --- a/hgext/record.py +++ b/hgext/record.py @@ -27,15 +27,15 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "record", + b"record", # same options as commit + white space diff options - [c for c in commands.table["commit|ci"][1][:] if c[1] != "interactive"] + [c for c in commands.table[b"commit|ci"][1][:] if c[1] != b"interactive"] + cmdutil.diffwsopts, - _("hg record [OPTION]... [FILE]..."), + _(b"hg record [OPTION]... [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, ) def record(ui, repo, *pats, **opts): @@ -69,12 +69,12 @@ if not ui.interactive(): raise error.Abort( - _("running non-interactively, use %s instead") % "commit" + _(b"running non-interactively, use %s instead") % b"commit" ) opts[r"interactive"] = True - overrides = {("experimental", "crecord"): False} - with ui.configoverride(overrides, "record"): + overrides = {(b"experimental", b"crecord"): False} + with ui.configoverride(overrides, b"record"): return commands.commit(ui, repo, *pats, **opts) @@ -82,7 +82,7 @@ if not opts[r"interactive"]: return origfn(ui, repo, *pats, **opts) - mq = extensions.find("mq") + mq = extensions.find(b"mq") def committomq(ui, repo, *pats, **opts): # At this point the working copy contains only changes that @@ -99,9 +99,9 @@ # This command registration is replaced during uisetup(). @command( - "qrecord", + b"qrecord", [], - _("hg qrecord [OPTION]... PATCH [FILE]..."), + _(b"hg qrecord [OPTION]... PATCH [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, inferrepo=True, ) @@ -111,14 +111,14 @@ See :hg:`help qnew` & :hg:`help record` for more information and usage. """ - return _qrecord("qnew", ui, repo, patch, *pats, **opts) + return _qrecord(b"qnew", ui, repo, patch, *pats, **opts) def _qrecord(cmdsuggest, ui, repo, patch, *pats, **opts): try: - mq = extensions.find("mq") + mq = extensions.find(b"mq") except KeyError: - raise error.Abort(_("'mq' extension not loaded")) + raise error.Abort(_(b"'mq' extension not loaded")) repo.mq.checkpatchname(patch) @@ -126,8 +126,8 @@ opts[r"checkname"] = False mq.new(ui, repo, patch, *pats, **opts) - overrides = {("experimental", "crecord"): False} - with ui.configoverride(overrides, "record"): + overrides = {(b"experimental", b"crecord"): False} + with ui.configoverride(overrides, b"record"): cmdutil.checkunfinished(repo) cmdutil.dorecord( ui, @@ -149,27 +149,27 @@ def uisetup(ui): try: - mq = extensions.find("mq") + mq = extensions.find(b"mq") except KeyError: return - cmdtable["qrecord"] = ( + cmdtable[b"qrecord"] = ( qrecord, # same options as qnew, but copy them so we don't get # -i/--interactive for qrecord and add white space diff options - mq.cmdtable["qnew"][1][:] + cmdutil.diffwsopts, - _("hg qrecord [OPTION]... PATCH [FILE]..."), + mq.cmdtable[b"qnew"][1][:] + cmdutil.diffwsopts, + _(b"hg qrecord [OPTION]... PATCH [FILE]..."), ) - _wrapcmd("qnew", mq.cmdtable, qnew, _("interactively record a new patch")) + _wrapcmd(b"qnew", mq.cmdtable, qnew, _(b"interactively record a new patch")) _wrapcmd( - "qrefresh", + b"qrefresh", mq.cmdtable, qrefresh, - _("interactively select changes to refresh"), + _(b"interactively select changes to refresh"), ) def _wrapcmd(cmd, table, wrapfn, msg): entry = extensions.wrapcommand(table, cmd, wrapfn) - entry[1].append(("i", "interactive", None, msg)) + entry[1].append((b"i", b"interactive", None, msg)) diff --git a/hgext/releasenotes.py b/hgext/releasenotes.py --- a/hgext/releasenotes.py +++ b/hgext/releasenotes.py @@ -44,20 +44,20 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" DEFAULT_SECTIONS = [ - ("feature", _("New Features")), - ("bc", _("Backwards Compatibility Changes")), - ("fix", _("Bug Fixes")), - ("perf", _("Performance Improvements")), - ("api", _("API Changes")), + (b"feature", _(b"New Features")), + (b"bc", _(b"Backwards Compatibility Changes")), + (b"fix", _(b"Bug Fixes")), + (b"perf", _(b"Performance Improvements")), + (b"api", _(b"API Changes")), ] RE_DIRECTIVE = re.compile(br"^\.\. ([a-zA-Z0-9_]+)::\s*([^$]+)?$") RE_ISSUE = br"\bissue ?[0-9]{4,6}(?![0-9])\b" -BULLET_SECTION = _("Other Changes") +BULLET_SECTION = _(b"Other Changes") class parsedreleasenotes(object): @@ -105,8 +105,8 @@ if not fuzz: ui.warn( _( - "module 'fuzzywuzzy' not found, merging of similar " - "releasenotes is disabled\n" + b"module 'fuzzywuzzy' not found, merging of similar " + b"releasenotes is disabled\n" ) ) @@ -119,13 +119,13 @@ # TODO prompt for resolution if different and running in # interactive mode. ui.write( - _("%s already exists in %s section; ignoring\n") + _(b"%s already exists in %s section; ignoring\n") % (title, section) ) continue incoming_str = converttitled([(title, paragraphs)])[0] - if section == "fix": + if section == b"fix": issue = getissuenum(incoming_str) if issue: if findissue(ui, existingnotes, issue): @@ -141,7 +141,7 @@ continue incoming_str = convertnontitled([paragraphs])[0] - if section == "fix": + if section == b"fix": issue = getissuenum(incoming_str) if issue: if findissue(ui, existingnotes, issue): @@ -187,7 +187,7 @@ lines = [] for para in paragraphs: lines.extend(para) - string_list.append(" ".join(lines)) + string_list.append(b" ".join(lines)) return string_list @@ -200,7 +200,7 @@ lines = [] for para in paragraphs: lines.extend(para) - string_list.append(" ".join(lines)) + string_list.append(b" ".join(lines)) return string_list @@ -219,7 +219,7 @@ Returns true if issue number already exists in notes. """ if any(issue in s for s in existing): - ui.write(_('"%s" already exists in notes; ignoring\n') % issue) + ui.write(_(b'"%s" already exists in notes; ignoring\n') % issue) return True else: return False @@ -233,7 +233,7 @@ merge = similaritycheck(incoming_str, existing) if not merge: ui.write( - _('"%s" already exists in notes file; ignoring\n') + _(b'"%s" already exists in notes file; ignoring\n') % incoming_str ) return True @@ -261,7 +261,7 @@ def getcustomadmonitions(repo): - ctx = repo["."] + ctx = repo[b"."] p = config.config() def read(f, sections=None, remap=None): @@ -270,12 +270,12 @@ p.parse(f, data, sections, remap, read) else: raise error.Abort( - _(".hgreleasenotes file '%s' not found") % repo.pathto(f) + _(b".hgreleasenotes file '%s' not found") % repo.pathto(f) ) - if ".hgreleasenotes" in ctx: - read(".hgreleasenotes") - return p["sections"] + if b".hgreleasenotes" in ctx: + read(b".hgreleasenotes") + return p[b"sections"] def checkadmonitions(ui, repo, directives, revs): @@ -299,7 +299,7 @@ continue else: ui.write( - _("Invalid admonition '%s' present in changeset %s" "\n") + _(b"Invalid admonition '%s' present in changeset %s" b"\n") % (admonition.group(1), ctx.hex()[:12]) ) sim = lambda x: difflib.SequenceMatcher( @@ -308,15 +308,15 @@ similar = [s for s in directives if sim(s) > 0.6] if len(similar) == 1: - ui.write(_("(did you mean %s?)\n") % similar[0]) + ui.write(_(b"(did you mean %s?)\n") % similar[0]) elif similar: - ss = ", ".join(sorted(similar)) - ui.write(_("(did you mean one of %s?)\n") % ss) + ss = b", ".join(sorted(similar)) + ui.write(_(b"(did you mean one of %s?)\n") % ss) def _getadmonitionlist(ui, sections): for section in sections: - ui.write("%s: %s\n" % (section[0], section[1])) + ui.write(b"%s: %s\n" % (section[0], section[1])) def parsenotesfromrevisions(repo, directives, revs): @@ -330,17 +330,17 @@ ) for i, block in enumerate(blocks): - if block["type"] != "admonition": + if block[b"type"] != b"admonition": continue - directive = block["admonitiontitle"] - title = block["lines"][0].strip() if block["lines"] else None + directive = block[b"admonitiontitle"] + title = block[b"lines"][0].strip() if block[b"lines"] else None if i + 1 == len(blocks): raise error.Abort( _( - "changeset %s: release notes directive %s " - "lacks content" + b"changeset %s: release notes directive %s " + b"lacks content" ) % (ctx, directive) ) @@ -352,30 +352,30 @@ pblock = blocks[j] # Margin blocks may appear between paragraphs. Ignore them. - if pblock["type"] == "margin": + if pblock[b"type"] == b"margin": continue - if pblock["type"] == "admonition": + if pblock[b"type"] == b"admonition": break - if pblock["type"] != "paragraph": + if pblock[b"type"] != b"paragraph": repo.ui.warn( _( - "changeset %s: unexpected block in release " - "notes directive %s\n" + b"changeset %s: unexpected block in release " + b"notes directive %s\n" ) % (ctx, directive) ) - if pblock["indent"] > 0: - paragraphs.append(pblock["lines"]) + if pblock[b"indent"] > 0: + paragraphs.append(pblock[b"lines"]) else: break # TODO consider using title as paragraph for more concise notes. if not paragraphs: repo.ui.warn( - _("error parsing releasenotes for revision: " "'%s'\n") + _(b"error parsing releasenotes for revision: " b"'%s'\n") % node.hex(ctx.node()) ) if title: @@ -398,51 +398,51 @@ for i in range(offset + 1, len(blocks)): block = blocks[i] - if block["type"] == "margin": + if block[b"type"] == b"margin": continue - elif block["type"] == "section": + elif block[b"type"] == b"section": break - elif block["type"] == "bullet": - if block["indent"] != 0: - raise error.Abort(_("indented bullet lists not supported")) + elif block[b"type"] == b"bullet": + if block[b"indent"] != 0: + raise error.Abort(_(b"indented bullet lists not supported")) if title: - lines = [l[1:].strip() for l in block["lines"]] + lines = [l[1:].strip() for l in block[b"lines"]] notefragment.append(lines) continue else: - lines = [[l[1:].strip() for l in block["lines"]]] + lines = [[l[1:].strip() for l in block[b"lines"]]] for block in blocks[i + 1 :]: - if block["type"] in ("bullet", "section"): + if block[b"type"] in (b"bullet", b"section"): break - if block["type"] == "paragraph": - lines.append(block["lines"]) + if block[b"type"] == b"paragraph": + lines.append(block[b"lines"]) notefragment.append(lines) continue - elif block["type"] != "paragraph": + elif block[b"type"] != b"paragraph": raise error.Abort( - _("unexpected block type in release notes: " "%s") - % block["type"] + _(b"unexpected block type in release notes: " b"%s") + % block[b"type"] ) if title: - notefragment.append(block["lines"]) + notefragment.append(block[b"lines"]) return notefragment currentsection = None for i, block in enumerate(blocks): - if block["type"] != "section": + if block[b"type"] != b"section": continue - title = block["lines"][0] + title = block[b"lines"][0] # TODO the parsing around paragraphs and bullet points needs some # work. - if block["underline"] == "=": # main section + if block[b"underline"] == b"=": # main section name = sections.sectionfromtitle(title) if not name: raise error.Abort( - _("unknown release notes section: %s") % title + _(b"unknown release notes section: %s") % title ) currentsection = name @@ -451,7 +451,7 @@ for para in bullet_points: notes.addnontitleditem(currentsection, para) - elif block["underline"] == "-": # sub-section + elif block[b"underline"] == b"-": # sub-section if title == BULLET_SECTION: bullet_points = gatherparagraphsbullets(i) for para in bullet_points: @@ -460,7 +460,7 @@ paragraphs = gatherparagraphsbullets(i, True) notes.addtitleditem(currentsection, title, paragraphs) else: - raise error.Abort(_("unsupported section type for %s") % title) + raise error.Abort(_(b"unsupported section type for %s") % title) return notes @@ -478,23 +478,23 @@ continue lines.append(sectiontitle) - lines.append("=" * len(sectiontitle)) - lines.append("") + lines.append(b"=" * len(sectiontitle)) + lines.append(b"") # First pass to emit sub-sections. for title, paragraphs in notes.titledforsection(sectionname): lines.append(title) - lines.append("-" * len(title)) - lines.append("") + lines.append(b"-" * len(title)) + lines.append(b"") for i, para in enumerate(paragraphs): if i: - lines.append("") + lines.append(b"") lines.extend( - stringutil.wrap(" ".join(para), width=78).splitlines() + stringutil.wrap(b" ".join(para), width=78).splitlines() ) - lines.append("") + lines.append(b"") # Second pass to emit bullet list items. @@ -506,58 +506,64 @@ if notes.titledforsection(sectionname) and nontitled: # TODO make configurable. lines.append(BULLET_SECTION) - lines.append("-" * len(BULLET_SECTION)) - lines.append("") + lines.append(b"-" * len(BULLET_SECTION)) + lines.append(b"") for paragraphs in nontitled: lines.extend( stringutil.wrap( - " ".join(paragraphs[0]), + b" ".join(paragraphs[0]), width=78, - initindent="* ", - hangindent=" ", + initindent=b"* ", + hangindent=b" ", ).splitlines() ) for para in paragraphs[1:]: - lines.append("") + lines.append(b"") lines.extend( stringutil.wrap( - " ".join(para), + b" ".join(para), width=78, - initindent=" ", - hangindent=" ", + initindent=b" ", + hangindent=b" ", ).splitlines() ) - lines.append("") + lines.append(b"") if lines and lines[-1]: - lines.append("") + lines.append(b"") - return "\n".join(lines) + return b"\n".join(lines) @command( - "releasenotes", + b"releasenotes", [ - ("r", "rev", "", _("revisions to process for release notes"), _("REV")), ( - "c", - "check", - False, - _("checks for validity of admonitions (if any)"), - _("REV"), + b"r", + b"rev", + b"", + _(b"revisions to process for release notes"), + _(b"REV"), ), ( - "l", - "list", + b"c", + b"check", False, - _("list the available admonitions with their title"), + _(b"checks for validity of admonitions (if any)"), + _(b"REV"), + ), + ( + b"l", + b"list", + False, + _(b"list the available admonitions with their title"), None, ), ], - _("hg releasenotes [-r REV] [-c] FILE"), + _(b"hg releasenotes [-r REV] [-c] FILE"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, ) def releasenotes(ui, repo, file_=None, **opts): @@ -646,29 +652,29 @@ opts = pycompat.byteskwargs(opts) sections = releasenotessections(ui, repo) - listflag = opts.get("list") + listflag = opts.get(b"list") - if listflag and opts.get("rev"): - raise error.Abort(_("cannot use both '--list' and '--rev'")) - if listflag and opts.get("check"): - raise error.Abort(_("cannot use both '--list' and '--check'")) + if listflag and opts.get(b"rev"): + raise error.Abort(_(b"cannot use both '--list' and '--rev'")) + if listflag and opts.get(b"check"): + raise error.Abort(_(b"cannot use both '--list' and '--check'")) if listflag: return _getadmonitionlist(ui, sections) - rev = opts.get("rev") - revs = scmutil.revrange(repo, [rev or "not public()"]) - if opts.get("check"): + rev = opts.get(b"rev") + revs = scmutil.revrange(repo, [rev or b"not public()"]) + if opts.get(b"check"): return checkadmonitions(ui, repo, sections.names(), revs) incoming = parsenotesfromrevisions(repo, sections.names(), revs) if file_ is None: - ui.pager("releasenotes") + ui.pager(b"releasenotes") return ui.write(serializenotes(sections, incoming)) try: - with open(file_, "rb") as fh: + with open(file_, b"rb") as fh: notes = parsereleasenotesfile(sections, fh.read()) except IOError as e: if e.errno != errno.ENOENT: @@ -678,17 +684,17 @@ notes.merge(ui, incoming) - with open(file_, "wb") as fh: + with open(file_, b"wb") as fh: fh.write(serializenotes(sections, notes)) -@command("debugparsereleasenotes", norepo=True) +@command(b"debugparsereleasenotes", norepo=True) def debugparsereleasenotes(ui, path, repo=None): """parse release notes and print resulting data structure""" - if path == "-": + if path == b"-": text = pycompat.stdin.read() else: - with open(path, "rb") as fh: + with open(path, b"rb") as fh: text = fh.read() sections = releasenotessections(ui, repo) @@ -696,13 +702,13 @@ notes = parsereleasenotesfile(sections, text) for section in notes: - ui.write(_("section: %s\n") % section) + ui.write(_(b"section: %s\n") % section) for title, paragraphs in notes.titledforsection(section): - ui.write(_(" subsection: %s\n") % title) + ui.write(_(b" subsection: %s\n") % title) for para in paragraphs: - ui.write(_(" paragraph: %s\n") % " ".join(para)) + ui.write(_(b" paragraph: %s\n") % b" ".join(para)) for paragraphs in notes.nontitledforsection(section): - ui.write(_(" bullet point:\n")) + ui.write(_(b" bullet point:\n")) for para in paragraphs: - ui.write(_(" paragraph: %s\n") % " ".join(para)) + ui.write(_(b" paragraph: %s\n") % b" ".join(para)) diff --git a/hgext/relink.py b/hgext/relink.py --- a/hgext/relink.py +++ b/hgext/relink.py @@ -26,10 +26,12 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" -@command("relink", [], _("[ORIGIN]"), helpcategory=command.CATEGORY_MAINTENANCE) +@command( + b"relink", [], _(b"[ORIGIN]"), helpcategory=command.CATEGORY_MAINTENANCE +) def relink(ui, repo, origin=None, **opts): """recreate hardlinks between two repositories @@ -55,22 +57,22 @@ command is running. (Both repositories will be locked against writes.) """ - if not util.safehasattr(util, "samefile") or not util.safehasattr( - util, "samedevice" + if not util.safehasattr(util, b"samefile") or not util.safehasattr( + util, b"samedevice" ): - raise error.Abort(_("hardlinks are not supported on this system")) + raise error.Abort(_(b"hardlinks are not supported on this system")) src = hg.repository( repo.baseui, - ui.expandpath(origin or "default-relink", origin or "default"), + ui.expandpath(origin or b"default-relink", origin or b"default"), ) - ui.status(_("relinking %s to %s\n") % (src.store.path, repo.store.path)) + ui.status(_(b"relinking %s to %s\n") % (src.store.path, repo.store.path)) if repo.root == src.root: - ui.status(_("there is nothing to relink\n")) + ui.status(_(b"there is nothing to relink\n")) return if not util.samedevice(src.store.path, repo.store.path): # No point in continuing - raise error.Abort(_("source and destination are on different devices")) + raise error.Abort(_(b"source and destination are on different devices")) with repo.lock(), src.lock(): candidates = sorted(collect(src, ui)) @@ -81,7 +83,7 @@ def collect(src, ui): seplen = len(os.path.sep) candidates = [] - live = len(src["tip"].manifest()) + live = len(src[b"tip"].manifest()) # Your average repository has some files which were deleted before # the tip revision. We account for that by assuming that there are # 3 tracked files for every 2 live files as of the tip version of @@ -90,17 +92,17 @@ # mozilla-central as of 2010-06-10 had a ratio of just over 7:5. total = live * 3 // 2 src = src.store.path - progress = ui.makeprogress(_("collecting"), unit=_("files"), total=total) + progress = ui.makeprogress(_(b"collecting"), unit=_(b"files"), total=total) pos = 0 ui.status( - _("tip has %d files, estimated total number of files: %d\n") + _(b"tip has %d files, estimated total number of files: %d\n") % (live, total) ) for dirpath, dirnames, filenames in os.walk(src): dirnames.sort() relpath = dirpath[len(src) + seplen :] for filename in sorted(filenames): - if filename[-2:] not in (".d", ".i"): + if filename[-2:] not in (b".d", b".i"): continue st = os.stat(os.path.join(dirpath, filename)) if not stat.S_ISREG(st.st_mode): @@ -110,7 +112,7 @@ progress.update(pos, item=filename) progress.complete() - ui.status(_("collected %d candidate storage files\n") % len(candidates)) + ui.status(_(b"collected %d candidate storage files\n") % len(candidates)) return candidates @@ -126,7 +128,7 @@ if not util.samedevice(src, dst): # No point in continuing raise error.Abort( - _("source and destination are on different devices") + _(b"source and destination are on different devices") ) if st.st_size != ts.st_size: return False @@ -134,7 +136,7 @@ targets = [] progress = ui.makeprogress( - _("pruning"), unit=_("files"), total=len(candidates) + _(b"pruning"), unit=_(b"files"), total=len(candidates) ) pos = 0 for fn, st in candidates: @@ -143,19 +145,21 @@ tgt = os.path.join(dst, fn) ts = linkfilter(srcpath, tgt, st) if not ts: - ui.debug("not linkable: %s\n" % fn) + ui.debug(b"not linkable: %s\n" % fn) continue targets.append((fn, ts.st_size)) progress.update(pos, item=fn) progress.complete() - ui.status(_("pruned down to %d probably relinkable files\n") % len(targets)) + ui.status( + _(b"pruned down to %d probably relinkable files\n") % len(targets) + ) return targets def do_relink(src, dst, files, ui): def relinkfile(src, dst): - bak = dst + ".bak" + bak = dst + b".bak" os.rename(dst, bak) try: util.oslink(src, dst) @@ -169,7 +173,7 @@ savedbytes = 0 progress = ui.makeprogress( - _("relinking"), unit=_("files"), total=len(files) + _(b"relinking"), unit=_(b"files"), total=len(files) ) pos = 0 for f, sz in files: @@ -177,8 +181,8 @@ source = os.path.join(src, f) tgt = os.path.join(dst, f) # Binary mode, so that read() works correctly, especially on Windows - sfp = open(source, "rb") - dfp = open(tgt, "rb") + sfp = open(source, b"rb") + dfp = open(tgt, b"rb") sin = sfp.read(CHUNKLEN) while sin: din = dfp.read(CHUNKLEN) @@ -188,7 +192,7 @@ sfp.close() dfp.close() if sin: - ui.debug("not linkable: %s\n" % f) + ui.debug(b"not linkable: %s\n" % f) continue try: relinkfile(source, tgt) @@ -196,11 +200,11 @@ relinked += 1 savedbytes += sz except OSError as inst: - ui.warn("%s: %s\n" % (tgt, stringutil.forcebytestr(inst))) + ui.warn(b"%s: %s\n" % (tgt, stringutil.forcebytestr(inst))) progress.complete() ui.status( - _("relinked %d files (%s reclaimed)\n") + _(b"relinked %d files (%s reclaimed)\n") % (relinked, util.bytecount(savedbytes)) ) diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py --- a/hgext/remotefilelog/__init__.py +++ b/hgext/remotefilelog/__init__.py @@ -185,72 +185,74 @@ configtable = {} configitem = registrar.configitem(configtable) -configitem("remotefilelog", "debug", default=False) +configitem(b"remotefilelog", b"debug", default=False) -configitem("remotefilelog", "reponame", default="") -configitem("remotefilelog", "cachepath", default=None) -configitem("remotefilelog", "cachegroup", default=None) -configitem("remotefilelog", "cacheprocess", default=None) -configitem("remotefilelog", "cacheprocess.includepath", default=None) -configitem("remotefilelog", "cachelimit", default="1000 GB") +configitem(b"remotefilelog", b"reponame", default=b"") +configitem(b"remotefilelog", b"cachepath", default=None) +configitem(b"remotefilelog", b"cachegroup", default=None) +configitem(b"remotefilelog", b"cacheprocess", default=None) +configitem(b"remotefilelog", b"cacheprocess.includepath", default=None) +configitem(b"remotefilelog", b"cachelimit", default=b"1000 GB") configitem( - "remotefilelog", - "fallbackpath", + b"remotefilelog", + b"fallbackpath", default=configitems.dynamicdefault, - alias=[("remotefilelog", "fallbackrepo")], + alias=[(b"remotefilelog", b"fallbackrepo")], ) -configitem("remotefilelog", "validatecachelog", default=None) -configitem("remotefilelog", "validatecache", default="on") -configitem("remotefilelog", "server", default=None) -configitem("remotefilelog", "servercachepath", default=None) -configitem("remotefilelog", "serverexpiration", default=30) -configitem("remotefilelog", "backgroundrepack", default=False) -configitem("remotefilelog", "bgprefetchrevs", default=None) -configitem("remotefilelog", "pullprefetch", default=None) -configitem("remotefilelog", "backgroundprefetch", default=False) -configitem("remotefilelog", "prefetchdelay", default=120) -configitem("remotefilelog", "prefetchdays", default=14) +configitem(b"remotefilelog", b"validatecachelog", default=None) +configitem(b"remotefilelog", b"validatecache", default=b"on") +configitem(b"remotefilelog", b"server", default=None) +configitem(b"remotefilelog", b"servercachepath", default=None) +configitem(b"remotefilelog", b"serverexpiration", default=30) +configitem(b"remotefilelog", b"backgroundrepack", default=False) +configitem(b"remotefilelog", b"bgprefetchrevs", default=None) +configitem(b"remotefilelog", b"pullprefetch", default=None) +configitem(b"remotefilelog", b"backgroundprefetch", default=False) +configitem(b"remotefilelog", b"prefetchdelay", default=120) +configitem(b"remotefilelog", b"prefetchdays", default=14) -configitem("remotefilelog", "getfilesstep", default=10000) -configitem("remotefilelog", "getfilestype", default="optimistic") -configitem("remotefilelog", "batchsize", configitems.dynamicdefault) -configitem("remotefilelog", "fetchwarning", default="") +configitem(b"remotefilelog", b"getfilesstep", default=10000) +configitem(b"remotefilelog", b"getfilestype", default=b"optimistic") +configitem(b"remotefilelog", b"batchsize", configitems.dynamicdefault) +configitem(b"remotefilelog", b"fetchwarning", default=b"") -configitem("remotefilelog", "includepattern", default=None) -configitem("remotefilelog", "excludepattern", default=None) +configitem(b"remotefilelog", b"includepattern", default=None) +configitem(b"remotefilelog", b"excludepattern", default=None) -configitem("remotefilelog", "gcrepack", default=False) -configitem("remotefilelog", "repackonhggc", default=False) -configitem("repack", "chainorphansbysize", default=True, experimental=True) +configitem(b"remotefilelog", b"gcrepack", default=False) +configitem(b"remotefilelog", b"repackonhggc", default=False) +configitem(b"repack", b"chainorphansbysize", default=True, experimental=True) -configitem("packs", "maxpacksize", default=0) -configitem("packs", "maxchainlen", default=1000) +configitem(b"packs", b"maxpacksize", default=0) +configitem(b"packs", b"maxchainlen", default=1000) -configitem("devel", "remotefilelog.ensurestart", default=False) +configitem(b"devel", b"remotefilelog.ensurestart", default=False) # default TTL limit is 30 days _defaultlimit = 60 * 60 * 24 * 30 -configitem("remotefilelog", "nodettl", default=_defaultlimit) +configitem(b"remotefilelog", b"nodettl", default=_defaultlimit) -configitem("remotefilelog", "data.gencountlimit", default=2), -configitem("remotefilelog", "data.generations", default=["1GB", "100MB", "1MB"]) -configitem("remotefilelog", "data.maxrepackpacks", default=50) -configitem("remotefilelog", "data.repackmaxpacksize", default="4GB") -configitem("remotefilelog", "data.repacksizelimit", default="100MB") +configitem(b"remotefilelog", b"data.gencountlimit", default=2), +configitem( + b"remotefilelog", b"data.generations", default=[b"1GB", b"100MB", b"1MB"] +) +configitem(b"remotefilelog", b"data.maxrepackpacks", default=50) +configitem(b"remotefilelog", b"data.repackmaxpacksize", default=b"4GB") +configitem(b"remotefilelog", b"data.repacksizelimit", default=b"100MB") -configitem("remotefilelog", "history.gencountlimit", default=2), -configitem("remotefilelog", "history.generations", default=["100MB"]) -configitem("remotefilelog", "history.maxrepackpacks", default=50) -configitem("remotefilelog", "history.repackmaxpacksize", default="400MB") -configitem("remotefilelog", "history.repacksizelimit", default="100MB") +configitem(b"remotefilelog", b"history.gencountlimit", default=2), +configitem(b"remotefilelog", b"history.generations", default=[b"100MB"]) +configitem(b"remotefilelog", b"history.maxrepackpacks", default=50) +configitem(b"remotefilelog", b"history.repackmaxpacksize", default=b"400MB") +configitem(b"remotefilelog", b"history.repacksizelimit", default=b"100MB") # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" repoclass = localrepo.localrepository repoclass._basesupported.add(constants.SHALLOWREPO_REQUIREMENT) @@ -264,80 +266,80 @@ """ hg.wirepeersetupfuncs.append(fileserverclient.peersetup) - entry = extensions.wrapcommand(commands.table, "clone", cloneshallow) + entry = extensions.wrapcommand(commands.table, b"clone", cloneshallow) entry[1].append( ( - "", - "shallow", + b"", + b"shallow", None, - _("create a shallow clone which uses remote file " "history"), + _(b"create a shallow clone which uses remote file " b"history"), ) ) extensions.wrapcommand( - commands.table, "debugindex", debugcommands.debugindex + commands.table, b"debugindex", debugcommands.debugindex ) extensions.wrapcommand( - commands.table, "debugindexdot", debugcommands.debugindexdot + commands.table, b"debugindexdot", debugcommands.debugindexdot ) - extensions.wrapcommand(commands.table, "log", log) - extensions.wrapcommand(commands.table, "pull", pull) + extensions.wrapcommand(commands.table, b"log", log) + extensions.wrapcommand(commands.table, b"pull", pull) # Prevent 'hg manifest --all' def _manifest(orig, ui, repo, *args, **opts): if isenabled(repo) and opts.get(r"all"): - raise error.Abort(_("--all is not supported in a shallow repo")) + raise error.Abort(_(b"--all is not supported in a shallow repo")) return orig(ui, repo, *args, **opts) - extensions.wrapcommand(commands.table, "manifest", _manifest) + extensions.wrapcommand(commands.table, b"manifest", _manifest) # Wrap remotefilelog with lfs code def _lfsloaded(loaded=False): lfsmod = None try: - lfsmod = extensions.find("lfs") + lfsmod = extensions.find(b"lfs") except KeyError: pass if lfsmod: lfsmod.wrapfilelog(remotefilelog.remotefilelog) fileserverclient._lfsmod = lfsmod - extensions.afterloaded("lfs", _lfsloaded) + extensions.afterloaded(b"lfs", _lfsloaded) # debugdata needs remotefilelog.len to work - extensions.wrapcommand(commands.table, "debugdata", debugdatashallow) + extensions.wrapcommand(commands.table, b"debugdata", debugdatashallow) changegroup.cgpacker = shallowbundle.shallowcg1packer extensions.wrapfunction( - changegroup, "_addchangegroupfiles", shallowbundle.addchangegroupfiles + changegroup, b"_addchangegroupfiles", shallowbundle.addchangegroupfiles ) extensions.wrapfunction( - changegroup, "makechangegroup", shallowbundle.makechangegroup + changegroup, b"makechangegroup", shallowbundle.makechangegroup ) - extensions.wrapfunction(localrepo, "makestore", storewrapper) - extensions.wrapfunction(exchange, "pull", exchangepull) - extensions.wrapfunction(merge, "applyupdates", applyupdates) - extensions.wrapfunction(merge, "_checkunknownfiles", checkunknownfiles) - extensions.wrapfunction(context.workingctx, "_checklookup", checklookup) - extensions.wrapfunction(scmutil, "_findrenames", findrenames) + extensions.wrapfunction(localrepo, b"makestore", storewrapper) + extensions.wrapfunction(exchange, b"pull", exchangepull) + extensions.wrapfunction(merge, b"applyupdates", applyupdates) + extensions.wrapfunction(merge, b"_checkunknownfiles", checkunknownfiles) + extensions.wrapfunction(context.workingctx, b"_checklookup", checklookup) + extensions.wrapfunction(scmutil, b"_findrenames", findrenames) extensions.wrapfunction( - copies, "_computeforwardmissing", computeforwardmissing + copies, b"_computeforwardmissing", computeforwardmissing ) - extensions.wrapfunction(dispatch, "runcommand", runcommand) - extensions.wrapfunction(repair, "_collectbrokencsets", _collectbrokencsets) - extensions.wrapfunction(context.changectx, "filectx", filectx) - extensions.wrapfunction(context.workingctx, "filectx", workingfilectx) - extensions.wrapfunction(patch, "trydiff", trydiff) - extensions.wrapfunction(hg, "verify", _verify) - scmutil.fileprefetchhooks.add("remotefilelog", _fileprefetchhook) + extensions.wrapfunction(dispatch, b"runcommand", runcommand) + extensions.wrapfunction(repair, b"_collectbrokencsets", _collectbrokencsets) + extensions.wrapfunction(context.changectx, b"filectx", filectx) + extensions.wrapfunction(context.workingctx, b"filectx", workingfilectx) + extensions.wrapfunction(patch, b"trydiff", trydiff) + extensions.wrapfunction(hg, b"verify", _verify) + scmutil.fileprefetchhooks.add(b"remotefilelog", _fileprefetchhook) # disappointing hacks below - extensions.wrapfunction(scmutil, "getrenamedfn", getrenamedfn) - extensions.wrapfunction(revset, "filelog", filelogrevset) - revset.symbols["filelog"] = revset.filelog - extensions.wrapfunction(cmdutil, "walkfilerevs", walkfilerevs) + extensions.wrapfunction(scmutil, b"getrenamedfn", getrenamedfn) + extensions.wrapfunction(revset, b"filelog", filelogrevset) + revset.symbols[b"filelog"] = revset.filelog + extensions.wrapfunction(cmdutil, b"walkfilerevs", walkfilerevs) def cloneshallow(orig, ui, repo, *args, **opts): @@ -366,7 +368,7 @@ else: return orig(self, *args, **kwargs) - extensions.wrapfunction(exchange, "pull", pull_shallow) + extensions.wrapfunction(exchange, b"pull", pull_shallow) # Wrap the stream logic to add requirements and to pass include/exclude # patterns around. @@ -378,30 +380,34 @@ if constants.NETWORK_CAP_LEGACY_SSH_GETFILES in caps: opts = {} if repo.includepattern: - opts[r"includepattern"] = "\0".join(repo.includepattern) + opts[r"includepattern"] = b"\0".join( + repo.includepattern + ) if repo.excludepattern: - opts[r"excludepattern"] = "\0".join(repo.excludepattern) - return remote._callstream("stream_out_shallow", **opts) + opts[r"excludepattern"] = b"\0".join( + repo.excludepattern + ) + return remote._callstream(b"stream_out_shallow", **opts) else: return orig() - extensions.wrapfunction(remote, "stream_out", stream_out_shallow) + extensions.wrapfunction(remote, b"stream_out", stream_out_shallow) def stream_wrap(orig, op): setup_streamout(op.repo, op.remote) return orig(op) extensions.wrapfunction( - streamclone, "maybeperformlegacystreamclone", stream_wrap + streamclone, b"maybeperformlegacystreamclone", stream_wrap ) def canperformstreamclone(orig, pullop, bundle2=False): # remotefilelog is currently incompatible with the # bundle2 flavor of streamclones, so force us to use # v1 instead. - if "v2" in pullop.remotebundle2caps.get("stream", []): - pullop.remotebundle2caps["stream"] = [ - c for c in pullop.remotebundle2caps["stream"] if c != "v2" + if b"v2" in pullop.remotebundle2caps.get(b"stream", []): + pullop.remotebundle2caps[b"stream"] = [ + c for c in pullop.remotebundle2caps[b"stream"] if c != b"v2" ] if bundle2: return False, None @@ -411,7 +417,7 @@ return supported, requirements extensions.wrapfunction( - streamclone, "canperformstreamclone", canperformstreamclone + streamclone, b"canperformstreamclone", canperformstreamclone ) try: @@ -419,7 +425,7 @@ finally: if opts.get(r"shallow"): for r in repos: - if util.safehasattr(r, "fileservice"): + if util.safehasattr(r, b"fileservice"): r.fileservice.close() @@ -437,14 +443,14 @@ return # put here intentionally bc doesnt work in uisetup - ui.setconfig("hooks", "update.prefetch", wcpprefetch) - ui.setconfig("hooks", "commit.prefetch", wcpprefetch) + ui.setconfig(b"hooks", b"update.prefetch", wcpprefetch) + ui.setconfig(b"hooks", b"commit.prefetch", wcpprefetch) - isserverenabled = ui.configbool("remotefilelog", "server") + isserverenabled = ui.configbool(b"remotefilelog", b"server") isshallowclient = isenabled(repo) if isserverenabled and isshallowclient: - raise RuntimeError("Cannot be both a server and shallow client.") + raise RuntimeError(b"Cannot be both a server and shallow client.") if isshallowclient: setupclient(ui, repo) @@ -481,7 +487,7 @@ if isenabled(repo): manifest = mctx.manifest() files = [] - for f, args, msg in actions["g"]: + for f, args, msg in actions[b"g"]: files.append((f, hex(manifest[f]))) # batch fetch the needed files from the server repo.fileservice.prefetch(files) @@ -498,9 +504,9 @@ for f, (m, actionargs, msg) in actions.iteritems(): if sparsematch and not sparsematch(f): continue - if m in ("c", "dc", "cm"): + if m in (b"c", b"dc", b"cm"): files.append((f, hex(mctx.filenode(f)))) - elif m == "dg": + elif m == b"dg": f2 = actionargs[0] files.append((f2, hex(mctx.filenode(f2)))) # batch fetch the needed files from the server @@ -526,7 +532,7 @@ def findrenames(orig, repo, matcher, added, removed, *args, **kwargs): if isenabled(repo): files = [] - pmf = repo["."].manifest() + pmf = repo[b"."].manifest() for f in removed: if f in pmf: files.append((f, hex(pmf[f]))) @@ -713,7 +719,7 @@ ) extensions.wrapfunction( - remotefilelog.remotefilelog, "addrawrevision", addrawrevision + remotefilelog.remotefilelog, b"addrawrevision", addrawrevision ) def changelogadd(orig, self, *args): @@ -728,7 +734,7 @@ log.addrawrevision(rt, tr, linknode, p1, p2, n, fl, c, m) else: raise error.ProgrammingError( - "pending multiple integer revisions are not supported" + b"pending multiple integer revisions are not supported" ) else: # "link" is actually wrong here (it is set to len(changelog)) @@ -736,12 +742,12 @@ # but still do a sanity check about pending multiple revisions if len(set(x[3] for x in pendingfilecommits)) > 1: raise error.ProgrammingError( - "pending multiple integer revisions are not supported" + b"pending multiple integer revisions are not supported" ) del pendingfilecommits[:] return node - extensions.wrapfunction(changelog.changelog, "add", changelogadd) + extensions.wrapfunction(changelog.changelog, b"add", changelogadd) def getrenamedfn(orig, repo, endrev=None): @@ -780,16 +786,16 @@ # remotefilelog's can't be walked in rev order, so throw. # The caller will see the exception and walk the commit tree instead. if not follow: - raise cmdutil.FileWalkError("Cannot walk via filelog") + raise cmdutil.FileWalkError(b"Cannot walk via filelog") wanted = set() minrev, maxrev = min(revs), max(revs) - pctx = repo["."] + pctx = repo[b"."] for filename in match.files(): if filename not in pctx: raise error.Abort( - _("cannot follow file not in parent " 'revision: "%s"') + _(b"cannot follow file not in parent " b'revision: "%s"') % filename ) fctx = pctx[filename] @@ -821,9 +827,9 @@ return orig(repo, subset, x) # i18n: "filelog" is a keyword - pat = revset.getstring(x, _("filelog requires a pattern")) + pat = revset.getstring(x, _(b"filelog requires a pattern")) m = match.match( - repo.root, repo.getcwd(), [pat], default="relpath", ctx=repo[None] + repo.root, repo.getcwd(), [pat], default=b"relpath", ctx=repo[None] ) s = set() @@ -848,7 +854,7 @@ return smartset.baseset([r for r in subset if r in s]) -@command("gc", [], _("hg gc [REPO...]"), norepo=True) +@command(b"gc", [], _(b"hg gc [REPO...]"), norepo=True) def gc(ui, *args, **opts): """garbage collect the client and server filelog caches """ @@ -861,7 +867,7 @@ # get repo client and server cache repopaths = [] - pwd = ui.environ.get("PWD") + pwd = ui.environ.get(b"PWD") if pwd: repopaths.append(pwd) @@ -889,12 +895,12 @@ def gcclient(ui, cachepath): # get list of repos that use this cache - repospath = os.path.join(cachepath, "repos") + repospath = os.path.join(cachepath, b"repos") if not os.path.exists(repospath): - ui.warn(_("no known cache at %s\n") % cachepath) + ui.warn(_(b"no known cache at %s\n") % cachepath) return - reposfile = open(repospath, "rb") + reposfile = open(repospath, b"rb") repos = {r[:-1] for r in reposfile.readlines()} reposfile.close() @@ -907,7 +913,7 @@ count = 0 progress = ui.makeprogress( - _("analyzing repositories"), unit="repos", total=len(repos) + _(b"analyzing repositories"), unit=b"repos", total=len(repos) ) for path in repos: progress.update(count) @@ -915,7 +921,7 @@ try: path = ui.expandpath(os.path.normpath(path)) except TypeError as e: - ui.warn(_("warning: malformed path: %r:%s\n") % (path, e)) + ui.warn(_(b"warning: malformed path: %r:%s\n") % (path, e)) traceback.print_exc() continue try: @@ -932,15 +938,17 @@ if not isenabled(repo): continue - if not util.safehasattr(repo, "name"): - ui.warn(_("repo %s is a misconfigured remotefilelog repo\n") % path) + if not util.safehasattr(repo, b"name"): + ui.warn( + _(b"repo %s is a misconfigured remotefilelog repo\n") % path + ) continue # If garbage collection on repack and repack on hg gc are enabled # then loose files are repacked and garbage collected. # Otherwise regular garbage collection is performed. - repackonhggc = repo.ui.configbool("remotefilelog", "repackonhggc") - gcrepack = repo.ui.configbool("remotefilelog", "gcrepack") + repackonhggc = repo.ui.configbool(b"remotefilelog", b"repackonhggc") + gcrepack = repo.ui.configbool(b"remotefilelog", b"gcrepack") if repackonhggc and gcrepack: try: repackmod.incrementalrepack(repo) @@ -966,8 +974,8 @@ # write list of valid repos back oldumask = os.umask(0o002) try: - reposfile = open(repospath, "wb") - reposfile.writelines([("%s\n" % r) for r in validrepos]) + reposfile = open(repospath, b"wb") + reposfile.writelines([(b"%s\n" % r) for r in validrepos]) reposfile.close() finally: os.umask(oldumask) @@ -976,7 +984,7 @@ if sharedcache is not None: sharedcache.gc(keepkeys) elif not filesrepacked: - ui.warn(_("warning: no valid repos in repofile\n")) + ui.warn(_(b"warning: no valid repos in repofile\n")) def log(orig, ui, repo, *pats, **opts): @@ -995,7 +1003,7 @@ # If this is a non-follow log without any revs specified, recommend that # the user add -f to speed it up. if not follow and not revs: - match = scmutil.match(repo["."], pats, pycompat.byteskwargs(opts)) + match = scmutil.match(repo[b"."], pats, pycompat.byteskwargs(opts)) isfile = not match.anypats() if isfile: for file in match.files(): @@ -1006,8 +1014,8 @@ if isfile: ui.warn( _( - "warning: file log can be slow on large repos - " - + "use -f to speed it up\n" + b"warning: file log can be slow on large repos - " + + b"use -f to speed it up\n" ) ) @@ -1019,9 +1027,9 @@ are included. The default value is set to 14 days. If 'prefetchdays' is set to zero or negative value then date restriction is not applied. """ - days = ui.configint("remotefilelog", "prefetchdays") + days = ui.configint(b"remotefilelog", b"prefetchdays") if days > 0: - revset = "(%s) & date(-%s)" % (revset, days) + revset = b"(%s) & date(-%s)" % (revset, days) return revset @@ -1030,11 +1038,11 @@ This only relates to prefetches after operations that change the working copy parent. Default delay between background prefetches is 2 minutes. """ - timeout = repo.ui.configint("remotefilelog", "prefetchdelay") - fname = repo.vfs.join("lastprefetch") + timeout = repo.ui.configint(b"remotefilelog", b"prefetchdelay") + fname = repo.vfs.join(b"lastprefetch") ready = False - with open(fname, "a"): + with open(fname, b"a"): # the with construct above is used to avoid race conditions modtime = os.path.getmtime(fname) if (time.time() - modtime) > timeout: @@ -1049,18 +1057,18 @@ Does background repack if backgroundrepack flag is set in config. """ shallow = isenabled(repo) - bgprefetchrevs = ui.config("remotefilelog", "bgprefetchrevs") + bgprefetchrevs = ui.config(b"remotefilelog", b"bgprefetchrevs") isready = readytofetch(repo) if not (shallow and bgprefetchrevs and isready): return - bgrepack = repo.ui.configbool("remotefilelog", "backgroundrepack") + bgrepack = repo.ui.configbool(b"remotefilelog", b"backgroundrepack") # update a revset with a date limit bgprefetchrevs = revdatelimit(ui, bgprefetchrevs) def anon(): - if util.safehasattr(repo, "ranprefetch") and repo.ranprefetch: + if util.safehasattr(repo, b"ranprefetch") and repo.ranprefetch: return repo.ranprefetch = True repo.backgroundprefetch(bgprefetchrevs, repack=bgrepack) @@ -1073,15 +1081,15 @@ if isenabled(repo): # prefetch if it's configured - prefetchrevset = ui.config("remotefilelog", "pullprefetch") - bgrepack = repo.ui.configbool("remotefilelog", "backgroundrepack") - bgprefetch = repo.ui.configbool("remotefilelog", "backgroundprefetch") - ensurestart = repo.ui.configbool("devel", "remotefilelog.ensurestart") + prefetchrevset = ui.config(b"remotefilelog", b"pullprefetch") + bgrepack = repo.ui.configbool(b"remotefilelog", b"backgroundrepack") + bgprefetch = repo.ui.configbool(b"remotefilelog", b"backgroundprefetch") + ensurestart = repo.ui.configbool(b"devel", b"remotefilelog.ensurestart") if prefetchrevset: - ui.status(_("prefetching file contents\n")) + ui.status(_(b"prefetching file contents\n")) revs = scmutil.revrange(repo, [prefetchrevset]) - base = repo["."].rev() + base = repo[b"."].rev() if bgprefetch: repo.backgroundprefetch( prefetchrevset, repack=bgrepack, ensurestart=ensurestart @@ -1113,10 +1121,10 @@ source, heads=heads, common=common, bundlecaps=bundlecaps, **kwargs ) - if util.safehasattr(remote, "_callstream"): + if util.safehasattr(remote, b"_callstream"): remote._localrepo = repo - elif util.safehasattr(remote, "getbundle"): - extensions.wrapfunction(remote, "getbundle", localgetbundle) + elif util.safehasattr(remote, b"getbundle"): + extensions.wrapfunction(remote, b"getbundle", localgetbundle) return orig(repo, remote, *args, **kwargs) @@ -1137,9 +1145,9 @@ @command( - "debugremotefilelog", - [("d", "decompress", None, _("decompress the filelog first")),], - _("hg debugremotefilelog "), + b"debugremotefilelog", + [(b"d", b"decompress", None, _(b"decompress the filelog first")),], + _(b"hg debugremotefilelog "), norepo=True, ) def debugremotefilelog(ui, path, **opts): @@ -1147,9 +1155,9 @@ @command( - "verifyremotefilelog", - [("d", "decompress", None, _("decompress the filelogs first")),], - _("hg verifyremotefilelogs "), + b"verifyremotefilelog", + [(b"d", b"decompress", None, _(b"decompress the filelogs first")),], + _(b"hg verifyremotefilelogs "), norepo=True, ) def verifyremotefilelog(ui, path, **opts): @@ -1157,24 +1165,24 @@ @command( - "debugdatapack", + b"debugdatapack", [ - ("", "long", None, _("print the long hashes")), - ("", "node", "", _("dump the contents of node"), "NODE"), + (b"", b"long", None, _(b"print the long hashes")), + (b"", b"node", b"", _(b"dump the contents of node"), b"NODE"), ], - _("hg debugdatapack "), + _(b"hg debugdatapack "), norepo=True, ) def debugdatapack(ui, *paths, **opts): return debugcommands.debugdatapack(ui, *paths, **opts) -@command("debughistorypack", [], _("hg debughistorypack "), norepo=True) +@command(b"debughistorypack", [], _(b"hg debughistorypack "), norepo=True) def debughistorypack(ui, path, **opts): return debugcommands.debughistorypack(ui, path) -@command("debugkeepset", [], _("hg debugkeepset")) +@command(b"debugkeepset", [], _(b"hg debugkeepset")) def debugkeepset(ui, repo, **opts): # The command is used to measure keepset computation time def keyfn(fname, fnode): @@ -1184,48 +1192,48 @@ return -@command("debugwaitonrepack", [], _("hg debugwaitonrepack")) +@command(b"debugwaitonrepack", [], _(b"hg debugwaitonrepack")) def debugwaitonrepack(ui, repo, **opts): return debugcommands.debugwaitonrepack(repo) -@command("debugwaitonprefetch", [], _("hg debugwaitonprefetch")) +@command(b"debugwaitonprefetch", [], _(b"hg debugwaitonprefetch")) def debugwaitonprefetch(ui, repo, **opts): return debugcommands.debugwaitonprefetch(repo) def resolveprefetchopts(ui, opts): - if not opts.get("rev"): - revset = [".", "draft()"] + if not opts.get(b"rev"): + revset = [b".", b"draft()"] - prefetchrevset = ui.config("remotefilelog", "pullprefetch", None) + prefetchrevset = ui.config(b"remotefilelog", b"pullprefetch", None) if prefetchrevset: - revset.append("(%s)" % prefetchrevset) - bgprefetchrevs = ui.config("remotefilelog", "bgprefetchrevs", None) + revset.append(b"(%s)" % prefetchrevset) + bgprefetchrevs = ui.config(b"remotefilelog", b"bgprefetchrevs", None) if bgprefetchrevs: - revset.append("(%s)" % bgprefetchrevs) - revset = "+".join(revset) + revset.append(b"(%s)" % bgprefetchrevs) + revset = b"+".join(revset) # update a revset with a date limit revset = revdatelimit(ui, revset) - opts["rev"] = [revset] + opts[b"rev"] = [revset] - if not opts.get("base"): - opts["base"] = None + if not opts.get(b"base"): + opts[b"base"] = None return opts @command( - "prefetch", + b"prefetch", [ - ("r", "rev", [], _("prefetch the specified revisions"), _("REV")), - ("", "repack", False, _("run repack after prefetch")), - ("b", "base", "", _("rev that is assumed to already be local")), + (b"r", b"rev", [], _(b"prefetch the specified revisions"), _(b"REV")), + (b"", b"repack", False, _(b"run repack after prefetch")), + (b"b", b"base", b"", _(b"rev that is assumed to already be local")), ] + commands.walkopts, - _("hg prefetch [OPTIONS] [FILE...]"), + _(b"hg prefetch [OPTIONS] [FILE...]"), ) def prefetch(ui, repo, *pats, **opts): """prefetch file revisions from the server @@ -1239,39 +1247,39 @@ """ opts = pycompat.byteskwargs(opts) if not isenabled(repo): - raise error.Abort(_("repo is not shallow")) + raise error.Abort(_(b"repo is not shallow")) opts = resolveprefetchopts(ui, opts) - revs = scmutil.revrange(repo, opts.get("rev")) - repo.prefetch(revs, opts.get("base"), pats, opts) + revs = scmutil.revrange(repo, opts.get(b"rev")) + repo.prefetch(revs, opts.get(b"base"), pats, opts) - ensurestart = repo.ui.configbool("devel", "remotefilelog.ensurestart") + ensurestart = repo.ui.configbool(b"devel", b"remotefilelog.ensurestart") # Run repack in background - if opts.get("repack"): + if opts.get(b"repack"): repackmod.backgroundrepack( repo, incremental=True, ensurestart=ensurestart ) @command( - "repack", + b"repack", [ - ("", "background", None, _("run in a background process"), None), - ("", "incremental", None, _("do an incremental repack"), None), + (b"", b"background", None, _(b"run in a background process"), None), + (b"", b"incremental", None, _(b"do an incremental repack"), None), ( - "", - "packsonly", + b"", + b"packsonly", None, - _("only repack packs (skip loose objects)"), + _(b"only repack packs (skip loose objects)"), None, ), ], - _("hg repack [OPTIONS]"), + _(b"hg repack [OPTIONS]"), ) def repack_(ui, repo, *pats, **opts): if opts.get(r"background"): - ensurestart = repo.ui.configbool("devel", "remotefilelog.ensurestart") + ensurestart = repo.ui.configbool(b"devel", b"remotefilelog.ensurestart") repackmod.backgroundrepack( repo, incremental=opts.get(r"incremental"), @@ -1280,7 +1288,7 @@ ) return - options = {"packsonly": opts.get(r"packsonly")} + options = {b"packsonly": opts.get(r"packsonly")} try: if opts.get(r"incremental"): @@ -1290,4 +1298,4 @@ except repackmod.RepackAlreadyRunning as ex: # Don't propogate the exception if the repack is already in # progress, since we want the command to exit 0. - repo.ui.warn("%s\n" % ex) + repo.ui.warn(b"%s\n" % ex) diff --git a/hgext/remotefilelog/basepack.py b/hgext/remotefilelog/basepack.py --- a/hgext/remotefilelog/basepack.py +++ b/hgext/remotefilelog/basepack.py @@ -56,9 +56,9 @@ # With glibc 2.7+ the 'e' flag uses O_CLOEXEC when opening. # The 'e' flag will be ignored on older versions of glibc. # Python 3 can't handle the 'e' flag. - PACKOPENMODE = "rbe" + PACKOPENMODE = b"rbe" else: - PACKOPENMODE = "rb" + PACKOPENMODE = b"rb" class _cachebackedpacks(object): @@ -132,7 +132,7 @@ # Someone could have removed the file since we retrieved the # list of paths. if getattr(ex, "errno", None) != errno.ENOENT: - ui.warn(_("unable to load pack %s: %s\n") % (filepath, ex)) + ui.warn(_(b"unable to load pack %s: %s\n") % (filepath, ex)) continue packs.append(pack) @@ -210,8 +210,8 @@ """Returns metrics on the state of this store.""" size, count = self.gettotalsizeandcount() return { - "numpacks": count, - "totalpacksize": size, + b"numpacks": count, + b"totalpacksize": size, } def getpack(self, path): @@ -276,9 +276,9 @@ # only affect this instance self.VERSION = version elif self.VERSION != version: - raise RuntimeError("inconsistent version: %d" % version) + raise RuntimeError(b"inconsistent version: %d" % version) else: - raise RuntimeError("unsupported version: %d" % version) + raise RuntimeError(b"unsupported version: %d" % version) class basepack(versionmixin): @@ -300,10 +300,10 @@ self._data = None self.freememory() # initialize the mmap - version = struct.unpack("!B", self._data[:PACKVERSIONSIZE])[0] + version = struct.unpack(b"!B", self._data[:PACKVERSIONSIZE])[0] self._checkversion(version) - version, config = struct.unpack("!BB", self._index[:INDEXVERSIONSIZE]) + version, config = struct.unpack(b"!BB", self._index[:INDEXVERSIONSIZE]) self._checkversion(version) if 0b10000000 & config: @@ -318,14 +318,14 @@ fanouttable = [] for i in pycompat.xrange(0, params.fanoutcount): loc = i * 4 - fanoutentry = struct.unpack("!I", rawfanout[loc : loc + 4])[0] + fanoutentry = struct.unpack(b"!I", rawfanout[loc : loc + 4])[0] fanouttable.append(fanoutentry) return fanouttable @util.propertycache def _indexend(self): nodecount = struct.unpack_from( - "!Q", self._index, self.params.indexstart - 8 + b"!Q", self._index, self.params.indexstart - 8 )[0] return self.params.indexstart + nodecount * self.INDEXENTRYLENGTH @@ -372,7 +372,7 @@ def __init__(self, ui, packdir, version=2): self._checkversion(version) # TODO(augie): make this configurable - self._compressor = "GZ" + self._compressor = b"GZ" opener = vfsmod.vfs(packdir) opener.createmode = 0o444 self.opener = opener @@ -381,10 +381,10 @@ shallowutil.mkstickygroupdir(ui, packdir) self.packfp, self.packpath = opener.mkstemp( - suffix=self.PACKSUFFIX + "-tmp" + suffix=self.PACKSUFFIX + b"-tmp" ) self.idxfp, self.idxpath = opener.mkstemp( - suffix=self.INDEXSUFFIX + "-tmp" + suffix=self.INDEXSUFFIX + b"-tmp" ) self.packfp = os.fdopen(self.packfp, r"wb+") self.idxfp = os.fdopen(self.idxfp, r"wb+") @@ -400,7 +400,7 @@ # Write header # TODO: make it extensible (ex: allow specifying compression algorithm, # a flexible key/value header, delta algorithm, fanout size, etc) - versionbuf = struct.pack("!B", self.VERSION) # unsigned 1 byte int + versionbuf = struct.pack(b"!B", self.VERSION) # unsigned 1 byte int self.writeraw(versionbuf) def __enter__(self): @@ -491,14 +491,14 @@ if fanouttable[fanoutkey] == EMPTYFANOUT: fanouttable[fanoutkey] = location - rawfanouttable = "" + rawfanouttable = b"" last = 0 for offset in fanouttable: offset = offset if offset != EMPTYFANOUT else last last = offset - rawfanouttable += struct.pack("!I", offset) + rawfanouttable += struct.pack(b"!I", offset) - rawentrieslength = struct.pack("!Q", len(self.entries)) + rawentrieslength = struct.pack(b"!Q", len(self.entries)) # The index offset is the it's location in the file. So after the 2 byte # header and the fanouttable. @@ -521,7 +521,7 @@ config = 0 if indexparams.fanoutprefix == LARGEFANOUTPREFIX: config = 0b10000000 - self.idxfp.write(struct.pack("!BB", self.VERSION, config)) + self.idxfp.write(struct.pack(b"!BB", self.VERSION, config)) class indexparams(object): @@ -540,11 +540,11 @@ # converts the node prefix into an integer location in the fanout # table). if prefixsize == SMALLFANOUTPREFIX: - self.fanoutstruct = "!B" + self.fanoutstruct = b"!B" elif prefixsize == LARGEFANOUTPREFIX: - self.fanoutstruct = "!H" + self.fanoutstruct = b"!H" else: - raise ValueError("invalid fanout prefix size: %s" % prefixsize) + raise ValueError(b"invalid fanout prefix size: %s" % prefixsize) # The number of fanout table entries self.fanoutcount = 2 ** (prefixsize * 8) diff --git a/hgext/remotefilelog/basestore.py b/hgext/remotefilelog/basestore.py --- a/hgext/remotefilelog/basestore.py +++ b/hgext/remotefilelog/basestore.py @@ -39,14 +39,14 @@ self._uid = os.getuid() if not pycompat.iswindows else None self._validatecachelog = self.ui.config( - "remotefilelog", "validatecachelog" + b"remotefilelog", b"validatecachelog" ) self._validatecache = self.ui.config( - "remotefilelog", "validatecache", "on" + b"remotefilelog", b"validatecache", b"on" ) - if self._validatecache not in ("on", "strict", "off"): - self._validatecache = "on" - if self._validatecache == "off": + if self._validatecache not in (b"on", b"strict", b"off"): + self._validatecache = b"on" + if self._validatecache == b"off": self._validatecache = False if shared: @@ -59,8 +59,8 @@ exists = os.path.exists(filepath) if ( exists - and self._validatecache == "strict" - and not self._validatekey(filepath, "contains") + and self._validatecache == b"strict" + and not self._validatekey(filepath, b"contains") ): exists = False if not exists: @@ -84,7 +84,7 @@ entries = ledger.sources.get(self, []) count = 0 progress = ui.makeprogress( - _("cleaning up"), unit="files", total=len(entries) + _(b"cleaning up"), unit=b"files", total=len(entries) ) for entry in entries: if entry.gced or (entry.datarepacked and entry.historyrepacked): @@ -121,7 +121,7 @@ pass elif stat.S_ISREG(mode): - if name.endswith("_old"): + if name.endswith(b"_old"): oldfiles.add(name[:-4]) else: otherfiles.add(name) @@ -130,7 +130,7 @@ # corresponding file without the suffix '_old'. See addremotefilelognode # method for the generation/purpose of files with '_old' suffix. for filename in oldfiles - otherfiles: - filepath = os.path.join(rootdir, filename + "_old") + filepath = os.path.join(rootdir, filename + b"_old") util.tryunlink(filepath) def _getfiles(self): @@ -164,7 +164,7 @@ missingfilename = set(hashes) # Start with a full manifest, since it'll cover the majority of files - for filename in self.repo["tip"].manifest(): + for filename in self.repo[b"tip"].manifest(): sha = hashlib.sha1(filename).digest() if sha in missingfilename: filenames[filename] = sha @@ -224,13 +224,13 @@ data = shallowutil.readfile(filepath) if self._validatecache and not self._validatedata(data, filepath): if self._validatecachelog: - with open(self._validatecachelog, "a+") as f: - f.write("corrupt %s during read\n" % filepath) - os.rename(filepath, filepath + ".corrupt") - raise KeyError("corrupt local cache file %s" % filepath) + with open(self._validatecachelog, b"a+") as f: + f.write(b"corrupt %s during read\n" % filepath) + os.rename(filepath, filepath + b".corrupt") + raise KeyError(b"corrupt local cache file %s" % filepath) except IOError: raise KeyError( - "no file found at %s for %s:%s" % (filepath, name, hex(node)) + b"no file found at %s for %s:%s" % (filepath, name, hex(node)) ) return data @@ -243,7 +243,7 @@ # if this node already exists, save the old version for # recovery/debugging purposes. if os.path.exists(filepath): - newfilename = filepath + "_old" + newfilename = filepath + b"_old" # newfilename can be read-only and shutil.copy will fail. # Delete newfilename to avoid it if os.path.exists(newfilename): @@ -254,9 +254,9 @@ shallowutil.writefile(filepath, data, readonly=True) if self._validatecache: - if not self._validatekey(filepath, "write"): + if not self._validatekey(filepath, b"write"): raise error.Abort( - _("local cache write was corrupted %s") % filepath + _(b"local cache write was corrupted %s") % filepath ) finally: os.umask(oldumask) @@ -267,26 +267,26 @@ collection, since it allows us to insecpt the repos to see what nodes they want to be kept alive in the store. """ - repospath = os.path.join(self._path, "repos") - with open(repospath, "ab") as reposfile: - reposfile.write(os.path.dirname(path) + "\n") + repospath = os.path.join(self._path, b"repos") + with open(repospath, b"ab") as reposfile: + reposfile.write(os.path.dirname(path) + b"\n") repospathstat = os.stat(repospath) if repospathstat.st_uid == self._uid: os.chmod(repospath, 0o0664) def _validatekey(self, path, action): - with open(path, "rb") as f: + with open(path, b"rb") as f: data = f.read() if self._validatedata(data, path): return True if self._validatecachelog: - with open(self._validatecachelog, "ab+") as f: - f.write("corrupt %s during %s\n" % (path, action)) + with open(self._validatecachelog, b"ab+") as f: + f.write(b"corrupt %s during %s\n" % (path, action)) - os.rename(path, path + ".corrupt") + os.rename(path, path + b".corrupt") return False def _validatedata(self, data, path): @@ -327,16 +327,16 @@ limit = time.time() - (60 * 60 * 24) progress = ui.makeprogress( - _("removing unnecessary files"), unit="files" + _(b"removing unnecessary files"), unit=b"files" ) progress.update(0) for root, dirs, files in os.walk(cachepath): for file in files: - if file == "repos": + if file == b"repos": continue # Don't delete pack files - if "/packs/" in root: + if b"/packs/" in root: continue progress.update(count) @@ -349,7 +349,9 @@ # errno.ENOENT = no such file or directory if e.errno != errno.ENOENT: raise - msg = _("warning: file %s was removed by another process\n") + msg = _( + b"warning: file %s was removed by another process\n" + ) ui.warn(msg % path) continue @@ -366,8 +368,8 @@ if e.errno != errno.ENOENT: raise msg = _( - "warning: file %s was removed by another " - "process\n" + b"warning: file %s was removed by another " + b"process\n" ) ui.warn(msg % path) continue @@ -375,11 +377,11 @@ progress.complete() # remove oldest files until under limit - limit = ui.configbytes("remotefilelog", "cachelimit") + limit = ui.configbytes(b"remotefilelog", b"cachelimit") if size > limit: excess = size - limit progress = ui.makeprogress( - _("enforcing cache limit"), unit="bytes", total=excess + _(b"enforcing cache limit"), unit=b"bytes", total=excess ) removedexcess = 0 while queue and size > limit and size > 0: @@ -391,7 +393,9 @@ # errno.ENOENT = no such file or directory if e.errno != errno.ENOENT: raise - msg = _("warning: file %s was removed by another process\n") + msg = _( + b"warning: file %s was removed by another process\n" + ) ui.warn(msg % oldpath) size -= oldpathstat.st_size removed += 1 @@ -399,7 +403,7 @@ progress.complete() ui.status( - _("finished: removed %d of %d files (%0.2f GB to %0.2f GB)\n") + _(b"finished: removed %d of %d files (%0.2f GB to %0.2f GB)\n") % ( removed, count, @@ -422,7 +426,7 @@ def markforrefresh(self): for store in self.stores: - if util.safehasattr(store, "markforrefresh"): + if util.safehasattr(store, b"markforrefresh"): store.markforrefresh() @staticmethod @@ -436,7 +440,7 @@ i = 0 while i < self.numattempts: if i > 0: - retrylog("re-attempting (n=%d) %s\n" % (i, funcname)) + retrylog(b"re-attempting (n=%d) %s\n" % (i, funcname)) self.markforrefresh() i += 1 try: @@ -445,7 +449,7 @@ if i == self.numattempts: # retries exhausted retrylog( - "retries exhausted in %s, raising KeyError\n" + b"retries exhausted in %s, raising KeyError\n" % pycompat.sysbytes(funcname) ) raise diff --git a/hgext/remotefilelog/connectionpool.py b/hgext/remotefilelog/connectionpool.py --- a/hgext/remotefilelog/connectionpool.py +++ b/hgext/remotefilelog/connectionpool.py @@ -46,13 +46,13 @@ # close pipee first so peer.cleanup reading it won't deadlock, # if there are other processes with pipeo open (i.e. us). peer = orig.im_self - if util.safehasattr(peer, "pipee"): + if util.safehasattr(peer, b"pipee"): peer.pipee.close() return orig() peer = hg.peer(self._repo.ui, {}, path) - if util.safehasattr(peer, "cleanup"): - extensions.wrapfunction(peer, "cleanup", _cleanup) + if util.safehasattr(peer, b"cleanup"): + extensions.wrapfunction(peer, b"cleanup", _cleanup) conn = connection(pathpool, peer) @@ -83,5 +83,5 @@ self.close() def close(self): - if util.safehasattr(self.peer, "cleanup"): + if util.safehasattr(self.peer, b"cleanup"): self.peer.cleanup() diff --git a/hgext/remotefilelog/constants.py b/hgext/remotefilelog/constants.py --- a/hgext/remotefilelog/constants.py +++ b/hgext/remotefilelog/constants.py @@ -4,40 +4,40 @@ from mercurial.i18n import _ -NETWORK_CAP_LEGACY_SSH_GETFILES = "exp-remotefilelog-ssh-getfiles-1" +NETWORK_CAP_LEGACY_SSH_GETFILES = b"exp-remotefilelog-ssh-getfiles-1" -SHALLOWREPO_REQUIREMENT = "exp-remotefilelog-repo-req-1" +SHALLOWREPO_REQUIREMENT = b"exp-remotefilelog-repo-req-1" -BUNDLE2_CAPABLITY = "exp-remotefilelog-b2cap-1" +BUNDLE2_CAPABLITY = b"exp-remotefilelog-b2cap-1" -FILENAMESTRUCT = "!H" +FILENAMESTRUCT = b"!H" FILENAMESIZE = struct.calcsize(FILENAMESTRUCT) NODESIZE = 20 -PACKREQUESTCOUNTSTRUCT = "!I" +PACKREQUESTCOUNTSTRUCT = b"!I" -NODECOUNTSTRUCT = "!I" +NODECOUNTSTRUCT = b"!I" NODECOUNTSIZE = struct.calcsize(NODECOUNTSTRUCT) -PATHCOUNTSTRUCT = "!I" +PATHCOUNTSTRUCT = b"!I" PATHCOUNTSIZE = struct.calcsize(PATHCOUNTSTRUCT) -FILEPACK_CATEGORY = "" -TREEPACK_CATEGORY = "manifests" +FILEPACK_CATEGORY = b"" +TREEPACK_CATEGORY = b"manifests" ALL_CATEGORIES = [FILEPACK_CATEGORY, TREEPACK_CATEGORY] # revision metadata keys. must be a single character. -METAKEYFLAG = "f" # revlog flag -METAKEYSIZE = "s" # full rawtext size +METAKEYFLAG = b"f" # revlog flag +METAKEYSIZE = b"s" # full rawtext size def getunits(category): if category == FILEPACK_CATEGORY: - return _("files") + return _(b"files") if category == TREEPACK_CATEGORY: - return _("trees") + return _(b"trees") # Repack options passed to ``markledger``. -OPTION_PACKSONLY = "packsonly" +OPTION_PACKSONLY = b"packsonly" diff --git a/hgext/remotefilelog/contentstore.py b/hgext/remotefilelog/contentstore.py --- a/hgext/remotefilelog/contentstore.py +++ b/hgext/remotefilelog/contentstore.py @@ -136,7 +136,7 @@ def add(self, name, node, data): raise RuntimeError( - "cannot add content only to remotefilelog " "contentstore" + b"cannot add content only to remotefilelog " b"contentstore" ) def getmissing(self, keys): @@ -150,7 +150,7 @@ if self.writestore: self.writestore.addremotefilelognode(name, node, data) else: - raise RuntimeError("no writable store configured") + raise RuntimeError(b"no writable store configured") def markledger(self, ledger, options=None): for store in self.stores: @@ -208,7 +208,7 @@ def add(self, name, node, data): raise RuntimeError( - "cannot add content only to remotefilelog " "contentstore" + b"cannot add content only to remotefilelog " b"contentstore" ) def _sanitizemetacache(self): @@ -255,7 +255,7 @@ return self._shared.getmeta(name, node) def add(self, name, node, data): - raise RuntimeError("cannot add to a remote store") + raise RuntimeError(b"cannot add to a remote store") def getmissing(self, keys): return keys @@ -269,7 +269,7 @@ self._store = repo.store self._svfs = repo.svfs self._revlogs = dict() - self._cl = revlog.revlog(self._svfs, "00changelog.i") + self._cl = revlog.revlog(self._svfs, b"00changelog.i") self._repackstartlinkrev = 0 def get(self, name, node): @@ -311,7 +311,7 @@ missing.add(p2) linknode = self._cl.node(rl.linkrev(ancrev)) - ancestors[rl.node(ancrev)] = (p1, p2, linknode, "") + ancestors[rl.node(ancrev)] = (p1, p2, linknode, b"") if not missing: break return ancestors @@ -324,14 +324,14 @@ return (parents[0], parents[1], cl.node(linkrev), None) def add(self, *args): - raise RuntimeError("cannot add to a revlog store") + raise RuntimeError(b"cannot add to a revlog store") def _revlog(self, name): rl = self._revlogs.get(name) if rl is None: - revlogname = "00manifesttree.i" - if name != "": - revlogname = "meta/%s/00manifest.i" % name + revlogname = b"00manifesttree.i" + if name != b"": + revlogname = b"meta/%s/00manifest.i" % name rl = revlog.revlog(self._svfs, revlogname) self._revlogs[name] = rl return rl @@ -352,8 +352,8 @@ def markledger(self, ledger, options=None): if options and options.get(constants.OPTION_PACKSONLY): return - treename = "" - rl = revlog.revlog(self._svfs, "00manifesttree.i") + treename = b"" + rl = revlog.revlog(self._svfs, b"00manifesttree.i") startlinkrev = self._repackstartlinkrev endlinkrev = self._repackendlinkrev for rev in pycompat.xrange(len(rl) - 1, -1, -1): @@ -367,10 +367,10 @@ ledger.markhistoryentry(self, treename, node) for path, encoded, size in self._store.datafiles(): - if path[:5] != "meta/" or path[-2:] != ".i": + if path[:5] != b"meta/" or path[-2:] != b".i": continue - treename = path[5 : -len("/00manifest.i")] + treename = path[5 : -len(b"/00manifest.i")] rl = revlog.revlog(self._svfs, path) for rev in pycompat.xrange(len(rl) - 1, -1, -1): diff --git a/hgext/remotefilelog/datapack.py b/hgext/remotefilelog/datapack.py --- a/hgext/remotefilelog/datapack.py +++ b/hgext/remotefilelog/datapack.py @@ -21,8 +21,8 @@ FULLTEXTINDEXMARK = -1 NOBASEINDEXMARK = -2 -INDEXSUFFIX = ".dataidx" -PACKSUFFIX = ".datapack" +INDEXSUFFIX = b".dataidx" +PACKSUFFIX = b".datapack" class datapackstore(basepack.basepackstore): @@ -36,7 +36,7 @@ return datapack(path) def get(self, name, node): - raise RuntimeError("must use getdeltachain with datapackstore") + raise RuntimeError(b"must use getdeltachain with datapackstore") def getmeta(self, name, node): for pack in self.packs: @@ -84,7 +84,7 @@ raise KeyError((name, hex(node))) def add(self, name, node, data): - raise RuntimeError("cannot add to datapackstore") + raise RuntimeError(b"cannot add to datapackstore") class datapack(basepack.basepack): @@ -93,7 +93,7 @@ # Format is # See the mutabledatapack doccomment for more details. - INDEXFORMAT = "!20siQQ" + INDEXFORMAT = b"!20siQQ" INDEXENTRYLENGTH = 40 SUPPORTED_VERSIONS = [2] @@ -109,7 +109,7 @@ def get(self, name, node): raise RuntimeError( - "must use getdeltachain with datapack (%s:%s)" % (name, hex(node)) + b"must use getdeltachain with datapack (%s:%s)" % (name, hex(node)) ) def getmeta(self, name, node): @@ -122,11 +122,11 @@ # see docstring of mutabledatapack for the format offset = 0 - offset += struct.unpack_from("!H", rawentry, offset)[0] + 2 # filename + offset += struct.unpack_from(b"!H", rawentry, offset)[0] + 2 # filename offset += 40 # node, deltabase node - offset += struct.unpack_from("!Q", rawentry, offset)[0] + 8 # delta + offset += struct.unpack_from(b"!Q", rawentry, offset)[0] + 8 # delta - metalen = struct.unpack_from("!I", rawentry, offset)[0] + metalen = struct.unpack_from(b"!I", rawentry, offset)[0] offset += 4 meta = shallowutil.parsepackmeta(rawentry[offset : offset + metalen]) @@ -186,7 +186,7 @@ # <2 byte len> + lengthsize = 2 - filenamelen = struct.unpack("!H", rawentry[:2])[0] + filenamelen = struct.unpack(b"!H", rawentry[:2])[0] filename = rawentry[lengthsize : lengthsize + filenamelen] # <20 byte node> + <20 byte deltabase> @@ -198,14 +198,14 @@ # <8 byte len> + deltastart = deltabasestart + NODELENGTH rawdeltalen = rawentry[deltastart : deltastart + 8] - deltalen = struct.unpack("!Q", rawdeltalen)[0] + deltalen = struct.unpack(b"!Q", rawdeltalen)[0] delta = rawentry[deltastart + 8 : deltastart + 8 + deltalen] delta = self._decompress(delta) if getmeta: metastart = deltastart + 8 + deltalen - metalen = struct.unpack_from("!I", rawentry, metastart)[0] + metalen = struct.unpack_from(b"!I", rawentry, metastart)[0] rawmeta = rawentry[metastart + 4 : metastart + 4 + metalen] meta = shallowutil.parsepackmeta(rawmeta) @@ -217,7 +217,7 @@ return zlib.decompress(data) def add(self, name, node, data): - raise RuntimeError("cannot add to datapack (%s:%s)" % (name, node)) + raise RuntimeError(b"cannot add to datapack (%s:%s)" % (name, node)) def _find(self, node): params = self.params @@ -292,7 +292,7 @@ oldoffset = offset # <2 byte len> + - filenamelen = struct.unpack("!H", data[offset : offset + 2])[0] + filenamelen = struct.unpack(b"!H", data[offset : offset + 2])[0] offset += 2 filename = data[offset : offset + filenamelen] offset += filenamelen @@ -306,7 +306,7 @@ # <8 byte len> + rawdeltalen = data[offset : offset + 8] - deltalen = struct.unpack("!Q", rawdeltalen)[0] + deltalen = struct.unpack(b"!Q", rawdeltalen)[0] offset += 8 # TODO(augie): we should store a header that is the @@ -317,7 +317,7 @@ offset += deltalen # <4 byte len> + - metalen = struct.unpack_from("!I", data, offset)[0] + metalen = struct.unpack_from(b"!I", data, offset)[0] offset += 4 + metalen yield (filename, node, deltabase, uncompressedlen) @@ -415,9 +415,9 @@ def add(self, name, node, deltabasenode, delta, metadata=None): # metadata is a dict, ex. {METAKEYFLAG: flag} if len(name) > 2 ** 16: - raise RuntimeError(_("name too long %s") % name) + raise RuntimeError(_(b"name too long %s") % name) if len(node) != 20: - raise RuntimeError(_("node should be 20 bytes %s") % node) + raise RuntimeError(_(b"node should be 20 bytes %s") % node) if node in self.entries: # The revision has already been added @@ -426,20 +426,20 @@ # TODO: allow configurable compression delta = self._compress(delta) - rawdata = "".join( + rawdata = b"".join( ( - struct.pack("!H", len(name)), # unsigned 2 byte int + struct.pack(b"!H", len(name)), # unsigned 2 byte int name, node, deltabasenode, - struct.pack("!Q", len(delta)), # unsigned 8 byte int + struct.pack(b"!Q", len(delta)), # unsigned 8 byte int delta, ) ) # v1 support metadata rawmeta = shallowutil.buildpackmeta(metadata) - rawdata += struct.pack("!I", len(rawmeta)) # unsigned 4 byte + rawdata += struct.pack(b"!I", len(rawmeta)) # unsigned 4 byte rawdata += rawmeta offset = self.packfp.tell() @@ -455,7 +455,7 @@ (n, db, o, s) for n, (db, o, s) in self.entries.iteritems() ) - rawindex = "" + rawindex = b"" fmt = self.INDEXFORMAT for node, deltabase, offset, size in entries: if deltabase == nullid: diff --git a/hgext/remotefilelog/debugcommands.py b/hgext/remotefilelog/debugcommands.py --- a/hgext/remotefilelog/debugcommands.py +++ b/hgext/remotefilelog/debugcommands.py @@ -35,13 +35,13 @@ size, firstnode, mapping = parsefileblob(path, decompress) - ui.status(_("size: %d bytes\n") % size) - ui.status(_("path: %s \n") % path) - ui.status(_("key: %s \n") % (short(firstnode))) - ui.status(_("\n")) + ui.status(_(b"size: %d bytes\n") % size) + ui.status(_(b"path: %s \n") % path) + ui.status(_(b"key: %s \n") % (short(firstnode))) + ui.status(_(b"\n")) ui.status( - _("%12s => %12s %13s %13s %12s\n") - % ("node", "p1", "p2", "linknode", "copyfrom") + _(b"%12s => %12s %13s %13s %12s\n") + % (b"node", b"p1", b"p2", b"linknode", b"copyfrom") ) queue = [firstnode] @@ -49,7 +49,7 @@ node = queue.pop(0) p1, p2, linknode, copyfrom = mapping[node] ui.status( - _("%s => %s %s %s %s\n") + _(b"%s => %s %s %s %s\n") % (short(node), short(p1), short(p2), short(linknode), copyfrom) ) if p1 != nullid: @@ -61,21 +61,21 @@ def buildtemprevlog(repo, file): # get filename key filekey = nodemod.hex(hashlib.sha1(file).digest()) - filedir = os.path.join(repo.path, "store/data", filekey) + filedir = os.path.join(repo.path, b"store/data", filekey) # sort all entries based on linkrev fctxs = [] for filenode in os.listdir(filedir): - if "_old" not in filenode: + if b"_old" not in filenode: fctxs.append(repo.filectx(file, fileid=bin(filenode))) fctxs = sorted(fctxs, key=lambda x: x.linkrev()) # add to revlog - temppath = repo.sjoin("data/temprevlog.i") + temppath = repo.sjoin(b"data/temprevlog.i") if os.path.exists(temppath): os.remove(temppath) - r = filelog.filelog(repo.svfs, "temprevlog") + r = filelog.filelog(repo.svfs, b"temprevlog") class faket(object): def add(self, a, b, c): @@ -89,8 +89,8 @@ p = fctx.filelog().parents(fctx.filenode()) meta = {} if fctx.renamed(): - meta["copy"] = fctx.renamed()[0] - meta["copyrev"] = hex(fctx.renamed()[1]) + meta[b"copy"] = fctx.renamed()[0] + meta[b"copyrev"] = hex(fctx.renamed()[1]) r.add(fctx.data(), meta, t, fctx.linkrev(), p[0], p[1]) @@ -111,29 +111,29 @@ r = buildtemprevlog(repo, file_) # debugindex like normal - format = opts.get("format", 0) + format = opts.get(b"format", 0) if format not in (0, 1): - raise error.Abort(_("unknown format %d") % format) + raise error.Abort(_(b"unknown format %d") % format) generaldelta = r.version & revlog.FLAG_GENERALDELTA if generaldelta: - basehdr = " delta" + basehdr = b" delta" else: - basehdr = " base" + basehdr = b" base" if format == 0: ui.write( ( - " rev offset length " + basehdr + " linkrev" - " nodeid p1 p2\n" + b" rev offset length " + basehdr + b" linkrev" + b" nodeid p1 p2\n" ) ) elif format == 1: ui.write( ( - " rev flag offset length" - " size " + basehdr + " link p1 p2" - " nodeid\n" + b" rev flag offset length" + b" size " + basehdr + b" link p1 p2" + b" nodeid\n" ) ) @@ -149,7 +149,7 @@ except Exception: pp = [nullid, nullid] ui.write( - "% 6d % 9d % 7d % 6d % 7d %s %s %s\n" + b"% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % ( i, r.start(i), @@ -164,7 +164,7 @@ elif format == 1: pr = r.parentrevs(i) ui.write( - "% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" + b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % ( i, r.flags(i), @@ -187,14 +187,14 @@ r = buildtemprevlog(repo, os.path.basename(file_)[:-2]) - ui.write("digraph G {\n") + ui.write(b"digraph G {\n") for i in r: node = r.node(i) pp = r.parents(node) - ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i)) + ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i)) if pp[1] != nullid: - ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i)) - ui.write("}\n") + ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i)) + ui.write(b"}\n") def verifyremotefilelog(ui, path, **opts): @@ -202,7 +202,7 @@ for root, dirs, files in os.walk(path): for file in files: - if file == "repos": + if file == b"repos": continue filepath = os.path.join(root, file) size, firstnode, mapping = parsefileblob(filepath, decompress) @@ -210,10 +210,10 @@ if linknode == nullid: actualpath = os.path.relpath(root, path) key = fileserverclient.getcachekey( - "reponame", actualpath, file + b"reponame", actualpath, file ) ui.status( - "%s %s\n" % (key, os.path.relpath(filepath, path)) + b"%s %s\n" % (key, os.path.relpath(filepath, path)) ) @@ -222,7 +222,7 @@ def parsefileblob(path, decompress): - f = open(path, "rb") + f = open(path, b"rb") try: raw = f.read() finally: @@ -238,7 +238,7 @@ mapping = {} while start < len(raw): - divider = raw.index("\0", start + 80) + divider = raw.index(b"\0", start + 80) currentnode = raw[start : (start + 20)] if not firstnode: @@ -257,13 +257,13 @@ def debugdatapack(ui, *paths, **opts): for path in paths: - if ".data" in path: - path = path[: path.index(".data")] - ui.write("%s:\n" % path) + if b".data" in path: + path = path[: path.index(b".data")] + ui.write(b"%s:\n" % path) dpack = datapack.datapack(path) node = opts.get(r"node") if node: - deltachain = dpack.getdeltachain("", bin(node)) + deltachain = dpack.getdeltachain(b"", bin(node)) dumpdeltachain(ui, deltachain, **opts) return @@ -280,21 +280,21 @@ def printtotals(): if lastfilename is not None: - ui.write("\n") + ui.write(b"\n") if not totaldeltasize or not totalblobsize: return difference = totalblobsize - totaldeltasize - deltastr = "%0.1f%% %s" % ( + deltastr = b"%0.1f%% %s" % ( (100.0 * abs(difference) / totalblobsize), - ("smaller" if difference > 0 else "bigger"), + (b"smaller" if difference > 0 else b"bigger"), ) ui.write( - "Total:%s%s %s (%s)\n" + b"Total:%s%s %s (%s)\n" % ( - "".ljust(2 * hashlen - len("Total:")), - ("%d" % totaldeltasize).ljust(12), - ("%d" % totalblobsize).ljust(9), + b"".ljust(2 * hashlen - len(b"Total:")), + (b"%d" % totaldeltasize).ljust(12), + (b"%d" % totalblobsize).ljust(9), deltastr, ) ) @@ -305,20 +305,20 @@ for filename, node, deltabase, deltalen in dpack.iterentries(): bases[node] = deltabase if node in nodes: - ui.write(("Bad entry: %s appears twice\n" % short(node))) + ui.write((b"Bad entry: %s appears twice\n" % short(node))) failures += 1 nodes.add(node) if filename != lastfilename: printtotals() - name = "(empty name)" if filename == "" else filename - ui.write("%s:\n" % name) + name = b"(empty name)" if filename == b"" else filename + ui.write(b"%s:\n" % name) ui.write( - "%s%s%s%s\n" + b"%s%s%s%s\n" % ( - "Node".ljust(hashlen), - "Delta Base".ljust(hashlen), - "Delta Length".ljust(14), - "Blob Size".ljust(9), + b"Node".ljust(hashlen), + b"Delta Base".ljust(hashlen), + b"Delta Length".ljust(14), + b"Blob Size".ljust(9), ) ) lastfilename = filename @@ -332,13 +332,13 @@ totaldeltasize += deltalen totalblobsize += blobsize else: - blobsize = "(missing)" + blobsize = b"(missing)" ui.write( - "%s %s %s%s\n" + b"%s %s %s%s\n" % ( hashformatter(node), hashformatter(deltabase), - ("%d" % deltalen).ljust(14), + (b"%d" % deltalen).ljust(14), pycompat.bytestr(blobsize), ) ) @@ -348,7 +348,7 @@ failures += _sanitycheck(ui, set(nodes), bases) if failures > 1: - ui.warn(("%d failures\n" % failures)) + ui.warn((b"%d failures\n" % failures)) return 1 @@ -370,7 +370,7 @@ if deltabase not in nodes: ui.warn( ( - "Bad entry: %s has an unknown deltabase (%s)\n" + b"Bad entry: %s has an unknown deltabase (%s)\n" % (short(node), short(deltabase)) ) ) @@ -380,7 +380,7 @@ if deltabase in seen: ui.warn( ( - "Bad entry: %s has a cycle (at %s)\n" + b"Bad entry: %s has a cycle (at %s)\n" % (short(node), short(deltabase)) ) ) @@ -403,20 +403,20 @@ lastfilename = None for filename, node, filename, deltabasenode, delta in deltachain: if filename != lastfilename: - ui.write("\n%s\n" % filename) + ui.write(b"\n%s\n" % filename) lastfilename = filename ui.write( - "%s %s %s %s\n" + b"%s %s %s %s\n" % ( - "Node".ljust(hashlen), - "Delta Base".ljust(hashlen), - "Delta SHA1".ljust(hashlen), - "Delta Length".ljust(6), + b"Node".ljust(hashlen), + b"Delta Base".ljust(hashlen), + b"Delta SHA1".ljust(hashlen), + b"Delta Length".ljust(6), ) ) ui.write( - "%s %s %s %d\n" + b"%s %s %s %d\n" % ( hashformatter(node), hashformatter(deltabasenode), @@ -427,28 +427,28 @@ def debughistorypack(ui, path): - if ".hist" in path: - path = path[: path.index(".hist")] + if b".hist" in path: + path = path[: path.index(b".hist")] hpack = historypack.historypack(path) lastfilename = None for entry in hpack.iterentries(): filename, node, p1node, p2node, linknode, copyfrom = entry if filename != lastfilename: - ui.write("\n%s\n" % filename) + ui.write(b"\n%s\n" % filename) ui.write( - "%s%s%s%s%s\n" + b"%s%s%s%s%s\n" % ( - "Node".ljust(14), - "P1 Node".ljust(14), - "P2 Node".ljust(14), - "Link Node".ljust(14), - "Copy From", + b"Node".ljust(14), + b"P1 Node".ljust(14), + b"P2 Node".ljust(14), + b"Link Node".ljust(14), + b"Copy From", ) ) lastfilename = filename ui.write( - "%s %s %s %s %s\n" + b"%s %s %s %s %s\n" % ( short(node), short(p1node), @@ -460,17 +460,17 @@ def debugwaitonrepack(repo): - with lockmod.lock(repack.repacklockvfs(repo), "repacklock", timeout=-1): + with lockmod.lock(repack.repacklockvfs(repo), b"repacklock", timeout=-1): return def debugwaitonprefetch(repo): with repo._lock( repo.svfs, - "prefetchlock", + b"prefetchlock", True, None, None, - _("prefetching in %s") % repo.origroot, + _(b"prefetching in %s") % repo.origroot, ): pass diff --git a/hgext/remotefilelog/fileserverclient.py b/hgext/remotefilelog/fileserverclient.py --- a/hgext/remotefilelog/fileserverclient.py +++ b/hgext/remotefilelog/fileserverclient.py @@ -58,38 +58,38 @@ class remotefilepeer(peer.__class__): @wireprotov1peer.batchable def x_rfl_getfile(self, file, node): - if not self.capable("x_rfl_getfile"): + if not self.capable(b"x_rfl_getfile"): raise error.Abort( - "configured remotefile server does not support getfile" + b"configured remotefile server does not support getfile" ) f = wireprotov1peer.future() - yield {"file": file, "node": node}, f - code, data = f.value.split("\0", 1) + yield {b"file": file, b"node": node}, f + code, data = f.value.split(b"\0", 1) if int(code): raise error.LookupError(file, node, data) yield data @wireprotov1peer.batchable def x_rfl_getflogheads(self, path): - if not self.capable("x_rfl_getflogheads"): + if not self.capable(b"x_rfl_getflogheads"): raise error.Abort( - "configured remotefile server does not " - "support getflogheads" + b"configured remotefile server does not " + b"support getflogheads" ) f = wireprotov1peer.future() - yield {"path": path}, f - heads = f.value.split("\n") if f.value else [] + yield {b"path": path}, f + heads = f.value.split(b"\n") if f.value else [] yield heads def _updatecallstreamopts(self, command, opts): - if command != "getbundle": + if command != b"getbundle": return if ( constants.NETWORK_CAP_LEGACY_SSH_GETFILES not in self.capabilities() ): return - if not util.safehasattr(self, "_localrepo"): + if not util.safehasattr(self, b"_localrepo"): return if ( constants.SHALLOWREPO_REQUIREMENT @@ -97,7 +97,7 @@ ): return - bundlecaps = opts.get("bundlecaps") + bundlecaps = opts.get(b"bundlecaps") if bundlecaps: bundlecaps = [bundlecaps] else: @@ -112,14 +112,14 @@ # do this more cleanly. bundlecaps.append(constants.BUNDLE2_CAPABLITY) if self._localrepo.includepattern: - patterns = "\0".join(self._localrepo.includepattern) - includecap = "includepattern=" + patterns + patterns = b"\0".join(self._localrepo.includepattern) + includecap = b"includepattern=" + patterns bundlecaps.append(includecap) if self._localrepo.excludepattern: - patterns = "\0".join(self._localrepo.excludepattern) - excludecap = "excludepattern=" + patterns + patterns = b"\0".join(self._localrepo.excludepattern) + excludecap = b"excludepattern=" + patterns bundlecaps.append(excludecap) - opts["bundlecaps"] = ",".join(bundlecaps) + opts[b"bundlecaps"] = b",".join(bundlecaps) def _sendrequest(self, command, args, **opts): self._updatecallstreamopts(command, args) @@ -129,7 +129,7 @@ def _callstream(self, command, **opts): supertype = super(remotefilepeer, self) - if not util.safehasattr(supertype, "_sendrequest"): + if not util.safehasattr(supertype, b"_sendrequest"): self._updatecallstreamopts(command, pycompat.byteskwargs(opts)) return super(remotefilepeer, self)._callstream(command, **opts) @@ -149,7 +149,7 @@ def connect(self, cachecommand): if self.pipeo: - raise error.Abort(_("cache connection already open")) + raise error.Abort(_(b"cache connection already open")) self.pipei, self.pipeo, self.pipee, self.subprocess = procutil.popen4( cachecommand ) @@ -164,7 +164,7 @@ if self.connected: try: - self.pipei.write("exit\n") + self.pipei.write(b"exit\n") except Exception: pass tryclose(self.pipei) @@ -223,7 +223,7 @@ for m in missed: futures.append( e.callcommand( - "x_rfl_getfile", {"file": idmap[m], "node": m[-40:]} + b"x_rfl_getfile", {b"file": idmap[m], b"node": m[-40:]} ) ) @@ -232,14 +232,14 @@ futures[i] = None # release memory file_ = idmap[m] node = m[-40:] - receivemissing(io.BytesIO("%d\n%s" % (len(r), r)), file_, node) + receivemissing(io.BytesIO(b"%d\n%s" % (len(r), r)), file_, node) progresstick() def _getfiles_optimistic( remote, receivemissing, progresstick, missed, idmap, step ): - remote._callstream("x_rfl_getfiles") + remote._callstream(b"x_rfl_getfiles") i = 0 pipeo = remote._pipeo pipei = remote._pipei @@ -252,7 +252,7 @@ # issue new request versionid = missingid[-40:] file = idmap[missingid] - sshrequest = "%s%s\n" % (versionid, file) + sshrequest = b"%s%s\n" % (versionid, file) pipeo.write(sshrequest) pipeo.flush() @@ -264,14 +264,14 @@ progresstick() # End the command - pipeo.write("\n") + pipeo.write(b"\n") pipeo.flush() def _getfiles_threaded( remote, receivemissing, progresstick, missed, idmap, step ): - remote._callstream("getfiles") + remote._callstream(b"getfiles") pipeo = remote._pipeo pipei = remote._pipei @@ -279,7 +279,7 @@ for missingid in missed: versionid = missingid[-40:] file = idmap[missingid] - sshrequest = "%s%s\n" % (versionid, file) + sshrequest = b"%s%s\n" % (versionid, file) pipeo.write(sshrequest) pipeo.flush() @@ -295,7 +295,7 @@ writerthread.join() # End the command - pipeo.write("\n") + pipeo.write(b"\n") pipeo.flush() @@ -307,17 +307,17 @@ ui = repo.ui self.repo = repo self.ui = ui - self.cacheprocess = ui.config("remotefilelog", "cacheprocess") + self.cacheprocess = ui.config(b"remotefilelog", b"cacheprocess") if self.cacheprocess: self.cacheprocess = util.expandpath(self.cacheprocess) # This option causes remotefilelog to pass the full file path to the # cacheprocess instead of a hashed key. self.cacheprocesspasspath = ui.configbool( - "remotefilelog", "cacheprocess.includepath" + b"remotefilelog", b"cacheprocess.includepath" ) - self.debugoutput = ui.configbool("remotefilelog", "debug") + self.debugoutput = ui.configbool(b"remotefilelog", b"debug") self.remotecache = cacheconnection() @@ -343,19 +343,19 @@ repo = self.repo total = len(fileids) - request = "get\n%d\n" % total + request = b"get\n%d\n" % total idmap = {} reponame = repo.name for file, id in fileids: fullid = getcachekey(reponame, file, id) if self.cacheprocesspasspath: - request += file + "\0" - request += fullid + "\n" + request += file + b"\0" + request += fullid + b"\n" idmap[fullid] = file cache.request(request) - progress = self.ui.makeprogress(_("downloading"), total=total) + progress = self.ui.makeprogress(_(b"downloading"), total=total) progress.update(0) missed = [] @@ -368,16 +368,16 @@ missed.append(missingid) self.ui.warn( _( - "warning: cache connection closed early - " - + "falling back to server\n" + b"warning: cache connection closed early - " + + b"falling back to server\n" ) ) break - if missingid == "0": + if missingid == b"0": break - if missingid.startswith("_hits_"): + if missingid.startswith(b"_hits_"): # receive progress reports - parts = missingid.split("_") + parts = missingid.split(b"_") progress.increment(int(parts[2])) continue @@ -389,8 +389,8 @@ fromcache = total - len(missed) progress.update(fromcache, total=total) self.ui.log( - "remotefilelog", - "remote cache hit rate is %r of %r\n", + b"remotefilelog", + b"remote cache hit rate is %r of %r\n", fromcache, total, hit=fromcache, @@ -414,15 +414,15 @@ ): if not isinstance(remote, _sshv1peer): raise error.Abort( - "remotefilelog requires ssh " "servers" + b"remotefilelog requires ssh " b"servers" ) step = self.ui.configint( - "remotefilelog", "getfilesstep" + b"remotefilelog", b"getfilesstep" ) getfilestype = self.ui.config( - "remotefilelog", "getfilestype" + b"remotefilelog", b"getfilestype" ) - if getfilestype == "threaded": + if getfilestype == b"threaded": _getfiles = _getfiles_threaded else: _getfiles = _getfiles_optimistic @@ -434,13 +434,13 @@ idmap, step, ) - elif remote.capable("x_rfl_getfile"): - if remote.capable("batch"): + elif remote.capable(b"x_rfl_getfile"): + if remote.capable(b"batch"): batchdefault = 100 else: batchdefault = 10 batchsize = self.ui.configint( - "remotefilelog", "batchsize", batchdefault + b"remotefilelog", b"batchsize", batchdefault ) self.ui.debug( b"requesting %d files from " @@ -456,20 +456,20 @@ ) else: raise error.Abort( - "configured remotefilelog server" - " does not support remotefilelog" + b"configured remotefilelog server" + b" does not support remotefilelog" ) self.ui.log( - "remotefilefetchlog", - "Success\n", + b"remotefilefetchlog", + b"Success\n", fetched_files=progress.pos - fromcache, total_to_fetch=total - fromcache, ) except Exception: self.ui.log( - "remotefilefetchlog", - "Fail\n", + b"remotefilefetchlog", + b"Fail\n", fetched_files=progress.pos - fromcache, total_to_fetch=total - fromcache, ) @@ -477,7 +477,7 @@ finally: self.ui.verbose = verbose # send to memcache - request = "set\n%d\n%s\n" % (len(missed), "\n".join(missed)) + request = b"set\n%d\n%s\n" % (len(missed), b"\n".join(missed)) cache.request(request) progress.complete() @@ -491,15 +491,15 @@ line = pipe.readline()[:-1] if not line: raise error.ResponseError( - _("error downloading file contents:"), - _("connection closed early"), + _(b"error downloading file contents:"), + _(b"connection closed early"), ) size = int(line) data = pipe.read(size) if len(data) != size: raise error.ResponseError( - _("error downloading file contents:"), - _("only received %s of %s bytes") % (len(data), size), + _(b"error downloading file contents:"), + _(b"only received %s of %s bytes") % (len(data), size), ) self.writedata.addremotefilelognode( @@ -508,7 +508,7 @@ def connect(self): if self.cacheprocess: - cmd = "%s %s" % (self.cacheprocess, self.writedata._path) + cmd = b"%s %s" % (self.cacheprocess, self.writedata._path) self.remotecache.connect(cmd) else: # If no cache process is specified, we fake one that always @@ -524,11 +524,11 @@ pass def request(self, value, flush=True): - lines = value.split("\n") - if lines[0] != "get": + lines = value.split(b"\n") + if lines[0] != b"get": return self.missingids = lines[2:-1] - self.missingids.append("0") + self.missingids.append(b"0") def receiveline(self): if len(self.missingids) > 0: @@ -540,8 +540,8 @@ def close(self): if fetches: msg = ( - "%d files fetched over %d fetches - " - + "(%d misses, %0.2f%% hit ratio) over %0.2fs\n" + b"%d files fetched over %d fetches - " + + b"(%d misses, %0.2f%% hit ratio) over %0.2fs\n" ) % ( fetched, fetches, @@ -552,8 +552,8 @@ if self.debugoutput: self.ui.warn(msg) self.ui.log( - "remotefilelog.prefetch", - msg.replace("%", "%%"), + b"remotefilelog.prefetch", + msg.replace(b"%", b"%%"), remotefilelogfetched=fetched, remotefilelogfetches=fetches, remotefilelogfetchmisses=fetchmisses, @@ -576,7 +576,7 @@ # - workingctx produces ids with length 42, # which we skip since they aren't in any cache if ( - file == ".hgtags" + file == b".hgtags" or len(id) == 42 or not repo.shallowmatch(file) ): @@ -605,10 +605,10 @@ missingids = [(f, id) for f, id in missingids if id != nullid] repo.ui.develwarn( ( - "remotefilelog not fetching %d null revs" - " - this is likely hiding bugs" % nullids + b"remotefilelog not fetching %d null revs" + b" - this is likely hiding bugs" % nullids ), - config="remotefilelog-ext", + config=b"remotefilelog-ext", ) if missingids: global fetches, fetched, fetchcost @@ -619,10 +619,10 @@ if fetches >= 15 and fetches < 18: if fetches == 15: fetchwarning = self.ui.config( - "remotefilelog", "fetchwarning" + b"remotefilelog", b"fetchwarning" ) if fetchwarning: - self.ui.warn(fetchwarning + "\n") + self.ui.warn(fetchwarning + b"\n") self.logstacktrace() missingids = [(file, hex(id)) for file, id in sorted(missingids)] fetched += len(missingids) @@ -630,14 +630,14 @@ missingids = self.request(missingids) if missingids: raise error.Abort( - _("unable to download %d files") % len(missingids) + _(b"unable to download %d files") % len(missingids) ) fetchcost += time.time() - start self._lfsprefetch(fileids) def _lfsprefetch(self, fileids): if not _lfsmod or not util.safehasattr( - self.repo.svfs, "lfslocalblobstore" + self.repo.svfs, b"lfslocalblobstore" ): return if not _lfsmod.wrapper.candownload(self.repo): @@ -661,7 +661,7 @@ import traceback self.ui.log( - "remotefilelog", - "excess remotefilelog fetching:\n%s\n", - "".join(traceback.format_stack()), + b"remotefilelog", + b"excess remotefilelog fetching:\n%s\n", + b"".join(traceback.format_stack()), ) diff --git a/hgext/remotefilelog/historypack.py b/hgext/remotefilelog/historypack.py --- a/hgext/remotefilelog/historypack.py +++ b/hgext/remotefilelog/historypack.py @@ -15,21 +15,21 @@ ) # (filename hash, offset, size) -INDEXFORMAT2 = "!20sQQII" +INDEXFORMAT2 = b"!20sQQII" INDEXENTRYLENGTH2 = struct.calcsize(INDEXFORMAT2) NODELENGTH = 20 -NODEINDEXFORMAT = "!20sQ" +NODEINDEXFORMAT = b"!20sQ" NODEINDEXENTRYLENGTH = struct.calcsize(NODEINDEXFORMAT) # (node, p1, p2, linknode) -PACKFORMAT = "!20s20s20s20sH" +PACKFORMAT = b"!20s20s20s20sH" PACKENTRYLENGTH = 82 ENTRYCOUNTSIZE = 4 -INDEXSUFFIX = ".histidx" -PACKSUFFIX = ".histpack" +INDEXSUFFIX = b".histidx" +PACKSUFFIX = b".histpack" ANC_NODE = 0 ANC_P1NODE = 1 @@ -77,7 +77,7 @@ def add(self, filename, node, p1, p2, linknode, copyfrom): raise RuntimeError( - "cannot add to historypackstore (%s:%s)" % (filename, hex(node)) + b"cannot add to historypackstore (%s:%s)" % (filename, hex(node)) ) @@ -168,7 +168,7 @@ def add(self, filename, node, p1, p2, linknode, copyfrom): raise RuntimeError( - "cannot add to historypack (%s:%s)" % (filename, hex(node)) + b"cannot add to historypack (%s:%s)" % (filename, hex(node)) ) def _findnode(self, name, node): @@ -193,7 +193,7 @@ # with the copyfrom string. return entry[:4] + (copyfrom,) - raise KeyError("unable to find history for %s:%s" % (name, hex(node))) + raise KeyError(b"unable to find history for %s:%s" % (name, hex(node))) def _findsection(self, name): params = self.params @@ -222,19 +222,19 @@ rawnamelen = self._index[ nodeindexoffset : nodeindexoffset + constants.FILENAMESIZE ] - actualnamelen = struct.unpack("!H", rawnamelen)[0] + actualnamelen = struct.unpack(b"!H", rawnamelen)[0] nodeindexoffset += constants.FILENAMESIZE actualname = self._index[ nodeindexoffset : nodeindexoffset + actualnamelen ] if actualname != name: raise KeyError( - "found file name %s when looking for %s" % (actualname, name) + b"found file name %s when looking for %s" % (actualname, name) ) nodeindexoffset += actualnamelen filenamelength = struct.unpack( - "!H", self._data[offset : offset + constants.FILENAMESIZE] + b"!H", self._data[offset : offset + constants.FILENAMESIZE] )[0] offset += constants.FILENAMESIZE @@ -243,7 +243,7 @@ if name != actualname: raise KeyError( - "found file name %s when looking for %s" % (actualname, name) + b"found file name %s when looking for %s" % (actualname, name) ) # Skip entry list size @@ -311,14 +311,14 @@ data = self._data # <2 byte len> + filenamelen = struct.unpack( - "!H", data[offset : offset + constants.FILENAMESIZE] + b"!H", data[offset : offset + constants.FILENAMESIZE] )[0] offset += constants.FILENAMESIZE filename = data[offset : offset + filenamelen] offset += filenamelen revcount = struct.unpack( - "!I", data[offset : offset + ENTRYCOUNTSIZE] + b"!I", data[offset : offset + ENTRYCOUNTSIZE] )[0] offset += ENTRYCOUNTSIZE @@ -440,8 +440,8 @@ self.NODEINDEXENTRYLENGTH = NODEINDEXENTRYLENGTH def add(self, filename, node, p1, p2, linknode, copyfrom): - copyfrom = copyfrom or "" - copyfromlen = struct.pack("!H", len(copyfrom)) + copyfrom = copyfrom or b"" + copyfromlen = struct.pack(b"!H", len(copyfrom)) self.fileentries.setdefault(filename, []).append( (node, p1, p2, linknode, copyfromlen, copyfrom) ) @@ -471,11 +471,11 @@ # Write the file section header self.writeraw( - "%s%s%s" + b"%s%s%s" % ( - struct.pack("!H", len(filename)), + struct.pack(b"!H", len(filename)), filename, - struct.pack("!I", len(sortednodes)), + struct.pack(b"!I", len(sortednodes)), ) ) @@ -488,11 +488,11 @@ offset = sectionstart + sectionlen for node in sortednodes: locations[node] = offset - raw = "%s%s%s%s%s%s" % entrymap[node] + raw = b"%s%s%s%s%s%s" % entrymap[node] rawstrings.append(raw) offset += len(raw) - rawdata = "".join(rawstrings) + rawdata = b"".join(rawstrings) sectionlen += len(rawdata) self.writeraw(rawdata) @@ -523,7 +523,7 @@ files = sorted(files) # node index is after file index size, file index, and node index size - indexlensize = struct.calcsize("!Q") + indexlensize = struct.calcsize(b"!Q") nodeindexoffset = ( indexoffset + indexlensize @@ -564,7 +564,9 @@ fileindexentries.append(rawentry) - nodecountraw = struct.pack("!Q", nodecount) + nodecountraw = struct.pack(b"!Q", nodecount) return ( - "".join(fileindexentries) + nodecountraw + "".join(nodeindexentries) + b"".join(fileindexentries) + + nodecountraw + + b"".join(nodeindexentries) ) diff --git a/hgext/remotefilelog/metadatastore.py b/hgext/remotefilelog/metadatastore.py --- a/hgext/remotefilelog/metadatastore.py +++ b/hgext/remotefilelog/metadatastore.py @@ -99,7 +99,7 @@ def add(self, name, node, data): raise RuntimeError( - "cannot add content only to remotefilelog " "contentstore" + b"cannot add content only to remotefilelog " b"contentstore" ) def getmissing(self, keys): @@ -136,7 +136,7 @@ def add(self, name, node, parents, linknode): raise RuntimeError( - "cannot add metadata only to remotefilelog " "metadatastore" + b"cannot add metadata only to remotefilelog " b"metadatastore" ) @@ -155,7 +155,7 @@ return self.getancestors(name, node)[node] def add(self, name, node, data): - raise RuntimeError("cannot add to a remote store") + raise RuntimeError(b"cannot add to a remote store") def getmissing(self, keys): return keys diff --git a/hgext/remotefilelog/remotefilectx.py b/hgext/remotefilelog/remotefilectx.py --- a/hgext/remotefilelog/remotefilectx.py +++ b/hgext/remotefilelog/remotefilectx.py @@ -246,14 +246,14 @@ return linknode commonlogkwargs = { - r"revs": " ".join([hex(cl.node(rev)) for rev in revs]), + r"revs": b" ".join([hex(cl.node(rev)) for rev in revs]), r"fnode": hex(fnode), r"filepath": path, r"user": shallowutil.getusername(repo.ui), r"reponame": shallowutil.getreponame(repo.ui), } - repo.ui.log("linkrevfixup", "adjusting linknode\n", **commonlogkwargs) + repo.ui.log(b"linkrevfixup", b"adjusting linknode\n", **commonlogkwargs) pc = repo._phasecache seenpublic = False @@ -322,7 +322,7 @@ # the slow path is used too much. One promising possibility is using # obsolescence markers to find a more-likely-correct linkrev. - logmsg = "" + logmsg = b"" start = time.time() try: repo.fileservice.prefetch([(path, hex(fnode))], force=True) @@ -333,18 +333,18 @@ self._ancestormap = None linknode = self.ancestormap()[fnode][2] # 2 is linknode if self._verifylinknode(revs, linknode): - logmsg = "remotefilelog prefetching succeeded" + logmsg = b"remotefilelog prefetching succeeded" return linknode - logmsg = "remotefilelog prefetching not found" + logmsg = b"remotefilelog prefetching not found" return None except Exception as e: - logmsg = "remotefilelog prefetching failed (%s)" % e + logmsg = b"remotefilelog prefetching failed (%s)" % e return None finally: elapsed = time.time() - start repo.ui.log( - "linkrevfixup", - logmsg + "\n", + b"linkrevfixup", + logmsg + b"\n", elapsed=elapsed * 1000, **commonlogkwargs ) @@ -473,7 +473,8 @@ queue.append(parent) self._repo.ui.debug( - "remotefilelog: prefetching %d files " "for annotate\n" % len(fetch) + b"remotefilelog: prefetching %d files " + b"for annotate\n" % len(fetch) ) if fetch: self._repo.fileservice.prefetch(fetch) @@ -518,7 +519,7 @@ p2ctx = self._repo.filectx(p2[0], fileid=p2[1]) m.update(p2ctx.filelog().ancestormap(p2[1])) - copyfrom = "" + copyfrom = b"" if renamed: copyfrom = renamed[0] m[None] = (p1[1], p2[1], nullid, copyfrom) diff --git a/hgext/remotefilelog/remotefilelog.py b/hgext/remotefilelog/remotefilelog.py --- a/hgext/remotefilelog/remotefilelog.py +++ b/hgext/remotefilelog/remotefilelog.py @@ -67,15 +67,15 @@ def read(self, node): """returns the file contents at this node""" t = self.revision(node) - if not t.startswith("\1\n"): + if not t.startswith(b"\1\n"): return t - s = t.index("\1\n", 2) + s = t.index(b"\1\n", 2) return t[s + 2 :] def add(self, text, meta, transaction, linknode, p1=None, p2=None): # hash with the metadata, like in vanilla filelogs hashtext = shallowutil.createrevlogtext( - text, meta.get("copy"), meta.get("copyrev") + text, meta.get(b"copy"), meta.get(b"copyrev") ) node = storageutil.hashrevisionsha1(hashtext, p1, p2) return self.addrevision( @@ -85,15 +85,15 @@ def _createfileblob(self, text, meta, flags, p1, p2, node, linknode): # text passed to "_createfileblob" does not include filelog metadata header = shallowutil.buildfileblobheader(len(text), flags) - data = "%s\0%s" % (header, text) + data = b"%s\0%s" % (header, text) realp1 = p1 - copyfrom = "" - if meta and "copy" in meta: - copyfrom = meta["copy"] - realp1 = bin(meta["copyrev"]) + copyfrom = b"" + if meta and b"copy" in meta: + copyfrom = meta[b"copy"] + realp1 = bin(meta[b"copyrev"]) - data += "%s%s%s%s%s\0" % (node, realp1, p2, linknode, copyfrom) + data += b"%s%s%s%s%s\0" % (node, realp1, p2, linknode, copyfrom) visited = set() @@ -112,15 +112,15 @@ queue.append(p2) visited.add(p2) - ancestortext = "" + ancestortext = b"" # add the ancestors in topological order while queue: c = queue.pop(0) pa1, pa2, ancestorlinknode, pacopyfrom = pancestors[c] - pacopyfrom = pacopyfrom or "" - ancestortext += "%s%s%s%s%s\0" % ( + pacopyfrom = pacopyfrom or b"" + ancestortext += b"%s%s%s%s%s\0" % ( c, pa1, pa2, @@ -249,14 +249,14 @@ __bool__ = __nonzero__ def __len__(self): - if self.filename == ".hgtags": + if self.filename == b".hgtags": # The length of .hgtags is used to fast path tag checking. # remotefilelog doesn't support .hgtags since the entire .hgtags # history is needed. Use the excludepattern setting to make # .hgtags a normal filelog. return 0 - raise RuntimeError("len not supported") + raise RuntimeError(b"len not supported") def empty(self): return False @@ -264,7 +264,7 @@ def flags(self, node): if isinstance(node, int): raise error.ProgrammingError( - "remotefilelog does not accept integer rev for flags" + b"remotefilelog does not accept integer rev for flags" ) store = self.repo.contentstore return store.getmeta(self.filename, node).get(constants.METAKEYFLAG, 0) @@ -338,7 +338,7 @@ node = bin(node) if len(node) != 20: raise error.LookupError( - node, self.filename, _("invalid lookup input") + node, self.filename, _(b"invalid lookup input") ) return node @@ -351,17 +351,17 @@ # This is a hack. if isinstance(rev, int): raise error.ProgrammingError( - "remotefilelog does not convert integer rev to node" + b"remotefilelog does not convert integer rev to node" ) return rev def _processflags(self, text, flags, operation, raw=False): """deprecated entry point to access flag processors""" - msg = "_processflag(...) use the specialized variant" - util.nouideprecwarn(msg, "5.2", stacklevel=2) + msg = b"_processflag(...) use the specialized variant" + util.nouideprecwarn(msg, b"5.2", stacklevel=2) if raw: return text, flagutil.processflagsraw(self, text, flags) - elif operation == "read": + elif operation == b"read": return flagutil.processflagsread(self, text, flags) else: # write operation return flagutil.processflagswrite(self, text, flags) @@ -373,10 +373,10 @@ hg clients. """ if node == nullid: - return "" + return b"" if len(node) != 20: raise error.LookupError( - node, self.filename, _("invalid revision input") + node, self.filename, _(b"invalid revision input") ) if node == wdirid or node in wdirfilenodeids: raise error.WdirUnsupported @@ -418,7 +418,7 @@ except KeyError: pass - raise error.LookupError(id, self.filename, _("no node")) + raise error.LookupError(id, self.filename, _(b"no node")) def ancestormap(self, node): return self.repo.metadatastore.getancestors(self.filename, node) diff --git a/hgext/remotefilelog/remotefilelogserver.py b/hgext/remotefilelog/remotefilelogserver.py --- a/hgext/remotefilelog/remotefilelogserver.py +++ b/hgext/remotefilelog/remotefilelogserver.py @@ -51,15 +51,15 @@ includepattern = None excludepattern = None for cap in self._bundlecaps or []: - if cap.startswith("includepattern="): - includepattern = cap[len("includepattern=") :].split("\0") - elif cap.startswith("excludepattern="): - excludepattern = cap[len("excludepattern=") :].split("\0") + if cap.startswith(b"includepattern="): + includepattern = cap[len(b"includepattern=") :].split(b"\0") + elif cap.startswith(b"excludepattern="): + excludepattern = cap[len(b"excludepattern=") :].split(b"\0") m = match.always() if includepattern or excludepattern: m = match.match( - repo.root, "", None, includepattern, excludepattern + repo.root, b"", None, includepattern, excludepattern ) changedfiles = list([f for f in changedfiles if not m(f)]) @@ -68,7 +68,7 @@ ) extensions.wrapfunction( - changegroup.cgpacker, "generatefiles", generatefiles + changegroup.cgpacker, b"generatefiles", generatefiles ) @@ -85,13 +85,13 @@ # support file content requests wireprotov1server.wireprotocommand( - "x_rfl_getflogheads", "path", permission="pull" + b"x_rfl_getflogheads", b"path", permission=b"pull" )(getflogheads) - wireprotov1server.wireprotocommand("x_rfl_getfiles", "", permission="pull")( - getfiles - ) wireprotov1server.wireprotocommand( - "x_rfl_getfile", "file node", permission="pull" + b"x_rfl_getfiles", b"", permission=b"pull" + )(getfiles) + wireprotov1server.wireprotocommand( + b"x_rfl_getfile", b"file node", permission=b"pull" )(getfile) class streamstate(object): @@ -104,12 +104,12 @@ def stream_out_shallow(repo, proto, other): includepattern = None excludepattern = None - raw = other.get("includepattern") + raw = other.get(b"includepattern") if raw: - includepattern = raw.split("\0") - raw = other.get("excludepattern") + includepattern = raw.split(b"\0") + raw = other.get(b"excludepattern") if raw: - excludepattern = raw.split("\0") + excludepattern = raw.split(b"\0") oldshallow = state.shallowremote oldmatch = state.match @@ -117,10 +117,10 @@ try: state.shallowremote = True state.match = match.always() - state.noflatmf = other.get("noflatmanifest") == "True" + state.noflatmf = other.get(b"noflatmanifest") == b"True" if includepattern or excludepattern: state.match = match.match( - repo.root, "", None, includepattern, excludepattern + repo.root, b"", None, includepattern, excludepattern ) streamres = wireprotov1server.stream(repo, proto) @@ -141,7 +141,10 @@ state.match = oldmatch state.noflatmf = oldnoflatmf - wireprotov1server.commands["stream_out_shallow"] = (stream_out_shallow, "*") + wireprotov1server.commands[b"stream_out_shallow"] = ( + stream_out_shallow, + b"*", + ) # don't clone filelogs to shallow clients def _walkstreamfiles(orig, repo, matcher=None): @@ -150,22 +153,24 @@ if shallowutil.isenabled(repo): striplen = len(repo.store.path) + 1 readdir = repo.store.rawvfs.readdir - visit = [os.path.join(repo.store.path, "data")] + visit = [os.path.join(repo.store.path, b"data")] while visit: p = visit.pop() for f, kind, st in readdir(p, stat=True): - fp = p + "/" + f + fp = p + b"/" + f if kind == stat.S_IFREG: - if not fp.endswith(".i") and not fp.endswith(".d"): + if not fp.endswith(b".i") and not fp.endswith( + b".d" + ): n = util.pconvert(fp[striplen:]) yield (store.decodedir(n), n, st.st_size) if kind == stat.S_IFDIR: visit.append(fp) - if "treemanifest" in repo.requirements: + if b"treemanifest" in repo.requirements: for (u, e, s) in repo.store.datafiles(): - if u.startswith("meta/") and ( - u.endswith(".i") or u.endswith(".d") + if u.startswith(b"meta/") and ( + u.endswith(b".i") or u.endswith(b".d") ): yield (u, e, s) @@ -178,7 +183,7 @@ yield (u, e, s) for x in repo.store.topfiles(): - if state.noflatmf and x[0][:11] == "00manifest.": + if state.noflatmf and x[0][:11] == b"00manifest.": continue yield x @@ -187,47 +192,47 @@ # since it would require fetching every version of every # file in order to create the revlogs. raise error.Abort( - _("Cannot clone from a shallow repo " "to a full repo.") + _(b"Cannot clone from a shallow repo " b"to a full repo.") ) else: for x in orig(repo, matcher): yield x - extensions.wrapfunction(streamclone, "_walkstreamfiles", _walkstreamfiles) + extensions.wrapfunction(streamclone, b"_walkstreamfiles", _walkstreamfiles) # expose remotefilelog capabilities def _capabilities(orig, repo, proto): caps = orig(repo, proto) if shallowutil.isenabled(repo) or ui.configbool( - "remotefilelog", "server" + b"remotefilelog", b"server" ): if isinstance(proto, _sshv1server): # legacy getfiles method which only works over ssh caps.append(constants.NETWORK_CAP_LEGACY_SSH_GETFILES) - caps.append("x_rfl_getflogheads") - caps.append("x_rfl_getfile") + caps.append(b"x_rfl_getflogheads") + caps.append(b"x_rfl_getfile") return caps - extensions.wrapfunction(wireprotov1server, "_capabilities", _capabilities) + extensions.wrapfunction(wireprotov1server, b"_capabilities", _capabilities) def _adjustlinkrev(orig, self, *args, **kwargs): # When generating file blobs, taking the real path is too slow on large # repos, so force it to just return the linkrev directly. repo = self._repo - if util.safehasattr(repo, "forcelinkrev") and repo.forcelinkrev: + if util.safehasattr(repo, b"forcelinkrev") and repo.forcelinkrev: return self._filelog.linkrev(self._filelog.rev(self._filenode)) return orig(self, *args, **kwargs) extensions.wrapfunction( - context.basefilectx, "_adjustlinkrev", _adjustlinkrev + context.basefilectx, b"_adjustlinkrev", _adjustlinkrev ) def _iscmd(orig, cmd): - if cmd == "x_rfl_getfiles": + if cmd == b"x_rfl_getfiles": return False return orig(cmd) - extensions.wrapfunction(wireprotoserver, "iscmd", _iscmd) + extensions.wrapfunction(wireprotoserver, b"iscmd", _iscmd) def _loadfileblob(repo, cachepath, path, node): @@ -255,7 +260,7 @@ f = None try: - f = util.atomictempfile(filecachepath, "wb") + f = util.atomictempfile(filecachepath, b"wb") f.write(text) except (IOError, OSError): # Don't abort if the user only has permission to read, @@ -267,7 +272,7 @@ finally: os.umask(oldumask) else: - with open(filecachepath, "rb") as f: + with open(filecachepath, b"rb") as f: text = f.read() return text @@ -277,7 +282,7 @@ """ flog = repo.file(path) heads = flog.heads() - return "\n".join((hex(head) for head in heads if head != nullid)) + return b"\n".join((hex(head) for head in heads if head != nullid)) def getfile(repo, proto, file, node): @@ -290,30 +295,30 @@ createfileblob for its content. """ if shallowutil.isenabled(repo): - return "1\0" + _("cannot fetch remote files from shallow repo") - cachepath = repo.ui.config("remotefilelog", "servercachepath") + return b"1\0" + _(b"cannot fetch remote files from shallow repo") + cachepath = repo.ui.config(b"remotefilelog", b"servercachepath") if not cachepath: - cachepath = os.path.join(repo.path, "remotefilelogcache") + cachepath = os.path.join(repo.path, b"remotefilelogcache") node = bin(node.strip()) if node == nullid: - return "0\0" - return "0\0" + _loadfileblob(repo, cachepath, file, node) + return b"0\0" + return b"0\0" + _loadfileblob(repo, cachepath, file, node) def getfiles(repo, proto): """A server api for requesting particular versions of particular files. """ if shallowutil.isenabled(repo): - raise error.Abort(_("cannot fetch remote files from shallow repo")) + raise error.Abort(_(b"cannot fetch remote files from shallow repo")) if not isinstance(proto, _sshv1server): - raise error.Abort(_("cannot fetch remote files over non-ssh protocol")) + raise error.Abort(_(b"cannot fetch remote files over non-ssh protocol")) def streamer(): fin = proto._fin - cachepath = repo.ui.config("remotefilelog", "servercachepath") + cachepath = repo.ui.config(b"remotefilelog", b"servercachepath") if not cachepath: - cachepath = os.path.join(repo.path, "remotefilelogcache") + cachepath = os.path.join(repo.path, b"remotefilelogcache") while True: request = fin.readline()[:-1] @@ -322,14 +327,14 @@ node = bin(request[:40]) if node == nullid: - yield "0\n" + yield b"0\n" continue path = request[40:] text = _loadfileblob(repo, cachepath, path, node) - yield "%d\n%s" % (len(text), text) + yield b"%d\n%s" % (len(text), text) # it would be better to only flush after processing a whole batch # but currently we don't know if there are more requests coming @@ -371,7 +376,7 @@ repo.forcelinkrev = True ancestors.extend([f for f in filectx.ancestors()]) - ancestortext = "" + ancestortext = b"" for ancestorctx in ancestors: parents = ancestorctx.parents() p1 = nullid @@ -381,12 +386,12 @@ if len(parents) > 1: p2 = parents[1].filenode() - copyname = "" + copyname = b"" rename = ancestorctx.renamed() if rename: copyname = rename[0] linknode = ancestorctx.node() - ancestortext += "%s%s%s%s%s\0" % ( + ancestortext += b"%s%s%s%s%s\0" % ( ancestorctx.filenode(), p1, p2, @@ -398,17 +403,17 @@ header = shallowutil.buildfileblobheader(len(text), revlogflags) - return "%s\0%s%s" % (header, text, ancestortext) + return b"%s\0%s%s" % (header, text, ancestortext) def gcserver(ui, repo): - if not repo.ui.configbool("remotefilelog", "server"): + if not repo.ui.configbool(b"remotefilelog", b"server"): return neededfiles = set() - heads = repo.revs("heads(tip~25000:) - null") + heads = repo.revs(b"heads(tip~25000:) - null") - cachepath = repo.vfs.join("remotefilelogcache") + cachepath = repo.vfs.join(b"remotefilelogcache") for head in heads: mf = repo[head].manifest() for filename, filenode in mf.iteritems(): @@ -416,10 +421,10 @@ neededfiles.add(filecachepath) # delete unneeded older files - days = repo.ui.configint("remotefilelog", "serverexpiration") + days = repo.ui.configint(b"remotefilelog", b"serverexpiration") expiration = time.time() - (days * 24 * 60 * 60) - progress = ui.makeprogress(_("removing old server cache"), unit="files") + progress = ui.makeprogress(_(b"removing old server cache"), unit=b"files") progress.update(0) for root, dirs, files in os.walk(cachepath): for file in files: diff --git a/hgext/remotefilelog/repack.py b/hgext/remotefilelog/repack.py --- a/hgext/remotefilelog/repack.py +++ b/hgext/remotefilelog/repack.py @@ -39,13 +39,13 @@ def backgroundrepack( repo, incremental=True, packsonly=False, ensurestart=False ): - cmd = [procutil.hgexecutable(), "-R", repo.origroot, "repack"] - msg = _("(running background repack)\n") + cmd = [procutil.hgexecutable(), b"-R", repo.origroot, b"repack"] + msg = _(b"(running background repack)\n") if incremental: - cmd.append("--incremental") - msg = _("(running background incremental repack)\n") + cmd.append(b"--incremental") + msg = _(b"(running background incremental repack)\n") if packsonly: - cmd.append("--packsonly") + cmd.append(b"--packsonly") repo.ui.warn(msg) # We know this command will find a binary, so don't block on it starting. procutil.runbgcommand(cmd, encoding.environ, ensurestart=ensurestart) @@ -54,7 +54,7 @@ def fullrepack(repo, options=None): """If ``packsonly`` is True, stores creating only loose objects are skipped. """ - if util.safehasattr(repo, "shareddatastores"): + if util.safehasattr(repo, b"shareddatastores"): datasource = contentstore.unioncontentstore(*repo.shareddatastores) historysource = metadatastore.unionmetadatastore( *repo.sharedhistorystores, allowincomplete=True @@ -72,7 +72,7 @@ options=options, ) - if util.safehasattr(repo.manifestlog, "datastore"): + if util.safehasattr(repo.manifestlog, b"datastore"): localdata, shareddata = _getmanifeststores(repo) lpackpath, ldstores, lhstores = localdata spackpath, sdstores, shstores = shareddata @@ -112,7 +112,7 @@ """This repacks the repo by looking at the distribution of pack files in the repo and performing the most minimal repack to keep the repo in good shape. """ - if util.safehasattr(repo, "shareddatastores"): + if util.safehasattr(repo, b"shareddatastores"): packpath = shallowutil.getcachepackpath( repo, constants.FILEPACK_CATEGORY ) @@ -125,7 +125,7 @@ options=options, ) - if util.safehasattr(repo.manifestlog, "datastore"): + if util.safehasattr(repo.manifestlog, b"datastore"): localdata, shareddata = _getmanifeststores(repo) lpackpath, ldstores, lhstores = localdata spackpath, sdstores, shstores = shareddata @@ -181,13 +181,13 @@ """Deletes packfiles that are bigger than ``packs.maxpacksize``. Returns ``files` with the removed files omitted.""" - maxsize = repo.ui.configbytes("packs", "maxpacksize") + maxsize = repo.ui.configbytes(b"packs", b"maxpacksize") if maxsize <= 0: return files # This only considers datapacks today, but we could broaden it to include # historypacks. - VALIDEXTS = [".datapack", ".dataidx"] + VALIDEXTS = [b".datapack", b".dataidx"] # Either an oversize index or datapack will trigger cleanup of the whole # pack: @@ -202,7 +202,7 @@ for ext in VALIDEXTS: path = rootpath + ext repo.ui.debug( - "removing oversize packfile %s (%s)\n" + b"removing oversize packfile %s (%s)\n" % (path, util.bytecount(os.stat(path).st_size)) ) os.unlink(path) @@ -273,14 +273,16 @@ def _computeincrementaldatapack(ui, files): opts = { - "gencountlimit": ui.configint("remotefilelog", "data.gencountlimit"), - "generations": ui.configlist("remotefilelog", "data.generations"), - "maxrepackpacks": ui.configint("remotefilelog", "data.maxrepackpacks"), - "repackmaxpacksize": ui.configbytes( - "remotefilelog", "data.repackmaxpacksize" + b"gencountlimit": ui.configint(b"remotefilelog", b"data.gencountlimit"), + b"generations": ui.configlist(b"remotefilelog", b"data.generations"), + b"maxrepackpacks": ui.configint( + b"remotefilelog", b"data.maxrepackpacks" ), - "repacksizelimit": ui.configbytes( - "remotefilelog", "data.repacksizelimit" + b"repackmaxpacksize": ui.configbytes( + b"remotefilelog", b"data.repackmaxpacksize" + ), + b"repacksizelimit": ui.configbytes( + b"remotefilelog", b"data.repacksizelimit" ), } @@ -292,18 +294,20 @@ def _computeincrementalhistorypack(ui, files): opts = { - "gencountlimit": ui.configint("remotefilelog", "history.gencountlimit"), - "generations": ui.configlist( - "remotefilelog", "history.generations", ["100MB"] + b"gencountlimit": ui.configint( + b"remotefilelog", b"history.gencountlimit" + ), + b"generations": ui.configlist( + b"remotefilelog", b"history.generations", [b"100MB"] ), - "maxrepackpacks": ui.configint( - "remotefilelog", "history.maxrepackpacks" + b"maxrepackpacks": ui.configint( + b"remotefilelog", b"history.maxrepackpacks" ), - "repackmaxpacksize": ui.configbytes( - "remotefilelog", "history.repackmaxpacksize", "400MB" + b"repackmaxpacksize": ui.configbytes( + b"remotefilelog", b"history.repackmaxpacksize", b"400MB" ), - "repacksizelimit": ui.configbytes( - "remotefilelog", "history.repacksizelimit" + b"repacksizelimit": ui.configbytes( + b"remotefilelog", b"history.repacksizelimit" ), } @@ -341,7 +345,7 @@ """ limits = list( - sorted((util.sizetoint(s) for s in opts["generations"]), reverse=True) + sorted((util.sizetoint(s) for s in opts[b"generations"]), reverse=True) ) limits.append(0) @@ -353,7 +357,7 @@ sizes = {} for prefix, mode, stat in files: size = stat.st_size - if size > opts["repackmaxpacksize"]: + if size > opts[b"repackmaxpacksize"]: continue sizes[prefix] = size @@ -370,7 +374,7 @@ # Find the largest generation with more than gencountlimit packs genpacks = [] for i, limit in enumerate(limits): - if len(generations[i]) > opts["gencountlimit"]: + if len(generations[i]) > opts[b"gencountlimit"]: # Sort to be smallest last, for easy popping later genpacks.extend( sorted(generations[i], reverse=True, key=lambda x: sizes[x]) @@ -382,9 +386,9 @@ genpacks = genpacks[:-3] repacksize = sum(sizes[n] for n in chosenpacks) while ( - repacksize < opts["repacksizelimit"] + repacksize < opts[b"repacksizelimit"] and genpacks - and len(chosenpacks) < opts["maxrepackpacks"] + and len(chosenpacks) < opts[b"maxrepackpacks"] ): chosenpacks.append(genpacks.pop()) repacksize += sizes[chosenpacks[-1]] @@ -404,12 +408,12 @@ filectx = repo.filectx(filename, fileid=node) filetime = repo[filectx.linkrev()].date() - ttl = repo.ui.configint("remotefilelog", "nodettl") + ttl = repo.ui.configint(b"remotefilelog", b"nodettl") limit = time.time() - ttl return filetime[0] < limit - garbagecollect = repo.ui.configbool("remotefilelog", "gcrepack") + garbagecollect = repo.ui.configbool(b"remotefilelog", b"gcrepack") if not fullhistory: fullhistory = history packer = repacker( @@ -429,7 +433,10 @@ packer.run(dpack, hpack) except error.LockHeld: raise RepackAlreadyRunning( - _("skipping repack - another repack " "is already running") + _( + b"skipping repack - another repack " + b"is already running" + ) ) @@ -449,16 +456,16 @@ # 2. Draft commits # 3. Parents of draft commits # 4. Pullprefetch and bgprefetchrevs revsets if specified - revs = [".", "draft()", "parents(draft())"] - prefetchrevs = repo.ui.config("remotefilelog", "pullprefetch", None) + revs = [b".", b"draft()", b"parents(draft())"] + prefetchrevs = repo.ui.config(b"remotefilelog", b"pullprefetch", None) if prefetchrevs: - revs.append("(%s)" % prefetchrevs) - prefetchrevs = repo.ui.config("remotefilelog", "bgprefetchrevs", None) + revs.append(b"(%s)" % prefetchrevs) + prefetchrevs = repo.ui.config(b"remotefilelog", b"bgprefetchrevs", None) if prefetchrevs: - revs.append("(%s)" % prefetchrevs) - revs = "+".join(revs) + revs.append(b"(%s)" % prefetchrevs) + revs = b"+".join(revs) - revs = ['sort((%s), "topo")' % revs] + revs = [b'sort((%s), "topo")' % revs] keep = scmutil.revrange(repo, revs) processed = set() @@ -520,7 +527,7 @@ self.options = options if self.garbagecollect: if not isold: - raise ValueError("Function 'isold' is not properly specified") + raise ValueError(b"Function 'isold' is not properly specified") # use (filename, node) tuple as a keepset key self.keepkeys = keepset(repo, lambda f, n: (f, n)) self.isold = isold @@ -529,9 +536,9 @@ ledger = repackledger() with lockmod.lock( - repacklockvfs(self.repo), "repacklock", desc=None, timeout=0 + repacklockvfs(self.repo), b"repacklock", desc=None, timeout=0 ): - self.repo.hook("prerepack") + self.repo.hook(b"prerepack") # Populate ledger from source self.data.markledger(ledger, options=self.options) @@ -571,8 +578,8 @@ orphans = list(sorted(orphans, key=getsize, reverse=True)) if ui.debugflag: ui.debug( - "%s: orphan chain: %s\n" - % (filename, ", ".join([short(s) for s in orphans])) + b"%s: orphan chain: %s\n" + % (filename, b", ".join([short(s) for s in orphans])) ) # Create one contiguous chain and reassign deltabases. @@ -588,7 +595,7 @@ def repackdata(self, ledger, target): ui = self.repo.ui - maxchainlen = ui.configint("packs", "maxchainlen", 1000) + maxchainlen = ui.configint(b"packs", b"maxchainlen", 1000) byfile = {} for entry in ledger.entries.itervalues(): @@ -597,7 +604,7 @@ count = 0 repackprogress = ui.makeprogress( - _("repacking data"), unit=self.unit, total=len(byfile) + _(b"repacking data"), unit=self.unit, total=len(byfile) ) for filename, entries in sorted(byfile.iteritems()): repackprogress.update(count) @@ -606,7 +613,7 @@ nodes = list(node for node in entries) nohistory = [] buildprogress = ui.makeprogress( - _("building history"), unit="nodes", total=len(nodes) + _(b"building history"), unit=b"nodes", total=len(nodes) ) for i, node in enumerate(nodes): if node in ancestors: @@ -629,7 +636,7 @@ orderednodes = list(reversed(self._toposort(ancestors))) if len(nohistory) > 0: ui.debug( - "repackdata: %d nodes without history\n" % len(nohistory) + b"repackdata: %d nodes without history\n" % len(nohistory) ) orderednodes.extend(sorted(nohistory)) @@ -659,7 +666,7 @@ referenced = set() nodes = set(nodes) processprogress = ui.makeprogress( - _("processing nodes"), unit="nodes", total=len(orderednodes) + _(b"processing nodes"), unit=b"nodes", total=len(orderednodes) ) for i, node in enumerate(orderednodes): processprogress.update(i) @@ -698,7 +705,7 @@ deltabases[p2] = (node, chainlen + 1) # experimental config: repack.chainorphansbysize - if ui.configbool("repack", "chainorphansbysize"): + if ui.configbool(b"repack", b"chainorphansbysize"): orphans = nobase - referenced orderednodes = self._chainorphans( ui, filename, orderednodes, orphans, deltabases @@ -751,7 +758,7 @@ byfile.setdefault(entry.filename, {})[entry.node] = entry progress = ui.makeprogress( - _("repacking history"), unit=self.unit, total=len(byfile) + _(b"repacking history"), unit=self.unit, total=len(byfile) ) for filename, entries in sorted(byfile.iteritems()): ancestors = {} @@ -894,7 +901,7 @@ def repacklockvfs(repo): - if util.safehasattr(repo, "name"): + if util.safehasattr(repo, b"name"): # Lock in the shared cache so repacks across multiple copies of the same # repo are coordinated. sharedcachepath = shallowutil.getcachepackpath( diff --git a/hgext/remotefilelog/shallowbundle.py b/hgext/remotefilelog/shallowbundle.py --- a/hgext/remotefilelog/shallowbundle.py +++ b/hgext/remotefilelog/shallowbundle.py @@ -79,11 +79,11 @@ # bundlerepo is heavily tied to revlogs. Instead require that # the user use unbundle instead. # Force load the filelog data. - bundlerepo.bundlerepository.file(repo, "foo") + bundlerepo.bundlerepository.file(repo, b"foo") if repo._cgfilespos: raise error.Abort( - "cannot pull from full bundles", - hint="use `hg unbundle` instead", + b"cannot pull from full bundles", + hint=b"use `hg unbundle` instead", ) return [] filestosend = self.shouldaddfilegroups(source) @@ -99,16 +99,16 @@ if not shallowutil.isenabled(repo): return AllFiles - if source == "push" or source == "bundle": + if source == b"push" or source == b"bundle": return AllFiles caps = self._bundlecaps or [] - if source == "serve" or source == "pull": + if source == b"serve" or source == b"pull": if constants.BUNDLE2_CAPABLITY in caps: return LocalFiles else: # Serving to a full repo requires us to serve everything - repo.ui.warn(_("pulling from a shallow repo\n")) + repo.ui.warn(_(b"pulling from a shallow repo\n")) return AllFiles return NoFiles @@ -128,7 +128,7 @@ return results def nodechunk(self, revlog, node, prevnode, linknode): - prefix = "" + prefix = b"" if prevnode == nullid: delta = revlog.rawdata(node) prefix = mdiff.trivialdiffheader(len(delta)) @@ -152,22 +152,22 @@ original = repo.shallowmatch try: # if serving, only send files the clients has patterns for - if source == "serve": + if source == b"serve": bundlecaps = kwargs.get(r"bundlecaps") includepattern = None excludepattern = None for cap in bundlecaps or []: - if cap.startswith("includepattern="): - raw = cap[len("includepattern=") :] + if cap.startswith(b"includepattern="): + raw = cap[len(b"includepattern=") :] if raw: - includepattern = raw.split("\0") - elif cap.startswith("excludepattern="): - raw = cap[len("excludepattern=") :] + includepattern = raw.split(b"\0") + elif cap.startswith(b"excludepattern="): + raw = cap[len(b"excludepattern=") :] if raw: - excludepattern = raw.split("\0") + excludepattern = raw.split(b"\0") if includepattern or excludepattern: repo.shallowmatch = match.match( - repo.root, "", None, includepattern, excludepattern + repo.root, b"", None, includepattern, excludepattern ) else: repo.shallowmatch = match.always() @@ -192,13 +192,13 @@ # files in topological order. # read all the file chunks but don't add them - progress = repo.ui.makeprogress(_("files"), total=expectedfiles) + progress = repo.ui.makeprogress(_(b"files"), total=expectedfiles) while True: chunkdata = source.filelogheader() if not chunkdata: break - f = chunkdata["filename"] - repo.ui.debug("adding %s revisions\n" % f) + f = chunkdata[b"filename"] + repo.ui.debug(b"adding %s revisions\n" % f) progress.increment() if not repo.shallowmatch(f): @@ -224,7 +224,7 @@ visited.add(f) if chain is None: - raise error.Abort(_("received file revlog group is empty")) + raise error.Abort(_(b"received file revlog group is empty")) processed = set() @@ -266,7 +266,7 @@ skipcount += 1 if skipcount > len(queue) + 1: - raise error.Abort(_("circular node dependency")) + raise error.Abort(_(b"circular node dependency")) fl = repo.file(f) @@ -283,9 +283,9 @@ text = bytes(text) meta, text = shallowutil.parsemeta(text) - if "copy" in meta: - copyfrom = meta["copy"] - copynode = bin(meta["copyrev"]) + if b"copy" in meta: + copyfrom = meta[b"copy"] + copynode = bin(meta[b"copyrev"]) if not available(f, node, copyfrom, copynode): continue diff --git a/hgext/remotefilelog/shallowrepo.py b/hgext/remotefilelog/shallowrepo.py --- a/hgext/remotefilelog/shallowrepo.py +++ b/hgext/remotefilelog/shallowrepo.py @@ -37,7 +37,7 @@ # them. def makelocalstores(repo): """In-repo stores, like .hg/store/data; can not be discarded.""" - localpath = os.path.join(repo.svfs.vfs.base, "data") + localpath = os.path.join(repo.svfs.vfs.base, b"data") if not os.path.exists(localpath): os.makedirs(localpath) @@ -92,7 +92,7 @@ repo.shareddatastores.append(packcontentstore) repo.sharedhistorystores.append(packmetadatastore) shallowutil.reportpackmetrics( - repo.ui, "filestore", packcontentstore, packmetadatastore + repo.ui, b"filestore", packcontentstore, packmetadatastore ) return packcontentstore, packmetadatastore @@ -134,7 +134,7 @@ fileservicehistorywrite, ) shallowutil.reportpackmetrics( - repo.ui, "filestore", packcontentstore, packmetadatastore + repo.ui, b"filestore", packcontentstore, packmetadatastore ) @@ -142,19 +142,19 @@ class shallowrepository(repo.__class__): @util.propertycache def name(self): - return self.ui.config("remotefilelog", "reponame") + return self.ui.config(b"remotefilelog", b"reponame") @util.propertycache def fallbackpath(self): path = repo.ui.config( - "remotefilelog", - "fallbackpath", - repo.ui.config("paths", "default"), + b"remotefilelog", + b"fallbackpath", + repo.ui.config(b"paths", b"default"), ) if not path: raise error.Abort( - "no remotefilelog server " - "configured - is your .hg/hgrc trusted?" + b"no remotefilelog server " + b"configured - is your .hg/hgrc trusted?" ) return path @@ -175,7 +175,7 @@ return ret def file(self, f): - if f[0] == "/": + if f[0] == b"/": f = f[1:] if self.shallowmatch(f): @@ -224,11 +224,11 @@ ): """Runs prefetch in background with optional repack """ - cmd = [procutil.hgexecutable(), "-R", repo.origroot, "prefetch"] + cmd = [procutil.hgexecutable(), b"-R", repo.origroot, b"prefetch"] if repack: - cmd.append("--repack") + cmd.append(b"--repack") if revs: - cmd += ["-r", revs] + cmd += [b"-r", revs] # We know this command will find a binary, so don't block # on it starting. procutil.runbgcommand( @@ -241,11 +241,11 @@ """ with repo._lock( repo.svfs, - "prefetchlock", + b"prefetchlock", True, None, None, - _("prefetching in %s") % repo.origroot, + _(b"prefetching in %s") % repo.origroot, ): self._prefetch(revs, base, pats, opts) @@ -255,10 +255,12 @@ # If we know a rev is on the server, we should fetch the server # version of those files, since our local file versions might # become obsolete if the local commits are stripped. - localrevs = repo.revs("outgoing(%s)", fallbackpath) + localrevs = repo.revs(b"outgoing(%s)", fallbackpath) if base is not None and base != nullrev: serverbase = list( - repo.revs("first(reverse(::%s) - %ld)", base, localrevs) + repo.revs( + b"first(reverse(::%s) - %ld)", base, localrevs + ) ) if serverbase: base = serverbase[0] @@ -266,7 +268,7 @@ localrevs = repo mfl = repo.manifestlog - mfrevlog = mfl.getstorage("") + mfrevlog = mfl.getstorage(b"") if base is not None: mfdict = mfl[repo[base].manifestnode()].read() skip = set(mfdict.iteritems()) @@ -280,7 +282,7 @@ visited = set() visited.add(nullrev) revcount = len(revs) - progress = self.ui.makeprogress(_("prefetching"), total=revcount) + progress = self.ui.makeprogress(_(b"prefetching"), total=revcount) progress.update(0) for rev in sorted(revs): ctx = repo[rev] @@ -337,15 +339,15 @@ makeunionstores(repo) repo.includepattern = repo.ui.configlist( - "remotefilelog", "includepattern", None + b"remotefilelog", b"includepattern", None ) repo.excludepattern = repo.ui.configlist( - "remotefilelog", "excludepattern", None + b"remotefilelog", b"excludepattern", None ) - if not util.safehasattr(repo, "connectionpool"): + if not util.safehasattr(repo, b"connectionpool"): repo.connectionpool = connectionpool.connectionpool(repo) if repo.includepattern or repo.excludepattern: repo.shallowmatch = match.match( - repo.root, "", None, repo.includepattern, repo.excludepattern + repo.root, b"", None, repo.includepattern, repo.excludepattern ) diff --git a/hgext/remotefilelog/shallowutil.py b/hgext/remotefilelog/shallowutil.py --- a/hgext/remotefilelog/shallowutil.py +++ b/hgext/remotefilelog/shallowutil.py @@ -48,13 +48,13 @@ def getcachepath(ui, allowempty=False): - cachepath = ui.config("remotefilelog", "cachepath") + cachepath = ui.config(b"remotefilelog", b"cachepath") if not cachepath: if allowempty: return None else: raise error.Abort( - _("could not find config option " "remotefilelog.cachepath") + _(b"could not find config option " b"remotefilelog.cachepath") ) return util.expandpath(cachepath) @@ -62,13 +62,13 @@ def getcachepackpath(repo, category): cachepath = getcachepath(repo.ui) if category != constants.FILEPACK_CATEGORY: - return os.path.join(cachepath, repo.name, "packs", category) + return os.path.join(cachepath, repo.name, b"packs", category) else: - return os.path.join(cachepath, repo.name, "packs") + return os.path.join(cachepath, repo.name, b"packs") def getlocalpackpath(base, category): - return os.path.join(base, "packs", category) + return os.path.join(base, b"packs", category) def createrevlogtext(text, copyfrom=None, copyrev=None): @@ -76,10 +76,10 @@ traditional revlog """ meta = {} - if copyfrom or text.startswith("\1\n"): + if copyfrom or text.startswith(b"\1\n"): if copyfrom: - meta["copy"] = copyfrom - meta["copyrev"] = copyrev + meta[b"copy"] = copyfrom + meta[b"copyrev"] = copyrev text = storageutil.packmeta(meta, text) return text @@ -88,8 +88,8 @@ def parsemeta(text): """parse mercurial filelog metadata""" meta, size = storageutil.parsemeta(text) - if text.startswith("\1\n"): - s = text.index("\1\n", 2) + if text.startswith(b"\1\n"): + s = text.index(b"\1\n", 2) text = text[s + 2 :] return meta or {}, text @@ -117,8 +117,8 @@ def reportpackmetrics(ui, prefix, *stores): dicts = [s.getmetrics() for s in stores] - dict = prefixkeys(sumdicts(*dicts), prefix + "_") - ui.log(prefix + "_packsizes", "\n", **pycompat.strkwargs(dict)) + dict = prefixkeys(sumdicts(*dicts), prefix + b"_") + ui.log(prefix + b"_packsizes", b"\n", **pycompat.strkwargs(dict)) def _parsepackmeta(metabuf): @@ -136,15 +136,15 @@ while buflen - offset >= 3: key = metabuf[offset : offset + 1] offset += 1 - metalen = struct.unpack_from("!H", metabuf, offset)[0] + metalen = struct.unpack_from(b"!H", metabuf, offset)[0] offset += 2 if offset + metalen > buflen: - raise ValueError("corrupted metadata: incomplete buffer") + raise ValueError(b"corrupted metadata: incomplete buffer") value = metabuf[offset : offset + metalen] metadict[key] = value offset += metalen if offset != buflen: - raise ValueError("corrupted metadata: redundant data") + raise ValueError(b"corrupted metadata: redundant data") return metadict @@ -158,16 +158,16 @@ raise ProgrammingError when metadata key is illegal, or ValueError if length limit is exceeded """ - metabuf = "" + metabuf = b"" for k, v in sorted((metadict or {}).iteritems()): if len(k) != 1: - raise error.ProgrammingError("packmeta: illegal key: %s" % k) + raise error.ProgrammingError(b"packmeta: illegal key: %s" % k) if len(v) > 0xFFFE: raise ValueError( - "metadata value is too long: 0x%x > 0xfffe" % len(v) + b"metadata value is too long: 0x%x > 0xfffe" % len(v) ) metabuf += k - metabuf += struct.pack("!H", len(v)) + metabuf += struct.pack(b"!H", len(v)) metabuf += v # len(metabuf) is guaranteed representable in 4 bytes, because there are # only 256 keys, and for each value, len(value) <= 0xfffe. @@ -190,7 +190,7 @@ for k, v in (metadict or {}).iteritems(): expectedtype = _metaitemtypes.get(k, (bytes,)) if not isinstance(v, expectedtype): - raise error.ProgrammingError("packmeta: wrong type of key %s" % k) + raise error.ProgrammingError(b"packmeta: wrong type of key %s" % k) # normalize int to binary buffer if int in expectedtype: # optimization: remove flag if it's 0 to save space @@ -241,19 +241,19 @@ flags = revlog.REVIDX_DEFAULT_FLAGS size = None try: - index = raw.index("\0") + index = raw.index(b"\0") header = raw[:index] - if header.startswith("v"): + if header.startswith(b"v"): # v1 and above, header starts with 'v' - if header.startswith("v1\n"): - for s in header.split("\n"): + if header.startswith(b"v1\n"): + for s in header.split(b"\n"): if s.startswith(constants.METAKEYSIZE): size = int(s[len(constants.METAKEYSIZE) :]) elif s.startswith(constants.METAKEYFLAG): flags = int(s[len(constants.METAKEYFLAG) :]) else: raise RuntimeError( - "unsupported remotefilelog header: %s" % header + b"unsupported remotefilelog header: %s" % header ) else: # v0, str(int(size)) is the header @@ -277,7 +277,7 @@ if version is None: version = int(bool(flags)) if version == 1: - header = "v1\n%s%d\n%s%d" % ( + header = b"v1\n%s%d\n%s%d" % ( constants.METAKEYSIZE, size, constants.METAKEYFLAG, @@ -285,10 +285,10 @@ ) elif version == 0: if flags: - raise error.ProgrammingError("fileblob v0 does not support flag") - header = "%d" % size + raise error.ProgrammingError(b"fileblob v0 does not support flag") + header = b"%d" % size else: - raise error.ProgrammingError("unknown fileblob version %d" % version) + raise error.ProgrammingError(b"unknown fileblob version %d" % version) return header @@ -298,7 +298,7 @@ mapping = {} while start < len(raw): - divider = raw.index("\0", start + 80) + divider = raw.index(b"\0", start + 80) currentnode = raw[start : (start + 20)] p1 = raw[(start + 20) : (start + 40)] @@ -313,14 +313,14 @@ def readfile(path): - f = open(path, "rb") + f = open(path, b"rb") try: result = f.read() # we should never have empty files if not result: os.remove(path) - raise IOError("empty file: %s" % path) + raise IOError(b"empty file: %s" % path) return result finally: @@ -355,11 +355,11 @@ if ex.errno != errno.EEXIST: raise - fd, temp = tempfile.mkstemp(prefix=".%s-" % filename, dir=dirname) + fd, temp = tempfile.mkstemp(prefix=b".%s-" % filename, dir=dirname) os.close(fd) try: - f = util.posixfile(temp, "wb") + f = util.posixfile(temp, b"wb") f.write(content) f.close() @@ -426,7 +426,7 @@ s = stream.read(n) if len(s) < n: raise error.Abort( - _("stream ended unexpectedly" " (got %d bytes, expected %d)") + _(b"stream ended unexpectedly" b" (got %d bytes, expected %d)") % (len(s), n) ) return s @@ -473,18 +473,18 @@ os.chmod(path, 0o2775) except (IOError, OSError) as ex: if warn: - warn(_("unable to chown/chmod on %s: %s\n") % (path, ex)) + warn(_(b"unable to chown/chmod on %s: %s\n") % (path, ex)) def mkstickygroupdir(ui, path): """Creates the given directory (if it doesn't exist) and give it a particular group with setgid enabled.""" gid = None - groupname = ui.config("remotefilelog", "cachegroup") + groupname = ui.config(b"remotefilelog", b"cachegroup") if groupname: gid = getgid(groupname) if gid is None: - ui.warn(_("unable to resolve group name: %s\n") % groupname) + ui.warn(_(b"unable to resolve group name: %s\n") % groupname) # we use a single stat syscall to test the existence and mode / group bit st = None @@ -525,11 +525,11 @@ try: return stringutil.shortuser(ui.username()) except Exception: - return "unknown" + return b"unknown" def getreponame(ui): - reponame = ui.config("paths", "default") + reponame = ui.config(b"paths", b"default") if reponame: return os.path.basename(reponame) - return "unknown" + return b"unknown" diff --git a/hgext/remotefilelog/shallowverifier.py b/hgext/remotefilelog/shallowverifier.py --- a/hgext/remotefilelog/shallowverifier.py +++ b/hgext/remotefilelog/shallowverifier.py @@ -14,6 +14,6 @@ def _verifyfiles(self, filenodes, filelinkrevs): """Skips files verification since repo's not guaranteed to have them""" self.repo.ui.status( - _("skipping filelog check since remotefilelog is used\n") + _(b"skipping filelog check since remotefilelog is used\n") ) return 0, 0 diff --git a/hgext/remotenames.py b/hgext/remotenames.py --- a/hgext/remotenames.py +++ b/hgext/remotenames.py @@ -58,7 +58,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) @@ -66,13 +66,13 @@ revsetpredicate = registrar.revsetpredicate() configitem( - "remotenames", "bookmarks", default=True, + b"remotenames", b"bookmarks", default=True, ) configitem( - "remotenames", "branches", default=True, + b"remotenames", b"branches", default=True, ) configitem( - "remotenames", "hoistedpeer", default="default", + b"remotenames", b"hoistedpeer", default=b"default", ) @@ -102,7 +102,7 @@ for node, rpath, rname in logexchange.readremotenamefile( repo, self._kind ): - name = rpath + "/" + rname + name = rpath + b"/" + rname self.potentialentries[name] = (node, rpath, name) def _resolvedata(self, potentialentry): @@ -118,7 +118,7 @@ except LookupError: return None # Skip closed branches - if self._kind == "branches" and repo[binnode].closesbranch(): + if self._kind == b"branches" and repo[binnode].closesbranch(): return None return [binnode] @@ -185,8 +185,8 @@ def clearnames(self): """ Clear all remote names state """ - self.bookmarks = lazyremotenamedict("bookmarks", self._repo) - self.branches = lazyremotenamedict("branches", self._repo) + self.bookmarks = lazyremotenamedict(b"bookmarks", self._repo) + self.branches = lazyremotenamedict(b"branches", self._repo) self._invalidatecache() def _invalidatecache(self): @@ -222,7 +222,7 @@ if not self._hoisttonodes: marktonodes = self.bmarktonodes() self._hoisttonodes = {} - hoist += "/" + hoist += b"/" for name, node in marktonodes.iteritems(): if name.startswith(hoist): name = name[len(hoist) :] @@ -233,7 +233,7 @@ if not self._nodetohoists: marktonodes = self.bmarktonodes() self._nodetohoists = {} - hoist += "/" + hoist += b"/" for name, node in marktonodes.iteritems(): if name.startswith(hoist): name = name[len(hoist) :] @@ -242,9 +242,9 @@ def wrapprintbookmarks(orig, ui, repo, fm, bmarks): - if "remotebookmarks" not in repo.names: + if b"remotebookmarks" not in repo.names: return - ns = repo.names["remotebookmarks"] + ns = repo.names[b"remotebookmarks"] for name in ns.listnames(repo): nodes = ns.nodes(repo, name) @@ -252,19 +252,19 @@ continue node = nodes[0] - bmarks[name] = (node, " ", "") + bmarks[name] = (node, b" ", b"") return orig(ui, repo, fm, bmarks) def extsetup(ui): - extensions.wrapfunction(bookmarks, "_printbookmarks", wrapprintbookmarks) + extensions.wrapfunction(bookmarks, b"_printbookmarks", wrapprintbookmarks) def reposetup(ui, repo): # set the config option to store remotenames - repo.ui.setconfig("experimental", "remotenames", True, "remotenames-ext") + repo.ui.setconfig(b"experimental", b"remotenames", True, b"remotenames-ext") if not repo.local(): return @@ -272,12 +272,12 @@ repo._remotenames = remotenames(repo) ns = namespaces.namespace - if ui.configbool("remotenames", "bookmarks"): + if ui.configbool(b"remotenames", b"bookmarks"): remotebookmarkns = ns( - "remotebookmarks", - templatename="remotebookmarks", - colorname="remotebookmark", - logfmt="remote bookmark: %s\n", + b"remotebookmarks", + templatename=b"remotebookmarks", + colorname=b"remotebookmark", + logfmt=b"remote bookmark: %s\n", listnames=lambda repo: repo._remotenames.bmarktonodes().keys(), namemap=lambda repo, name: repo._remotenames.bmarktonodes().get( name, [] @@ -289,13 +289,13 @@ repo.names.addnamespace(remotebookmarkns) # hoisting only works if there are remote bookmarks - hoist = ui.config("remotenames", "hoistedpeer") + hoist = ui.config(b"remotenames", b"hoistedpeer") if hoist: hoistednamens = ns( - "hoistednames", - templatename="hoistednames", - colorname="hoistedname", - logfmt="hoisted name: %s\n", + b"hoistednames", + templatename=b"hoistednames", + colorname=b"hoistedname", + logfmt=b"hoisted name: %s\n", listnames=lambda repo: repo._remotenames.hoisttonodes( hoist ).keys(), @@ -308,12 +308,12 @@ ) repo.names.addnamespace(hoistednamens) - if ui.configbool("remotenames", "branches"): + if ui.configbool(b"remotenames", b"branches"): remotebranchns = ns( - "remotebranches", - templatename="remotebranches", - colorname="remotebranch", - logfmt="remote branch: %s\n", + b"remotebranches", + templatename=b"remotebranches", + colorname=b"remotebranch", + logfmt=b"remote branch: %s\n", listnames=lambda repo: repo._remotenames.branchtonodes().keys(), namemap=lambda repo, name: repo._remotenames.branchtonodes().get( name, [] @@ -325,68 +325,68 @@ repo.names.addnamespace(remotebranchns) -@templatekeyword("remotenames", requires={"repo", "ctx"}) +@templatekeyword(b"remotenames", requires={b"repo", b"ctx"}) def remotenameskw(context, mapping): """List of strings. Remote names associated with the changeset.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") remotenames = [] - if "remotebookmarks" in repo.names: - remotenames = repo.names["remotebookmarks"].names(repo, ctx.node()) + if b"remotebookmarks" in repo.names: + remotenames = repo.names[b"remotebookmarks"].names(repo, ctx.node()) - if "remotebranches" in repo.names: - remotenames += repo.names["remotebranches"].names(repo, ctx.node()) + if b"remotebranches" in repo.names: + remotenames += repo.names[b"remotebranches"].names(repo, ctx.node()) return templateutil.compatlist( - context, mapping, "remotename", remotenames, plural="remotenames" + context, mapping, b"remotename", remotenames, plural=b"remotenames" ) -@templatekeyword("remotebookmarks", requires={"repo", "ctx"}) +@templatekeyword(b"remotebookmarks", requires={b"repo", b"ctx"}) def remotebookmarkskw(context, mapping): """List of strings. Remote bookmarks associated with the changeset.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") remotebmarks = [] - if "remotebookmarks" in repo.names: - remotebmarks = repo.names["remotebookmarks"].names(repo, ctx.node()) + if b"remotebookmarks" in repo.names: + remotebmarks = repo.names[b"remotebookmarks"].names(repo, ctx.node()) return templateutil.compatlist( context, mapping, - "remotebookmark", + b"remotebookmark", remotebmarks, - plural="remotebookmarks", + plural=b"remotebookmarks", ) -@templatekeyword("remotebranches", requires={"repo", "ctx"}) +@templatekeyword(b"remotebranches", requires={b"repo", b"ctx"}) def remotebrancheskw(context, mapping): """List of strings. Remote branches associated with the changeset.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") remotebranches = [] - if "remotebranches" in repo.names: - remotebranches = repo.names["remotebranches"].names(repo, ctx.node()) + if b"remotebranches" in repo.names: + remotebranches = repo.names[b"remotebranches"].names(repo, ctx.node()) return templateutil.compatlist( context, mapping, - "remotebranch", + b"remotebranch", remotebranches, - plural="remotebranches", + plural=b"remotebranches", ) def _revsetutil(repo, subset, x, rtypes): """utility function to return a set of revs based on the rtypes""" - args = revsetlang.getargs(x, 0, 1, _("only one argument accepted")) + args = revsetlang.getargs(x, 0, 1, _(b"only one argument accepted")) if args: kind, pattern, matcher = stringutil.stringmatcher( - revsetlang.getstring(args[0], _("argument must be a string")) + revsetlang.getstring(args[0], _(b"argument must be a string")) ) else: kind = pattern = None @@ -401,40 +401,40 @@ if not matcher(name): continue nodes.update(ns.nodes(repo, name)) - if kind == "literal" and not nodes: + if kind == b"literal" and not nodes: raise error.RepoLookupError( - _("remote name '%s' does not exist") % pattern + _(b"remote name '%s' does not exist") % pattern ) revs = (cl.rev(n) for n in nodes if cl.hasnode(n)) return subset & smartset.baseset(revs) -@revsetpredicate("remotenames([name])") +@revsetpredicate(b"remotenames([name])") def remotenamesrevset(repo, subset, x): """All changesets which have a remotename on them. If `name` is specified, only remotenames of matching remote paths are considered. Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. """ - return _revsetutil(repo, subset, x, ("remotebookmarks", "remotebranches")) + return _revsetutil(repo, subset, x, (b"remotebookmarks", b"remotebranches")) -@revsetpredicate("remotebranches([name])") +@revsetpredicate(b"remotebranches([name])") def remotebranchesrevset(repo, subset, x): """All changesets which are branch heads on remotes. If `name` is specified, only remotenames of matching remote paths are considered. Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. """ - return _revsetutil(repo, subset, x, ("remotebranches",)) + return _revsetutil(repo, subset, x, (b"remotebranches",)) -@revsetpredicate("remotebookmarks([name])") +@revsetpredicate(b"remotebookmarks([name])") def remotebmarksrevset(repo, subset, x): """All changesets which have bookmarks on remotes. If `name` is specified, only remotenames of matching remote paths are considered. Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. """ - return _revsetutil(repo, subset, x, ("remotebookmarks",)) + return _revsetutil(repo, subset, x, (b"remotebookmarks",)) diff --git a/hgext/schemes.py b/hgext/schemes.py --- a/hgext/schemes.py +++ b/hgext/schemes.py @@ -61,7 +61,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" _partre = re.compile(br"\{(\d+)\}") @@ -77,7 +77,7 @@ self.parts = 0 def __repr__(self): - return "" % self.scheme + return b"" % self.scheme def instance(self, ui, url, create, intents=None, createopts=None): url = self.resolve(url) @@ -88,60 +88,63 @@ def resolve(self, url): # Should this use the util.url class, or is manual parsing better? try: - url = url.split("://", 1)[1] + url = url.split(b"://", 1)[1] except IndexError: - raise error.Abort(_("no '://' in scheme url '%s'") % url) - parts = url.split("/", self.parts) + raise error.Abort(_(b"no '://' in scheme url '%s'") % url) + parts = url.split(b"/", self.parts) if len(parts) > self.parts: tail = parts[-1] parts = parts[:-1] else: - tail = "" - context = dict(("%d" % (i + 1), v) for i, v in enumerate(parts)) - return "".join(self.templater.process(self.url, context)) + tail + tail = b"" + context = dict((b"%d" % (i + 1), v) for i, v in enumerate(parts)) + return b"".join(self.templater.process(self.url, context)) + tail def hasdriveletter(orig, path): if path: for scheme in schemes: - if path.startswith(scheme + ":"): + if path.startswith(scheme + b":"): return False return orig(path) schemes = { - "py": "http://hg.python.org/", - "bb": "https://bitbucket.org/", - "bb+ssh": "ssh://hg@bitbucket.org/", - "gcode": "https://{1}.googlecode.com/hg/", - "kiln": "https://{1}.kilnhg.com/Repo/", + b"py": b"http://hg.python.org/", + b"bb": b"https://bitbucket.org/", + b"bb+ssh": b"ssh://hg@bitbucket.org/", + b"gcode": b"https://{1}.googlecode.com/hg/", + b"kiln": b"https://{1}.kilnhg.com/Repo/", } def extsetup(ui): - schemes.update(dict(ui.configitems("schemes"))) + schemes.update(dict(ui.configitems(b"schemes"))) t = templater.engine(templater.parse) for scheme, url in schemes.items(): if ( pycompat.iswindows and len(scheme) == 1 and scheme.isalpha() - and os.path.exists("%s:\\" % scheme) + and os.path.exists(b"%s:\\" % scheme) ): raise error.Abort( - _("custom scheme %s:// conflicts with drive " "letter %s:\\\n") + _( + b"custom scheme %s:// conflicts with drive " + b"letter %s:\\\n" + ) % (scheme, scheme.upper()) ) hg.schemes[scheme] = ShortRepository(url, scheme, t) - extensions.wrapfunction(util, "hasdriveletter", hasdriveletter) + extensions.wrapfunction(util, b"hasdriveletter", hasdriveletter) -@command("debugexpandscheme", norepo=True) +@command(b"debugexpandscheme", norepo=True) def expandscheme(ui, url, **opts): """given a repo path, provide the scheme-expanded path """ repo = hg._peerlookup(url) if isinstance(repo, ShortRepository): url = repo.resolve(url) - ui.write(url + "\n") + ui.write(url + b"\n") diff --git a/hgext/share.py b/hgext/share.py --- a/hgext/share.py +++ b/hgext/share.py @@ -58,22 +58,22 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "share", + b"share", [ - ("U", "noupdate", None, _("do not create a working directory")), - ("B", "bookmarks", None, _("also share bookmarks")), + (b"U", b"noupdate", None, _(b"do not create a working directory")), + (b"B", b"bookmarks", None, _(b"also share bookmarks")), ( - "", - "relative", + b"", + b"relative", None, - _("point to source using a relative path " "(EXPERIMENTAL)"), + _(b"point to source using a relative path " b"(EXPERIMENTAL)"), ), ], - _("[-U] [-B] SOURCE [DEST]"), + _(b"[-U] [-B] SOURCE [DEST]"), helpcategory=command.CATEGORY_REPO_CREATION, norepo=True, ) @@ -108,7 +108,7 @@ return 0 -@command("unshare", [], "", helpcategory=command.CATEGORY_MAINTENANCE) +@command(b"unshare", [], b"", helpcategory=command.CATEGORY_MAINTENANCE) def unshare(ui, repo): """convert a shared repository to a normal one @@ -116,30 +116,30 @@ """ if not repo.shared(): - raise error.Abort(_("this is not a shared repo")) + raise error.Abort(_(b"this is not a shared repo")) hg.unshare(ui, repo) # Wrap clone command to pass auto share options. def clone(orig, ui, source, *args, **opts): - pool = ui.config("share", "pool") + pool = ui.config(b"share", b"pool") if pool: pool = util.expandpath(pool) opts[r"shareopts"] = { - "pool": pool, - "mode": ui.config("share", "poolnaming"), + b"pool": pool, + b"mode": ui.config(b"share", b"poolnaming"), } return orig(ui, source, *args, **opts) def extsetup(ui): - extensions.wrapfunction(bookmarks, "_getbkfile", getbkfile) - extensions.wrapfunction(bookmarks.bmstore, "_recordchange", recordchange) - extensions.wrapfunction(bookmarks.bmstore, "_writerepo", writerepo) - extensions.wrapcommand(commands.table, "clone", clone) + extensions.wrapfunction(bookmarks, b"_getbkfile", getbkfile) + extensions.wrapfunction(bookmarks.bmstore, b"_recordchange", recordchange) + extensions.wrapfunction(bookmarks.bmstore, b"_writerepo", writerepo) + extensions.wrapcommand(commands.table, b"clone", clone) def _hassharedbookmarks(repo): @@ -149,7 +149,7 @@ # from/to the source repo. return False try: - shared = repo.vfs.read("shared").splitlines() + shared = repo.vfs.read(b"shared").splitlines() except IOError as inst: if inst.errno != errno.ENOENT: raise @@ -165,7 +165,7 @@ # HG_PENDING refers repo.root. try: fp, pending = txnutil.trypending( - repo.root, repo.vfs, "bookmarks" + repo.root, repo.vfs, b"bookmarks" ) if pending: # only in this case, bookmark information in repo @@ -194,7 +194,7 @@ if _hassharedbookmarks(self._repo): srcrepo = hg.sharedreposource(self._repo) if srcrepo is not None: - category = "share-bookmarks" + category = b"share-bookmarks" tr.addpostclose(category, lambda tr: self._writerepo(srcrepo)) diff --git a/hgext/show.py b/hgext/show.py --- a/hgext/show.py +++ b/hgext/show.py @@ -49,7 +49,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @@ -61,7 +61,7 @@ """Register a function to be invoked for an `hg show `.""" # Used by _formatdoc(). - _docformat = "%s -- %s" + _docformat = b"%s -- %s" def _extrasetup(self, name, func, fmtopic=None, csettopic=None): """Called with decorator arguments to register a show view. @@ -88,16 +88,16 @@ @command( - "show", + b"show", [ # TODO: Switch this template flag to use cmdutil.formatteropts if # 'hg show' becomes stable before --template/-T is stable. For now, # we are putting it here without the '(EXPERIMENTAL)' flag because it # is an important part of the 'hg show' user experience and the entire # 'hg show' experience is experimental. - ("T", "template", "", "display with template", _("TEMPLATE")), + (b"T", b"template", b"", b"display with template", _(b"TEMPLATE")), ], - _("VIEW"), + _(b"VIEW"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, ) def show(ui, repo, view=None, template=None): @@ -119,45 +119,47 @@ List of available views: """ if ui.plain() and not template: - hint = _("invoke with -T/--template to control output format") - raise error.Abort(_("must specify a template in plain mode"), hint=hint) + hint = _(b"invoke with -T/--template to control output format") + raise error.Abort( + _(b"must specify a template in plain mode"), hint=hint + ) views = showview._table if not view: - ui.pager("show") + ui.pager(b"show") # TODO consider using formatter here so available views can be # rendered to custom format. - ui.write(_("available views:\n")) - ui.write("\n") + ui.write(_(b"available views:\n")) + ui.write(b"\n") for name, func in sorted(views.items()): - ui.write("%s\n" % pycompat.sysbytes(func.__doc__)) + ui.write(b"%s\n" % pycompat.sysbytes(func.__doc__)) - ui.write("\n") + ui.write(b"\n") raise error.Abort( - _("no view requested"), - hint=_('use "hg show VIEW" to choose a view'), + _(b"no view requested"), + hint=_(b'use "hg show VIEW" to choose a view'), ) # TODO use same logic as dispatch to perform prefix matching. if view not in views: raise error.Abort( - _("unknown view: %s") % view, - hint=_('run "hg show" to see available views'), + _(b"unknown view: %s") % view, + hint=_(b'run "hg show" to see available views'), ) - template = template or "show" + template = template or b"show" fn = views[view] - ui.pager("show") + ui.pager(b"show") if fn._fmtopic: - fmtopic = "show%s" % fn._fmtopic - with ui.formatter(fmtopic, {"template": template}) as fm: + fmtopic = b"show%s" % fn._fmtopic + with ui.formatter(fmtopic, {b"template": template}) as fm: return fn(ui, repo, fm) elif fn._csettopic: - ref = "show%s" % fn._csettopic + ref = b"show%s" % fn._csettopic spec = formatter.lookuptemplate(ui, ref, template) displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True) return fn(ui, repo, displayer) @@ -165,7 +167,7 @@ return fn(ui, repo) -@showview("bookmarks", fmtopic="bookmarks") +@showview(b"bookmarks", fmtopic=b"bookmarks") def showbookmarks(ui, repo, fm): """bookmarks and their associated changeset""" marks = repo._bookmarks @@ -174,7 +176,7 @@ # specify an empty output, but we shouldn't corrupt JSON while # waiting for this functionality. if not isinstance(fm, formatter.jsonformatter): - ui.write(_("(no bookmarks set)\n")) + ui.write(_(b"(no bookmarks set)\n")) return revs = [repo[node].rev() for node in marks.values()] @@ -185,27 +187,30 @@ for bm, node in sorted(marks.items()): fm.startitem() fm.context(ctx=repo[node]) - fm.write("bookmark", "%s", bm) - fm.write("node", fm.hexfunc(node), fm.hexfunc(node)) + fm.write(b"bookmark", b"%s", bm) + fm.write(b"node", fm.hexfunc(node), fm.hexfunc(node)) fm.data( active=bm == active, longestbookmarklen=longestname, nodelen=nodelen ) -@showview("stack", csettopic="stack") +@showview(b"stack", csettopic=b"stack") def showstack(ui, repo, displayer): """current line of work""" - wdirctx = repo["."] + wdirctx = repo[b"."] if wdirctx.rev() == nullrev: raise error.Abort( - _("stack view only available when there is a " "working directory") + _( + b"stack view only available when there is a " + b"working directory" + ) ) if wdirctx.phase() == phases.public: ui.write( _( - "(empty stack; working directory parent is a published " - "changeset)\n" + b"(empty stack; working directory parent is a published " + b"changeset)\n" ) ) return @@ -220,7 +225,7 @@ baserev = wdirctx.rev() stackrevs = {wdirctx.rev()} else: - stackrevs = set(repo.revs("%d::.", baserev)) + stackrevs = set(repo.revs(b"%d::.", baserev)) ctx = repo[baserev] if ctx.p1().rev() != nullrev: @@ -256,7 +261,7 @@ # TODO make this customizable? newheads = set( repo.revs( - "heads(%d::) - %ld - not public()", basectx.rev(), stackrevs + b"heads(%d::) - %ld - not public()", basectx.rev(), stackrevs ) ) else: @@ -266,7 +271,7 @@ nodelen = longestshortest(repo, allrevs) try: - cmdutil.findcmd("rebase", commands.table) + cmdutil.findcmd(b"rebase", commands.table) haverebase = True except (error.AmbiguousCommand, error.UnknownCommand): haverebase = False @@ -278,11 +283,11 @@ tres = formatter.templateresources(ui, repo) shortesttmpl = formatter.maketemplater( - ui, "{shortest(node, %d)}" % nodelen, resources=tres + ui, b"{shortest(node, %d)}" % nodelen, resources=tres ) def shortest(ctx): - return shortesttmpl.renderdefault({"ctx": ctx, "node": ctx.hex()}) + return shortesttmpl.renderdefault({b"ctx": ctx, b"node": ctx.hex()}) # We write out new heads to aid in DAG awareness and to help with decision # making on how the stack should be reconciled with commits made since the @@ -307,60 +312,60 @@ ctx = repo[rev] if i: - ui.write(": ") + ui.write(b": ") else: - ui.write(" ") + ui.write(b" ") - ui.write("o ") + ui.write(b"o ") displayer.show(ctx, nodelen=nodelen) displayer.flush(ctx) - ui.write("\n") + ui.write(b"\n") if i: - ui.write(":/") + ui.write(b":/") else: - ui.write(" /") + ui.write(b" /") - ui.write(" (") + ui.write(b" (") ui.write( - _("%d commits ahead") % revdistance[rev], - label="stack.commitdistance", + _(b"%d commits ahead") % revdistance[rev], + label=b"stack.commitdistance", ) if haverebase: # TODO may be able to omit --source in some scenarios - ui.write("; ") + ui.write(b"; ") ui.write( ( - "hg rebase --source %s --dest %s" + b"hg rebase --source %s --dest %s" % (shortest(sourcectx), shortest(ctx)) ), - label="stack.rebasehint", + label=b"stack.rebasehint", ) - ui.write(")\n") + ui.write(b")\n") - ui.write(":\n: ") - ui.write(_("(stack head)\n"), label="stack.label") + ui.write(b":\n: ") + ui.write(_(b"(stack head)\n"), label=b"stack.label") if branchpointattip: - ui.write(" \\ / ") - ui.write(_("(multiple children)\n"), label="stack.label") - ui.write(" |\n") + ui.write(b" \\ / ") + ui.write(_(b"(multiple children)\n"), label=b"stack.label") + ui.write(b" |\n") for rev in stackrevs: ctx = repo[rev] - symbol = "@" if rev == wdirctx.rev() else "o" + symbol = b"@" if rev == wdirctx.rev() else b"o" if newheads: - ui.write(": ") + ui.write(b": ") else: - ui.write(" ") + ui.write(b" ") - ui.write(symbol, " ") + ui.write(symbol, b" ") displayer.show(ctx, nodelen=nodelen) displayer.flush(ctx) - ui.write("\n") + ui.write(b"\n") # TODO display histedit hint? @@ -368,25 +373,25 @@ # Vertically and horizontally separate stack base from parent # to reinforce stack boundary. if newheads: - ui.write(":/ ") + ui.write(b":/ ") else: - ui.write(" / ") + ui.write(b" / ") - ui.write(_("(stack base)"), "\n", label="stack.label") - ui.write("o ") + ui.write(_(b"(stack base)"), b"\n", label=b"stack.label") + ui.write(b"o ") displayer.show(basectx, nodelen=nodelen) displayer.flush(basectx) - ui.write("\n") + ui.write(b"\n") -@revsetpredicate("_underway([commitage[, headage]])") +@revsetpredicate(b"_underway([commitage[, headage]])") def underwayrevset(repo, subset, x): - args = revset.getargsdict(x, "underway", "commitage headage") - if "commitage" not in args: - args["commitage"] = None - if "headage" not in args: - args["headage"] = None + args = revset.getargsdict(x, b"underway", b"commitage headage") + if b"commitage" not in args: + args[b"commitage"] = None + if b"headage" not in args: + args[b"headage"] = None # We assume callers of this revset add a topographical sort on the # result. This means there is no benefit to making the revset lazy @@ -399,13 +404,13 @@ # to return. ``not public()`` will also pull in obsolete changesets if # there is a non-obsolete changeset with obsolete ancestors. This is # why we exclude obsolete changesets from this query. - rs = "not public() and not obsolete()" + rs = b"not public() and not obsolete()" rsargs = [] - if args["commitage"]: - rs += " and date(%s)" + if args[b"commitage"]: + rs += b" and date(%s)" rsargs.append( revsetlang.getstring( - args["commitage"], _("commitage requires a string") + args[b"commitage"], _(b"commitage requires a string") ) ) @@ -413,55 +418,55 @@ relevant = revset.baseset(mutable) # Add parents of mutable changesets to provide context. - relevant += repo.revs("parents(%ld)", mutable) + relevant += repo.revs(b"parents(%ld)", mutable) # We also pull in (public) heads if they a) aren't closing a branch # b) are recent. - rs = "head() and not closed()" + rs = b"head() and not closed()" rsargs = [] - if args["headage"]: - rs += " and date(%s)" + if args[b"headage"]: + rs += b" and date(%s)" rsargs.append( revsetlang.getstring( - args["headage"], _("headage requires a string") + args[b"headage"], _(b"headage requires a string") ) ) relevant += repo.revs(rs, *rsargs) # Add working directory parent. - wdirrev = repo["."].rev() + wdirrev = repo[b"."].rev() if wdirrev != nullrev: relevant += revset.baseset({wdirrev}) return subset & relevant -@showview("work", csettopic="work") +@showview(b"work", csettopic=b"work") def showwork(ui, repo, displayer): """changesets that aren't finished""" # TODO support date-based limiting when calling revset. - revs = repo.revs("sort(_underway(), topo)") + revs = repo.revs(b"sort(_underway(), topo)") nodelen = longestshortest(repo, revs) revdag = graphmod.dagwalker(repo, revs) - ui.setconfig("experimental", "graphshorten", True) + ui.setconfig(b"experimental", b"graphshorten", True) logcmdutil.displaygraph( ui, repo, revdag, displayer, graphmod.asciiedges, - props={"nodelen": nodelen}, + props={b"nodelen": nodelen}, ) def extsetup(ui): # Alias `hg ` to `hg show `. - for prefix in ui.configlist("commands", "show.aliasprefix"): + for prefix in ui.configlist(b"commands", b"show.aliasprefix"): for view in showview._table: - name = "%s%s" % (prefix, view) + name = b"%s%s" % (prefix, view) choice, allcommands = cmdutil.findpossible( name, commands.table, strict=True @@ -472,10 +477,10 @@ continue # Same for aliases. - if ui.config("alias", name, None): + if ui.config(b"alias", name, None): continue - ui.setconfig("alias", name, "show %s" % view, source="show") + ui.setconfig(b"alias", name, b"show %s" % view, source=b"show") def longestshortest(repo, revs, minlen=4): @@ -516,9 +521,9 @@ ) ) - cmdtable["show"][0].__doc__ = pycompat.sysstr("%s\n\n%s\n ") % ( - cmdtable["show"][0].__doc__.rstrip(), - pycompat.sysstr("\n\n").join(entries), + cmdtable[b"show"][0].__doc__ = pycompat.sysstr(b"%s\n\n%s\n ") % ( + cmdtable[b"show"][0].__doc__.rstrip(), + pycompat.sysstr(b"\n\n").join(entries), ) diff --git a/hgext/sparse.py b/hgext/sparse.py --- a/hgext/sparse.py +++ b/hgext/sparse.py @@ -92,7 +92,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" cmdtable = {} command = registrar.command(cmdtable) @@ -121,24 +121,24 @@ if cls is object: raise AttributeError( - _("type '%s' has no property '%s'") % (origcls, propname) + _(b"type '%s' has no property '%s'") % (origcls, propname) ) def _setuplog(ui): - entry = commands.table["log|history"] + entry = commands.table[b"log|history"] entry[1].append( ( - "", - "sparse", + b"", + b"sparse", None, - "limit to changesets affecting the sparse checkout", + b"limit to changesets affecting the sparse checkout", ) ) def _initialrevs(orig, repo, opts): revs = orig(repo, opts) - if opts.get("sparse"): + if opts.get(b"sparse"): sparsematch = sparse.matcher(repo) def ctxmatch(rev): @@ -148,7 +148,7 @@ revs = revs.filter(ctxmatch) return revs - extensions.wrapfunction(logcmdutil, "_initialrevs", _initialrevs) + extensions.wrapfunction(logcmdutil, b"_initialrevs", _initialrevs) def _clonesparsecmd(orig, ui, repo, *args, **opts): @@ -167,7 +167,7 @@ pat = enableprofile_pat enableprofile = True if sum([include, exclude, enableprofile]) > 1: - raise error.Abort(_("too many flags specified.")) + raise error.Abort(_(b"too many flags specified.")) # if --narrow is passed, it means they are includes and excludes for narrow # clone if not narrow_pat and (include or exclude or enableprofile): @@ -184,26 +184,26 @@ ) return orig(self, node, overwrite, *args, **kwargs) - extensions.wrapfunction(hg, "updaterepo", clonesparse) + extensions.wrapfunction(hg, b"updaterepo", clonesparse) return orig(ui, repo, *args, **opts) def _setupclone(ui): - entry = commands.table["clone"] - entry[1].append(("", "enable-profile", [], "enable a sparse profile")) - entry[1].append(("", "include", [], "include sparse pattern")) - entry[1].append(("", "exclude", [], "exclude sparse pattern")) - extensions.wrapcommand(commands.table, "clone", _clonesparsecmd) + entry = commands.table[b"clone"] + entry[1].append((b"", b"enable-profile", [], b"enable a sparse profile")) + entry[1].append((b"", b"include", [], b"include sparse pattern")) + entry[1].append((b"", b"exclude", [], b"exclude sparse pattern")) + extensions.wrapcommand(commands.table, b"clone", _clonesparsecmd) def _setupadd(ui): - entry = commands.table["add"] + entry = commands.table[b"add"] entry[1].append( ( - "s", - "sparse", + b"s", + b"sparse", None, - "also include directories of added files in sparse config", + b"also include directories of added files in sparse config", ) ) @@ -216,7 +216,7 @@ sparse.updateconfig(repo, list(dirs), opts, include=True) return orig(ui, repo, *pats, **opts) - extensions.wrapcommand(commands.table, "add", _add) + extensions.wrapcommand(commands.table, b"add", _add) def _setupdirstate(ui): @@ -232,7 +232,7 @@ match = matchmod.intersectmatchers(match, sm) return orig(self, match, subrepos, unknown, ignored, full) - extensions.wrapfunction(dirstate.dirstate, "walk", walk) + extensions.wrapfunction(dirstate.dirstate, b"walk", walk) # dirstate.rebuild should not add non-matching files def _rebuild(orig, self, parent, allfiles, changedfiles=None): @@ -250,13 +250,20 @@ return orig(self, parent, allfiles, changedfiles) - extensions.wrapfunction(dirstate.dirstate, "rebuild", _rebuild) + extensions.wrapfunction(dirstate.dirstate, b"rebuild", _rebuild) # Prevent adding files that are outside the sparse checkout - editfuncs = ["normal", "add", "normallookup", "copy", "remove", "merge"] + editfuncs = [ + b"normal", + b"add", + b"normallookup", + b"copy", + b"remove", + b"merge", + ] hint = _( - "include file with `hg debugsparse --include ` or use " - + "`hg add -s ` to include file directory while adding" + b"include file with `hg debugsparse --include ` or use " + + b"`hg add -s ` to include file directory while adding" ) for func in editfuncs: @@ -267,8 +274,8 @@ if f is not None and not sparsematch(f) and f not in self: raise error.Abort( _( - "cannot add '%s' - it is outside " - "the sparse checkout" + b"cannot add '%s' - it is outside " + b"the sparse checkout" ) % f, hint=hint, @@ -279,31 +286,31 @@ @command( - "debugsparse", + b"debugsparse", [ - ("I", "include", False, _("include files in the sparse checkout")), - ("X", "exclude", False, _("exclude files in the sparse checkout")), - ("d", "delete", False, _("delete an include/exclude rule")), + (b"I", b"include", False, _(b"include files in the sparse checkout")), + (b"X", b"exclude", False, _(b"exclude files in the sparse checkout")), + (b"d", b"delete", False, _(b"delete an include/exclude rule")), ( - "f", - "force", + b"f", + b"force", False, - _("allow changing rules even with pending changes"), + _(b"allow changing rules even with pending changes"), ), - ("", "enable-profile", False, _("enables the specified profile")), - ("", "disable-profile", False, _("disables the specified profile")), - ("", "import-rules", False, _("imports rules from a file")), - ("", "clear-rules", False, _("clears local include/exclude rules")), + (b"", b"enable-profile", False, _(b"enables the specified profile")), + (b"", b"disable-profile", False, _(b"disables the specified profile")), + (b"", b"import-rules", False, _(b"imports rules from a file")), + (b"", b"clear-rules", False, _(b"clears local include/exclude rules")), ( - "", - "refresh", + b"", + b"refresh", False, - _("updates the working after sparseness changes"), + _(b"updates the working after sparseness changes"), ), - ("", "reset", False, _("makes the repo full again")), + (b"", b"reset", False, _(b"makes the repo full again")), ] + commands.templateopts, - _("[--OPTION] PATTERN..."), + _(b"[--OPTION] PATTERN..."), helpbasic=True, ) def debugsparse(ui, repo, *pats, **opts): @@ -348,16 +355,16 @@ Returns 0 if editing the sparse checkout succeeds. """ opts = pycompat.byteskwargs(opts) - include = opts.get("include") - exclude = opts.get("exclude") - force = opts.get("force") - enableprofile = opts.get("enable_profile") - disableprofile = opts.get("disable_profile") - importrules = opts.get("import_rules") - clearrules = opts.get("clear_rules") - delete = opts.get("delete") - refresh = opts.get("refresh") - reset = opts.get("reset") + include = opts.get(b"include") + exclude = opts.get(b"exclude") + force = opts.get(b"force") + enableprofile = opts.get(b"enable_profile") + disableprofile = opts.get(b"disable_profile") + importrules = opts.get(b"import_rules") + clearrules = opts.get(b"clear_rules") + delete = opts.get(b"delete") + refresh = opts.get(b"refresh") + reset = opts.get(b"reset") count = sum( [ include, @@ -372,21 +379,23 @@ ] ) if count > 1: - raise error.Abort(_("too many flags specified")) + raise error.Abort(_(b"too many flags specified")) if count == 0: - if repo.vfs.exists("sparse"): - ui.status(repo.vfs.read("sparse") + "\n") + if repo.vfs.exists(b"sparse"): + ui.status(repo.vfs.read(b"sparse") + b"\n") temporaryincludes = sparse.readtemporaryincludes(repo) if temporaryincludes: - ui.status(_("Temporarily Included Files (for merge/rebase):\n")) - ui.status(("\n".join(temporaryincludes) + "\n")) + ui.status( + _(b"Temporarily Included Files (for merge/rebase):\n") + ) + ui.status((b"\n".join(temporaryincludes) + b"\n")) return else: raise error.Abort( _( - "the debugsparse command is only supported on" - " sparse repositories" + b"the debugsparse command is only supported on" + b" sparse repositories" ) ) diff --git a/hgext/split.py b/hgext/split.py --- a/hgext/split.py +++ b/hgext/split.py @@ -40,17 +40,17 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" @command( - "split", + b"split", [ - ("r", "rev", "", _("revision to split"), _("REV")), - ("", "rebase", True, _("rebase descendants after split")), + (b"r", b"rev", b"", _(b"revision to split"), _(b"REV")), + (b"", b"rebase", True, _(b"rebase descendants after split")), ] + cmdutil.commitopts2, - _("hg split [--no-rebase] [[-r] REV]"), + _(b"hg split [--no-rebase] [[-r] REV]"), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True, ) @@ -67,21 +67,21 @@ """ opts = pycompat.byteskwargs(opts) revlist = [] - if opts.get("rev"): - revlist.append(opts.get("rev")) + if opts.get(b"rev"): + revlist.append(opts.get(b"rev")) revlist.extend(revs) - with repo.wlock(), repo.lock(), repo.transaction("split") as tr: - revs = scmutil.revrange(repo, revlist or ["."]) + with repo.wlock(), repo.lock(), repo.transaction(b"split") as tr: + revs = scmutil.revrange(repo, revlist or [b"."]) if len(revs) > 1: - raise error.Abort(_("cannot split multiple revisions")) + raise error.Abort(_(b"cannot split multiple revisions")) rev = revs.first() ctx = repo[rev] if rev is None or ctx.node() == nullid: - ui.status(_("nothing to split\n")) + ui.status(_(b"nothing to split\n")) return 1 if ctx.node() is None: - raise error.Abort(_("cannot split working directory")) + raise error.Abort(_(b"cannot split working directory")) # rewriteutil.precheck is not very useful here because: # 1. null check is done above and it's more friendly to return 1 @@ -92,33 +92,33 @@ # So only "public" check is useful and it's checked directly here. if ctx.phase() == phases.public: raise error.Abort( - _("cannot split public changeset"), - hint=_("see 'hg help phases' for details"), + _(b"cannot split public changeset"), + hint=_(b"see 'hg help phases' for details"), ) - descendants = list(repo.revs("(%d::) - (%d)", rev, rev)) + descendants = list(repo.revs(b"(%d::) - (%d)", rev, rev)) alloworphaned = obsolete.isenabled(repo, obsolete.allowunstableopt) - if opts.get("rebase"): + if opts.get(b"rebase"): # Skip obsoleted descendants and their descendants so the rebase # won't cause conflicts for sure. torebase = list( repo.revs( - "%ld - (%ld & obsolete())::", descendants, descendants + b"%ld - (%ld & obsolete())::", descendants, descendants ) ) if not alloworphaned and len(torebase) != len(descendants): raise error.Abort( - _("split would leave orphaned changesets " "behind") + _(b"split would leave orphaned changesets " b"behind") ) else: if not alloworphaned and descendants: raise error.Abort( - _("cannot split changeset with children without rebase") + _(b"cannot split changeset with children without rebase") ) torebase = () if len(ctx.parents()) > 1: - raise error.Abort(_("cannot split a merge changeset")) + raise error.Abort(_(b"cannot split a merge changeset")) cmdutil.bailifchanged(repo) @@ -127,7 +127,7 @@ if bname and repo._bookmarks[bname] != ctx.node(): bookmarks.deactivate(repo) - wnode = repo["."].node() + wnode = repo[b"."].node() top = None try: top = dosplit(ui, repo, tr, ctx, opts) @@ -158,37 +158,37 @@ while incomplete(repo): if committed: header = _( - "HG: Splitting %s. So far it has been split into:\n" + b"HG: Splitting %s. So far it has been split into:\n" ) % short(ctx.node()) for c in committed: - firstline = c.description().split("\n", 1)[0] - header += _("HG: - %s: %s\n") % (short(c.node()), firstline) + firstline = c.description().split(b"\n", 1)[0] + header += _(b"HG: - %s: %s\n") % (short(c.node()), firstline) header += _( - "HG: Write commit message for the next split " "changeset.\n" + b"HG: Write commit message for the next split " b"changeset.\n" ) else: header = _( - "HG: Splitting %s. Write commit message for the " - "first split changeset.\n" + b"HG: Splitting %s. Write commit message for the " + b"first split changeset.\n" ) % short(ctx.node()) opts.update( { - "edit": True, - "interactive": True, - "message": header + ctx.description(), + b"edit": True, + b"interactive": True, + b"message": header + ctx.description(), } ) commands.commit(ui, repo, **pycompat.strkwargs(opts)) - newctx = repo["."] + newctx = repo[b"."] committed.append(newctx) if not committed: - raise error.Abort(_("cannot split an empty revision")) + raise error.Abort(_(b"cannot split an empty revision")) scmutil.cleanupnodes( repo, {ctx.node(): [c.node() for c in committed]}, - operation="split", + operation=b"split", fixphase=True, ) @@ -199,6 +199,6 @@ rebase.rebase( ui, repo, - rev=[revsetlang.formatspec("%ld", src)], - dest=revsetlang.formatspec("%d", destctx.rev()), + rev=[revsetlang.formatspec(b"%ld", src)], + dest=revsetlang.formatspec(b"%d", destctx.rev()), ) diff --git a/hgext/sqlitestore.py b/hgext/sqlitestore.py --- a/hgext/sqlitestore.py +++ b/hgext/sqlitestore.py @@ -89,9 +89,9 @@ # experimental config: storage.sqlite.compression configitem( - "storage", - "sqlite.compression", - default="zstd" if zstd else "zlib", + b"storage", + b"sqlite.compression", + default=b"zstd" if zstd else b"zlib", experimental=True, ) @@ -99,7 +99,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" REQUIREMENT = b"exp-sqlite-001" REQUIREMENT_ZSTD = b"exp-sqlite-comp-001=zstd" @@ -224,7 +224,7 @@ delta = zlib.decompress(delta) else: raise SQLiteStoreError( - "unhandled compression type: %d" % compression + b"unhandled compression type: %d" % compression ) deltas.append(delta) @@ -319,7 +319,7 @@ self._compengine = compression - if compression == "zstd": + if compression == b"zstd": self._cctx = zstd.ZstdCompressor(level=3) self._dctx = zstd.ZstdDecompressor() else: @@ -358,7 +358,7 @@ if i != rev: raise SQLiteStoreError( - _("sqlite database has inconsistent " "revision numbers") + _(b"sqlite database has inconsistent " b"revision numbers") ) if p1rev == nullrev: @@ -411,7 +411,7 @@ return nullid, nullid if node not in self._revisions: - raise error.LookupError(node, self._path, _("no node")) + raise error.LookupError(node, self._path, _(b"no node")) entry = self._revisions[node] return entry.p1node, entry.p2node @@ -431,7 +431,7 @@ return nullrev if node not in self._nodetorev: - raise error.LookupError(node, self._path, _("no node")) + raise error.LookupError(node, self._path, _(b"no node")) return self._nodetorev[node] @@ -532,7 +532,7 @@ node = self.node(node) if node not in self._nodetorev: - raise error.LookupError(node, self._path, _("no node")) + raise error.LookupError(node, self._path, _(b"no node")) if node in self._revisioncache: return self._revisioncache[node] @@ -586,9 +586,9 @@ assumehaveparentrevisions=False, deltamode=repository.CG_DELTAMODE_STD, ): - if nodesorder not in ("nodes", "storage", "linear", None): + if nodesorder not in (b"nodes", b"storage", b"linear", None): raise error.ProgrammingError( - "unhandled value for nodesorder: %s" % nodesorder + b"unhandled value for nodesorder: %s" % nodesorder ) nodes = [n for n in nodes if n != nullid] @@ -649,7 +649,7 @@ cachedelta=None, ): if flags: - raise SQLiteStoreError(_("flags not supported on revisions")) + raise SQLiteStoreError(_(b"flags not supported on revisions")) validatehash = node is not None node = node or storageutil.hashrevisionsha1(revisiondata, p1, p2) @@ -684,7 +684,7 @@ storeflags |= FLAG_CENSORED if wireflags & ~repository.REVISION_FLAG_CENSORED: - raise SQLiteStoreError("unhandled revision flag") + raise SQLiteStoreError(b"unhandled revision flag") if maybemissingparents: if p1 != nullid and not self.hasnode(p1): @@ -700,7 +700,7 @@ # If base is censored, delta must be full replacement in a single # patch operation. if baserev != nullrev and self.iscensored(baserev): - hlen = struct.calcsize(">lll") + hlen = struct.calcsize(b">lll") oldlen = len(self.rawdata(deltabase, _verifyhash=False)) newlen = len(delta) - hlen @@ -772,7 +772,7 @@ # SQLite, since columns can be resized at will. if len(tombstone) > len(self.rawdata(censornode)): raise error.Abort( - _("censor tombstone must be no longer than " "censored data") + _(b"censor tombstone must be no longer than " b"censored data") ) # We need to replace the censored revision's data with the tombstone. @@ -811,18 +811,18 @@ deltahash = hashlib.sha1(fulltext).digest() - if self._compengine == "zstd": + if self._compengine == b"zstd": deltablob = self._cctx.compress(fulltext) compression = COMPRESSION_ZSTD - elif self._compengine == "zlib": + elif self._compengine == b"zlib": deltablob = zlib.compress(fulltext) compression = COMPRESSION_ZLIB - elif self._compengine == "none": + elif self._compengine == b"none": deltablob = fulltext compression = COMPRESSION_NONE else: raise error.ProgrammingError( - "unhandled compression engine: %s" % self._compengine + b"unhandled compression engine: %s" % self._compengine ) if len(deltablob) >= len(fulltext): @@ -904,28 +904,28 @@ d = {} if exclusivefiles: - d["exclusivefiles"] = [] + d[b"exclusivefiles"] = [] if sharedfiles: # TODO list sqlite file(s) here. - d["sharedfiles"] = [] + d[b"sharedfiles"] = [] if revisionscount: - d["revisionscount"] = len(self) + d[b"revisionscount"] = len(self) if trackedsize: - d["trackedsize"] = sum( + d[b"trackedsize"] = sum( len(self.revision(node)) for node in self._nodetorev ) if storedsize: # TODO implement this? - d["storedsize"] = None + d[b"storedsize"] = None return d def verifyintegrity(self, state): - state["skipread"] = set() + state[b"skipread"] = set() for rev in self: node = self.node(rev) @@ -934,10 +934,10 @@ self.revision(node) except Exception as e: yield sqliteproblem( - error=_("unpacking %s: %s") % (short(node), e), node=node + error=_(b"unpacking %s: %s") % (short(node), e), node=node ) - state["skipread"].add(node) + state[b"skipread"].add(node) # End of ifilestorage interface. @@ -956,7 +956,7 @@ if storageutil.iscensoredtext(fulltext): raise error.CensoredNodeError(self._path, node, fulltext) - raise SQLiteStoreError(_("integrity check failed on %s") % self._path) + raise SQLiteStoreError(_(b"integrity check failed on %s") % self._path) def _addrawrevision( self, @@ -1008,18 +1008,18 @@ # first. deltahash = hashlib.sha1(delta).digest() - if self._compengine == "zstd": + if self._compengine == b"zstd": deltablob = self._cctx.compress(delta) compression = COMPRESSION_ZSTD - elif self._compengine == "zlib": + elif self._compengine == b"zlib": deltablob = zlib.compress(delta) compression = COMPRESSION_ZLIB - elif self._compengine == "none": + elif self._compengine == b"none": deltablob = delta compression = COMPRESSION_NONE else: raise error.ProgrammingError( - "unhandled compression engine: %s" % self._compengine + b"unhandled compression engine: %s" % self._compengine ) # Don't store compressed data if it isn't practical. @@ -1095,7 +1095,7 @@ def committransaction(_): self._dbconn.commit() - tr.addfinalize("sqlitestore", committransaction) + tr.addfinalize(b"sqlitestore", committransaction) return tr @@ -1110,7 +1110,7 @@ if self._db[0] == tid: return self._db[1] - db = makedb(self.svfs.join("db.sqlite")) + db = makedb(self.svfs.join(b"db.sqlite")) self._db = (tid, db) return db @@ -1135,7 +1135,7 @@ pass else: - raise error.Abort(_("sqlite database has unrecognized version")) + raise error.Abort(_(b"sqlite database has unrecognized version")) db.execute(r"PRAGMA journal_mode=WAL") @@ -1155,65 +1155,65 @@ def newreporequirements(orig, ui, createopts): - if createopts["backend"] != "sqlite": + if createopts[b"backend"] != b"sqlite": return orig(ui, createopts) # This restriction can be lifted once we have more confidence. - if "sharedrepo" in createopts: + if b"sharedrepo" in createopts: raise error.Abort( - _("shared repositories not supported with SQLite " "store") + _(b"shared repositories not supported with SQLite " b"store") ) # This filtering is out of an abundance of caution: we want to ensure # we honor creation options and we do that by annotating exactly the # creation options we recognize. known = { - "narrowfiles", - "backend", - "shallowfilestore", + b"narrowfiles", + b"backend", + b"shallowfilestore", } unsupported = set(createopts) - known if unsupported: raise error.Abort( - _("SQLite store does not support repo creation " "option: %s") - % ", ".join(sorted(unsupported)) + _(b"SQLite store does not support repo creation " b"option: %s") + % b", ".join(sorted(unsupported)) ) # Since we're a hybrid store that still relies on revlogs, we fall back # to using the revlogv1 backend's storage requirements then adding our # own requirement. - createopts["backend"] = "revlogv1" + createopts[b"backend"] = b"revlogv1" requirements = orig(ui, createopts) requirements.add(REQUIREMENT) - compression = ui.config("storage", "sqlite.compression") + compression = ui.config(b"storage", b"sqlite.compression") - if compression == "zstd" and not zstd: + if compression == b"zstd" and not zstd: raise error.Abort( _( - 'storage.sqlite.compression set to "zstd" but ' - "zstandard compression not available to this " - "Mercurial install" + b'storage.sqlite.compression set to "zstd" but ' + b"zstandard compression not available to this " + b"Mercurial install" ) ) - if compression == "zstd": + if compression == b"zstd": requirements.add(REQUIREMENT_ZSTD) - elif compression == "zlib": + elif compression == b"zlib": requirements.add(REQUIREMENT_ZLIB) - elif compression == "none": + elif compression == b"none": requirements.add(REQUIREMENT_NONE) else: raise error.Abort( _( - "unknown compression engine defined in " - "storage.sqlite.compression: %s" + b"unknown compression engine defined in " + b"storage.sqlite.compression: %s" ) % compression ) - if createopts.get("shallowfilestore"): + if createopts.get(b"shallowfilestore"): requirements.add(REQUIREMENT_SHALLOW_FILES) return requirements @@ -1228,16 +1228,16 @@ path = path[1:] if REQUIREMENT_ZSTD in self.requirements: - compression = "zstd" + compression = b"zstd" elif REQUIREMENT_ZLIB in self.requirements: - compression = "zlib" + compression = b"zlib" elif REQUIREMENT_NONE in self.requirements: - compression = "none" + compression = b"none" else: raise error.Abort( _( - "unable to determine what compression engine " - "to use for SQLite storage" + b"unable to determine what compression engine " + b"to use for SQLite storage" ) ) @@ -1260,8 +1260,8 @@ if REQUIREMENT_ZSTD in requirements and not zstd: raise error.Abort( _( - "repository uses zstandard compression, which " - "is not available to this Mercurial install" + b"repository uses zstandard compression, which " + b"is not available to this Mercurial install" ) ) @@ -1281,11 +1281,11 @@ def extsetup(ui): localrepo.featuresetupfuncs.add(featuresetup) extensions.wrapfunction( - localrepo, "newreporequirements", newreporequirements + localrepo, b"newreporequirements", newreporequirements ) - extensions.wrapfunction(localrepo, "makefilestorage", makefilestorage) - extensions.wrapfunction(localrepo, "makemain", makemain) - extensions.wrapfunction(verify.verifier, "__init__", verifierinit) + extensions.wrapfunction(localrepo, b"makefilestorage", makefilestorage) + extensions.wrapfunction(localrepo, b"makemain", makemain) + extensions.wrapfunction(verify.verifier, b"__init__", verifierinit) def reposetup(ui, repo): diff --git a/hgext/strip.py b/hgext/strip.py --- a/hgext/strip.py +++ b/hgext/strip.py @@ -30,7 +30,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def checklocalchanges(repo, force=False): @@ -48,14 +48,14 @@ currentbranch = repo[None].branch() if ( - util.safehasattr(repo, "mq") + util.safehasattr(repo, b"mq") and p2 != nullid and p2 in [x.node for x in repo.mq.applied] ): unode = p2 elif currentbranch != repo[unode].branch(): - pwdir = "parents(wdir())" - revset = "max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))" + pwdir = b"parents(wdir())" + revset = b"max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))" branchtarget = repo.revs( revset, nodes, pwdir, pwdir, nodes, pwdir, currentbranch ) @@ -91,61 +91,66 @@ repomarks = repo._bookmarks if bookmarks: - with repo.transaction("strip") as tr: + with repo.transaction(b"strip") as tr: if repo._activebookmark in bookmarks: bookmarksmod.deactivate(repo) repomarks.applychanges(repo, tr, [(b, None) for b in bookmarks]) for bookmark in sorted(bookmarks): - ui.write(_("bookmark '%s' deleted\n") % bookmark) + ui.write(_(b"bookmark '%s' deleted\n") % bookmark) @command( - "strip", + b"strip", [ ( - "r", - "rev", + b"r", + b"rev", [], _( - "strip specified revision (optional, " - "can specify revisions without this " - "option)" + b"strip specified revision (optional, " + b"can specify revisions without this " + b"option)" ), - _("REV"), + _(b"REV"), ), ( - "f", - "force", + b"f", + b"force", None, _( - "force removal of changesets, discard " - "uncommitted changes (no backup)" + b"force removal of changesets, discard " + b"uncommitted changes (no backup)" ), ), - ("", "no-backup", None, _("do not save backup bundle")), - ("", "nobackup", None, _("do not save backup bundle " "(DEPRECATED)")), - ("n", "", None, _("ignored (DEPRECATED)")), + (b"", b"no-backup", None, _(b"do not save backup bundle")), ( - "k", - "keep", + b"", + b"nobackup", None, - _("do not modify working directory during " "strip"), + _(b"do not save backup bundle " b"(DEPRECATED)"), + ), + (b"n", b"", None, _(b"ignored (DEPRECATED)")), + ( + b"k", + b"keep", + None, + _(b"do not modify working directory during " b"strip"), ), ( - "B", - "bookmark", + b"B", + b"bookmark", [], - _("remove revs only reachable from given" " bookmark"), - _("BOOKMARK"), + _(b"remove revs only reachable from given" b" bookmark"), + _(b"BOOKMARK"), ), ( - "", - "soft", + b"", + b"soft", None, - _("simply drop changesets from visible history (EXPERIMENTAL)"), + _(b"simply drop changesets from visible history (EXPERIMENTAL)"), ), ], - _("hg strip [-k] [-f] [-B bookmark] [-r] REV..."), + _(b"hg strip [-k] [-f] [-B bookmark] [-r] REV..."), helpcategory=command.CATEGORY_MAINTENANCE, ) def stripcmd(ui, repo, *revs, **opts): @@ -179,21 +184,21 @@ """ opts = pycompat.byteskwargs(opts) backup = True - if opts.get("no_backup") or opts.get("nobackup"): + if opts.get(b"no_backup") or opts.get(b"nobackup"): backup = False cl = repo.changelog - revs = list(revs) + opts.get("rev") + revs = list(revs) + opts.get(b"rev") revs = set(scmutil.revrange(repo, revs)) with repo.wlock(): - bookmarks = set(opts.get("bookmark")) + bookmarks = set(opts.get(b"bookmark")) if bookmarks: repomarks = repo._bookmarks if not bookmarks.issubset(repomarks): raise error.Abort( - _("bookmark '%s' not found") - % ",".join(sorted(bookmarks - set(repomarks.keys()))) + _(b"bookmark '%s' not found") + % b",".join(sorted(bookmarks - set(repomarks.keys()))) ) # If the requested bookmark is not the only one pointing to a @@ -207,14 +212,14 @@ rsrevs = scmutil.bookmarkrevs(repo, marks[0]) revs.update(set(rsrevs)) if not revs: - with repo.lock(), repo.transaction("bookmark") as tr: + with repo.lock(), repo.transaction(b"bookmark") as tr: bmchanges = [(b, None) for b in bookmarks] repomarks.applychanges(repo, tr, bmchanges) for bookmark in sorted(bookmarks): - ui.write(_("bookmark '%s' deleted\n") % bookmark) + ui.write(_(b"bookmark '%s' deleted\n") % bookmark) if not revs: - raise error.Abort(_("empty revision set")) + raise error.Abort(_(b"empty revision set")) descendants = set(cl.descendants(revs)) strippedrevs = revs.union(descendants) @@ -233,7 +238,7 @@ if q is not None and q.applied: # refresh queue state if we're about to strip # applied patches - if cl.rev(repo.lookup("qtip")) in strippedrevs: + if cl.rev(repo.lookup(b"qtip")) in strippedrevs: q.applieddirty = True start = 0 end = len(q.applied) @@ -247,7 +252,7 @@ q.savedirty() revs = sorted(rootnodes) - if update and opts.get("keep"): + if update and opts.get(b"keep"): urev = _findupdatetarget(repo, revs) uctx = repo[urev] @@ -261,14 +266,14 @@ # reset files that only changed in the dirstate too dirstate = repo.dirstate - dirchanges = [f for f in dirstate if dirstate[f] != "n"] + dirchanges = [f for f in dirstate if dirstate[f] != b"n"] changedfiles.extend(dirchanges) repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) repo.dirstate.write(repo.currenttransaction()) # clear resolve state - merge.mergestate.clean(repo, repo["."].node()) + merge.mergestate.clean(repo, repo[b"."].node()) update = False @@ -278,9 +283,9 @@ revs, backup=backup, update=update, - force=opts.get("force"), + force=opts.get(b"force"), bookmarks=bookmarks, - soft=opts["soft"], + soft=opts[b"soft"], ) return 0 diff --git a/hgext/transplant.py b/hgext/transplant.py --- a/hgext/transplant.py +++ b/hgext/transplant.py @@ -55,16 +55,16 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "transplant", "filter", default=None, + b"transplant", b"filter", default=None, ) configitem( - "transplant", "log", default=None, + b"transplant", b"log", default=None, ) @@ -90,7 +90,7 @@ abspath = os.path.join(self.path, self.transplantfile) if self.transplantfile and os.path.exists(abspath): for line in self.opener.read(self.transplantfile).splitlines(): - lnode, rnode = map(revlog.bin, line.split(":")) + lnode, rnode = map(revlog.bin, line.split(b":")) list = self.transplants.setdefault(rnode, []) list.append(transplantentry(lnode, rnode)) @@ -98,11 +98,11 @@ if self.dirty and self.transplantfile: if not os.path.isdir(self.path): os.mkdir(self.path) - fp = self.opener(self.transplantfile, "w") + fp = self.opener(self.transplantfile, b"w") for list in self.transplants.itervalues(): for t in list: l, r = map(nodemod.hex, (t.lnode, t.rnode)) - fp.write(l + ":" + r + "\n") + fp.write(l + b":" + r + b"\n") fp.close() self.dirty = False @@ -124,14 +124,14 @@ class transplanter(object): def __init__(self, ui, repo, opts): self.ui = ui - self.path = repo.vfs.join("transplant") + self.path = repo.vfs.join(b"transplant") self.opener = vfsmod.vfs(self.path) self.transplants = transplants( - self.path, "transplants", opener=self.opener + self.path, b"transplants", opener=self.opener ) def getcommiteditor(): - editform = cmdutil.mergeeditform(repo[None], "transplant") + editform = cmdutil.mergeeditform(repo[None], b"transplant") return cmdutil.getcommiteditor( editform=editform, **pycompat.strkwargs(opts) ) @@ -175,19 +175,19 @@ lock = tr = None try: lock = repo.lock() - tr = repo.transaction("transplant") + tr = repo.transaction(b"transplant") for rev in revs: node = revmap[rev] - revstr = "%d:%s" % (rev, nodemod.short(node)) + revstr = b"%d:%s" % (rev, nodemod.short(node)) if self.applied(repo, node, p1): self.ui.warn( - _("skipping already applied revision %s\n") % revstr + _(b"skipping already applied revision %s\n") % revstr ) continue parents = source.changelog.parents(node) - if not (opts.get("filter") or opts.get("log")): + if not (opts.get(b"filter") or opts.get(b"log")): # If the changeset parent is the same as the # wdir's parent, just pull it. if parents[0] == p1: @@ -214,17 +214,17 @@ skipmerge = False if parents[1] != revlog.nullid: - if not opts.get("parent"): + if not opts.get(b"parent"): self.ui.note( - _("skipping merge changeset %d:%s\n") + _(b"skipping merge changeset %d:%s\n") % (rev, nodemod.short(node)) ) skipmerge = True else: - parent = source.lookup(opts["parent"]) + parent = source.lookup(opts[b"parent"]) if parent not in parents: raise error.Abort( - _("%s is not a parent of %s") + _(b"%s is not a parent of %s") % (nodemod.short(parent), nodemod.short(node)) ) else: @@ -233,7 +233,7 @@ if skipmerge: patchfile = None else: - fd, patchfile = pycompat.mkstemp(prefix="hg-transplant-") + fd, patchfile = pycompat.mkstemp(prefix=b"hg-transplant-") fp = os.fdopen(fd, r"wb") gen = patch.diff(source, parent, node, opts=diffopts) for chunk in gen: @@ -250,8 +250,8 @@ source.changelog.read(node), patchfile, merge=domerge, - log=opts.get("log"), - filter=opts.get("filter"), + log=opts.get(b"log"), + filter=opts.get(b"filter"), ) except TransplantError: # Do not rollback, it is up to the user to @@ -260,12 +260,12 @@ raise if n and domerge: self.ui.status( - _("%s merged at %s\n") + _(b"%s merged at %s\n") % (revstr, nodemod.short(n)) ) elif n: self.ui.status( - _("%s transplanted to %s\n") + _(b"%s transplanted to %s\n") % (nodemod.short(node), nodemod.short(n)) ) finally: @@ -286,33 +286,33 @@ def filter(self, filter, node, changelog, patchfile): """arbitrarily rewrite changeset before applying it""" - self.ui.status(_("filtering %s\n") % patchfile) + self.ui.status(_(b"filtering %s\n") % patchfile) user, date, msg = (changelog[1], changelog[2], changelog[4]) - fd, headerfile = pycompat.mkstemp(prefix="hg-transplant-") + fd, headerfile = pycompat.mkstemp(prefix=b"hg-transplant-") fp = os.fdopen(fd, r"wb") - fp.write("# HG changeset patch\n") - fp.write("# User %s\n" % user) - fp.write("# Date %d %d\n" % date) - fp.write(msg + "\n") + fp.write(b"# HG changeset patch\n") + fp.write(b"# User %s\n" % user) + fp.write(b"# Date %d %d\n" % date) + fp.write(msg + b"\n") fp.close() try: self.ui.system( - "%s %s %s" + b"%s %s %s" % ( filter, procutil.shellquote(headerfile), procutil.shellquote(patchfile), ), environ={ - "HGUSER": changelog[1], - "HGREVISION": nodemod.hex(node), + b"HGUSER": changelog[1], + b"HGREVISION": nodemod.hex(node), }, onerr=error.Abort, - errprefix=_("filter failed"), - blockedtag="transplant_filter", + errprefix=_(b"filter failed"), + blockedtag=b"transplant_filter", ) - user, date, msg = self.parselog(open(headerfile, "rb"))[1:4] + user, date, msg = self.parselog(open(headerfile, b"rb"))[1:4] finally: os.unlink(headerfile) @@ -323,37 +323,37 @@ ): """apply the patch in patchfile to the repository as a transplant""" (manifest, user, (time, timezone), files, message) = cl[:5] - date = "%d %d" % (time, timezone) - extra = {"transplant_source": node} + date = b"%d %d" % (time, timezone) + extra = {b"transplant_source": node} if filter: (user, date, message) = self.filter(filter, node, cl, patchfile) if log: # we don't translate messages inserted into commits - message += "\n(transplanted from %s)" % nodemod.hex(node) + message += b"\n(transplanted from %s)" % nodemod.hex(node) - self.ui.status(_("applying %s\n") % nodemod.short(node)) - self.ui.note("%s %s\n%s\n" % (user, date, message)) + self.ui.status(_(b"applying %s\n") % nodemod.short(node)) + self.ui.note(b"%s %s\n%s\n" % (user, date, message)) if not patchfile and not merge: - raise error.Abort(_("can only omit patchfile if merging")) + raise error.Abort(_(b"can only omit patchfile if merging")) if patchfile: try: files = set() patch.patch(self.ui, repo, patchfile, files=files, eolmode=None) files = list(files) except Exception as inst: - seriespath = os.path.join(self.path, "series") + seriespath = os.path.join(self.path, b"series") if os.path.exists(seriespath): os.unlink(seriespath) p1 = repo.dirstate.p1() p2 = node self.log(user, date, message, p1, p2, merge=merge) - self.ui.write(stringutil.forcebytestr(inst) + "\n") + self.ui.write(stringutil.forcebytestr(inst) + b"\n") raise TransplantError( _( - "fix up the working directory and run " - "hg transplant --continue" + b"fix up the working directory and run " + b"hg transplant --continue" ) ) else: @@ -375,7 +375,7 @@ ) if not n: self.ui.warn( - _("skipping emptied changeset %s\n") % nodemod.short(node) + _(b"skipping emptied changeset %s\n") % nodemod.short(node) ) return None if not merge: @@ -384,22 +384,23 @@ return n def canresume(self): - return os.path.exists(os.path.join(self.path, "journal")) + return os.path.exists(os.path.join(self.path, b"journal")) def resume(self, repo, source, opts): """recover last transaction and apply remaining changesets""" - if os.path.exists(os.path.join(self.path, "journal")): + if os.path.exists(os.path.join(self.path, b"journal")): n, node = self.recover(repo, source, opts) if n: self.ui.status( - _("%s transplanted as %s\n") + _(b"%s transplanted as %s\n") % (nodemod.short(node), nodemod.short(n)) ) else: self.ui.status( - _("%s skipped due to empty diff\n") % (nodemod.short(node),) + _(b"%s skipped due to empty diff\n") + % (nodemod.short(node),) ) - seriespath = os.path.join(self.path, "series") + seriespath = os.path.join(self.path, b"series") if not os.path.exists(seriespath): self.transplants.write() return @@ -417,26 +418,26 @@ merge = False if not user or not date or not message or not parents[0]: - raise error.Abort(_("transplant log file is corrupt")) + raise error.Abort(_(b"transplant log file is corrupt")) parent = parents[0] if len(parents) > 1: - if opts.get("parent"): - parent = source.lookup(opts["parent"]) + if opts.get(b"parent"): + parent = source.lookup(opts[b"parent"]) if parent not in parents: raise error.Abort( - _("%s is not a parent of %s") + _(b"%s is not a parent of %s") % (nodemod.short(parent), nodemod.short(node)) ) else: merge = True - extra = {"transplant_source": node} + extra = {b"transplant_source": node} try: p1 = repo.dirstate.p1() if p1 != parent: raise error.Abort( - _("working directory not at transplant " "parent %s") + _(b"working directory not at transplant " b"parent %s") % nodemod.hex(parent) ) if merge: @@ -451,7 +452,7 @@ editor=self.getcommiteditor(), ) if not n: - raise error.Abort(_("commit failed")) + raise error.Abort(_(b"commit failed")) if not merge: self.transplants.set(n, node) else: @@ -467,11 +468,11 @@ def stop(self, ui, repo): """logic to stop an interrupted transplant""" if self.canresume(): - startctx = repo["."] + startctx = repo[b"."] hg.updaterepo(repo, startctx.node(), overwrite=True) - ui.status(_("stopped the interrupted transplant\n")) + ui.status(_(b"stopped the interrupted transplant\n")) ui.status( - _("working directory is now at %s\n") % startctx.hex()[:12] + _(b"working directory is now at %s\n") % startctx.hex()[:12] ) self.unlog() return 0 @@ -480,8 +481,8 @@ nodes = [] merges = [] cur = nodes - for line in self.opener.read("series").splitlines(): - if line.startswith("# Merges"): + for line in self.opener.read(b"series").splitlines(): + if line.startswith(b"# Merges"): cur = merges continue cur.append(revlog.bin(line)) @@ -494,13 +495,13 @@ if not os.path.isdir(self.path): os.mkdir(self.path) - series = self.opener("series", "w") + series = self.opener(b"series", b"w") for rev in sorted(revmap): - series.write(nodemod.hex(revmap[rev]) + "\n") + series.write(nodemod.hex(revmap[rev]) + b"\n") if merges: - series.write("# Merges\n") + series.write(b"# Merges\n") for m in merges: - series.write(nodemod.hex(m) + "\n") + series.write(nodemod.hex(m) + b"\n") series.close() def parselog(self, fp): @@ -513,42 +514,44 @@ for line in fp.read().splitlines(): if inmsg: message.append(line) - elif line.startswith("# User "): + elif line.startswith(b"# User "): user = line[7:] - elif line.startswith("# Date "): + elif line.startswith(b"# Date "): date = line[7:] - elif line.startswith("# Node ID "): + elif line.startswith(b"# Node ID "): node = revlog.bin(line[10:]) - elif line.startswith("# Parent "): + elif line.startswith(b"# Parent "): parents.append(revlog.bin(line[9:])) - elif not line.startswith("# "): + elif not line.startswith(b"# "): inmsg = True message.append(line) if None in (user, date): - raise error.Abort(_("filter corrupted changeset (no user or date)")) - return (node, user, date, "\n".join(message), parents) + raise error.Abort( + _(b"filter corrupted changeset (no user or date)") + ) + return (node, user, date, b"\n".join(message), parents) def log(self, user, date, message, p1, p2, merge=False): """journal changelog metadata for later recover""" if not os.path.isdir(self.path): os.mkdir(self.path) - fp = self.opener("journal", "w") - fp.write("# User %s\n" % user) - fp.write("# Date %s\n" % date) - fp.write("# Node ID %s\n" % nodemod.hex(p2)) - fp.write("# Parent " + nodemod.hex(p1) + "\n") + fp = self.opener(b"journal", b"w") + fp.write(b"# User %s\n" % user) + fp.write(b"# Date %s\n" % date) + fp.write(b"# Node ID %s\n" % nodemod.hex(p2)) + fp.write(b"# Parent " + nodemod.hex(p1) + b"\n") if merge: - fp.write("# Parent " + nodemod.hex(p2) + "\n") - fp.write(message.rstrip() + "\n") + fp.write(b"# Parent " + nodemod.hex(p2) + b"\n") + fp.write(message.rstrip() + b"\n") fp.close() def readlog(self): - return self.parselog(self.opener("journal")) + return self.parselog(self.opener(b"journal")) def unlog(self): """remove changelog journal""" - absdst = os.path.join(self.path, "journal") + absdst = os.path.join(self.path, b"journal") if os.path.exists(absdst): os.unlink(absdst) @@ -559,7 +562,7 @@ if source.changelog.parents(node)[1] != revlog.nullid: return False extra = source.changelog.read(node)[5] - cnode = extra.get("transplant_source") + cnode = extra.get(b"transplant_source") if cnode and self.applied(repo, cnode, root): return False return True @@ -580,37 +583,37 @@ transplants = [] merges = [] prompt = _( - "apply changeset? [ynmpcq?]:" - "$$ &yes, transplant this changeset" - "$$ &no, skip this changeset" - "$$ &merge at this changeset" - "$$ show &patch" - "$$ &commit selected changesets" - "$$ &quit and cancel transplant" - "$$ &? (show this help)" + b"apply changeset? [ynmpcq?]:" + b"$$ &yes, transplant this changeset" + b"$$ &no, skip this changeset" + b"$$ &merge at this changeset" + b"$$ show &patch" + b"$$ &commit selected changesets" + b"$$ &quit and cancel transplant" + b"$$ &? (show this help)" ) for node in nodes: displayer.show(repo[node]) action = None while not action: choice = ui.promptchoice(prompt) - action = "ynmpcq?"[choice : choice + 1] - if action == "?": + action = b"ynmpcq?"[choice : choice + 1] + if action == b"?": for c, t in ui.extractchoices(prompt)[1]: - ui.write("%s: %s\n" % (c, t)) + ui.write(b"%s: %s\n" % (c, t)) action = None - elif action == "p": + elif action == b"p": parent = repo.changelog.parents(node)[0] for chunk in patch.diff(repo, parent, node): ui.write(chunk) action = None - if action == "y": + if action == b"y": transplants.append(node) - elif action == "m": + elif action == b"m": merges.append(node) - elif action == "c": + elif action == b"c": break - elif action == "q": + elif action == b"q": transplants = () merges = () break @@ -619,37 +622,58 @@ @command( - "transplant", + b"transplant", [ - ("s", "source", "", _("transplant changesets from REPO"), _("REPO")), - ("b", "branch", [], _("use this source changeset as head"), _("REV")), + ( + b"s", + b"source", + b"", + _(b"transplant changesets from REPO"), + _(b"REPO"), + ), ( - "a", - "all", + b"b", + b"branch", + [], + _(b"use this source changeset as head"), + _(b"REV"), + ), + ( + b"a", + b"all", None, - _("pull all changesets up to the --branch revisions"), + _(b"pull all changesets up to the --branch revisions"), ), - ("p", "prune", [], _("skip over REV"), _("REV")), - ("m", "merge", [], _("merge at REV"), _("REV")), + (b"p", b"prune", [], _(b"skip over REV"), _(b"REV")), + (b"m", b"merge", [], _(b"merge at REV"), _(b"REV")), ( - "", - "parent", - "", - _("parent to choose when transplanting merge"), - _("REV"), + b"", + b"parent", + b"", + _(b"parent to choose when transplanting merge"), + _(b"REV"), ), - ("e", "edit", False, _("invoke editor on commit messages")), - ("", "log", None, _("append transplant info to log message")), - ("", "stop", False, _("stop interrupted transplant")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), + (b"", b"log", None, _(b"append transplant info to log message")), + (b"", b"stop", False, _(b"stop interrupted transplant")), + ( + b"c", + b"continue", + None, + _(b"continue last transplant session " b"after fixing conflicts"), + ), ( - "c", - "continue", - None, - _("continue last transplant session " "after fixing conflicts"), + b"", + b"filter", + b"", + _(b"filter changesets through command"), + _(b"CMD"), ), - ("", "filter", "", _("filter changesets through command"), _("CMD")), ], - _("hg transplant [-s REPO] [-b BRANCH [-a]] [-p REV] " "[-m REV] [REV]..."), + _( + b"hg transplant [-s REPO] [-b BRANCH [-a]] [-p REV] " + b"[-m REV] [REV]..." + ), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def transplant(ui, repo, *revs, **opts): @@ -728,74 +752,74 @@ yield node def checkopts(opts, revs): - if opts.get("continue"): - if opts.get("branch") or opts.get("all") or opts.get("merge"): + if opts.get(b"continue"): + if opts.get(b"branch") or opts.get(b"all") or opts.get(b"merge"): raise error.Abort( _( - "--continue is incompatible with " - "--branch, --all and --merge" + b"--continue is incompatible with " + b"--branch, --all and --merge" ) ) return - if opts.get("stop"): - if opts.get("branch") or opts.get("all") or opts.get("merge"): + if opts.get(b"stop"): + if opts.get(b"branch") or opts.get(b"all") or opts.get(b"merge"): raise error.Abort( _( - "--stop is incompatible with " - "--branch, --all and --merge" + b"--stop is incompatible with " + b"--branch, --all and --merge" ) ) return if not ( - opts.get("source") + opts.get(b"source") or revs - or opts.get("merge") - or opts.get("branch") + or opts.get(b"merge") + or opts.get(b"branch") ): raise error.Abort( _( - "no source URL, branch revision, or revision " - "list provided" + b"no source URL, branch revision, or revision " + b"list provided" ) ) - if opts.get("all"): - if not opts.get("branch"): - raise error.Abort(_("--all requires a branch revision")) + if opts.get(b"all"): + if not opts.get(b"branch"): + raise error.Abort(_(b"--all requires a branch revision")) if revs: raise error.Abort( - _("--all is incompatible with a " "revision list") + _(b"--all is incompatible with a " b"revision list") ) opts = pycompat.byteskwargs(opts) checkopts(opts, revs) - if not opts.get("log"): + if not opts.get(b"log"): # deprecated config: transplant.log - opts["log"] = ui.config("transplant", "log") - if not opts.get("filter"): + opts[b"log"] = ui.config(b"transplant", b"log") + if not opts.get(b"filter"): # deprecated config: transplant.filter - opts["filter"] = ui.config("transplant", "filter") + opts[b"filter"] = ui.config(b"transplant", b"filter") tp = transplanter(ui, repo, opts) p1 = repo.dirstate.p1() if len(repo) > 0 and p1 == revlog.nullid: - raise error.Abort(_("no revision checked out")) - if opts.get("continue"): + raise error.Abort(_(b"no revision checked out")) + if opts.get(b"continue"): if not tp.canresume(): - raise error.Abort(_("no transplant to continue")) - elif opts.get("stop"): + raise error.Abort(_(b"no transplant to continue")) + elif opts.get(b"stop"): if not tp.canresume(): - raise error.Abort(_("no interrupted transplant found")) + raise error.Abort(_(b"no interrupted transplant found")) return tp.stop(ui, repo) else: cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) - sourcerepo = opts.get("source") + sourcerepo = opts.get(b"source") if sourcerepo: peer = hg.peer(repo, opts, ui.expandpath(sourcerepo)) - heads = pycompat.maplist(peer.lookup, opts.get("branch", ())) + heads = pycompat.maplist(peer.lookup, opts.get(b"branch", ())) target = set(heads) for r in revs: try: @@ -807,36 +831,36 @@ ) else: source = repo - heads = pycompat.maplist(source.lookup, opts.get("branch", ())) + heads = pycompat.maplist(source.lookup, opts.get(b"branch", ())) cleanupfn = None try: - if opts.get("continue"): + if opts.get(b"continue"): tp.resume(repo, source, opts) return tf = tp.transplantfilter(repo, source, p1) - if opts.get("prune"): + if opts.get(b"prune"): prune = set( source[r].node() - for r in scmutil.revrange(source, opts.get("prune")) + for r in scmutil.revrange(source, opts.get(b"prune")) ) matchfn = lambda x: tf(x) and x not in prune else: matchfn = tf - merges = pycompat.maplist(source.lookup, opts.get("merge", ())) + merges = pycompat.maplist(source.lookup, opts.get(b"merge", ())) revmap = {} if revs: for r in scmutil.revrange(source, revs): revmap[int(r)] = source[r].node() - elif opts.get("all") or not merges: + elif opts.get(b"all") or not merges: if source != repo: alltransplants = incwalk(source, csets, match=matchfn) else: alltransplants = transplantwalk( source, p1, heads, match=matchfn ) - if opts.get("all"): + if opts.get(b"all"): revs = alltransplants else: revs, newmerges = browserevs(ui, source, alltransplants, opts) @@ -863,7 +887,7 @@ revsetpredicate = registrar.revsetpredicate() -@revsetpredicate("transplanted([set])") +@revsetpredicate(b"transplanted([set])") def revsettransplanted(repo, subset, x): """Transplanted changesets in set, or all transplanted changesets. """ @@ -872,33 +896,33 @@ else: s = subset return smartset.baseset( - [r for r in s if repo[r].extra().get("transplant_source")] + [r for r in s if repo[r].extra().get(b"transplant_source")] ) templatekeyword = registrar.templatekeyword() -@templatekeyword("transplanted", requires={"ctx"}) +@templatekeyword(b"transplanted", requires={b"ctx"}) def kwtransplanted(context, mapping): """String. The node identifier of the transplanted changeset if any.""" - ctx = context.resource(mapping, "ctx") - n = ctx.extra().get("transplant_source") - return n and nodemod.hex(n) or "" + ctx = context.resource(mapping, b"ctx") + n = ctx.extra().get(b"transplant_source") + return n and nodemod.hex(n) or b"" def extsetup(ui): statemod.addunfinished( - "transplant", - fname="transplant/journal", + b"transplant", + fname=b"transplant/journal", clearable=True, continuefunc=continuecmd, statushint=_( - "To continue: hg transplant --continue\n" - "To stop: hg transplant --stop" + b"To continue: hg transplant --continue\n" + b"To stop: hg transplant --stop" ), - cmdhint=_("use 'hg transplant --continue' or 'hg transplant --stop'"), + cmdhint=_(b"use 'hg transplant --continue' or 'hg transplant --stop'"), ) diff --git a/hgext/uncommit.py b/hgext/uncommit.py --- a/hgext/uncommit.py +++ b/hgext/uncommit.py @@ -43,17 +43,17 @@ configitem = registrar.configitem(configtable) configitem( - "experimental", "uncommitondirtywdir", default=False, + b"experimental", b"uncommitondirtywdir", default=False, ) configitem( - "experimental", "uncommit.keep", default=False, + b"experimental", b"uncommit.keep", default=False, ) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" def _commitfiltered( @@ -96,7 +96,7 @@ return mctx if not files: - repo.ui.status(_("note: keeping empty commit\n")) + repo.ui.status(_(b"note: keeping empty commit\n")) if message is None: message = ctx.description() @@ -119,14 +119,14 @@ @command( - "uncommit", + b"uncommit", [ - ("", "keep", None, _("allow an empty commit after uncommitting")), + (b"", b"keep", None, _(b"allow an empty commit after uncommitting")), ( - "", - "allow-dirty-working-copy", + b"", + b"allow-dirty-working-copy", False, - _("allow uncommit with outstanding changes"), + _(b"allow uncommit with outstanding changes"), ), (b"n", b"note", b"", _(b"store a note on uncommit"), _(b"TEXT")), ] @@ -134,7 +134,7 @@ + commands.commitopts + commands.commitopts2 + commands.commitopts3, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def uncommit(ui, repo, *pats, **opts): @@ -158,17 +158,17 @@ m, a, r, d = repo.status()[:4] isdirtypath = any(set(m + a + r + d) & set(pats)) allowdirtywcopy = opts[ - "allow_dirty_working_copy" - ] or repo.ui.configbool("experimental", "uncommitondirtywdir") + b"allow_dirty_working_copy" + ] or repo.ui.configbool(b"experimental", b"uncommitondirtywdir") if not allowdirtywcopy and (not pats or isdirtypath): cmdutil.bailifchanged( repo, - hint=_("requires " "--allow-dirty-working-copy to uncommit"), + hint=_(b"requires " b"--allow-dirty-working-copy to uncommit"), ) - old = repo["."] - rewriteutil.precheck(repo, [old.rev()], "uncommit") + old = repo[b"."] + rewriteutil.precheck(repo, [old.rev()], b"uncommit") if len(old.parents()) > 1: - raise error.Abort(_("cannot uncommit merge changeset")) + raise error.Abort(_(b"cannot uncommit merge changeset")) match = scmutil.match(old, pats, opts) @@ -200,17 +200,19 @@ hint=hint, ) - with repo.transaction("uncommit"): + with repo.transaction(b"uncommit"): if not (opts[b"message"] or opts[b"logfile"]): opts[b"message"] = old.description() message = cmdutil.logmessage(ui, opts) keepcommit = pats if not keepcommit: - if opts.get("keep") is not None: - keepcommit = opts.get("keep") + if opts.get(b"keep") is not None: + keepcommit = opts.get(b"keep") else: - keepcommit = ui.configbool("experimental", "uncommit.keep") + keepcommit = ui.configbool( + b"experimental", b"uncommit.keep" + ) newid = _commitfiltered( repo, old, @@ -221,7 +223,7 @@ date=opts.get(b"date"), ) if newid is None: - ui.status(_("nothing to uncommit\n")) + ui.status(_(b"nothing to uncommit\n")) return 1 mapping = {} @@ -235,7 +237,7 @@ with repo.dirstate.parentchange(): scmutil.movedirstate(repo, repo[newid], match) - scmutil.cleanupnodes(repo, mapping, "uncommit", fixphase=True) + scmutil.cleanupnodes(repo, mapping, b"uncommit", fixphase=True) def predecessormarkers(ctx): @@ -245,7 +247,7 @@ @command( - "unamend", + b"unamend", [], helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True, @@ -260,17 +262,17 @@ """ unfi = repo.unfiltered() - with repo.wlock(), repo.lock(), repo.transaction("unamend"): + with repo.wlock(), repo.lock(), repo.transaction(b"unamend"): # identify the commit from which to unamend - curctx = repo["."] + curctx = repo[b"."] - rewriteutil.precheck(repo, [curctx.rev()], "unamend") + rewriteutil.precheck(repo, [curctx.rev()], b"unamend") # identify the commit to which to unamend markers = list(predecessormarkers(curctx)) if len(markers) != 1: - e = _("changeset must have one predecessor, found %i predecessors") + e = _(b"changeset must have one predecessor, found %i predecessors") raise error.Abort(e % len(markers)) prednode = markers[0].prednode() @@ -279,7 +281,7 @@ # add an extra so that we get a new hash # note: allowing unamend to undo an unamend is an intentional feature extras = predctx.extra() - extras["unamend_source"] = curctx.hex() + extras[b"unamend_source"] = curctx.hex() def filectxfn(repo, ctx_, path): try: @@ -306,4 +308,4 @@ scmutil.movedirstate(repo, newpredctx) mapping = {curctx.node(): (newprednode,)} - scmutil.cleanupnodes(repo, mapping, "unamend", fixphase=True) + scmutil.cleanupnodes(repo, mapping, b"unamend", fixphase=True) diff --git a/hgext/win32mbcs.py b/hgext/win32mbcs.py --- a/hgext/win32mbcs.py +++ b/hgext/win32mbcs.py @@ -61,7 +61,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) @@ -69,7 +69,7 @@ # Encoding.encoding may be updated by --encoding option. # Use a lambda do delay the resolution. configitem( - "win32mbcs", "encoding", default=lambda: encoding.encoding, + b"win32mbcs", b"encoding", default=lambda: encoding.encoding, ) _encoding = None # see extsetup @@ -80,7 +80,7 @@ uarg = arg.decode(_encoding) if arg == uarg.encode(_encoding): return uarg - raise UnicodeError("Not local encoding") + raise UnicodeError(b"Not local encoding") elif isinstance(arg, tuple): return tuple(map(decode, arg)) elif isinstance(arg, list): @@ -110,7 +110,7 @@ us = decode(s) except UnicodeError: us = s - if us and us[-1] not in ":/\\": + if us and us[-1] not in b":/\\": s += pycompat.ossep return s @@ -127,7 +127,7 @@ return enc(func(*dec(args), **dec(kwds))) except UnicodeError: raise error.Abort( - _("[win32mbcs] filename conversion failed with" " %s encoding\n") + _(b"[win32mbcs] filename conversion failed with" b" %s encoding\n") % _encoding ) @@ -146,13 +146,13 @@ if args: args = list(args) args[0] = appendsep(args[0]) - if "path" in kwds: - kwds["path"] = appendsep(kwds["path"]) + if b"path" in kwds: + kwds[b"path"] = appendsep(kwds[b"path"]) return func(*args, **kwds) def wrapname(name, wrapper): - module, name = name.rsplit(".", 1) + module, name = name.rsplit(b".", 1) module = sys.modules[module] func = getattr(module, name) @@ -166,7 +166,7 @@ # List of functions to be wrapped. # NOTE: os.path.dirname() and os.path.basename() are safe because # they use result of os.path.split() -funcs = """os.path.join os.path.split os.path.splitext +funcs = b"""os.path.join os.path.split os.path.splitext os.path.normpath os.makedirs mercurial.util.endswithsep mercurial.util.splitpath mercurial.util.fscasesensitive mercurial.util.fspath mercurial.util.pconvert mercurial.util.normpath @@ -176,14 +176,14 @@ # These functions are required to be called with local encoded string # because they expects argument is local encoded string and cause # problem with unicode string. -rfuncs = """mercurial.encoding.upper mercurial.encoding.lower +rfuncs = b"""mercurial.encoding.upper mercurial.encoding.lower mercurial.util._filenamebytestr""" # List of Windows specific functions to be wrapped. -winfuncs = """os.path.splitunc""" +winfuncs = b"""os.path.splitunc""" # codec and alias names of sjis and big5 to be faked. -problematic_encodings = """big5 big5-tw csbig5 big5hkscs big5-hkscs +problematic_encodings = b"""big5 big5-tw csbig5 big5hkscs big5-hkscs hkscs cp932 932 ms932 mskanji ms-kanji shift_jis csshiftjis shiftjis sjis s_jis shift_jis_2004 shiftjis2004 sjis_2004 sjis2004 shift_jisx0213 shiftjisx0213 sjisx0213 s_jisx0213 950 cp950 ms950 """ @@ -192,13 +192,13 @@ def extsetup(ui): # TODO: decide use of config section for this extension if (not os.path.supports_unicode_filenames) and ( - pycompat.sysplatform != "cygwin" + pycompat.sysplatform != b"cygwin" ): - ui.warn(_("[win32mbcs] cannot activate on this platform.\n")) + ui.warn(_(b"[win32mbcs] cannot activate on this platform.\n")) return # determine encoding for filename global _encoding - _encoding = ui.config("win32mbcs", "encoding") + _encoding = ui.config(b"win32mbcs", b"encoding") # fake is only for relevant environment. if _encoding.lower() in problematic_encodings.split(): for f in funcs.split(): @@ -206,13 +206,13 @@ if pycompat.iswindows: for f in winfuncs.split(): wrapname(f, wrapper) - wrapname("mercurial.util.listdir", wrapperforlistdir) - wrapname("mercurial.windows.listdir", wrapperforlistdir) + wrapname(b"mercurial.util.listdir", wrapperforlistdir) + wrapname(b"mercurial.windows.listdir", wrapperforlistdir) # wrap functions to be called with local byte string arguments for f in rfuncs.split(): wrapname(f, reversewrapper) # Check sys.args manually instead of using ui.debug() because # command line options is not yet applied when # extensions.loadall() is called. - if "--debug" in sys.argv: - ui.write("[win32mbcs] activated with encoding: %s\n" % _encoding) + if b"--debug" in sys.argv: + ui.write(b"[win32mbcs] activated with encoding: %s\n" % _encoding) diff --git a/hgext/win32text.py b/hgext/win32text.py --- a/hgext/win32text.py +++ b/hgext/win32text.py @@ -56,20 +56,20 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" configtable = {} configitem = registrar.configitem(configtable) configitem( - "win32text", "warn", default=True, + b"win32text", b"warn", default=True, ) # regexp for single LF without CR preceding. -re_single_lf = re.compile("(^|[^\r])\n", re.MULTILINE) +re_single_lf = re.compile(b"(^|[^\r])\n", re.MULTILINE) -newlinestr = {"\r\n": "CRLF", "\r": "CR"} -filterstr = {"\r\n": "clever", "\r": "mac"} +newlinestr = {b"\r\n": b"CRLF", b"\r": b"CR"} +filterstr = {b"\r\n": b"clever", b"\r": b"mac"} def checknewline(s, newline, ui=None, repo=None, filename=None): @@ -80,32 +80,32 @@ if newline in s and ui and filename and repo: ui.warn( _( - "WARNING: %s already has %s line endings\n" - "and does not need EOL conversion by the win32text plugin.\n" - "Before your next commit, please reconsider your " - "encode/decode settings in \nMercurial.ini or %s.\n" + b"WARNING: %s already has %s line endings\n" + b"and does not need EOL conversion by the win32text plugin.\n" + b"Before your next commit, please reconsider your " + b"encode/decode settings in \nMercurial.ini or %s.\n" ) - % (filename, newlinestr[newline], repo.vfs.join("hgrc")) + % (filename, newlinestr[newline], repo.vfs.join(b"hgrc")) ) def dumbdecode(s, cmd, **kwargs): - checknewline(s, "\r\n", **kwargs) + checknewline(s, b"\r\n", **kwargs) # replace single LF to CRLF - return re_single_lf.sub("\\1\r\n", s) + return re_single_lf.sub(b"\\1\r\n", s) def dumbencode(s, cmd): - return s.replace("\r\n", "\n") + return s.replace(b"\r\n", b"\n") def macdumbdecode(s, cmd, **kwargs): - checknewline(s, "\r", **kwargs) - return s.replace("\n", "\r") + checknewline(s, b"\r", **kwargs) + return s.replace(b"\n", b"\r") def macdumbencode(s, cmd): - return s.replace("\r", "\n") + return s.replace(b"\r", b"\n") def cleverdecode(s, cmd, **kwargs): @@ -133,14 +133,14 @@ _filters = { - "dumbdecode:": dumbdecode, - "dumbencode:": dumbencode, - "cleverdecode:": cleverdecode, - "cleverencode:": cleverencode, - "macdumbdecode:": macdumbdecode, - "macdumbencode:": macdumbencode, - "macdecode:": macdecode, - "macencode:": macencode, + b"dumbdecode:": dumbdecode, + b"dumbencode:": dumbencode, + b"cleverdecode:": cleverdecode, + b"cleverencode:": cleverencode, + b"macdumbdecode:": macdumbdecode, + b"macdumbencode:": macdumbencode, + b"macdecode:": macdecode, + b"macencode:": macencode, } @@ -152,7 +152,7 @@ # newest version as canonical. this prevents us from blocking a # changegroup that contains an unacceptable commit followed later # by a commit that fixes the problem. - tip = repo["tip"] + tip = repo[b"tip"] for rev in pycompat.xrange( repo.changelog.tiprev(), repo[node].rev() - 1, -1 ): @@ -166,32 +166,32 @@ if not halt: ui.warn( _( - "attempt to commit or push text file(s) " - "using %s line endings\n" + b"attempt to commit or push text file(s) " + b"using %s line endings\n" ) % newlinestr[newline] ) - ui.warn(_("in %s: %s\n") % (short(c.node()), f)) + ui.warn(_(b"in %s: %s\n") % (short(c.node()), f)) halt = True - if halt and hooktype == "pretxnchangegroup": + if halt and hooktype == b"pretxnchangegroup": crlf = newlinestr[newline].lower() filter = filterstr[newline] ui.warn( _( - "\nTo prevent this mistake in your local repository,\n" - "add to Mercurial.ini or .hg/hgrc:\n" - "\n" - "[hooks]\n" - "pretxncommit.%s = python:hgext.win32text.forbid%s\n" - "\n" - "and also consider adding:\n" - "\n" - "[extensions]\n" - "win32text =\n" - "[encode]\n" - "** = %sencode:\n" - "[decode]\n" - "** = %sdecode:\n" + b"\nTo prevent this mistake in your local repository,\n" + b"add to Mercurial.ini or .hg/hgrc:\n" + b"\n" + b"[hooks]\n" + b"pretxncommit.%s = python:hgext.win32text.forbid%s\n" + b"\n" + b"and also consider adding:\n" + b"\n" + b"[extensions]\n" + b"win32text =\n" + b"[encode]\n" + b"** = %sencode:\n" + b"[decode]\n" + b"** = %sdecode:\n" ) % (crlf, crlf, filter, filter) ) @@ -199,11 +199,11 @@ def forbidcrlf(ui, repo, hooktype, node, **kwargs): - return forbidnewline(ui, repo, hooktype, node, "\r\n", **kwargs) + return forbidnewline(ui, repo, hooktype, node, b"\r\n", **kwargs) def forbidcr(ui, repo, hooktype, node, **kwargs): - return forbidnewline(ui, repo, hooktype, node, "\r", **kwargs) + return forbidnewline(ui, repo, hooktype, node, b"\r", **kwargs) def reposetup(ui, repo): @@ -215,10 +215,10 @@ def extsetup(ui): # deprecated config: win32text.warn - if ui.configbool("win32text", "warn"): + if ui.configbool(b"win32text", b"warn"): ui.warn( _( - "win32text is deprecated: " - "https://mercurial-scm.org/wiki/Win32TextExtension\n" + b"win32text is deprecated: " + b"https://mercurial-scm.org/wiki/Win32TextExtension\n" ) ) diff --git a/hgext/zeroconf/Zeroconf.py b/hgext/zeroconf/Zeroconf.py --- a/hgext/zeroconf/Zeroconf.py +++ b/hgext/zeroconf/Zeroconf.py @@ -76,9 +76,9 @@ ensure names end in '.local.' timeout on receiving socket for clean shutdown""" -__author__ = "Paul Scott-Murphy" -__email__ = "paul at scott dash murphy dot com" -__version__ = "0.12" +__author__ = b"Paul Scott-Murphy" +__email__ = b"paul at scott dash murphy dot com" +__version__ = b"0.12" import errno import itertools @@ -91,11 +91,11 @@ from mercurial import pycompat -__all__ = ["Zeroconf", "ServiceInfo", "ServiceBrowser"] +__all__ = [b"Zeroconf", b"ServiceInfo", b"ServiceBrowser"] # hook for threads -globals()["_GLOBAL_DONE"] = 0 +globals()[b"_GLOBAL_DONE"] = 0 # Some timing constants @@ -160,34 +160,34 @@ # Mapping constants to names _CLASSES = { - _CLASS_IN: "in", - _CLASS_CS: "cs", - _CLASS_CH: "ch", - _CLASS_HS: "hs", - _CLASS_NONE: "none", - _CLASS_ANY: "any", + _CLASS_IN: b"in", + _CLASS_CS: b"cs", + _CLASS_CH: b"ch", + _CLASS_HS: b"hs", + _CLASS_NONE: b"none", + _CLASS_ANY: b"any", } _TYPES = { - _TYPE_A: "a", - _TYPE_NS: "ns", - _TYPE_MD: "md", - _TYPE_MF: "mf", - _TYPE_CNAME: "cname", - _TYPE_SOA: "soa", - _TYPE_MB: "mb", - _TYPE_MG: "mg", - _TYPE_MR: "mr", - _TYPE_NULL: "null", - _TYPE_WKS: "wks", - _TYPE_PTR: "ptr", - _TYPE_HINFO: "hinfo", - _TYPE_MINFO: "minfo", - _TYPE_MX: "mx", - _TYPE_TXT: "txt", - _TYPE_AAAA: "quada", - _TYPE_SRV: "srv", - _TYPE_ANY: "any", + _TYPE_A: b"a", + _TYPE_NS: b"ns", + _TYPE_MD: b"md", + _TYPE_MF: b"mf", + _TYPE_CNAME: b"cname", + _TYPE_SOA: b"soa", + _TYPE_MB: b"mb", + _TYPE_MG: b"mg", + _TYPE_MR: b"mr", + _TYPE_NULL: b"null", + _TYPE_WKS: b"wks", + _TYPE_PTR: b"ptr", + _TYPE_HINFO: b"hinfo", + _TYPE_MINFO: b"minfo", + _TYPE_MX: b"mx", + _TYPE_TXT: b"txt", + _TYPE_AAAA: b"quada", + _TYPE_SRV: b"srv", + _TYPE_ANY: b"any", } # utility functions @@ -223,7 +223,7 @@ class BadDomainName(Exception): def __init__(self, pos): - Exception.__init__(self, "at position %s" % pos) + Exception.__init__(self, b"at position %s" % pos) class BadDomainNameCircular(BadDomainName): @@ -262,31 +262,31 @@ try: return _CLASSES[clazz] except KeyError: - return "?(%s)" % clazz + return b"?(%s)" % clazz def getType(self, type): """Type accessor""" try: return _TYPES[type] except KeyError: - return "?(%s)" % type + return b"?(%s)" % type def toString(self, hdr, other): """String representation with additional information""" - result = "%s[%s,%s" % ( + result = b"%s[%s,%s" % ( hdr, self.getType(self.type), self.getClazz(self.clazz), ) if self.unique: - result += "-unique," + result += b"-unique," else: - result += "," + result += b"," result += self.name if other is not None: - result += ",%s]" % other + result += b",%s]" % other else: - result += "]" + result += b"]" return result @@ -296,7 +296,7 @@ def __init__(self, name, type, clazz): if pycompat.ispy3 and isinstance(name, str): name = name.encode("ascii") - if not name.endswith(".local."): + if not name.endswith(b".local."): raise NonLocalNameException(name) DNSEntry.__init__(self, name, type, clazz) @@ -310,7 +310,7 @@ def __repr__(self): """String representation""" - return DNSEntry.toString(self, "question", None) + return DNSEntry.toString(self, b"question", None) class DNSRecord(DNSEntry): @@ -371,12 +371,12 @@ def toString(self, other): """String representation with additional information""" - arg = "%s/%s,%s" % ( + arg = b"%s/%s,%s" % ( self.ttl, self.getRemainingTTL(currentTimeMillis()), other, ) - return DNSEntry.toString(self, "record", arg) + return DNSEntry.toString(self, b"record", arg) class DNSAddress(DNSRecord): @@ -425,7 +425,7 @@ def __repr__(self): """String representation""" - return self.cpu + " " + self.os + return self.cpu + b" " + self.os class DNSPointer(DNSRecord): @@ -470,7 +470,7 @@ def __repr__(self): """String representation""" if len(self.text) > 10: - return self.toString(self.text[:7] + "...") + return self.toString(self.text[:7] + b"...") else: return self.toString(self.text) @@ -505,7 +505,7 @@ def __repr__(self): """String representation""" - return self.toString("%s:%s" % (self.server, self.port)) + return self.toString(b"%s:%s" % (self.server, self.port)) class DNSIncoming(object): @@ -528,7 +528,7 @@ def readHeader(self): """Reads header portion of packet""" - format = "!HHHHHH" + format = b"!HHHHHH" length = struct.calcsize(format) info = struct.unpack( format, self.data[self.offset : self.offset + length] @@ -544,7 +544,7 @@ def readQuestions(self): """Reads questions section of packet""" - format = "!HH" + format = b"!HH" length = struct.calcsize(format) for i in range(0, self.numquestions): name = self.readName() @@ -561,7 +561,7 @@ def readInt(self): """Reads an integer from the packet""" - format = "!I" + format = b"!I" length = struct.calcsize(format) info = struct.unpack( format, self.data[self.offset : self.offset + length] @@ -577,7 +577,7 @@ def readString(self, len): """Reads a string of a given length from the packet""" - format = "!%ds" % len + format = b"!%ds" % len length = struct.calcsize(format) info = struct.unpack( format, self.data[self.offset : self.offset + length] @@ -587,7 +587,7 @@ def readUnsignedShort(self): """Reads an unsigned short from the packet""" - format = "!H" + format = b"!H" length = struct.calcsize(format) info = struct.unpack( format, self.data[self.offset : self.offset + length] @@ -597,7 +597,7 @@ def readOthers(self): """Reads answers, authorities and additionals section of the packet""" - format = "!HHiH" + format = b"!HHiH" length = struct.calcsize(format) n = self.numanswers + self.numauthorities + self.numadditionals for i in range(0, n): @@ -746,31 +746,31 @@ def writeByte(self, value): """Writes a single byte to the packet""" - format = "!c" + format = b"!c" self.data.append(struct.pack(format, chr(value))) self.size += 1 def insertShort(self, index, value): """Inserts an unsigned short in a certain position in the packet""" - format = "!H" + format = b"!H" self.data.insert(index, struct.pack(format, value)) self.size += 2 def writeShort(self, value): """Writes an unsigned short to the packet""" - format = "!H" + format = b"!H" self.data.append(struct.pack(format, value)) self.size += 2 def writeInt(self, value): """Writes an unsigned integer to the packet""" - format = "!I" + format = b"!I" self.data.append(struct.pack(format, int(value))) self.size += 4 def writeString(self, value, length): """Writes a string to the packet""" - format = "!" + str(length) + "s" + format = b"!" + str(length) + b"s" self.data.append(struct.pack(format, value)) self.size += length @@ -796,8 +796,8 @@ # for future pointers to it. # self.names[name] = self.size - parts = name.split(".") - if parts[-1] == "": + parts = name.split(b".") + if parts[-1] == b"": parts = parts[:-1] for part in parts: self.writeUTF(part) @@ -835,7 +835,7 @@ record.write(self) self.size -= 2 - length = len("".join(self.data[index:])) + length = len(b"".join(self.data[index:])) self.insertShort(index, length) # Here is the short we adjusted for def packet(self): @@ -863,7 +863,7 @@ self.insertShort(0, 0) else: self.insertShort(0, self.id) - return "".join(self.data) + return b"".join(self.data) class DNSCache(object): @@ -939,7 +939,7 @@ self.start() def run(self): - while not globals()["_GLOBAL_DONE"]: + while not globals()[b"_GLOBAL_DONE"]: rs = self.getReaders() if len(rs) == 0: # No sockets to manage, but we wait for the timeout @@ -955,7 +955,7 @@ try: self.readers[sock].handle_read() except Exception: - if not globals()["_GLOBAL_DONE"]: + if not globals()[b"_GLOBAL_DONE"]: traceback.print_exc() except Exception: pass @@ -1035,7 +1035,7 @@ def run(self): while True: self.zeroconf.wait(10 * 1000) - if globals()["_GLOBAL_DONE"]: + if globals()[b"_GLOBAL_DONE"]: return now = currentTimeMillis() for record in self.zeroconf.cache.entries(): @@ -1108,7 +1108,7 @@ now = currentTimeMillis() if len(self.list) == 0 and self.nexttime > now: self.zeroconf.wait(self.nexttime - now) - if globals()["_GLOBAL_DONE"] or self.done: + if globals()[b"_GLOBAL_DONE"] or self.done: return now = currentTimeMillis() @@ -1174,24 +1174,24 @@ if isinstance(properties, dict): self.properties = properties list = [] - result = "" + result = b"" for key in properties: value = properties[key] if value is None: - suffix = "" + suffix = b"" elif isinstance(value, str): suffix = value elif isinstance(value, int): if value: - suffix = "true" + suffix = b"true" else: - suffix = "false" + suffix = b"false" else: - suffix = "" - list.append("=".join((key, suffix))) + suffix = b"" + list.append(b"=".join((key, suffix))) for item in list: - result = "".join( - (result, struct.pack("!c", chr(len(item))), item) + result = b"".join( + (result, struct.pack(b"!c", chr(len(item))), item) ) self.text = result else: @@ -1212,7 +1212,7 @@ index += length for s in strs: - eindex = s.find("=") + eindex = s.find(b"=") if eindex == -1: # No equals sign at all key = s @@ -1220,9 +1220,9 @@ else: key = s[:eindex] value = s[eindex + 1 :] - if value == "true": + if value == b"true": value = 1 - elif value == "false" or not value: + elif value == b"false" or not value: value = 0 # Only update non-existent properties @@ -1240,7 +1240,7 @@ def getName(self): """Name accessor""" - if self.type is not None and self.name.endswith("." + self.type): + if self.type is not None and self.name.endswith(b"." + self.type): return self.name[: len(self.name) - len(self.type) - 1] return self.name @@ -1368,19 +1368,19 @@ def __repr__(self): """String representation""" - result = "service[%s,%s:%s," % ( + result = b"service[%s,%s:%s," % ( self.name, socket.inet_ntoa(self.getAddress()), self.port, ) if self.text is None: - result += "None" + result += b"None" else: if len(self.text) < 20: result += self.text else: - result += self.text[:17] + "..." - result += "]" + result += self.text[:17] + b"..." + result += b"]" return result @@ -1393,12 +1393,12 @@ def __init__(self, bindaddress=None): """Creates an instance of the Zeroconf class, establishing multicast communications, listening and reaping threads.""" - globals()["_GLOBAL_DONE"] = 0 + globals()[b"_GLOBAL_DONE"] = 0 if bindaddress is None: self.intf = socket.gethostbyname(socket.gethostname()) else: self.intf = bindaddress - self.group = ("", _MDNS_PORT) + self.group = (b"", _MDNS_PORT) self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -1414,8 +1414,8 @@ # work as expected. # pass - self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, "\xff") - self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, "\x01") + self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, b"\xff") + self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, b"\x01") try: self.socket.bind(self.group) except Exception: @@ -1442,10 +1442,10 @@ self.reaper = Reaper(self) def isLoopback(self): - return self.intf.startswith("127.0.0.1") + return self.intf.startswith(b"127.0.0.1") def isLinklocal(self): - return self.intf.startswith("169.254.") + return self.intf.startswith(b"169.254.") def wait(self, timeout): """Calling thread waits for a given number of milliseconds or @@ -1642,8 +1642,8 @@ and not record.isExpired(now) and record.alias == info.name ): - if info.name.find(".") < 0: - info.name = "%w.[%s:%d].%s" % ( + if info.name.find(b".") < 0: + info.name = b"%w.[%s:%d].%s" % ( info.name, info.address, info.port, @@ -1726,14 +1726,14 @@ for question in msg.questions: if question.type == _TYPE_PTR: - if question.name == "_services._dns-sd._udp.local.": + if question.name == b"_services._dns-sd._udp.local.": for stype in self.servicetypes.keys(): if out is None: out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) out.addAnswer( msg, DNSPointer( - "_services._dns-sd._udp.local.", + b"_services._dns-sd._udp.local.", _TYPE_PTR, _CLASS_IN, _DNS_TTL, @@ -1833,8 +1833,8 @@ def close(self): """Ends the background threads, and prevent this instance from servicing further queries.""" - if globals()["_GLOBAL_DONE"] == 0: - globals()["_GLOBAL_DONE"] = 1 + if globals()[b"_GLOBAL_DONE"] == 0: + globals()[b"_GLOBAL_DONE"] = 1 self.notifyAll() self.engine.notify() self.unregisterAllServices() @@ -1850,39 +1850,39 @@ # query (for Zoe), and service unregistration. if __name__ == "__main__": - print("Multicast DNS Service Discovery for Python, version", __version__) + print(b"Multicast DNS Service Discovery for Python, version", __version__) r = Zeroconf() - print("1. Testing registration of a service...") - desc = {"version": "0.10", "a": "test value", "b": "another value"} + print(b"1. Testing registration of a service...") + desc = {b"version": b"0.10", b"a": b"test value", b"b": b"another value"} info = ServiceInfo( - "_http._tcp.local.", - "My Service Name._http._tcp.local.", - socket.inet_aton("127.0.0.1"), + b"_http._tcp.local.", + b"My Service Name._http._tcp.local.", + socket.inet_aton(b"127.0.0.1"), 1234, 0, 0, desc, ) - print(" Registering service...") + print(b" Registering service...") r.registerService(info) - print(" Registration done.") - print("2. Testing query of service information...") + print(b" Registration done.") + print(b"2. Testing query of service information...") print( - " Getting ZOE service:", - str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local.")), + b" Getting ZOE service:", + str(r.getServiceInfo(b"_http._tcp.local.", b"ZOE._http._tcp.local.")), ) - print(" Query done.") - print("3. Testing query of own service...") + print(b" Query done.") + print(b"3. Testing query of own service...") print( - " Getting self:", + b" Getting self:", str( r.getServiceInfo( - "_http._tcp.local.", "My Service Name._http._tcp.local." + b"_http._tcp.local.", b"My Service Name._http._tcp.local." ) ), ) - print(" Query done.") - print("4. Testing unregister of service information...") + print(b" Query done.") + print(b"4. Testing unregister of service information...") r.unregisterService(info) - print(" Unregister done.") + print(b" Unregister done.") r.close() diff --git a/hgext/zeroconf/__init__.py b/hgext/zeroconf/__init__.py --- a/hgext/zeroconf/__init__.py +++ b/hgext/zeroconf/__init__.py @@ -43,7 +43,7 @@ # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. -testedwith = "ships-with-hg-core" +testedwith = b"ships-with-hg-core" # publish @@ -99,11 +99,11 @@ # advertise to browsers svc = Zeroconf.ServiceInfo( - "_http._tcp.local.", + b"_http._tcp.local.", pycompat.bytestr(name + r"._http._tcp.local."), server=host, port=port, - properties={"description": desc, "path": "/" + path}, + properties={b"description": desc, b"path": b"/" + path}, address=localip, weight=0, priority=0, @@ -112,11 +112,11 @@ # advertise to Mercurial clients svc = Zeroconf.ServiceInfo( - "_hg._tcp.local.", + b"_hg._tcp.local.", pycompat.bytestr(name + r"._hg._tcp.local."), server=host, port=port, - properties={"description": desc, "path": "/" + path}, + properties={b"description": desc, b"path": b"/" + path}, address=localip, weight=0, priority=0, @@ -134,20 +134,20 @@ # single repo with app._obtainrepo() as repo: name = app.reponame or os.path.basename(repo.root) - path = repo.ui.config("web", "prefix", "").strip("/") - desc = repo.ui.config("web", "description") + path = repo.ui.config(b"web", b"prefix", b"").strip(b"/") + desc = repo.ui.config(b"web", b"description") if not desc: desc = name publish(name, desc, path, port) else: # webdir - prefix = app.ui.config("web", "prefix", "").strip("/") + "/" + prefix = app.ui.config(b"web", b"prefix", b"").strip(b"/") + b"/" for repo, path in repos: u = app.ui.copy() - u.readconfig(os.path.join(path, ".hg", "hgrc")) + u.readconfig(os.path.join(path, b".hg", b"hgrc")) name = os.path.basename(repo) - path = (prefix + repo).strip("/") - desc = u.config("web", "description") + path = (prefix + repo).strip(b"/") + desc = u.config(b"web", b"description") if not desc: desc = name publish(name, desc, path, port) @@ -175,7 +175,7 @@ return server = Zeroconf.Zeroconf(ip) l = listener() - Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l) + Zeroconf.ServiceBrowser(server, b"_hg._tcp.local.", l) time.sleep(1) server.close() for value in l.found.values(): @@ -189,7 +189,7 @@ def config(orig, self, section, key, *args, **kwargs): - if section == "paths" and key.startswith("zc-"): + if section == b"paths" and key.startswith(b"zc-"): for name, path in getzcpaths(): if name == key: return path @@ -198,14 +198,14 @@ def configitems(orig, self, section, *args, **kwargs): repos = orig(self, section, *args, **kwargs) - if section == "paths": + if section == b"paths": repos += getzcpaths() return repos def configsuboptions(orig, self, section, name, *args, **kwargs): opt, sub = orig(self, section, name, *args, **kwargs) - if section == "paths" and name.startswith("zc-"): + if section == b"paths" and name.startswith(b"zc-"): # We have to find the URL in the zeroconf paths. We can't cons up any # suboptions, so we use any that we found in the original config. for zcname, zcurl in getzcpaths(): @@ -232,10 +232,10 @@ server.close() -extensions.wrapfunction(dispatch, "_runcommand", cleanupafterdispatch) +extensions.wrapfunction(dispatch, b"_runcommand", cleanupafterdispatch) -extensions.wrapfunction(uimod.ui, "config", config) -extensions.wrapfunction(uimod.ui, "configitems", configitems) -extensions.wrapfunction(uimod.ui, "configsuboptions", configsuboptions) -extensions.wrapfunction(hg, "defaultdest", defaultdest) -extensions.wrapfunction(servermod, "create_server", zc_create_server) +extensions.wrapfunction(uimod.ui, b"config", config) +extensions.wrapfunction(uimod.ui, b"configitems", configitems) +extensions.wrapfunction(uimod.ui, b"configsuboptions", configsuboptions) +extensions.wrapfunction(hg, b"defaultdest", defaultdest) +extensions.wrapfunction(servermod, b"create_server", zc_create_server) diff --git a/mercurial/__init__.py b/mercurial/__init__.py --- a/mercurial/__init__.py +++ b/mercurial/__init__.py @@ -31,23 +31,23 @@ def find_spec(self, fullname, path, target=None): # Only handle Mercurial-related modules. - if not fullname.startswith(("mercurial.", "hgext.")): + if not fullname.startswith((b"mercurial.", b"hgext.")): return None # don't try to parse binary - if fullname.startswith("mercurial.cext."): + if fullname.startswith(b"mercurial.cext."): return None # third-party packages are expected to be dual-version clean - if fullname.startswith("mercurial.thirdparty"): + if fullname.startswith(b"mercurial.thirdparty"): return None # zstd is already dual-version clean, don't try and mangle it - if fullname.startswith("mercurial.zstd"): + if fullname.startswith(b"mercurial.zstd"): return None # rustext is built for the right python version, # don't try and mangle it - if fullname.startswith("mercurial.rustext"): + if fullname.startswith(b"mercurial.rustext"): return None # pywatchman is already dual-version clean, don't try and mangle it - if fullname.startswith("hgext.fsmonitor.pywatchman"): + if fullname.startswith(b"hgext.fsmonitor.pywatchman"): return None # Try to find the module using other registered finders. @@ -123,7 +123,7 @@ """ nested = 0 for j in range(i + 2, len(tokens)): - if _isop(j, ")", "]", "}"): + if _isop(j, b")", b"]", b"}"): # end of call, tuple, subscription or dict / set nested -= 1 if nested < 0: @@ -131,9 +131,9 @@ elif n == 0: # this is the starting position of arg return j - elif _isop(j, "(", "[", "{"): + elif _isop(j, b"(", b"[", b"{"): nested += 1 - elif _isop(j, ",") and nested == 0: + elif _isop(j, b",") and nested == 0: n -= 1 return None @@ -149,8 +149,8 @@ """ st = tokens[j] - if st.type == token.STRING and st.string.startswith(("'", '"')): - tokens[j] = st._replace(string="u%s" % st.string) + if st.type == token.STRING and st.string.startswith((b"'", b'"')): + tokens[j] = st._replace(string=b"u%s" % st.string) for i, t in enumerate(tokens): # Convert most string literals to byte literals. String literals @@ -170,33 +170,33 @@ # docstrings as unprefixed to avoid this. This means Mercurial # components touching docstrings need to handle unicode, # unfortunately. - if s[0:3] in ("'''", '"""'): + if s[0:3] in (b"'''", b'"""'): yield t continue # If the first character isn't a quote, it is likely a string # prefixing character (such as 'b', 'u', or 'r'. Ignore. - if s[0] not in ("'", '"'): + if s[0] not in (b"'", b'"'): yield t continue # String literal. Prefix to make a b'' string. - yield t._replace(string="b%s" % t.string) + yield t._replace(string=b"b%s" % t.string) continue # Insert compatibility imports at "from __future__ import" line. # No '\n' should be added to preserve line numbers. if ( t.type == token.NAME - and t.string == "import" + and t.string == b"import" and all(u.type == token.NAME for u in tokens[i - 2 : i]) and [u.string for u in tokens[i - 2 : i]] - == ["from", "__future__"] + == [b"from", b"__future__"] ): futureimpline = True if t.type == token.NEWLINE and futureimpline: futureimpline = False - if fullname == "mercurial.pycompat": + if fullname == b"mercurial.pycompat": yield t continue r, c = t.start @@ -214,23 +214,23 @@ continue # This looks like a function call. - if t.type == token.NAME and _isop(i + 1, "("): + if t.type == token.NAME and _isop(i + 1, b"("): fn = t.string # *attr() builtins don't accept byte strings to 2nd argument. if fn in ( - "getattr", - "setattr", - "hasattr", - "safehasattr", - ) and not _isop(i - 1, "."): + b"getattr", + b"setattr", + b"hasattr", + b"safehasattr", + ) and not _isop(i - 1, b"."): arg1idx = _findargnofcall(1) if arg1idx is not None: _ensureunicode(arg1idx) # .encode() and .decode() on str/bytes/unicode don't accept # byte strings on Python 3. - elif fn in ("encode", "decode") and _isop(i - 1, "."): + elif fn in (b"encode", b"decode") and _isop(i - 1, b"."): for argn in range(2): argidx = _findargnofcall(argn) if argidx is not None: @@ -238,9 +238,9 @@ # It changes iteritems/values to items/values as they are not # present in Python 3 world. - elif fn in ("iteritems", "itervalues") and not ( + elif fn in (b"iteritems", b"itervalues") and not ( tokens[i - 1].type == token.NAME - and tokens[i - 1].string == "def" + and tokens[i - 1].string == b"def" ): yield t._replace(string=fn[4:]) continue @@ -296,9 +296,9 @@ # ``SourceFileLoader.get_code()`` expects when loading bytecode # paths to indicate the cached file is "bad." if data[0:2] != b"HG": - raise OSError("no hg header") + raise OSError(b"no hg header") if data[0:4] != BYTECODEHEADER: - raise OSError("hg header version mismatch") + raise OSError(b"hg header version mismatch") return data[4:] diff --git a/mercurial/archival.py b/mercurial/archival.py --- a/mercurial/archival.py +++ b/mercurial/archival.py @@ -43,7 +43,7 @@ prefix = util.normpath(prefix) else: if not isinstance(dest, bytes): - raise ValueError("dest must be string if no prefix") + raise ValueError(b"dest must be string if no prefix") prefix = os.path.basename(dest) lower = prefix.lower() for sfx in exts.get(kind, []): @@ -52,23 +52,23 @@ break lpfx = os.path.normpath(util.localpath(prefix)) prefix = util.pconvert(lpfx) - if not prefix.endswith("/"): - prefix += "/" + if not prefix.endswith(b"/"): + prefix += b"/" # Drop the leading '.' path component if present, so Windows can read the # zip files (issue4634) - if prefix.startswith("./"): + if prefix.startswith(b"./"): prefix = prefix[2:] - if prefix.startswith("../") or os.path.isabs(lpfx) or "/../" in prefix: - raise error.Abort(_("archive prefix contains illegal components")) + if prefix.startswith(b"../") or os.path.isabs(lpfx) or b"/../" in prefix: + raise error.Abort(_(b"archive prefix contains illegal components")) return prefix exts = { - "tar": [".tar"], - "tbz2": [".tbz2", ".tar.bz2"], - "tgz": [".tgz", ".tar.gz"], - "zip": [".zip"], - "txz": [".txz", ".tar.xz"], + b"tar": [b".tar"], + b"tbz2": [b".tbz2", b".tar.bz2"], + b"tgz": [b".tgz", b".tar.gz"], + b"zip": [b".zip"], + b"txz": [b".txz", b".tar.xz"], } @@ -108,22 +108,22 @@ repo = ctx.repo() opts = { - "template": repo.ui.config( - "experimental", "archivemetatemplate", _defaultmetatemplate + b"template": repo.ui.config( + b"experimental", b"archivemetatemplate", _defaultmetatemplate ) } out = util.stringio() - fm = formatter.formatter(repo.ui, out, "archive", opts) + fm = formatter.formatter(repo.ui, out, b"archive", opts) fm.startitem() fm.context(ctx=ctx) fm.data(root=_rootctx(repo).hex()) if ctx.rev() is None: - dirty = "" + dirty = b"" if ctx.dirty(missing=True): - dirty = "+" + dirty = b"+" fm.data(dirty=dirty) fm.end() @@ -146,33 +146,33 @@ gzip.GzipFile.__init__(self, *args, **kw) def _write_gzip_header(self): - self.fileobj.write("\037\213") # magic header - self.fileobj.write("\010") # compression method + self.fileobj.write(b"\037\213") # magic header + self.fileobj.write(b"\010") # compression method fname = self.name - if fname and fname.endswith(".gz"): + if fname and fname.endswith(b".gz"): fname = fname[:-3] flags = 0 if fname: flags = gzip.FNAME self.fileobj.write(pycompat.bytechr(flags)) gzip.write32u(self.fileobj, int(self.timestamp)) - self.fileobj.write("\002") - self.fileobj.write("\377") + self.fileobj.write(b"\002") + self.fileobj.write(b"\377") if fname: - self.fileobj.write(fname + "\000") + self.fileobj.write(fname + b"\000") - def __init__(self, dest, mtime, kind=""): + def __init__(self, dest, mtime, kind=b""): self.mtime = mtime self.fileobj = None - def taropen(mode, name="", fileobj=None): - if kind == "gz": + def taropen(mode, name=b"", fileobj=None): + if kind == b"gz": mode = mode[0:1] if not fileobj: - fileobj = open(name, mode + "b") + fileobj = open(name, mode + b"b") gzfileobj = self.GzipFileWithTime( name, - pycompat.sysstr(mode + "b"), + pycompat.sysstr(mode + b"b"), zlib.Z_BEST_COMPRESSION, fileobj, timestamp=mtime, @@ -185,9 +185,9 @@ return tarfile.open(name, pycompat.sysstr(mode + kind), fileobj) if isinstance(dest, bytes): - self.z = taropen("w:", name=dest) + self.z = taropen(b"w:", name=dest) else: - self.z = taropen("w|", fileobj=dest) + self.z = taropen(b"w|", fileobj=dest) def addfile(self, name, mode, islink, data): name = pycompat.fsdecode(name) @@ -246,7 +246,7 @@ # without this will be extracted with unexpected timestamp, # if TZ is not configured as GMT i.extra += struct.pack( - " 3 and not force: try: @@ -316,9 +318,9 @@ if shadowhash: self._repo.ui.warn( _( - "bookmark %s matches a changeset hash\n" - "(did you leave a -r out of an 'hg bookmark' " - "command?)\n" + b"bookmark %s matches a changeset hash\n" + b"(did you leave a -r out of an 'hg bookmark' " + b"command?)\n" ) % mark ) @@ -333,9 +335,9 @@ """ # No readline() in osutil.posixfile, reading everything is # cheap. - content = repo.vfs.tryread("bookmarks.current") - mark = encoding.tolocal((content.splitlines() or [""])[0]) - if mark == "" or mark not in marks: + content = repo.vfs.tryread(b"bookmarks.current") + mark = encoding.tolocal((content.splitlines() or [b""])[0]) + if mark == b"" or mark not in marks: mark = None return mark @@ -379,9 +381,11 @@ the list of bookmark to delete.""" todelete = [] marks = repo._bookmarks - divergent = [b for b in marks if b.split("@", 1)[0] == bm.split("@", 1)[0]] + divergent = [ + b for b in marks if b.split(b"@", 1)[0] == bm.split(b"@", 1)[0] + ] for mark in divergent: - if mark == "@" or "@" not in mark: + if mark == b"@" or b"@" not in mark: # can't be divergent by definition continue if mark and marks[mark] in deletefrom: @@ -404,12 +408,12 @@ """ if not repo._activebookmark: raise ValueError( - "headsforactive() only makes sense with an active bookmark" + b"headsforactive() only makes sense with an active bookmark" ) - name = repo._activebookmark.split("@", 1)[0] + name = repo._activebookmark.split(b"@", 1)[0] heads = [] for mark, n in repo._bookmarks.iteritems(): - if mark.split("@", 1)[0] == name: + if mark.split(b"@", 1)[0] == name: heads.append(n) return heads @@ -420,9 +424,9 @@ checkout, movemarkfrom = None, None activemark = repo._activebookmark if isactivewdirparent(repo): - movemarkfrom = repo["."].node() + movemarkfrom = repo[b"."].node() elif activemark: - ui.status(_("updating to active bookmark %s\n") % activemark) + ui.status(_(b"updating to active bookmark %s\n") % activemark) checkout = activemark return (checkout, movemarkfrom) @@ -440,7 +444,7 @@ divs = [ repo[marks[b]] for b in marks - if b.split("@", 1)[0] == active.split("@", 1)[0] + if b.split(b"@", 1)[0] == active.split(b"@", 1)[0] ] anc = repo.changelog.ancestors([new.rev()]) deletefrom = [b.node() for b in divs if b.rev() in anc or b == new] @@ -451,7 +455,7 @@ bmchanges.append((bm, None)) if bmchanges: - with repo.lock(), repo.transaction("bookmark") as tr: + with repo.lock(), repo.transaction(b"bookmark") as tr: marks.applychanges(repo, tr, bmchanges) return bool(bmchanges) @@ -464,7 +468,7 @@ hasnode = repo.changelog.hasnode for k, v in marks.iteritems(): # don't expose local divergent bookmarks - if hasnode(v) and ("@" not in k or k.endswith("@")): + if hasnode(v) and (b"@" not in k or k.endswith(b"@")): yield k, v @@ -480,12 +484,12 @@ wlock = util.nullcontextmanager() else: wlock = repo.wlock() - with wlock, repo.lock(), repo.transaction("bookmarks") as tr: + with wlock, repo.lock(), repo.transaction(b"bookmarks") as tr: marks = repo._bookmarks - existing = hex(marks.get(key, "")) + existing = hex(marks.get(key, b"")) if existing != old and existing != new: return False - if new == "": + if new == b"": changes = [(key, None)] else: if new not in repo: @@ -580,21 +584,21 @@ This reuses already existing one with "@number" suffix, if it refers ``remotenode``. """ - if b == "@": - b = "" + if b == b"@": + b = b"" # try to use an @pathalias suffix # if an @pathalias already exists, we overwrite (update) it - if path.startswith("file:"): + if path.startswith(b"file:"): path = util.url(path).path - for p, u in ui.configitems("paths"): - if u.startswith("file:"): + for p, u in ui.configitems(b"paths"): + if u.startswith(b"file:"): u = util.url(u).path if path == u: - return "%s@%s" % (b, p) + return b"%s@%s" % (b, p) # assign a unique "@number" suffix newly for x in range(1, 100): - n = "%s@%d" % (b, x) + n = b"%s@%d" % (b, x) if n not in localmarks or localmarks[n] == remotenode: return n @@ -608,7 +612,7 @@ return binremotemarks -_binaryentry = struct.Struct(">20sH") +_binaryentry = struct.Struct(b">20sH") def binaryencode(bookmarks): @@ -630,7 +634,7 @@ node = wdirid binarydata.append(_binaryentry.pack(node, len(book))) binarydata.append(book) - return "".join(binarydata) + return b"".join(binarydata) def binarydecode(stream): @@ -652,13 +656,13 @@ entry = stream.read(entrysize) if len(entry) < entrysize: if entry: - raise error.Abort(_("bad bookmark stream")) + raise error.Abort(_(b"bad bookmark stream")) break node, length = _binaryentry.unpack(entry) bookmark = stream.read(length) if len(bookmark) < length: if entry: - raise error.Abort(_("bad bookmark stream")) + raise error.Abort(_(b"bad bookmark stream")) if node == wdirid: node = None books.append((bookmark, node)) @@ -666,7 +670,7 @@ def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()): - ui.debug("checking for updated bookmarks\n") + ui.debug(b"checking for updated bookmarks\n") localmarks = repo._bookmarks ( addsrc, @@ -681,7 +685,7 @@ status = ui.status warn = ui.warn - if ui.configbool("ui", "quietbookmarkmove"): + if ui.configbool(b"ui", b"quietbookmarkmove"): status = warn = ui.debug explicit = set(explicit) @@ -689,24 +693,24 @@ for b, scid, dcid in addsrc: if scid in repo: # add remote bookmarks for changes we already have changed.append( - (b, scid, status, _("adding remote bookmark %s\n") % b) + (b, scid, status, _(b"adding remote bookmark %s\n") % b) ) elif b in explicit: explicit.remove(b) ui.warn( - _("remote bookmark %s points to locally missing %s\n") + _(b"remote bookmark %s points to locally missing %s\n") % (b, hex(scid)[:12]) ) for b, scid, dcid in advsrc: - changed.append((b, scid, status, _("updating bookmark %s\n") % b)) + changed.append((b, scid, status, _(b"updating bookmark %s\n") % b)) # remove normal movement from explicit set explicit.difference_update(d[0] for d in changed) for b, scid, dcid in diverge: if b in explicit: explicit.discard(b) - changed.append((b, scid, status, _("importing bookmark %s\n") % b)) + changed.append((b, scid, status, _(b"importing bookmark %s\n") % b)) else: db = _diverge(ui, b, path, localmarks, scid) if db: @@ -715,26 +719,26 @@ db, scid, warn, - _("divergent bookmark %s stored as %s\n") % (b, db), + _(b"divergent bookmark %s stored as %s\n") % (b, db), ) ) else: warn( _( - "warning: failed to assign numbered name " - "to divergent bookmark %s\n" + b"warning: failed to assign numbered name " + b"to divergent bookmark %s\n" ) % b ) for b, scid, dcid in adddst + advdst: if b in explicit: explicit.discard(b) - changed.append((b, scid, status, _("importing bookmark %s\n") % b)) + changed.append((b, scid, status, _(b"importing bookmark %s\n") % b)) for b, scid, dcid in differ: if b in explicit: explicit.remove(b) ui.warn( - _("remote bookmark %s points to locally missing %s\n") + _(b"remote bookmark %s points to locally missing %s\n") % (b, hex(scid)[:12]) ) @@ -750,11 +754,11 @@ def incoming(ui, repo, peer): """Show bookmarks incoming from other to repo """ - ui.status(_("searching for changed bookmarks\n")) + ui.status(_(b"searching for changed bookmarks\n")) with peer.commandexecutor() as e: remotemarks = unhexlifybookmarks( - e.callcommand("listkeys", {"namespace": "bookmarks",}).result() + e.callcommand(b"listkeys", {b"namespace": b"bookmarks",}).result() ) r = comparebookmarks(repo, remotemarks, repo._bookmarks) @@ -768,28 +772,28 @@ if ui.verbose: def add(b, id, st): - incomings.append(" %-25s %s %s\n" % (b, getid(id), st)) + incomings.append(b" %-25s %s %s\n" % (b, getid(id), st)) else: def add(b, id, st): - incomings.append(" %-25s %s\n" % (b, getid(id))) + incomings.append(b" %-25s %s\n" % (b, getid(id))) for b, scid, dcid in addsrc: # i18n: "added" refers to a bookmark - add(b, hex(scid), _("added")) + add(b, hex(scid), _(b"added")) for b, scid, dcid in advsrc: # i18n: "advanced" refers to a bookmark - add(b, hex(scid), _("advanced")) + add(b, hex(scid), _(b"advanced")) for b, scid, dcid in diverge: # i18n: "diverged" refers to a bookmark - add(b, hex(scid), _("diverged")) + add(b, hex(scid), _(b"diverged")) for b, scid, dcid in differ: # i18n: "changed" refers to a bookmark - add(b, hex(scid), _("changed")) + add(b, hex(scid), _(b"changed")) if not incomings: - ui.status(_("no changed bookmarks found\n")) + ui.status(_(b"no changed bookmarks found\n")) return 1 for s in sorted(incomings): @@ -801,9 +805,9 @@ def outgoing(ui, repo, other): """Show bookmarks outgoing from repo to other """ - ui.status(_("searching for changed bookmarks\n")) + ui.status(_(b"searching for changed bookmarks\n")) - remotemarks = unhexlifybookmarks(other.listkeys("bookmarks")) + remotemarks = unhexlifybookmarks(other.listkeys(b"bookmarks")) r = comparebookmarks(repo, repo._bookmarks, remotemarks) addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r @@ -815,31 +819,31 @@ if ui.verbose: def add(b, id, st): - outgoings.append(" %-25s %s %s\n" % (b, getid(id), st)) + outgoings.append(b" %-25s %s %s\n" % (b, getid(id), st)) else: def add(b, id, st): - outgoings.append(" %-25s %s\n" % (b, getid(id))) + outgoings.append(b" %-25s %s\n" % (b, getid(id))) for b, scid, dcid in addsrc: # i18n: "added refers to a bookmark - add(b, hex(scid), _("added")) + add(b, hex(scid), _(b"added")) for b, scid, dcid in adddst: # i18n: "deleted" refers to a bookmark - add(b, " " * 40, _("deleted")) + add(b, b" " * 40, _(b"deleted")) for b, scid, dcid in advsrc: # i18n: "advanced" refers to a bookmark - add(b, hex(scid), _("advanced")) + add(b, hex(scid), _(b"advanced")) for b, scid, dcid in diverge: # i18n: "diverged" refers to a bookmark - add(b, hex(scid), _("diverged")) + add(b, hex(scid), _(b"diverged")) for b, scid, dcid in differ: # i18n: "changed" refers to a bookmark - add(b, hex(scid), _("changed")) + add(b, hex(scid), _(b"changed")) if not outgoings: - ui.status(_("no changed bookmarks found\n")) + ui.status(_(b"no changed bookmarks found\n")) return 1 for s in sorted(outgoings): @@ -855,7 +859,7 @@ """ with peer.commandexecutor() as e: remotemarks = unhexlifybookmarks( - e.callcommand("listkeys", {"namespace": "bookmarks",}).result() + e.callcommand(b"listkeys", {b"namespace": b"bookmarks",}).result() ) r = comparebookmarks(repo, remotemarks, repo._bookmarks) @@ -888,9 +892,9 @@ mark = mark.strip() if not mark: raise error.Abort( - _("bookmark names cannot consist entirely of " "whitespace") + _(b"bookmark names cannot consist entirely of " b"whitespace") ) - scmutil.checknewlabel(repo, mark, "bookmark") + scmutil.checknewlabel(repo, mark, b"bookmark") return mark @@ -903,7 +907,7 @@ changes = [] for mark in names: if mark not in marks: - raise error.Abort(_("bookmark '%s' does not exist") % mark) + raise error.Abort(_(b"bookmark '%s' does not exist") % mark) if mark == repo._activebookmark: deactivate(repo) changes.append((mark, None)) @@ -923,7 +927,7 @@ marks = repo._bookmarks mark = checkformat(repo, new) if old not in marks: - raise error.Abort(_("bookmark '%s' does not exist") % old) + raise error.Abort(_(b"bookmark '%s' does not exist") % old) changes = [] for bm in marks.checkconflict(mark, force): changes.append((bm, None)) @@ -945,14 +949,14 @@ Raises an abort error if old is not in the bookmark store. """ marks = repo._bookmarks - cur = repo["."].node() + cur = repo[b"."].node() newact = None changes = [] hiddenrev = None # unhide revs if any if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") for mark in names: mark = checkformat(repo, mark) @@ -972,11 +976,11 @@ changes.append((mark, tgt)) if hiddenrev: - repo.ui.warn(_("bookmarking hidden changeset %s\n") % hiddenrev) + repo.ui.warn(_(b"bookmarking hidden changeset %s\n") % hiddenrev) if ctx.obsolete(): - msg = obsutil._getfilteredreason(repo, "%s" % hiddenrev, ctx) - repo.ui.warn("(%s)\n" % msg) + msg = obsutil._getfilteredreason(repo, b"%s" % hiddenrev, ctx) + repo.ui.warn(b"(%s)\n" % msg) marks.applychanges(repo, tr, changes) if not inactive and cur == marks[newact] and not rev: @@ -993,24 +997,24 @@ """ hexfn = fm.hexfunc if len(bmarks) == 0 and fm.isplain(): - ui.status(_("no bookmarks set\n")) + ui.status(_(b"no bookmarks set\n")) for bmark, (n, prefix, label) in sorted(bmarks.iteritems()): fm.startitem() fm.context(repo=repo) if not ui.quiet: - fm.plain(" %s " % prefix, label=label) - fm.write("bookmark", "%s", bmark, label=label) - pad = " " * (25 - encoding.colwidth(bmark)) + fm.plain(b" %s " % prefix, label=label) + fm.write(b"bookmark", b"%s", bmark, label=label) + pad = b" " * (25 - encoding.colwidth(bmark)) fm.condwrite( not ui.quiet, - "rev node", - pad + " %d:%s", + b"rev node", + pad + b" %d:%s", repo.changelog.rev(n), hexfn(n), label=label, ) fm.data(active=(activebookmarklabel in label)) - fm.plain("\n") + fm.plain(b"\n") def printbookmarks(ui, repo, fm, names=None): @@ -1022,12 +1026,12 @@ bmarks = {} for bmark in names or marks: if bmark not in marks: - raise error.Abort(_("bookmark '%s' does not exist") % bmark) + raise error.Abort(_(b"bookmark '%s' does not exist") % bmark) active = repo._activebookmark if bmark == active: - prefix, label = "*", activebookmarklabel + prefix, label = b"*", activebookmarklabel else: - prefix, label = " ", "" + prefix, label = b" ", b"" bmarks[bmark] = (marks[bmark], prefix, label) _printbookmarks(ui, repo, fm, bmarks) @@ -1035,7 +1039,7 @@ def preparehookargs(name, old, new): if new is None: - new = "" + new = b"" if old is None: - old = "" - return {"bookmark": name, "node": hex(new), "oldnode": hex(old)} + old = b"" + return {b"bookmark": name, b"node": hex(new), b"oldnode": hex(old)} diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py --- a/mercurial/branchmap.py +++ b/mercurial/branchmap.py @@ -110,7 +110,7 @@ # Try to stick it as low as possible # filter above served are unlikely to be fetch from a clone - for candidate in ("base", "immutable", "served"): + for candidate in (b"base", b"immutable", b"served"): rview = repo.filtered(candidate) if cache.validfor(rview): self._per_filter[candidate] = cache @@ -129,9 +129,9 @@ def _branchcachedesc(repo): if repo.filtername is not None: - return "branch cache (%s)" % repo.filtername + return b"branch cache (%s)" % repo.filtername else: - return "branch cache" + return b"branch cache" class branchcache(object): @@ -245,7 +245,7 @@ try: f = repo.cachevfs(cls._filename(repo)) lineiter = iter(f) - cachekey = next(lineiter).rstrip("\n").split(" ", 2) + cachekey = next(lineiter).rstrip(b"\n").split(b" ", 2) last, lrev = cachekey[:2] last, lrev = bin(last), int(lrev) filteredhash = None @@ -267,7 +267,7 @@ except Exception as inst: if repo.ui.debugflag: - msg = "invalid %s: %s\n" + msg = b"invalid %s: %s\n" repo.ui.debug( msg % (_branchcachedesc(repo), pycompat.bytestr(inst)) ) @@ -283,24 +283,24 @@ """ fully loads the branchcache by reading from the file using the line iterator passed""" for line in lineiter: - line = line.rstrip("\n") + line = line.rstrip(b"\n") if not line: continue - node, state, label = line.split(" ", 2) - if state not in "oc": + node, state, label = line.split(b" ", 2) + if state not in b"oc": raise ValueError(r"invalid branch state") label = encoding.tolocal(label.strip()) node = bin(node) self._entries.setdefault(label, []).append(node) - if state == "c": + if state == b"c": self._closednodes.add(node) @staticmethod def _filename(repo): """name of a branchcache file for a given repo or repoview""" - filename = "branch2" + filename = b"branch2" if repo.filtername: - filename = "%s-%s" % (filename, repo.filtername) + filename = b"%s-%s" % (filename, repo.filtername) return filename def validfor(self, repo): @@ -364,25 +364,25 @@ def write(self, repo): try: - f = repo.cachevfs(self._filename(repo), "w", atomictemp=True) - cachekey = [hex(self.tipnode), "%d" % self.tiprev] + f = repo.cachevfs(self._filename(repo), b"w", atomictemp=True) + cachekey = [hex(self.tipnode), b"%d" % self.tiprev] if self.filteredhash is not None: cachekey.append(hex(self.filteredhash)) - f.write(" ".join(cachekey) + "\n") + f.write(b" ".join(cachekey) + b"\n") nodecount = 0 for label, nodes in sorted(self._entries.iteritems()): label = encoding.fromlocal(label) for node in nodes: nodecount += 1 if node in self._closednodes: - state = "c" + state = b"c" else: - state = "o" - f.write("%s %s %s\n" % (hex(node), state, label)) + state = b"o" + f.write(b"%s %s %s\n" % (hex(node), state, label)) f.close() repo.ui.log( - "branchcache", - "wrote %s with %d labels and %d nodes\n", + b"branchcache", + b"wrote %s with %d labels and %d nodes\n", _branchcachedesc(repo), len(self._entries), nodecount, @@ -390,7 +390,7 @@ except (IOError, OSError, error.Abort) as inst: # Abort may be raised by read only opener, so log and continue repo.ui.debug( - "couldn't write branch cache: %s\n" + b"couldn't write branch cache: %s\n" % stringutil.forcebytestr(inst) ) @@ -460,8 +460,8 @@ duration = util.timer() - starttime repo.ui.log( - "branchcache", - "updated %s in %.4f seconds\n", + b"branchcache", + b"updated %s in %.4f seconds\n", _branchcachedesc(repo), duration, ) @@ -478,11 +478,11 @@ # Revision branch info cache -_rbcversion = "-v1" -_rbcnames = "rbc-names" + _rbcversion -_rbcrevs = "rbc-revs" + _rbcversion +_rbcversion = b"-v1" +_rbcnames = b"rbc-names" + _rbcversion +_rbcrevs = b"rbc-revs" + _rbcversion # [4 byte hash prefix][4 byte branch name number with sign bit indicating open] -_rbcrecfmt = ">4sI" +_rbcrecfmt = b">4sI" _rbcrecsize = calcsize(_rbcrecfmt) _rbcnodelen = 4 _rbcbranchidxmask = 0x7FFFFFFF @@ -523,7 +523,7 @@ self._rbcsnameslen = len(bndata) # for verification before writing if bndata: self._names = [ - encoding.tolocal(bn) for bn in bndata.split("\0") + encoding.tolocal(bn) for bn in bndata.split(b"\0") ] except (IOError, OSError): if readonly: @@ -536,7 +536,7 @@ self._rbcrevs[:] = data except (IOError, OSError) as inst: repo.ui.debug( - "couldn't read revision branch cache: %s\n" + b"couldn't read revision branch cache: %s\n" % stringutil.forcebytestr(inst) ) # remember number of good records on disk @@ -554,7 +554,7 @@ self._rbcnamescount = 0 self._rbcrevslen = len(self._repo.changelog) self._rbcrevs = bytearray(self._rbcrevslen * _rbcrecsize) - util.clearcachedproperty(self, "_namesreverse") + util.clearcachedproperty(self, b"_namesreverse") @util.propertycache def _namesreverse(self): @@ -582,7 +582,7 @@ close = bool(branchidx & _rbccloseflag) if close: branchidx &= _rbcbranchidxmask - if cachenode == "\0\0\0\0": + if cachenode == b"\0\0\0\0": pass elif cachenode == reponode: try: @@ -590,15 +590,15 @@ except IndexError: # recover from invalid reference to unknown branch self._repo.ui.debug( - "referenced branch names not found" - " - rebuilding revision branch cache from scratch\n" + b"referenced branch names not found" + b" - rebuilding revision branch cache from scratch\n" ) self._clear() else: # rev/node map has changed, invalidate the cache from here up self._repo.ui.debug( - "history modification detected - truncating " - "revision branch cache to revision %d\n" % rev + b"history modification detected - truncating " + b"revision branch cache to revision %d\n" % rev ) truncate = rbcrevidx + _rbcrecsize del self._rbcrevs[truncate:] @@ -650,7 +650,7 @@ rbcrevidx = rev * _rbcrecsize if len(self._rbcrevs) < rbcrevidx + _rbcrecsize: self._rbcrevs.extend( - "\0" + b"\0" * (len(self._repo.changelog) * _rbcrecsize - len(self._rbcrevs)) ) pack_into(_rbcrecfmt, self._rbcrevs, rbcrevidx, node, branchidx) @@ -658,31 +658,31 @@ tr = self._repo.currenttransaction() if tr: - tr.addfinalize("write-revbranchcache", self.write) + tr.addfinalize(b"write-revbranchcache", self.write) def write(self, tr=None): """Save branch cache if it is dirty.""" repo = self._repo wlock = None - step = "" + step = b"" try: # write the new names if self._rbcnamescount < len(self._names): wlock = repo.wlock(wait=False) - step = " names" + step = b" names" self._writenames(repo) # write the new revs start = self._rbcrevslen * _rbcrecsize if start != len(self._rbcrevs): - step = "" + step = b"" if wlock is None: wlock = repo.wlock(wait=False) self._writerevs(repo, start) except (IOError, OSError, error.Abort, error.LockError) as inst: repo.ui.debug( - "couldn't write revision branch cache%s: %s\n" + b"couldn't write revision branch cache%s: %s\n" % (step, stringutil.forcebytestr(inst)) ) finally: @@ -692,20 +692,20 @@ def _writenames(self, repo): """ write the new branch names to revbranchcache """ if self._rbcnamescount != 0: - f = repo.cachevfs.open(_rbcnames, "ab") + f = repo.cachevfs.open(_rbcnames, b"ab") if f.tell() == self._rbcsnameslen: - f.write("\0") + f.write(b"\0") else: f.close() - repo.ui.debug("%s changed - rewriting it\n" % _rbcnames) + repo.ui.debug(b"%s changed - rewriting it\n" % _rbcnames) self._rbcnamescount = 0 self._rbcrevslen = 0 if self._rbcnamescount == 0: # before rewriting names, make sure references are removed repo.cachevfs.unlinkpath(_rbcrevs, ignoremissing=True) - f = repo.cachevfs.open(_rbcnames, "wb") + f = repo.cachevfs.open(_rbcnames, b"wb") f.write( - "\0".join( + b"\0".join( encoding.fromlocal(b) for b in self._names[self._rbcnamescount :] ) @@ -717,9 +717,11 @@ def _writerevs(self, repo, start): """ write the new revs to revbranchcache """ revs = min(len(repo.changelog), len(self._rbcrevs) // _rbcrecsize) - with repo.cachevfs.open(_rbcrevs, "ab") as f: + with repo.cachevfs.open(_rbcrevs, b"ab") as f: if f.tell() != start: - repo.ui.debug("truncating cache/%s to %d\n" % (_rbcrevs, start)) + repo.ui.debug( + b"truncating cache/%s to %d\n" % (_rbcrevs, start) + ) f.seek(start) if f.tell() != start: start = 0 diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -179,28 +179,28 @@ _pack = struct.pack _unpack = struct.unpack -_fstreamparamsize = ">i" -_fpartheadersize = ">i" -_fparttypesize = ">B" -_fpartid = ">I" -_fpayloadsize = ">i" -_fpartparamcount = ">BB" +_fstreamparamsize = b">i" +_fpartheadersize = b">i" +_fparttypesize = b">B" +_fpartid = b">I" +_fpayloadsize = b">i" +_fpartparamcount = b">BB" preferedchunksize = 32768 -_parttypeforbidden = re.compile("[^a-zA-Z0-9_:-]") +_parttypeforbidden = re.compile(b"[^a-zA-Z0-9_:-]") def outdebug(ui, message): """debug regarding output stream (bundling)""" - if ui.configbool("devel", "bundle2.debug"): - ui.debug("bundle2-output: %s\n" % message) + if ui.configbool(b"devel", b"bundle2.debug"): + ui.debug(b"bundle2-output: %s\n" % message) def indebug(ui, message): """debug on input stream (unbundling)""" - if ui.configbool("devel", "bundle2.debug"): - ui.debug("bundle2-input: %s\n" % message) + if ui.configbool(b"devel", b"bundle2.debug"): + ui.debug(b"bundle2-input: %s\n" % message) def validateparttype(parttype): @@ -215,7 +215,7 @@ The number parameters is variable so we need to build that format dynamically. """ - return ">" + ("BB" * nbparams) + return b">" + (b"BB" * nbparams) parthandlermapping = {} @@ -307,7 +307,7 @@ * a way to construct a bundle response when applicable. """ - def __init__(self, repo, transactiongetter, captureoutput=True, source=""): + def __init__(self, repo, transactiongetter, captureoutput=True, source=b""): self.repo = repo self.ui = repo.ui self.records = unbundlerecords() @@ -337,8 +337,8 @@ def addhookargs(self, hookargs): if self.hookargs is None: raise error.ProgrammingError( - "attempted to add hookargs to " - "operation after transaction started" + b"attempted to add hookargs to " + b"operation after transaction started" ) self.hookargs.update(hookargs) @@ -358,11 +358,11 @@ def applybundle(repo, unbundler, tr, source, url=None, **kwargs): # transform me into unbundler.apply() as soon as the freeze is lifted if isinstance(unbundler, unbundle20): - tr.hookargs["bundle2"] = "1" - if source is not None and "source" not in tr.hookargs: - tr.hookargs["source"] = source - if url is not None and "url" not in tr.hookargs: - tr.hookargs["url"] = url + tr.hookargs[b"bundle2"] = b"1" + if source is not None and b"source" not in tr.hookargs: + tr.hookargs[b"source"] = source + if url is not None and b"url" not in tr.hookargs: + tr.hookargs[b"url"] = url return processbundle(repo, unbundler, lambda: tr, source=source) else: # the transactiongetter won't be used, but we might as well set it @@ -438,11 +438,11 @@ raise exc self.repo.ui.debug( - "bundle2-input-bundle: %i parts total\n" % self.count + b"bundle2-input-bundle: %i parts total\n" % self.count ) -def processbundle(repo, unbundler, transactiongetter=None, op=None, source=""): +def processbundle(repo, unbundler, transactiongetter=None, op=None, source=b""): """This function process a bundle, apply effect to/from a repo It iterates over each part then searches for and uses the proper handling @@ -464,15 +464,15 @@ # - exception catching unbundler.params if repo.ui.debugflag: - msg = ["bundle2-input-bundle:"] + msg = [b"bundle2-input-bundle:"] if unbundler.params: - msg.append(" %i params" % len(unbundler.params)) + msg.append(b" %i params" % len(unbundler.params)) if op._gettransaction is None or op._gettransaction is _notransaction: - msg.append(" no-transaction") + msg.append(b" no-transaction") else: - msg.append(" with-transaction") - msg.append("\n") - repo.ui.debug("".join(msg)) + msg.append(b" with-transaction") + msg.append(b"\n") + repo.ui.debug(b"".join(msg)) processparts(repo, op, unbundler) @@ -487,48 +487,48 @@ def _processchangegroup(op, cg, tr, source, url, **kwargs): ret = cg.apply(op.repo, tr, source, url, **kwargs) - op.records.add("changegroup", {"return": ret,}) + op.records.add(b"changegroup", {b"return": ret,}) return ret def _gethandler(op, part): - status = "unknown" # used by debug output + status = b"unknown" # used by debug output try: handler = parthandlermapping.get(part.type) if handler is None: - status = "unsupported-type" + status = b"unsupported-type" raise error.BundleUnknownFeatureError(parttype=part.type) - indebug(op.ui, "found a handler for part %s" % part.type) + indebug(op.ui, b"found a handler for part %s" % part.type) unknownparams = part.mandatorykeys - handler.params if unknownparams: unknownparams = list(unknownparams) unknownparams.sort() - status = "unsupported-params (%s)" % ", ".join(unknownparams) + status = b"unsupported-params (%s)" % b", ".join(unknownparams) raise error.BundleUnknownFeatureError( parttype=part.type, params=unknownparams ) - status = "supported" + status = b"supported" except error.BundleUnknownFeatureError as exc: if part.mandatory: # mandatory parts raise - indebug(op.ui, "ignoring unsupported advisory part %s" % exc) + indebug(op.ui, b"ignoring unsupported advisory part %s" % exc) return # skip to part processing finally: if op.ui.debugflag: - msg = ['bundle2-input-part: "%s"' % part.type] + msg = [b'bundle2-input-part: "%s"' % part.type] if not part.mandatory: - msg.append(" (advisory)") + msg.append(b" (advisory)") nbmp = len(part.mandatorykeys) nbap = len(part.params) - nbmp if nbmp or nbap: - msg.append(" (params:") + msg.append(b" (params:") if nbmp: - msg.append(" %i mandatory" % nbmp) + msg.append(b" %i mandatory" % nbmp) if nbap: - msg.append(" %i advisory" % nbmp) - msg.append(")") - msg.append(" %s\n" % status) - op.ui.debug("".join(msg)) + msg.append(b" %i advisory" % nbmp) + msg.append(b")") + msg.append(b" %s\n" % status) + op.ui.debug(b"".join(msg)) return handler @@ -549,16 +549,16 @@ output = None if op.captureoutput and op.reply is not None: op.ui.pushbuffer(error=True, subproc=True) - output = "" + output = b"" try: handler(op, part) finally: if output is not None: output = op.ui.popbuffer() if output: - outpart = op.reply.newpart("output", data=output, mandatory=False) + outpart = op.reply.newpart(b"output", data=output, mandatory=False) outpart.addparam( - "in-reply-to", pycompat.bytestr(part.id), mandatory=False + b"in-reply-to", pycompat.bytestr(part.id), mandatory=False ) @@ -575,11 +575,11 @@ for line in blob.splitlines(): if not line: continue - if "=" not in line: + if b"=" not in line: key, vals = line, () else: - key, vals = line.split("=", 1) - vals = vals.split(",") + key, vals = line.split(b"=", 1) + vals = vals.split(b",") key = urlreq.unquote(key) vals = [urlreq.unquote(v) for v in vals] caps[key] = vals @@ -594,23 +594,23 @@ ca = urlreq.quote(ca) vals = [urlreq.quote(v) for v in vals] if vals: - ca = "%s=%s" % (ca, ",".join(vals)) + ca = b"%s=%s" % (ca, b",".join(vals)) chunks.append(ca) - return "\n".join(chunks) + return b"\n".join(chunks) bundletypes = { - "": ("", "UN"), # only when using unbundle on ssh and old http servers + b"": (b"", b"UN"), # only when using unbundle on ssh and old http servers # since the unification ssh accepts a header but there # is no capability signaling it. - "HG20": (), # special-cased below - "HG10UN": ("HG10UN", "UN"), - "HG10BZ": ("HG10", "BZ"), - "HG10GZ": ("HG10GZ", "GZ"), + b"HG20": (), # special-cased below + b"HG10UN": (b"HG10UN", b"UN"), + b"HG10BZ": (b"HG10", b"BZ"), + b"HG10GZ": (b"HG10GZ", b"GZ"), } # hgweb uses this list to communicate its preferred type -bundlepriority = ["HG10GZ", "HG10BZ", "HG10UN"] +bundlepriority = [b"HG10GZ", b"HG10BZ", b"HG10UN"] class bundle20(object): @@ -620,14 +620,14 @@ populate it. Then call `getchunks` to retrieve all the binary chunks of data that compose the bundle2 container.""" - _magicstring = "HG20" + _magicstring = b"HG20" def __init__(self, ui, capabilities=()): self.ui = ui self._params = [] self._parts = [] self.capabilities = dict(capabilities) - self._compengine = util.compengines.forbundletype("UN") + self._compengine = util.compengines.forbundletype(b"UN") self._compopts = None # If compression is being handled by a consumer of the raw # data (e.g. the wire protocol), unsetting this flag tells @@ -636,10 +636,10 @@ def setcompression(self, alg, compopts=None): """setup core part compression to """ - if alg in (None, "UN"): + if alg in (None, b"UN"): return - assert not any(n.lower() == "compression" for n, v in self._params) - self.addparam("Compression", alg) + assert not any(n.lower() == b"compression" for n, v in self._params) + self.addparam(b"Compression", alg) self._compengine = util.compengines.forbundletype(alg) self._compopts = compopts @@ -683,15 +683,15 @@ # methods used to generate the bundle2 stream def getchunks(self): if self.ui.debugflag: - msg = ['bundle2-output-bundle: "%s",' % self._magicstring] + msg = [b'bundle2-output-bundle: "%s",' % self._magicstring] if self._params: - msg.append(" (%i params)" % len(self._params)) - msg.append(" %i parts total\n" % len(self._parts)) - self.ui.debug("".join(msg)) - outdebug(self.ui, "start emission of %s stream" % self._magicstring) + msg.append(b" (%i params)" % len(self._params)) + msg.append(b" %i parts total\n" % len(self._parts)) + self.ui.debug(b"".join(msg)) + outdebug(self.ui, b"start emission of %s stream" % self._magicstring) yield self._magicstring param = self._paramchunk() - outdebug(self.ui, "bundle parameter: %s" % param) + outdebug(self.ui, b"bundle parameter: %s" % param) yield _pack(_fstreamparamsize, len(param)) if param: yield param @@ -707,20 +707,20 @@ par = urlreq.quote(par) if value is not None: value = urlreq.quote(value) - par = "%s=%s" % (par, value) + par = b"%s=%s" % (par, value) blocks.append(par) - return " ".join(blocks) + return b" ".join(blocks) def _getcorechunk(self): """yield chunk for the core part of the bundle (all but headers and parameters)""" - outdebug(self.ui, "start of parts") + outdebug(self.ui, b"start of parts") for part in self._parts: - outdebug(self.ui, 'bundle part: "%s"' % part.type) + outdebug(self.ui, b'bundle part: "%s"' % part.type) for chunk in part.getchunks(ui=self.ui): yield chunk - outdebug(self.ui, "end of bundle") + outdebug(self.ui, b"end of bundle") yield _pack(_fpartheadersize, 0) def salvageoutput(self): @@ -730,7 +730,7 @@ server output""" salvaged = [] for part in self._parts: - if part.type.startswith("output"): + if part.type.startswith(b"output"): salvaged.append(part.copy()) return salvaged @@ -768,17 +768,17 @@ if magicstring is None: magicstring = changegroup.readexactly(fp, 4) magic, version = magicstring[0:2], magicstring[2:4] - if magic != "HG": + if magic != b"HG": ui.debug( - "error: invalid magic: %r (version %r), should be 'HG'\n" + b"error: invalid magic: %r (version %r), should be 'HG'\n" % (magic, version) ) - raise error.Abort(_("not a Mercurial bundle")) + raise error.Abort(_(b"not a Mercurial bundle")) unbundlerclass = formatmap.get(version) if unbundlerclass is None: - raise error.Abort(_("unknown bundle version %s") % version) + raise error.Abort(_(b"unknown bundle version %s") % version) unbundler = unbundlerclass(ui, fp) - indebug(ui, "start processing of %s stream" % magicstring) + indebug(ui, b"start processing of %s stream" % magicstring) return unbundler @@ -788,24 +788,24 @@ This class is fed with a binary stream and yields parts through its `iterparts` methods.""" - _magicstring = "HG20" + _magicstring = b"HG20" def __init__(self, ui, fp): """If header is specified, we do not read it out of the stream.""" self.ui = ui - self._compengine = util.compengines.forbundletype("UN") + self._compengine = util.compengines.forbundletype(b"UN") self._compressed = None super(unbundle20, self).__init__(fp) @util.propertycache def params(self): """dictionary of stream level parameters""" - indebug(self.ui, "reading bundle2 stream parameters") + indebug(self.ui, b"reading bundle2 stream parameters") params = {} paramssize = self._unpack(_fstreamparamsize)[0] if paramssize < 0: raise error.BundleValueError( - "negative bundle param size: %i" % paramssize + b"negative bundle param size: %i" % paramssize ) if paramssize: params = self._readexact(paramssize) @@ -815,8 +815,8 @@ def _processallparams(self, paramsblock): """""" params = util.sortdict() - for p in paramsblock.split(" "): - p = p.split("=", 1) + for p in paramsblock.split(b" "): + p = p.split(b"=", 1) p = [urlreq.unquote(i) for i in p] if len(p) < 2: p.append(None) @@ -842,7 +842,7 @@ handler = b2streamparamsmap[name.lower()] except KeyError: if name[0:1].islower(): - indebug(self.ui, "ignoring unknown parameter %s" % name) + indebug(self.ui, b"ignoring unknown parameter %s" % name) else: raise error.BundleUnknownFeatureError(params=(name,)) else: @@ -857,11 +857,11 @@ needed to move forward to get general delta enabled. """ yield self._magicstring - assert "params" not in vars(self) + assert b"params" not in vars(self) paramssize = self._unpack(_fstreamparamsize)[0] if paramssize < 0: raise error.BundleValueError( - "negative bundle param size: %i" % paramssize + b"negative bundle param size: %i" % paramssize ) if paramssize: params = self._readexact(paramssize) @@ -869,11 +869,11 @@ # The payload itself is decompressed below, so drop # the compression parameter passed down to compensate. outparams = [] - for p in params.split(" "): - k, v = p.split("=", 1) - if k.lower() != "compression": + for p in params.split(b" "): + k, v = p.split(b"=", 1) + if k.lower() != b"compression": outparams.append(p) - outparams = " ".join(outparams) + outparams = b" ".join(outparams) yield _pack(_fstreamparamsize, len(outparams)) yield outparams else: @@ -894,7 +894,7 @@ if size == flaginterrupt: continue elif size < 0: - raise error.BundleValueError("negative chunk size: %i") + raise error.BundleValueError(b"negative chunk size: %i") yield self._readexact(size) def iterparts(self, seekable=False): @@ -904,7 +904,7 @@ self.params # From there, payload need to be decompressed self._fp = self._compengine.decompressorreader(self._fp) - indebug(self.ui, "start extraction of bundle2 parts") + indebug(self.ui, b"start extraction of bundle2 parts") headerblock = self._readpartheader() while headerblock is not None: part = cls(self.ui, headerblock, self._fp) @@ -914,7 +914,7 @@ part.consume() headerblock = self._readpartheader() - indebug(self.ui, "end of bundle2 stream") + indebug(self.ui, b"end of bundle2 stream") def _readpartheader(self): """reads a part header size and return the bytes blob @@ -923,9 +923,9 @@ headersize = self._unpack(_fpartheadersize)[0] if headersize < 0: raise error.BundleValueError( - "negative part header size: %i" % headersize + b"negative part header size: %i" % headersize ) - indebug(self.ui, "part header size: %i" % headersize) + indebug(self.ui, b"part header size: %i" % headersize) if headersize: return self._readexact(headersize) return None @@ -936,11 +936,11 @@ def close(self): """close underlying file""" - if util.safehasattr(self._fp, "close"): + if util.safehasattr(self._fp, b"close"): return self._fp.close() -formatmap = {"20": unbundle20} +formatmap = {b"20": unbundle20} b2streamparamsmap = {} @@ -956,7 +956,7 @@ return decorator -@b2streamparamhandler("compression") +@b2streamparamhandler(b"compression") def processcompression(unbundler, param, value): """read compression parameter and install payload decompression""" if value not in util.compengines.supportedbundletypes: @@ -987,7 +987,7 @@ parttype, mandatoryparams=(), advisoryparams=(), - data="", + data=b"", mandatory=True, ): validateparttype(parttype) @@ -1000,7 +1000,7 @@ self._seenparams = set() for pname, __ in self._mandatoryparams + self._advisoryparams: if pname in self._seenparams: - raise error.ProgrammingError("duplicated params: %s" % pname) + raise error.ProgrammingError(b"duplicated params: %s" % pname) self._seenparams.add(pname) # status of the part's generation: # - None: not started, @@ -1010,8 +1010,8 @@ self.mandatory = mandatory def __repr__(self): - cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) - return "<%s object at %x; id: %s; type: %s; mandatory: %s>" % ( + cls = b"%s.%s" % (self.__class__.__module__, self.__class__.__name__) + return b"<%s object at %x; id: %s; type: %s; mandatory: %s>" % ( cls, id(self), self.id, @@ -1024,7 +1024,7 @@ The new part have the very same content but no partid assigned yet. Parts with generated data cannot be copied.""" - assert not util.safehasattr(self.data, "next") + assert not util.safehasattr(self.data, b"next") return self.__class__( self.type, self._mandatoryparams, @@ -1041,7 +1041,7 @@ @data.setter def data(self, data): if self._generated is not None: - raise error.ReadOnlyPartError("part is being generated") + raise error.ReadOnlyPartError(b"part is being generated") self._data = data @property @@ -1054,7 +1054,7 @@ # make it an immutable tuple to force people through ``addparam`` return tuple(self._advisoryparams) - def addparam(self, name, value="", mandatory=True): + def addparam(self, name, value=b"", mandatory=True): """add a parameter to the part If 'mandatory' is set to True, the remote handler must claim support @@ -1063,9 +1063,9 @@ The 'name' and 'value' cannot exceed 255 bytes each. """ if self._generated is not None: - raise error.ReadOnlyPartError("part is being generated") + raise error.ReadOnlyPartError(b"part is being generated") if name in self._seenparams: - raise ValueError("duplicated params: %s" % name) + raise ValueError(b"duplicated params: %s" % name) self._seenparams.add(name) params = self._advisoryparams if mandatory: @@ -1075,39 +1075,39 @@ # methods used to generates the bundle2 stream def getchunks(self, ui): if self._generated is not None: - raise error.ProgrammingError("part can only be consumed once") + raise error.ProgrammingError(b"part can only be consumed once") self._generated = False if ui.debugflag: - msg = ['bundle2-output-part: "%s"' % self.type] + msg = [b'bundle2-output-part: "%s"' % self.type] if not self.mandatory: - msg.append(" (advisory)") + msg.append(b" (advisory)") nbmp = len(self.mandatoryparams) nbap = len(self.advisoryparams) if nbmp or nbap: - msg.append(" (params:") + msg.append(b" (params:") if nbmp: - msg.append(" %i mandatory" % nbmp) + msg.append(b" %i mandatory" % nbmp) if nbap: - msg.append(" %i advisory" % nbmp) - msg.append(")") + msg.append(b" %i advisory" % nbmp) + msg.append(b")") if not self.data: - msg.append(" empty payload") - elif util.safehasattr(self.data, "next") or util.safehasattr( - self.data, "__next__" + msg.append(b" empty payload") + elif util.safehasattr(self.data, b"next") or util.safehasattr( + self.data, b"__next__" ): - msg.append(" streamed payload") + msg.append(b" streamed payload") else: - msg.append(" %i bytes payload" % len(self.data)) - msg.append("\n") - ui.debug("".join(msg)) + msg.append(b" %i bytes payload" % len(self.data)) + msg.append(b"\n") + ui.debug(b"".join(msg)) #### header if self.mandatory: parttype = self.type.upper() else: parttype = self.type.lower() - outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype)) + outdebug(ui, b'part %s: "%s"' % (pycompat.bytestr(self.id), parttype)) ## parttype header = [ _pack(_fparttypesize, len(parttype)), @@ -1138,48 +1138,48 @@ header.append(value) ## finalize header try: - headerchunk = "".join(header) + headerchunk = b"".join(header) except TypeError: raise TypeError( r"Found a non-bytes trying to " r"build bundle part header: %r" % header ) - outdebug(ui, "header chunk size: %i" % len(headerchunk)) + outdebug(ui, b"header chunk size: %i" % len(headerchunk)) yield _pack(_fpartheadersize, len(headerchunk)) yield headerchunk ## payload try: for chunk in self._payloadchunks(): - outdebug(ui, "payload chunk size: %i" % len(chunk)) + outdebug(ui, b"payload chunk size: %i" % len(chunk)) yield _pack(_fpayloadsize, len(chunk)) yield chunk except GeneratorExit: # GeneratorExit means that nobody is listening for our # results anyway, so just bail quickly rather than trying # to produce an error part. - ui.debug("bundle2-generatorexit\n") + ui.debug(b"bundle2-generatorexit\n") raise except BaseException as exc: bexc = stringutil.forcebytestr(exc) # backup exception data for later ui.debug( - "bundle2-input-stream-interrupt: encoding exception %s" % bexc + b"bundle2-input-stream-interrupt: encoding exception %s" % bexc ) tb = sys.exc_info()[2] - msg = "unexpected error: %s" % bexc + msg = b"unexpected error: %s" % bexc interpart = bundlepart( - "error:abort", [("message", msg)], mandatory=False + b"error:abort", [(b"message", msg)], mandatory=False ) interpart.id = 0 yield _pack(_fpayloadsize, -1) for chunk in interpart.getchunks(ui=ui): yield chunk - outdebug(ui, "closing payload chunk") + outdebug(ui, b"closing payload chunk") # abort current part payload yield _pack(_fpayloadsize, 0) pycompat.raisewithtb(exc, tb) # end of payload - outdebug(ui, "closing payload chunk") + outdebug(ui, b"closing payload chunk") yield _pack(_fpayloadsize, 0) self._generated = True @@ -1189,8 +1189,8 @@ Exists to handle the different methods to provide data to a part.""" # we only support fixed size data now. # This will be improved in the future. - if util.safehasattr(self.data, "next") or util.safehasattr( - self.data, "__next__" + if util.safehasattr(self.data, b"next") or util.safehasattr( + self.data, b"__next__" ): buff = util.chunkbuffer(self.data) chunk = buff.read(preferedchunksize) @@ -1223,9 +1223,9 @@ headersize = self._unpack(_fpartheadersize)[0] if headersize < 0: raise error.BundleValueError( - "negative part header size: %i" % headersize + b"negative part header size: %i" % headersize ) - indebug(self.ui, "part header size: %i\n" % headersize) + indebug(self.ui, b"part header size: %i\n" % headersize) if headersize: return self._readexact(headersize) return None @@ -1233,12 +1233,12 @@ def __call__(self): self.ui.debug( - "bundle2-input-stream-interrupt:" " opening out of band context\n" + b"bundle2-input-stream-interrupt:" b" opening out of band context\n" ) - indebug(self.ui, "bundle2 stream interruption, looking for a part.") + indebug(self.ui, b"bundle2 stream interruption, looking for a part.") headerblock = self._readpartheader() if headerblock is None: - indebug(self.ui, "no part found during interruption.") + indebug(self.ui, b"no part found during interruption.") return part = unbundlepart(self.ui, headerblock, self._fp) op = interruptoperation(self.ui) @@ -1252,7 +1252,7 @@ if not hardabort: part.consume() self.ui.debug( - "bundle2-input-stream-interrupt:" " closing out of band context\n" + b"bundle2-input-stream-interrupt:" b" closing out of band context\n" ) @@ -1269,10 +1269,10 @@ @property def repo(self): - raise error.ProgrammingError("no repo access from stream interruption") + raise error.ProgrammingError(b"no repo access from stream interruption") def gettransaction(self): - raise TransactionUnavailable("no repo access from stream interruption") + raise TransactionUnavailable(b"no repo access from stream interruption") def decodepayloadchunks(ui, fh): @@ -1281,7 +1281,7 @@ Part payload data consists of framed chunks. This function takes a file handle and emits those chunks. """ - dolog = ui.configbool("devel", "bundle2.debug") + dolog = ui.configbool(b"devel", b"bundle2.debug") debug = ui.debug headerstruct = struct.Struct(_fpayloadsize) @@ -1292,7 +1292,7 @@ read = fh.read chunksize = unpack(readexactly(fh, headersize))[0] - indebug(ui, "payload chunk size: %i" % chunksize) + indebug(ui, b"payload chunk size: %i" % chunksize) # changegroup.readexactly() is inlined below for performance. while chunksize: @@ -1301,8 +1301,8 @@ if len(s) < chunksize: raise error.Abort( _( - "stream ended unexpectedly " - " (got %d bytes, expected %d)" + b"stream ended unexpectedly " + b" (got %d bytes, expected %d)" ) % (len(s), chunksize) ) @@ -1314,13 +1314,13 @@ interrupthandler(ui, fh)() else: raise error.BundleValueError( - "negative payload chunk size: %s" % chunksize + b"negative payload chunk size: %s" % chunksize ) s = read(headersize) if len(s) < headersize: raise error.Abort( - _("stream ended unexpectedly " " (got %d bytes, expected %d)") + _(b"stream ended unexpectedly " b" (got %d bytes, expected %d)") % (len(s), chunksize) ) @@ -1328,7 +1328,7 @@ # indebug() inlined for performance. if dolog: - debug("bundle2-input: payload chunk size: %i\n" % chunksize) + debug(b"bundle2-input: payload chunk size: %i\n" % chunksize) class unbundlepart(unpackermixin): @@ -1336,8 +1336,8 @@ def __init__(self, ui, header, fp): super(unbundlepart, self).__init__(fp) - self._seekable = util.safehasattr(fp, "seek") and util.safehasattr( - fp, "tell" + self._seekable = util.safehasattr(fp, b"seek") and util.safehasattr( + fp, b"tell" ) self.ui = ui # unbundle state attr @@ -1384,16 +1384,16 @@ """read the header and setup the object""" typesize = self._unpackheader(_fparttypesize)[0] self.type = self._fromheader(typesize) - indebug(self.ui, 'part type: "%s"' % self.type) + indebug(self.ui, b'part type: "%s"' % self.type) self.id = self._unpackheader(_fpartid)[0] - indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id)) + indebug(self.ui, b'part id: "%s"' % pycompat.bytestr(self.id)) # extract mandatory bit from type self.mandatory = self.type != self.type.lower() self.type = self.type.lower() ## reading parameters # param count mancount, advcount = self._unpackheader(_fpartparamcount) - indebug(self.ui, "part parameters: %i" % (mancount + advcount)) + indebug(self.ui, b"part parameters: %i" % (mancount + advcount)) # param size fparamsizes = _makefpartparamsizes(mancount + advcount) paramsizes = self._unpackheader(fparamsizes) @@ -1445,7 +1445,7 @@ if size is None or len(data) < size: if not self.consumed and self._pos: self.ui.debug( - "bundle2-input-part: total payload size %i\n" % self._pos + b"bundle2-input-part: total payload size %i\n" % self._pos ) self.consumed = True return data @@ -1478,11 +1478,11 @@ def _payloadchunks(self, chunknum=0): """seek to specified chunk and start yielding data""" if len(self._chunkindex) == 0: - assert chunknum == 0, "Must start with chunk 0" + assert chunknum == 0, b"Must start with chunk 0" self._chunkindex.append((0, self._tellfp())) else: assert chunknum < len(self._chunkindex), ( - "Unknown chunk %d" % chunknum + b"Unknown chunk %d" % chunknum ) self._seekfp(self._chunkindex[chunknum][1]) @@ -1503,7 +1503,7 @@ return chunk, 0 elif ppos > pos: return chunk - 1, pos - self._chunkindex[chunk - 1][0] - raise ValueError("Unknown chunk") + raise ValueError(b"Unknown chunk") def tell(self): return self._pos @@ -1521,7 +1521,7 @@ chunk = self.read(32768) newpos = self._chunkindex[-1][0] - offset else: - raise ValueError("Unknown whence value: %r" % (whence,)) + raise ValueError(b"Unknown whence value: %r" % (whence,)) if newpos > self._chunkindex[-1][0] and not self.consumed: # Can't use self.consume() here because it advances self._pos. @@ -1530,14 +1530,14 @@ chunk = self.read(32668) if not 0 <= newpos <= self._chunkindex[-1][0]: - raise ValueError("Offset out of range") + raise ValueError(b"Offset out of range") if self._pos != newpos: chunk, internaloffset = self._findchunk(newpos) self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk)) adjust = self.read(internaloffset) if len(adjust) != internaloffset: - raise error.Abort(_("Seek failed\n")) + raise error.Abort(_(b"Seek failed\n")) self._pos = newpos def _seekfp(self, offset, whence=0): @@ -1551,7 +1551,7 @@ if self._seekable: return self._fp.seek(offset, whence) else: - raise NotImplementedError(_("File pointer is not seekable")) + raise NotImplementedError(_(b"File pointer is not seekable")) def _tellfp(self): """return the file offset, or None if file is not seekable @@ -1575,17 +1575,17 @@ # These are only the static capabilities. # Check the 'getrepocaps' function for the rest. capabilities = { - "HG20": (), - "bookmarks": (), - "error": ("abort", "unsupportedcontent", "pushraced", "pushkey"), - "listkeys": (), - "pushkey": (), - "digests": tuple(sorted(util.DIGESTS.keys())), - "remote-changegroup": ("http", "https"), - "hgtagsfnodes": (), - "rev-branch-cache": (), - "phases": ("heads",), - "stream": ("v2",), + b"HG20": (), + b"bookmarks": (), + b"error": (b"abort", b"unsupportedcontent", b"pushraced", b"pushkey"), + b"listkeys": (), + b"pushkey": (), + b"digests": tuple(sorted(util.DIGESTS.keys())), + b"remote-changegroup": (b"http", b"https"), + b"hgtagsfnodes": (), + b"rev-branch-cache": (), + b"phases": (b"heads",), + b"stream": (b"v2",), } @@ -1598,33 +1598,33 @@ well as clients advertising their capabilities to servers as part of bundle2 requests. The ``role`` argument specifies which is which. """ - if role not in ("client", "server"): - raise error.ProgrammingError("role argument must be client or server") + if role not in (b"client", b"server"): + raise error.ProgrammingError(b"role argument must be client or server") caps = capabilities.copy() - caps["changegroup"] = tuple( + caps[b"changegroup"] = tuple( sorted(changegroup.supportedincomingversions(repo)) ) if obsolete.isenabled(repo, obsolete.exchangeopt): - supportedformat = tuple("V%i" % v for v in obsolete.formats) - caps["obsmarkers"] = supportedformat + supportedformat = tuple(b"V%i" % v for v in obsolete.formats) + caps[b"obsmarkers"] = supportedformat if allowpushback: - caps["pushback"] = () - cpmode = repo.ui.config("server", "concurrent-push-mode") - if cpmode == "check-related": - caps["checkheads"] = ("related",) - if "phases" in repo.ui.configlist("devel", "legacy.exchange"): - caps.pop("phases") + caps[b"pushback"] = () + cpmode = repo.ui.config(b"server", b"concurrent-push-mode") + if cpmode == b"check-related": + caps[b"checkheads"] = (b"related",) + if b"phases" in repo.ui.configlist(b"devel", b"legacy.exchange"): + caps.pop(b"phases") # Don't advertise stream clone support in server mode if not configured. - if role == "server": + if role == b"server": streamsupported = repo.ui.configbool( - "server", "uncompressed", untrusted=True + b"server", b"uncompressed", untrusted=True ) - featuresupported = repo.ui.configbool("server", "bundle2.stream") + featuresupported = repo.ui.configbool(b"server", b"bundle2.stream") if not streamsupported or not featuresupported: - caps.pop("stream") + caps.pop(b"stream") # Else always advertise support on client, because payload support # should always be advertised. @@ -1633,18 +1633,18 @@ def bundle2caps(remote): """return the bundle capabilities of a peer as dict""" - raw = remote.capable("bundle2") - if not raw and raw != "": + raw = remote.capable(b"bundle2") + if not raw and raw != b"": return {} - capsblob = urlreq.unquote(remote.capable("bundle2")) + capsblob = urlreq.unquote(remote.capable(b"bundle2")) return decodecaps(capsblob) def obsmarkersversion(caps): """extract the list of supported obsmarkers versions from a bundle2caps dict """ - obscaps = caps.get("obsmarkers", ()) - return [int(c[1:]) for c in obscaps if c.startswith("V")] + obscaps = caps.get(b"obsmarkers", ()) + return [int(c[1:]) for c in obscaps if c.startswith(b"V")] def writenewbundle( @@ -1659,8 +1659,8 @@ compression=None, compopts=None, ): - if bundletype.startswith("HG10"): - cg = changegroup.makechangegroup(repo, outgoing, "01", source) + if bundletype.startswith(b"HG10"): + cg = changegroup.makechangegroup(repo, outgoing, b"01", source) return writebundle( ui, cg, @@ -1670,12 +1670,12 @@ compression=compression, compopts=compopts, ) - elif not bundletype.startswith("HG20"): - raise error.ProgrammingError("unknown bundle type: %s" % bundletype) + elif not bundletype.startswith(b"HG20"): + raise error.ProgrammingError(b"unknown bundle type: %s" % bundletype) caps = {} - if "obsolescence" in opts: - caps["obsmarkers"] = ("V1",) + if b"obsolescence" in opts: + caps[b"obsmarkers"] = (b"V1",) bundle = bundle20(ui, caps) bundle.setcompression(compression, compopts) _addpartsfromopts(ui, repo, bundle, source, outgoing, opts) @@ -1694,39 +1694,41 @@ # we might not always want a changegroup in such bundle, for example in # stream bundles - if opts.get("changegroup", True): - cgversion = opts.get("cg.version") + if opts.get(b"changegroup", True): + cgversion = opts.get(b"cg.version") if cgversion is None: cgversion = changegroup.safeversion(repo) cg = changegroup.makechangegroup(repo, outgoing, cgversion, source) - part = bundler.newpart("changegroup", data=cg.getchunks()) - part.addparam("version", cg.version) - if "clcount" in cg.extras: + part = bundler.newpart(b"changegroup", data=cg.getchunks()) + part.addparam(b"version", cg.version) + if b"clcount" in cg.extras: part.addparam( - "nbchanges", "%d" % cg.extras["clcount"], mandatory=False + b"nbchanges", b"%d" % cg.extras[b"clcount"], mandatory=False ) - if opts.get("phases") and repo.revs( - "%ln and secret()", outgoing.missingheads + if opts.get(b"phases") and repo.revs( + b"%ln and secret()", outgoing.missingheads ): - part.addparam("targetphase", "%d" % phases.secret, mandatory=False) - - if opts.get("streamv2", False): + part.addparam( + b"targetphase", b"%d" % phases.secret, mandatory=False + ) + + if opts.get(b"streamv2", False): addpartbundlestream2(bundler, repo, stream=True) - if opts.get("tagsfnodescache", True): + if opts.get(b"tagsfnodescache", True): addparttagsfnodescache(repo, bundler, outgoing) - if opts.get("revbranchcache", True): + if opts.get(b"revbranchcache", True): addpartrevbranchcache(repo, bundler, outgoing) - if opts.get("obsolescence", False): + if opts.get(b"obsolescence", False): obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing) buildobsmarkerspart(bundler, obsmarkers) - if opts.get("phases", False): + if opts.get(b"phases", False): headsbyphase = phases.subsetphaseheads(repo, outgoing.missing) phasedata = phases.binaryencode(headsbyphase) - bundler.newpart("phase-heads", data=phasedata) + bundler.newpart(b"phase-heads", data=phasedata) def addparttagsfnodescache(repo, bundler, outgoing): @@ -1751,7 +1753,7 @@ chunks.extend([node, fnode]) if chunks: - bundler.newpart("hgtagsfnodes", data="".join(chunks)) + bundler.newpart(b"hgtagsfnodes", data=b"".join(chunks)) def addpartrevbranchcache(repo, bundler, outgoing): @@ -1774,17 +1776,17 @@ for n in sorted(closed): yield n - bundler.newpart("cache:rev-branch-cache", data=generate(), mandatory=False) + bundler.newpart(b"cache:rev-branch-cache", data=generate(), mandatory=False) def _formatrequirementsspec(requirements): - requirements = [req for req in requirements if req != "shared"] - return urlreq.quote(",".join(sorted(requirements))) + requirements = [req for req in requirements if req != b"shared"] + return urlreq.quote(b",".join(sorted(requirements))) def _formatrequirementsparams(requirements): requirements = _formatrequirementsspec(requirements) - params = "%s%s" % (urlreq.quote("requirements="), requirements) + params = b"%s%s" % (urlreq.quote(b"requirements="), requirements) return params @@ -1795,13 +1797,13 @@ if not streamclone.allowservergeneration(repo): raise error.Abort( _( - "stream data requested but server does not allow " - "this feature" + b"stream data requested but server does not allow " + b"this feature" ), hint=_( - "well-behaved clients should not be " - "requesting stream data from servers not " - "advertising it; the client may be buggy" + b"well-behaved clients should not be " + b"requesting stream data from servers not " + b"advertising it; the client may be buggy" ), ) @@ -1815,11 +1817,11 @@ excludepats = kwargs.get(r"excludepats") narrowstream = repo.ui.configbool( - "experimental", "server.stream-narrow-clones" + b"experimental", b"server.stream-narrow-clones" ) if (includepats or excludepats) and not narrowstream: - raise error.Abort(_("server does not support narrow stream clones")) + raise error.Abort(_(b"server does not support narrow stream clones")) includeobsmarkers = False if repo.obsstore: @@ -1827,8 +1829,8 @@ if not remoteversions: raise error.Abort( _( - "server has obsolescence markers, but client " - "cannot receive them via stream clone" + b"server has obsolescence markers, but client " + b"cannot receive them via stream clone" ) ) elif repo.obsstore._version in remoteversions: @@ -1838,10 +1840,10 @@ repo, includepats, excludepats, includeobsmarkers ) requirements = _formatrequirementsspec(repo.requirements) - part = bundler.newpart("stream2", data=it) - part.addparam("bytecount", "%d" % bytecount, mandatory=True) - part.addparam("filecount", "%d" % filecount, mandatory=True) - part.addparam("requirements", requirements, mandatory=True) + part = bundler.newpart(b"stream2", data=it) + part.addparam(b"bytecount", b"%d" % bytecount, mandatory=True) + part.addparam(b"filecount", b"%d" % filecount, mandatory=True) + part.addparam(b"requirements", requirements, mandatory=True) def buildobsmarkerspart(bundler, markers): @@ -1856,9 +1858,9 @@ remoteversions = obsmarkersversion(bundler.capabilities) version = obsolete.commonversion(remoteversions) if version is None: - raise ValueError("bundler does not support common obsmarker format") + raise ValueError(b"bundler does not support common obsmarker format") stream = obsolete.encodemarkers(markers, True, version=version) - return bundler.newpart("obsmarkers", data=stream) + return bundler.newpart(b"obsmarkers", data=stream) def writebundle( @@ -1872,26 +1874,26 @@ The bundle file will be deleted in case of errors. """ - if bundletype == "HG20": + if bundletype == b"HG20": bundle = bundle20(ui) bundle.setcompression(compression, compopts) - part = bundle.newpart("changegroup", data=cg.getchunks()) - part.addparam("version", cg.version) - if "clcount" in cg.extras: + part = bundle.newpart(b"changegroup", data=cg.getchunks()) + part.addparam(b"version", cg.version) + if b"clcount" in cg.extras: part.addparam( - "nbchanges", "%d" % cg.extras["clcount"], mandatory=False + b"nbchanges", b"%d" % cg.extras[b"clcount"], mandatory=False ) chunkiter = bundle.getchunks() else: # compression argument is only for the bundle2 case assert compression is None - if cg.version != "01": + if cg.version != b"01": raise error.Abort( - _("old bundle types only supports v1 " "changegroups") + _(b"old bundle types only supports v1 " b"changegroups") ) header, comp = bundletypes[bundletype] if comp not in util.compengines.supportedbundletypes: - raise error.Abort(_("unknown stream compression type: %s") % comp) + raise error.Abort(_(b"unknown stream compression type: %s") % comp) compengine = util.compengines.forbundletype(comp) def chunkiter(): @@ -1908,7 +1910,7 @@ def combinechangegroupresults(op): """logic to combine 0 or more addchangegroup results into one""" - results = [r.get("return", 0) for r in op.records["changegroup"]] + results = [r.get(b"return", 0) for r in op.records[b"changegroup"]] changedheads = 0 result = 1 for ret in results: @@ -1928,7 +1930,7 @@ @parthandler( - "changegroup", ("version", "nbchanges", "treemanifest", "targetphase") + b"changegroup", (b"version", b"nbchanges", b"treemanifest", b"targetphase") ) def handlechangegroup(op, inpart): """apply a changegroup part on the repo @@ -1939,60 +1941,61 @@ from . import localrepo tr = op.gettransaction() - unpackerversion = inpart.params.get("version", "01") + unpackerversion = inpart.params.get(b"version", b"01") # We should raise an appropriate exception here cg = changegroup.getunbundler(unpackerversion, inpart, None) # the source and url passed here are overwritten by the one contained in # the transaction.hookargs argument. So 'bundle2' is a placeholder nbchangesets = None - if "nbchanges" in inpart.params: - nbchangesets = int(inpart.params.get("nbchanges")) + if b"nbchanges" in inpart.params: + nbchangesets = int(inpart.params.get(b"nbchanges")) if ( - "treemanifest" in inpart.params - and "treemanifest" not in op.repo.requirements + b"treemanifest" in inpart.params + and b"treemanifest" not in op.repo.requirements ): if len(op.repo.changelog) != 0: raise error.Abort( _( - "bundle contains tree manifests, but local repo is " - "non-empty and does not use tree manifests" + b"bundle contains tree manifests, but local repo is " + b"non-empty and does not use tree manifests" ) ) - op.repo.requirements.add("treemanifest") + op.repo.requirements.add(b"treemanifest") op.repo.svfs.options = localrepo.resolvestorevfsoptions( op.repo.ui, op.repo.requirements, op.repo.features ) op.repo._writerequirements() extrakwargs = {} - targetphase = inpart.params.get("targetphase") + targetphase = inpart.params.get(b"targetphase") if targetphase is not None: extrakwargs[r"targetphase"] = int(targetphase) ret = _processchangegroup( op, cg, tr, - "bundle2", - "bundle2", + b"bundle2", + b"bundle2", expectedtotal=nbchangesets, **extrakwargs ) if op.reply is not None: # This is definitely not the final form of this # return. But one need to start somewhere. - part = op.reply.newpart("reply:changegroup", mandatory=False) + part = op.reply.newpart(b"reply:changegroup", mandatory=False) part.addparam( - "in-reply-to", pycompat.bytestr(inpart.id), mandatory=False + b"in-reply-to", pycompat.bytestr(inpart.id), mandatory=False ) - part.addparam("return", "%i" % ret, mandatory=False) + part.addparam(b"return", b"%i" % ret, mandatory=False) assert not inpart.read() _remotechangegroupparams = tuple( - ["url", "size", "digests"] + ["digest:%s" % k for k in util.DIGESTS.keys()] + [b"url", b"size", b"digests"] + + [b"digest:%s" % k for k in util.DIGESTS.keys()] ) -@parthandler("remote-changegroup", _remotechangegroupparams) +@parthandler(b"remote-changegroup", _remotechangegroupparams) def handleremotechangegroup(op, inpart): """apply a bundle10 on the repo, given an url and validation information @@ -2010,32 +2013,35 @@ When multiple digest types are given, all of them are checked. """ try: - raw_url = inpart.params["url"] + raw_url = inpart.params[b"url"] except KeyError: - raise error.Abort(_('remote-changegroup: missing "%s" param') % "url") + raise error.Abort(_(b'remote-changegroup: missing "%s" param') % b"url") parsed_url = util.url(raw_url) - if parsed_url.scheme not in capabilities["remote-changegroup"]: + if parsed_url.scheme not in capabilities[b"remote-changegroup"]: raise error.Abort( - _("remote-changegroup does not support %s urls") % parsed_url.scheme + _(b"remote-changegroup does not support %s urls") + % parsed_url.scheme ) try: - size = int(inpart.params["size"]) + size = int(inpart.params[b"size"]) except ValueError: raise error.Abort( - _('remote-changegroup: invalid value for param "%s"') % "size" + _(b'remote-changegroup: invalid value for param "%s"') % b"size" ) except KeyError: - raise error.Abort(_('remote-changegroup: missing "%s" param') % "size") + raise error.Abort( + _(b'remote-changegroup: missing "%s" param') % b"size" + ) digests = {} - for typ in inpart.params.get("digests", "").split(): - param = "digest:%s" % typ + for typ in inpart.params.get(b"digests", b"").split(): + param = b"digest:%s" % typ try: value = inpart.params[param] except KeyError: raise error.Abort( - _('remote-changegroup: missing "%s" param') % param + _(b'remote-changegroup: missing "%s" param') % param ) digests[typ] = value @@ -2047,35 +2053,35 @@ cg = exchange.readbundle(op.repo.ui, real_part, raw_url) if not isinstance(cg, changegroup.cg1unpacker): raise error.Abort( - _("%s: not a bundle version 1.0") % util.hidepassword(raw_url) + _(b"%s: not a bundle version 1.0") % util.hidepassword(raw_url) ) - ret = _processchangegroup(op, cg, tr, "bundle2", "bundle2") + ret = _processchangegroup(op, cg, tr, b"bundle2", b"bundle2") if op.reply is not None: # This is definitely not the final form of this # return. But one need to start somewhere. - part = op.reply.newpart("reply:changegroup") + part = op.reply.newpart(b"reply:changegroup") part.addparam( - "in-reply-to", pycompat.bytestr(inpart.id), mandatory=False + b"in-reply-to", pycompat.bytestr(inpart.id), mandatory=False ) - part.addparam("return", "%i" % ret, mandatory=False) + part.addparam(b"return", b"%i" % ret, mandatory=False) try: real_part.validate() except error.Abort as e: raise error.Abort( - _("bundle at %s is corrupted:\n%s") + _(b"bundle at %s is corrupted:\n%s") % (util.hidepassword(raw_url), bytes(e)) ) assert not inpart.read() -@parthandler("reply:changegroup", ("return", "in-reply-to")) +@parthandler(b"reply:changegroup", (b"return", b"in-reply-to")) def handlereplychangegroup(op, inpart): - ret = int(inpart.params["return"]) - replyto = int(inpart.params["in-reply-to"]) - op.records.add("changegroup", {"return": ret}, replyto) - - -@parthandler("check:bookmarks") + ret = int(inpart.params[b"return"]) + replyto = int(inpart.params[b"in-reply-to"]) + op.records.add(b"changegroup", {b"return": ret}, replyto) + + +@parthandler(b"check:bookmarks") def handlecheckbookmarks(op, inpart): """check location of bookmarks @@ -2086,16 +2092,16 @@ bookdata = bookmarks.binarydecode(inpart) msgstandard = ( - "remote repository changed while pushing - please try again " - '(bookmark "%s" move from %s to %s)' + b"remote repository changed while pushing - please try again " + b'(bookmark "%s" move from %s to %s)' ) msgmissing = ( - "remote repository changed while pushing - please try again " - '(bookmark "%s" is missing, expected %s)' + b"remote repository changed while pushing - please try again " + b'(bookmark "%s" is missing, expected %s)' ) msgexist = ( - "remote repository changed while pushing - please try again " - '(bookmark "%s" set on %s, expected missing)' + b"remote repository changed while pushing - please try again " + b'(bookmark "%s" set on %s, expected missing)' ) for book, node in bookdata: currentnode = op.repo._bookmarks.get(book) @@ -2113,7 +2119,7 @@ raise error.PushRaced(finalmsg) -@parthandler("check:heads") +@parthandler(b"check:heads") def handlecheckheads(op, inpart): """check that head of the repo did not change @@ -2126,15 +2132,15 @@ h = inpart.read(20) assert not h # Trigger a transaction so that we are guaranteed to have the lock now. - if op.ui.configbool("experimental", "bundle2lazylocking"): + if op.ui.configbool(b"experimental", b"bundle2lazylocking"): op.gettransaction() if sorted(heads) != sorted(op.repo.heads()): raise error.PushRaced( - "remote repository changed while pushing - " "please try again" + b"remote repository changed while pushing - " b"please try again" ) -@parthandler("check:updated-heads") +@parthandler(b"check:updated-heads") def handlecheckupdatedheads(op, inpart): """check for race on the heads touched by a push @@ -2151,7 +2157,7 @@ h = inpart.read(20) assert not h # trigger a transaction so that we are guaranteed to have the lock now. - if op.ui.configbool("experimental", "bundle2lazylocking"): + if op.ui.configbool(b"experimental", b"bundle2lazylocking"): op.gettransaction() currentheads = set() @@ -2161,11 +2167,12 @@ for h in heads: if h not in currentheads: raise error.PushRaced( - "remote repository changed while pushing - " "please try again" + b"remote repository changed while pushing - " + b"please try again" ) -@parthandler("check:phases") +@parthandler(b"check:phases") def handlecheckphases(op, inpart): """check that phase boundaries of the repository did not change @@ -2176,8 +2183,8 @@ cl = unfi.changelog phasecache = unfi._phasecache msg = ( - "remote repository changed while pushing - please try again " - "(%s is %s expected %s)" + b"remote repository changed while pushing - please try again " + b"(%s is %s expected %s)" ) for expectedphase, nodes in enumerate(phasetonodes): for n in nodes: @@ -2191,14 +2198,14 @@ raise error.PushRaced(finalmsg) -@parthandler("output") +@parthandler(b"output") def handleoutput(op, inpart): """forward output captured on the server to the client""" for line in inpart.read().splitlines(): - op.ui.status(_("remote: %s\n") % line) - - -@parthandler("replycaps") + op.ui.status(_(b"remote: %s\n") % line) + + +@parthandler(b"replycaps") def handlereplycaps(op, inpart): """Notify that a reply bundle should be created @@ -2212,89 +2219,90 @@ """Sub-class of Abort that denotes an error from a bundle2 part.""" -@parthandler("error:abort", ("message", "hint")) +@parthandler(b"error:abort", (b"message", b"hint")) def handleerrorabort(op, inpart): """Used to transmit abort error over the wire""" raise AbortFromPart( - inpart.params["message"], hint=inpart.params.get("hint") + inpart.params[b"message"], hint=inpart.params.get(b"hint") ) @parthandler( - "error:pushkey", ("namespace", "key", "new", "old", "ret", "in-reply-to") + b"error:pushkey", + (b"namespace", b"key", b"new", b"old", b"ret", b"in-reply-to"), ) def handleerrorpushkey(op, inpart): """Used to transmit failure of a mandatory pushkey over the wire""" kwargs = {} - for name in ("namespace", "key", "new", "old", "ret"): + for name in (b"namespace", b"key", b"new", b"old", b"ret"): value = inpart.params.get(name) if value is not None: kwargs[name] = value raise error.PushkeyFailed( - inpart.params["in-reply-to"], **pycompat.strkwargs(kwargs) + inpart.params[b"in-reply-to"], **pycompat.strkwargs(kwargs) ) -@parthandler("error:unsupportedcontent", ("parttype", "params")) +@parthandler(b"error:unsupportedcontent", (b"parttype", b"params")) def handleerrorunsupportedcontent(op, inpart): """Used to transmit unknown content error over the wire""" kwargs = {} - parttype = inpart.params.get("parttype") + parttype = inpart.params.get(b"parttype") if parttype is not None: - kwargs["parttype"] = parttype - params = inpart.params.get("params") + kwargs[b"parttype"] = parttype + params = inpart.params.get(b"params") if params is not None: - kwargs["params"] = params.split("\0") + kwargs[b"params"] = params.split(b"\0") raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs)) -@parthandler("error:pushraced", ("message",)) +@parthandler(b"error:pushraced", (b"message",)) def handleerrorpushraced(op, inpart): """Used to transmit push race error over the wire""" - raise error.ResponseError(_("push failed:"), inpart.params["message"]) - - -@parthandler("listkeys", ("namespace",)) + raise error.ResponseError(_(b"push failed:"), inpart.params[b"message"]) + + +@parthandler(b"listkeys", (b"namespace",)) def handlelistkeys(op, inpart): """retrieve pushkey namespace content stored in a bundle2""" - namespace = inpart.params["namespace"] + namespace = inpart.params[b"namespace"] r = pushkey.decodekeys(inpart.read()) - op.records.add("listkeys", (namespace, r)) - - -@parthandler("pushkey", ("namespace", "key", "old", "new")) + op.records.add(b"listkeys", (namespace, r)) + + +@parthandler(b"pushkey", (b"namespace", b"key", b"old", b"new")) def handlepushkey(op, inpart): """process a pushkey request""" dec = pushkey.decode - namespace = dec(inpart.params["namespace"]) - key = dec(inpart.params["key"]) - old = dec(inpart.params["old"]) - new = dec(inpart.params["new"]) + namespace = dec(inpart.params[b"namespace"]) + key = dec(inpart.params[b"key"]) + old = dec(inpart.params[b"old"]) + new = dec(inpart.params[b"new"]) # Grab the transaction to ensure that we have the lock before performing the # pushkey. - if op.ui.configbool("experimental", "bundle2lazylocking"): + if op.ui.configbool(b"experimental", b"bundle2lazylocking"): op.gettransaction() ret = op.repo.pushkey(namespace, key, old, new) - record = {"namespace": namespace, "key": key, "old": old, "new": new} - op.records.add("pushkey", record) + record = {b"namespace": namespace, b"key": key, b"old": old, b"new": new} + op.records.add(b"pushkey", record) if op.reply is not None: - rpart = op.reply.newpart("reply:pushkey") + rpart = op.reply.newpart(b"reply:pushkey") rpart.addparam( - "in-reply-to", pycompat.bytestr(inpart.id), mandatory=False + b"in-reply-to", pycompat.bytestr(inpart.id), mandatory=False ) - rpart.addparam("return", "%i" % ret, mandatory=False) + rpart.addparam(b"return", b"%i" % ret, mandatory=False) if inpart.mandatory and not ret: kwargs = {} - for key in ("namespace", "key", "new", "old", "ret"): + for key in (b"namespace", b"key", b"new", b"old", b"ret"): if key in inpart.params: kwargs[key] = inpart.params[key] raise error.PushkeyFailed( - partid="%d" % inpart.id, **pycompat.strkwargs(kwargs) + partid=b"%d" % inpart.id, **pycompat.strkwargs(kwargs) ) -@parthandler("bookmarks") +@parthandler(b"bookmarks") def handlebookmark(op, inpart): """transmit bookmark information @@ -2313,26 +2321,30 @@ """ changes = bookmarks.binarydecode(inpart) - pushkeycompat = op.repo.ui.configbool("server", "bookmarks-pushkey-compat") - bookmarksmode = op.modes.get("bookmarks", "apply") - - if bookmarksmode == "apply": + pushkeycompat = op.repo.ui.configbool( + b"server", b"bookmarks-pushkey-compat" + ) + bookmarksmode = op.modes.get(b"bookmarks", b"apply") + + if bookmarksmode == b"apply": tr = op.gettransaction() bookstore = op.repo._bookmarks if pushkeycompat: allhooks = [] for book, node in changes: hookargs = tr.hookargs.copy() - hookargs["pushkeycompat"] = "1" - hookargs["namespace"] = "bookmarks" - hookargs["key"] = book - hookargs["old"] = nodemod.hex(bookstore.get(book, "")) - hookargs["new"] = nodemod.hex(node if node is not None else "") + hookargs[b"pushkeycompat"] = b"1" + hookargs[b"namespace"] = b"bookmarks" + hookargs[b"key"] = book + hookargs[b"old"] = nodemod.hex(bookstore.get(book, b"")) + hookargs[b"new"] = nodemod.hex( + node if node is not None else b"" + ) allhooks.append(hookargs) for hookargs in allhooks: op.repo.hook( - "prepushkey", throw=True, **pycompat.strkwargs(hookargs) + b"prepushkey", throw=True, **pycompat.strkwargs(hookargs) ) bookstore.applychanges(op.repo, op.gettransaction(), changes) @@ -2341,72 +2353,78 @@ def runhook(): for hookargs in allhooks: - op.repo.hook("pushkey", **pycompat.strkwargs(hookargs)) + op.repo.hook(b"pushkey", **pycompat.strkwargs(hookargs)) op.repo._afterlock(runhook) - elif bookmarksmode == "records": + elif bookmarksmode == b"records": for book, node in changes: - record = {"bookmark": book, "node": node} - op.records.add("bookmarks", record) + record = {b"bookmark": book, b"node": node} + op.records.add(b"bookmarks", record) else: - raise error.ProgrammingError("unkown bookmark mode: %s" % bookmarksmode) - - -@parthandler("phase-heads") + raise error.ProgrammingError( + b"unkown bookmark mode: %s" % bookmarksmode + ) + + +@parthandler(b"phase-heads") def handlephases(op, inpart): """apply phases from bundle part to repo""" headsbyphase = phases.binarydecode(inpart) phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase) -@parthandler("reply:pushkey", ("return", "in-reply-to")) +@parthandler(b"reply:pushkey", (b"return", b"in-reply-to")) def handlepushkeyreply(op, inpart): """retrieve the result of a pushkey request""" - ret = int(inpart.params["return"]) - partid = int(inpart.params["in-reply-to"]) - op.records.add("pushkey", {"return": ret}, partid) - - -@parthandler("obsmarkers") + ret = int(inpart.params[b"return"]) + partid = int(inpart.params[b"in-reply-to"]) + op.records.add(b"pushkey", {b"return": ret}, partid) + + +@parthandler(b"obsmarkers") def handleobsmarker(op, inpart): """add a stream of obsmarkers to the repo""" tr = op.gettransaction() markerdata = inpart.read() - if op.ui.config("experimental", "obsmarkers-exchange-debug"): - op.ui.write("obsmarker-exchange: %i bytes received\n" % len(markerdata)) + if op.ui.config(b"experimental", b"obsmarkers-exchange-debug"): + op.ui.write( + b"obsmarker-exchange: %i bytes received\n" % len(markerdata) + ) # The mergemarkers call will crash if marker creation is not enabled. # we want to avoid this if the part is advisory. if not inpart.mandatory and op.repo.obsstore.readonly: - op.repo.ui.debug("ignoring obsolescence markers, feature not enabled\n") + op.repo.ui.debug( + b"ignoring obsolescence markers, feature not enabled\n" + ) return new = op.repo.obsstore.mergemarkers(tr, markerdata) op.repo.invalidatevolatilesets() - op.records.add("obsmarkers", {"new": new}) + op.records.add(b"obsmarkers", {b"new": new}) if op.reply is not None: - rpart = op.reply.newpart("reply:obsmarkers") + rpart = op.reply.newpart(b"reply:obsmarkers") rpart.addparam( - "in-reply-to", pycompat.bytestr(inpart.id), mandatory=False + b"in-reply-to", pycompat.bytestr(inpart.id), mandatory=False ) - rpart.addparam("new", "%i" % new, mandatory=False) - - -@parthandler("reply:obsmarkers", ("new", "in-reply-to")) + rpart.addparam(b"new", b"%i" % new, mandatory=False) + + +@parthandler(b"reply:obsmarkers", (b"new", b"in-reply-to")) def handleobsmarkerreply(op, inpart): """retrieve the result of a pushkey request""" - ret = int(inpart.params["new"]) - partid = int(inpart.params["in-reply-to"]) - op.records.add("obsmarkers", {"new": ret}, partid) - - -@parthandler("hgtagsfnodes") + ret = int(inpart.params[b"new"]) + partid = int(inpart.params[b"in-reply-to"]) + op.records.add(b"obsmarkers", {b"new": ret}, partid) + + +@parthandler(b"hgtagsfnodes") def handlehgtagsfnodes(op, inpart): """Applies .hgtags fnodes cache entries to the local repo. Payload is pairs of 20 byte changeset nodes and filenodes. """ # Grab the transaction so we ensure that we have the lock at this point. - if op.ui.configbool("experimental", "bundle2lazylocking"): + if op.ui.configbool(b"experimental", b"bundle2lazylocking"): op.gettransaction() cache = tags.hgtagsfnodescache(op.repo.unfiltered()) @@ -2415,19 +2433,19 @@ node = inpart.read(20) fnode = inpart.read(20) if len(node) < 20 or len(fnode) < 20: - op.ui.debug("ignoring incomplete received .hgtags fnodes data\n") + op.ui.debug(b"ignoring incomplete received .hgtags fnodes data\n") break cache.setfnode(node, fnode) count += 1 cache.write() - op.ui.debug("applied %i hgtags fnodes cache entries\n" % count) - - -rbcstruct = struct.Struct(">III") - - -@parthandler("cache:rev-branch-cache") + op.ui.debug(b"applied %i hgtags fnodes cache entries\n" % count) + + +rbcstruct = struct.Struct(b">III") + + +@parthandler(b"cache:rev-branch-cache") def handlerbc(op, inpart): """receive a rev-branch-cache payload and update the local cache @@ -2460,34 +2478,34 @@ cache.write() -@parthandler("pushvars") +@parthandler(b"pushvars") def bundle2getvars(op, part): """unbundle a bundle2 containing shellvars on the server""" # An option to disable unbundling on server-side for security reasons - if op.ui.configbool("push", "pushvars.server"): + if op.ui.configbool(b"push", b"pushvars.server"): hookargs = {} for key, value in part.advisoryparams: key = key.upper() # We want pushed variables to have USERVAR_ prepended so we know # they came from the --pushvar flag. - key = "USERVAR_" + key + key = b"USERVAR_" + key hookargs[key] = value op.addhookargs(hookargs) -@parthandler("stream2", ("requirements", "filecount", "bytecount")) +@parthandler(b"stream2", (b"requirements", b"filecount", b"bytecount")) def handlestreamv2bundle(op, part): - requirements = urlreq.unquote(part.params["requirements"]).split(",") - filecount = int(part.params["filecount"]) - bytecount = int(part.params["bytecount"]) + requirements = urlreq.unquote(part.params[b"requirements"]).split(b",") + filecount = int(part.params[b"filecount"]) + bytecount = int(part.params[b"bytecount"]) repo = op.repo if len(repo): - msg = _("cannot apply stream clone to non empty repository") + msg = _(b"cannot apply stream clone to non empty repository") raise error.Abort(msg) - repo.ui.debug("applying stream bundle\n") + repo.ui.debug(b"applying stream bundle\n") streamclone.applybundlev2(repo, part, filecount, bytecount, requirements) @@ -2509,7 +2527,7 @@ """ commonnodes = set() cl = repo.changelog - for r in repo.revs("::%ln", common): + for r in repo.revs(b"::%ln", common): commonnodes.add(cl.node(r)) if commonnodes: # XXX: we should only send the filelogs (and treemanifest). user @@ -2525,13 +2543,13 @@ {nodemod.nullid}, list(commonnodes), False, - "narrow_widen", + b"narrow_widen", changelog=False, ) - part = bundler.newpart("changegroup", data=cgdata) - part.addparam("version", cgversion) - if "treemanifest" in repo.requirements: - part.addparam("treemanifest", "1") + part = bundler.newpart(b"changegroup", data=cgdata) + part.addparam(b"version", cgversion) + if b"treemanifest" in repo.requirements: + part.addparam(b"treemanifest", b"1") return bundler diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -72,12 +72,12 @@ for p in (p1, p2): if p not in self.nodemap: raise error.LookupError( - p, self.indexfile, _("unknown parent") + p, self.indexfile, _(b"unknown parent") ) if deltabase not in self.nodemap: raise LookupError( - deltabase, self.indexfile, _("unknown delta base") + deltabase, self.indexfile, _(b"unknown delta base") ) baserev = self.rev(deltabase) @@ -133,7 +133,7 @@ chain.append(iterrev) iterrev = self.index[iterrev][3] if iterrev == nullrev: - rawtext = "" + rawtext = b"" elif rawtext is None: r = super(bundlerevlog, self)._rawtext( self.node(iterrev), iterrev, _df=_df @@ -170,7 +170,7 @@ class bundlemanifest(bundlerevlog, manifest.manifestrevlog): def __init__( - self, opener, cgunpacker, linkmapper, dirlogstarts=None, dir="" + self, opener, cgunpacker, linkmapper, dirlogstarts=None, dir=b"" ): manifest.manifestrevlog.__init__(self, opener, tree=dir) bundlerevlog.__init__( @@ -178,7 +178,7 @@ ) if dirlogstarts is None: dirlogstarts = {} - if self.bundle.version == "03": + if self.bundle.version == b"03": dirlogstarts = _getfilestarts(self.bundle) self._dirlogstarts = dirlogstarts self._linkmapper = linkmapper @@ -212,7 +212,7 @@ class bundlephasecache(phases.phasecache): def __init__(self, *args, **kwargs): super(bundlephasecache, self).__init__(*args, **kwargs) - if util.safehasattr(self, "opener"): + if util.safehasattr(self, b"opener"): self.opener = vfsmod.readonlyvfs(self.opener) def write(self): @@ -230,7 +230,7 @@ def _getfilestarts(cgunpacker): filespos = {} for chunkdata in iter(cgunpacker.filelogheader, {}): - fname = chunkdata["filename"] + fname = chunkdata[b"filename"] filespos[fname] = cgunpacker.tell() for chunk in iter(lambda: cgunpacker.deltachunk(None), {}): pass @@ -254,10 +254,10 @@ self._tempparent = tempparent self._url = url - self.ui.setconfig("phases", "publish", False, "bundlerepo") + self.ui.setconfig(b"phases", b"publish", False, b"bundlerepo") self.tempfile = None - f = util.posixfile(bundlepath, "rb") + f = util.posixfile(bundlepath, b"rb") bundle = exchange.readbundle(self.ui, f, bundlepath) if isinstance(bundle, bundle2.unbundle20): @@ -266,17 +266,17 @@ cgpart = None for part in bundle.iterparts(seekable=True): - if part.type == "changegroup": + if part.type == b"changegroup": if cgpart: raise NotImplementedError( - "can't process " "multiple changegroups" + b"can't process " b"multiple changegroups" ) cgpart = part self._handlebundle2part(bundle, part) if not cgpart: - raise error.Abort(_("No changegroups found")) + raise error.Abort(_(b"No changegroups found")) # This is required to placate a later consumer, which expects # the payload offset to be at the beginning of the changegroup. @@ -288,14 +288,16 @@ elif isinstance(bundle, changegroup.cg1unpacker): if bundle.compressed(): f = self._writetempbundle( - bundle.read, ".hg10un", header="HG10UN" + bundle.read, b".hg10un", header=b"HG10UN" ) bundle = exchange.readbundle(self.ui, f, bundlepath, self.vfs) self._bundlefile = bundle self._cgunpacker = bundle else: - raise error.Abort(_("bundle type %s cannot be read") % type(bundle)) + raise error.Abort( + _(b"bundle type %s cannot be read") % type(bundle) + ) # dict with the mapping 'filename' -> position in the changegroup. self._cgfilespos = {} @@ -309,24 +311,24 @@ ) def _handlebundle2part(self, bundle, part): - if part.type != "changegroup": + if part.type != b"changegroup": return cgstream = part - version = part.params.get("version", "01") + version = part.params.get(b"version", b"01") legalcgvers = changegroup.supportedincomingversions(self) if version not in legalcgvers: - msg = _("Unsupported changegroup version: %s") + msg = _(b"Unsupported changegroup version: %s") raise error.Abort(msg % version) if bundle.compressed(): - cgstream = self._writetempbundle(part.read, ".cg%sun" % version) + cgstream = self._writetempbundle(part.read, b".cg%sun" % version) - self._cgunpacker = changegroup.getunbundler(version, cgstream, "UN") + self._cgunpacker = changegroup.getunbundler(version, cgstream, b"UN") - def _writetempbundle(self, readfn, suffix, header=""): + def _writetempbundle(self, readfn, suffix, header=b""): """Write a temporary file to disk """ - fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-", suffix=suffix) + fdtemp, temp = self.vfs.mkstemp(prefix=b"hg-bundle-", suffix=suffix) self.tempfile = temp with os.fdopen(fdtemp, r"wb") as fptemp: @@ -337,7 +339,7 @@ break fptemp.write(chunk) - return self.vfs.open(self.tempfile, mode="rb") + return self.vfs.open(self.tempfile, mode=b"rb") @localrepo.unfilteredpropertycache def _phasecache(self): @@ -432,7 +434,7 @@ def setparents(self, p1, p2=nullid): p1rev = self.changelog.rev(p1) p2rev = self.changelog.rev(p2) - msg = _("setting parent to node %s that only exists in the bundle\n") + msg = _(b"setting parent to node %s that only exists in the bundle\n") if self.changelog.repotiprev < p1rev: self.ui.warn(msg % nodemod.hex(p1)) if self.changelog.repotiprev < p2rev: @@ -442,28 +444,28 @@ def instance(ui, path, create, intents=None, createopts=None): if create: - raise error.Abort(_("cannot create new bundle repository")) + raise error.Abort(_(b"cannot create new bundle repository")) # internal config: bundle.mainreporoot - parentpath = ui.config("bundle", "mainreporoot") + parentpath = ui.config(b"bundle", b"mainreporoot") if not parentpath: # try to find the correct path to the working directory repo parentpath = cmdutil.findrepo(encoding.getcwd()) if parentpath is None: - parentpath = "" + parentpath = b"" if parentpath: # Try to make the full path relative so we get a nice, short URL. # In particular, we don't want temp dir names in test outputs. cwd = encoding.getcwd() if parentpath == cwd: - parentpath = "" + parentpath = b"" else: cwd = pathutil.normasprefix(cwd) if parentpath.startswith(cwd): parentpath = parentpath[len(cwd) :] u = util.url(path) path = u.localpath() - if u.scheme == "bundle": - s = path.split("+", 1) + if u.scheme == b"bundle": + s = path.split(b"+", 1) if len(s) == 1: repopath, bundlename = parentpath, s[0] else: @@ -477,9 +479,9 @@ def makebundlerepository(ui, repopath, bundlepath): """Make a bundle repository object based on repo and bundle paths.""" if repopath: - url = "bundle:%s+%s" % (util.expandpath(repopath), bundlepath) + url = b"bundle:%s+%s" % (util.expandpath(repopath), bundlepath) else: - url = "bundle:%s" % bundlepath + url = b"bundle:%s" % bundlepath # Because we can't make any guarantees about the type of the base # repository, we can't have a static class representing the bundle @@ -565,23 +567,25 @@ # create a bundle (uncompressed if peer repo is not local) # developer config: devel.legacy.exchange - legexc = ui.configlist("devel", "legacy.exchange") - forcebundle1 = "bundle2" not in legexc and "bundle1" in legexc + legexc = ui.configlist(b"devel", b"legacy.exchange") + forcebundle1 = b"bundle2" not in legexc and b"bundle1" in legexc canbundle2 = ( not forcebundle1 - and peer.capable("getbundle") - and peer.capable("bundle2") + and peer.capable(b"getbundle") + and peer.capable(b"bundle2") ) if canbundle2: with peer.commandexecutor() as e: b2 = e.callcommand( - "getbundle", + b"getbundle", { - "source": "incoming", - "common": common, - "heads": rheads, - "bundlecaps": exchange.caps20to10(repo, role="client"), - "cg": True, + b"source": b"incoming", + b"common": common, + b"heads": rheads, + b"bundlecaps": exchange.caps20to10( + repo, role=b"client" + ), + b"cg": True, }, ).result() @@ -589,41 +593,41 @@ ui, b2._forwardchunks(), bundlename ) else: - if peer.capable("getbundle"): + if peer.capable(b"getbundle"): with peer.commandexecutor() as e: cg = e.callcommand( - "getbundle", + b"getbundle", { - "source": "incoming", - "common": common, - "heads": rheads, + b"source": b"incoming", + b"common": common, + b"heads": rheads, }, ).result() - elif onlyheads is None and not peer.capable("changegroupsubset"): + elif onlyheads is None and not peer.capable(b"changegroupsubset"): # compat with older servers when pulling all remote heads with peer.commandexecutor() as e: cg = e.callcommand( - "changegroup", - {"nodes": incoming, "source": "incoming",}, + b"changegroup", + {b"nodes": incoming, b"source": b"incoming",}, ).result() rheads = None else: with peer.commandexecutor() as e: cg = e.callcommand( - "changegroupsubset", + b"changegroupsubset", { - "bases": incoming, - "heads": rheads, - "source": "incoming", + b"bases": incoming, + b"heads": rheads, + b"source": b"incoming", }, ).result() if localrepo: - bundletype = "HG10BZ" + bundletype = b"HG10BZ" else: - bundletype = "HG10UN" + bundletype = b"HG10UN" fname = bundle = bundle2.writebundle(ui, cg, bundlename, bundletype) # keep written bundle? if bundlename: @@ -649,7 +653,7 @@ with peer.commandexecutor() as e: remotephases = e.callcommand( - "listkeys", {"namespace": "phases",} + b"listkeys", {b"namespace": b"phases",} ).result() pullop = exchange.pulloperation(bundlerepo, peer, heads=reponodes) diff --git a/mercurial/cacheutil.py b/mercurial/cacheutil.py --- a/mercurial/cacheutil.py +++ b/mercurial/cacheutil.py @@ -13,10 +13,10 @@ """return the list of cache file valuable to copy during a clone""" # In local clones we're copying all nodes, not just served # ones. Therefore copy all branch caches over. - cachefiles = ["branch2"] - cachefiles += ["branch2-%s" % f for f in repoview.filtertable] - cachefiles += ["rbc-names-v1", "rbc-revs-v1"] - cachefiles += ["tags2"] - cachefiles += ["tags2-%s" % f for f in repoview.filtertable] - cachefiles += ["hgtagsfnodes1"] + cachefiles = [b"branch2"] + cachefiles += [b"branch2-%s" % f for f in repoview.filtertable] + cachefiles += [b"rbc-names-v1", b"rbc-revs-v1"] + cachefiles += [b"tags2"] + cachefiles += [b"tags2-%s" % f for f in repoview.filtertable] + cachefiles += [b"hgtagsfnodes1"] return cachefiles diff --git a/mercurial/cffi/bdiff.py b/mercurial/cffi/bdiff.py --- a/mercurial/cffi/bdiff.py +++ b/mercurial/cffi/bdiff.py @@ -17,11 +17,11 @@ def blocks(sa, sb): - a = ffi.new("struct bdiff_line**") - b = ffi.new("struct bdiff_line**") - ac = ffi.new("char[]", str(sa)) - bc = ffi.new("char[]", str(sb)) - l = ffi.new("struct bdiff_hunk*") + a = ffi.new(b"struct bdiff_line**") + b = ffi.new(b"struct bdiff_line**") + ac = ffi.new(b"char[]", str(sa)) + bc = ffi.new(b"char[]", str(sb)) + l = ffi.new(b"struct bdiff_hunk*") try: an = lib.bdiff_splitlines(ac, len(sa), a) bn = lib.bdiff_splitlines(bc, len(sb), b) @@ -45,11 +45,11 @@ def bdiff(sa, sb): - a = ffi.new("struct bdiff_line**") - b = ffi.new("struct bdiff_line**") - ac = ffi.new("char[]", str(sa)) - bc = ffi.new("char[]", str(sb)) - l = ffi.new("struct bdiff_hunk*") + a = ffi.new(b"struct bdiff_line**") + b = ffi.new(b"struct bdiff_line**") + ac = ffi.new(b"char[]", str(sa)) + bc = ffi.new(b"char[]", str(sb)) + l = ffi.new(b"struct bdiff_hunk*") try: an = lib.bdiff_splitlines(ac, len(sa), a) bn = lib.bdiff_splitlines(bc, len(sb), b) @@ -66,7 +66,7 @@ lgt = (b[0] + h.b1).l - (b[0] + lb).l rl.append( struct.pack( - ">lll", + b">lll", (a[0] + la).l - a[0].l, (a[0] + h.a1).l - a[0].l, lgt, @@ -81,4 +81,4 @@ lib.free(a[0]) lib.free(b[0]) lib.bdiff_freehunks(l.next) - return "".join(rl) + return b"".join(rl) diff --git a/mercurial/cffi/bdiffbuild.py b/mercurial/cffi/bdiffbuild.py --- a/mercurial/cffi/bdiffbuild.py +++ b/mercurial/cffi/bdiffbuild.py @@ -5,10 +5,10 @@ ffi = cffi.FFI() with open( - os.path.join(os.path.join(os.path.dirname(__file__), ".."), "bdiff.c") + os.path.join(os.path.join(os.path.dirname(__file__), b".."), b"bdiff.c") ) as f: ffi.set_source( - "mercurial.cffi._bdiff", f.read(), include_dirs=["mercurial"] + b"mercurial.cffi._bdiff", f.read(), include_dirs=[b"mercurial"] ) ffi.cdef( """ diff --git a/mercurial/cffi/mpatch.py b/mercurial/cffi/mpatch.py --- a/mercurial/cffi/mpatch.py +++ b/mercurial/cffi/mpatch.py @@ -18,8 +18,8 @@ @ffi.def_extern() def cffi_get_next_item(arg, pos): all, bins = ffi.from_handle(arg) - container = ffi.new("struct mpatch_flist*[1]") - to_pass = ffi.new("char[]", str(bins[pos])) + container = ffi.new(b"struct mpatch_flist*[1]") + to_pass = ffi.new(b"char[]", str(bins[pos])) all.append(to_pass) r = lib.mpatch_decode(to_pass, len(to_pass) - 1, container) if r < 0: @@ -35,15 +35,15 @@ arg = (all, bins) patch = lib.mpatch_fold(ffi.new_handle(arg), lib.cffi_get_next_item, 0, lgt) if not patch: - raise mpatchError("cannot decode chunk") + raise mpatchError(b"cannot decode chunk") outlen = lib.mpatch_calcsize(len(text), patch) if outlen < 0: lib.mpatch_lfree(patch) - raise mpatchError("inconsistency detected") - buf = ffi.new("char[]", outlen) + raise mpatchError(b"inconsistency detected") + buf = ffi.new(b"char[]", outlen) if lib.mpatch_apply(buf, text, len(text), patch) < 0: lib.mpatch_lfree(patch) - raise mpatchError("error applying patches") + raise mpatchError(b"error applying patches") res = ffi.buffer(buf, outlen)[:] lib.mpatch_lfree(patch) return res diff --git a/mercurial/cffi/mpatchbuild.py b/mercurial/cffi/mpatchbuild.py --- a/mercurial/cffi/mpatchbuild.py +++ b/mercurial/cffi/mpatchbuild.py @@ -5,11 +5,11 @@ ffi = cffi.FFI() mpatch_c = os.path.join( - os.path.join(os.path.dirname(__file__), "..", "mpatch.c") + os.path.join(os.path.dirname(__file__), b"..", b"mpatch.c") ) with open(mpatch_c) as f: ffi.set_source( - "mercurial.cffi._mpatch", f.read(), include_dirs=["mercurial"] + b"mercurial.cffi._mpatch", f.read(), include_dirs=[b"mercurial"] ) ffi.cdef( """ diff --git a/mercurial/cffi/osutil.py b/mercurial/cffi/osutil.py --- a/mercurial/cffi/osutil.py +++ b/mercurial/cffi/osutil.py @@ -40,8 +40,8 @@ self.st_mtime = st_mtime self.st_size = st_size - tv_sec_ofs = ffi.offsetof("struct timespec", "tv_sec") - buf = ffi.new("char[]", listdir_batch_size) + tv_sec_ofs = ffi.offsetof(b"struct timespec", b"tv_sec") + buf = ffi.new(b"char[]", listdir_batch_size) def listdirinternal(dfd, req, stat, skip): ret = [] @@ -51,20 +51,20 @@ break if r == -1: raise OSError(ffi.errno, os.strerror(ffi.errno)) - cur = ffi.cast("val_attrs_t*", buf) + cur = ffi.cast(b"val_attrs_t*", buf) for i in range(r): lgt = cur.length - assert lgt == ffi.cast("uint32_t*", cur)[0] + assert lgt == ffi.cast(b"uint32_t*", cur)[0] ofs = cur.name_info.attr_dataoffset str_lgt = cur.name_info.attr_length - base_ofs = ffi.offsetof("val_attrs_t", "name_info") + base_ofs = ffi.offsetof(b"val_attrs_t", b"name_info") name = str( ffi.buffer( - ffi.cast("char*", cur) + base_ofs + ofs, str_lgt - 1 + ffi.cast(b"char*", cur) + base_ofs + ofs, str_lgt - 1 ) ) tp = attrkinds[cur.obj_type] - if name == "." or name == "..": + if name == b"." or name == b"..": continue if skip == name and tp == statmod.S_ISDIR: return [] @@ -85,12 +85,12 @@ else: ret.append((name, tp)) cur = ffi.cast( - "val_attrs_t*", int(ffi.cast("intptr_t", cur)) + lgt + b"val_attrs_t*", int(ffi.cast(b"intptr_t", cur)) + lgt ) return ret def listdir(path, stat=False, skip=None): - req = ffi.new("struct attrlist*") + req = ffi.new(b"struct attrlist*") req.bitmapcount = lib.ATTR_BIT_MAP_COUNT req.commonattr = ( lib.ATTR_CMN_RETURNED_ATTRS diff --git a/mercurial/cffi/osutilbuild.py b/mercurial/cffi/osutilbuild.py --- a/mercurial/cffi/osutilbuild.py +++ b/mercurial/cffi/osutilbuild.py @@ -4,7 +4,7 @@ ffi = cffi.FFI() ffi.set_source( - "mercurial.cffi._osutil", + b"mercurial.cffi._osutil", """ #include #include @@ -22,7 +22,7 @@ off_t datalength; } __attribute__((aligned(4), packed)) val_attrs_t; """, - include_dirs=["mercurial"], + include_dirs=[b"mercurial"], ) ffi.cdef( """ diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py --- a/mercurial/changegroup.py +++ b/mercurial/changegroup.py @@ -30,11 +30,11 @@ from .interfaces import repository -_CHANGEGROUPV1_DELTA_HEADER = struct.Struct("20s20s20s20s") -_CHANGEGROUPV2_DELTA_HEADER = struct.Struct("20s20s20s20s20s") -_CHANGEGROUPV3_DELTA_HEADER = struct.Struct(">20s20s20s20s20sH") +_CHANGEGROUPV1_DELTA_HEADER = struct.Struct(b"20s20s20s20s") +_CHANGEGROUPV2_DELTA_HEADER = struct.Struct(b"20s20s20s20s20s") +_CHANGEGROUPV3_DELTA_HEADER = struct.Struct(b">20s20s20s20s20sH") -LFS_REQUIREMENT = "lfs" +LFS_REQUIREMENT = b"lfs" readexactly = util.readexactly @@ -42,22 +42,22 @@ def getchunk(stream): """return the next chunk from stream as a string""" d = readexactly(stream, 4) - l = struct.unpack(">l", d)[0] + l = struct.unpack(b">l", d)[0] if l <= 4: if l: - raise error.Abort(_("invalid chunk length %d") % l) - return "" + raise error.Abort(_(b"invalid chunk length %d") % l) + return b"" return readexactly(stream, l - 4) def chunkheader(length): """return a changegroup chunk header (string)""" - return struct.pack(">l", length + 4) + return struct.pack(b">l", length + 4) def closechunk(): """return a changegroup chunk header (string) for a zero-length chunk""" - return struct.pack(">l", 0) + return struct.pack(b">l", 0) def _fileheader(path): @@ -77,13 +77,13 @@ try: if filename: if vfs: - fh = vfs.open(filename, "wb") + fh = vfs.open(filename, b"wb") else: # Increase default buffer size because default is usually # small (4k is common on Linux). - fh = open(filename, "wb", 131072) + fh = open(filename, b"wb", 131072) else: - fd, filename = pycompat.mkstemp(prefix="hg-bundle-", suffix=".hg") + fd, filename = pycompat.mkstemp(prefix=b"hg-bundle-", suffix=b".hg") fh = os.fdopen(fd, r"wb") cleanup = filename for c in chunks: @@ -121,16 +121,16 @@ deltaheader = _CHANGEGROUPV1_DELTA_HEADER deltaheadersize = deltaheader.size - version = "01" + version = b"01" _grouplistcount = 1 # One list of files after the manifests def __init__(self, fh, alg, extras=None): if alg is None: - alg = "UN" + alg = b"UN" if alg not in util.compengines.supportedbundletypes: - raise error.Abort(_("unknown stream compression type: %s") % alg) - if alg == "BZ": - alg = "_truncatedBZ" + raise error.Abort(_(b"unknown stream compression type: %s") % alg) + if alg == b"BZ": + alg = b"_truncatedBZ" compengine = util.compengines.forbundletype(alg) self._stream = compengine.decompressorreader(fh) @@ -141,7 +141,7 @@ # These methods (compressed, read, seek, tell) all appear to only # be used by bundlerepo, but it's a little hard to tell. def compressed(self): - return self._type is not None and self._type != "UN" + return self._type is not None and self._type != b"UN" def read(self, l): return self._stream.read(l) @@ -157,10 +157,10 @@ def _chunklength(self): d = readexactly(self._stream, 4) - l = struct.unpack(">l", d)[0] + l = struct.unpack(b">l", d)[0] if l <= 4: if l: - raise error.Abort(_("invalid chunk length %d") % l) + raise error.Abort(_(b"invalid chunk length %d") % l) return 0 if self.callback: self.callback() @@ -180,7 +180,7 @@ if not l: return {} fname = readexactly(self._stream, l) - return {"filename": fname} + return {b"filename": fname} def _deltaheader(self, headertuple, prevnode): node, p1, p2, cs = headertuple @@ -280,7 +280,7 @@ repo = repo.unfiltered() def csmap(x): - repo.ui.debug("add changeset %s\n" % short(x)) + repo.ui.debug(b"add changeset %s\n" % short(x)) return len(cl) def revmap(x): @@ -293,10 +293,10 @@ # case we use the top level data. We overwrite the argument # because we need to use the top level value (if they exist) # in this function. - srctype = tr.hookargs.setdefault("source", srctype) - tr.hookargs.setdefault("url", url) + srctype = tr.hookargs.setdefault(b"source", srctype) + tr.hookargs.setdefault(b"url", url) repo.hook( - "prechangegroup", throw=True, **pycompat.strkwargs(tr.hookargs) + b"prechangegroup", throw=True, **pycompat.strkwargs(tr.hookargs) ) # write changelog data to temp files so concurrent readers @@ -307,10 +307,10 @@ trp = weakref.proxy(tr) # pull off the changeset group - repo.ui.status(_("adding changesets\n")) + repo.ui.status(_(b"adding changesets\n")) clstart = len(cl) progress = repo.ui.makeprogress( - _("changesets"), unit=_("chunks"), total=expectedtotal + _(b"changesets"), unit=_(b"chunks"), total=expectedtotal ) self.callback = progress.increment @@ -326,8 +326,8 @@ if not cgnodes: repo.ui.develwarn( - "applied empty changelog from changegroup", - config="warn-empty-changegroup", + b"applied empty changelog from changegroup", + config=b"warn-empty-changegroup", ) clend = len(cl) changesets = clend - clstart @@ -335,16 +335,16 @@ self.callback = None # pull off the manifest group - repo.ui.status(_("adding manifests\n")) + repo.ui.status(_(b"adding manifests\n")) # We know that we'll never have more manifests than we had # changesets. progress = repo.ui.makeprogress( - _("manifests"), unit=_("chunks"), total=changesets + _(b"manifests"), unit=_(b"chunks"), total=changesets ) self._unpackmanifests(repo, revmap, trp, progress) needfiles = {} - if repo.ui.configbool("server", "validate"): + if repo.ui.configbool(b"server", b"validate"): cl = repo.changelog ml = repo.manifestlog # validate incoming csets have their manifests @@ -356,16 +356,16 @@ needfiles.setdefault(f, set()).add(n) # process the files - repo.ui.status(_("adding file changes\n")) + repo.ui.status(_(b"adding file changes\n")) newrevs, newfiles = _addchangegroupfiles( repo, self, revmap, trp, efiles, needfiles ) # making sure the value exists - tr.changes.setdefault("changegroup-count-changesets", 0) - tr.changes.setdefault("changegroup-count-revisions", 0) - tr.changes.setdefault("changegroup-count-files", 0) - tr.changes.setdefault("changegroup-count-heads", 0) + tr.changes.setdefault(b"changegroup-count-changesets", 0) + tr.changes.setdefault(b"changegroup-count-revisions", 0) + tr.changes.setdefault(b"changegroup-count-files", 0) + tr.changes.setdefault(b"changegroup-count-heads", 0) # some code use bundle operation for internal purpose. They usually # set `ui.quiet` to do this outside of user sight. Size the report @@ -377,9 +377,9 @@ # something better, but this is a good first step to allow the "end # of transaction report" to pass tests. if not repo.ui.quiet: - tr.changes["changegroup-count-changesets"] += changesets - tr.changes["changegroup-count-revisions"] += newrevs - tr.changes["changegroup-count-files"] += newfiles + tr.changes[b"changegroup-count-changesets"] += changesets + tr.changes[b"changegroup-count-revisions"] += newrevs + tr.changes[b"changegroup-count-files"] += newfiles deltaheads = 0 if oldheads: @@ -391,27 +391,27 @@ # see previous comment about checking ui.quiet if not repo.ui.quiet: - tr.changes["changegroup-count-heads"] += deltaheads + tr.changes[b"changegroup-count-heads"] += deltaheads repo.invalidatevolatilesets() if changesets > 0: - if "node" not in tr.hookargs: - tr.hookargs["node"] = hex(cl.node(clstart)) - tr.hookargs["node_last"] = hex(cl.node(clend - 1)) + if b"node" not in tr.hookargs: + tr.hookargs[b"node"] = hex(cl.node(clstart)) + tr.hookargs[b"node_last"] = hex(cl.node(clend - 1)) hookargs = dict(tr.hookargs) else: hookargs = dict(tr.hookargs) - hookargs["node"] = hex(cl.node(clstart)) - hookargs["node_last"] = hex(cl.node(clend - 1)) + hookargs[b"node"] = hex(cl.node(clstart)) + hookargs[b"node_last"] = hex(cl.node(clend - 1)) repo.hook( - "pretxnchangegroup", + b"pretxnchangegroup", throw=True, **pycompat.strkwargs(hookargs) ) added = [cl.node(r) for r in pycompat.xrange(clstart, clend)] phaseall = None - if srctype in ("push", "serve"): + if srctype in (b"push", b"serve"): # Old servers can not push the boundary themselves. # New servers won't push the boundary if changeset already # exists locally as secret @@ -442,24 +442,24 @@ if clstart >= len(repo): return - repo.hook("changegroup", **pycompat.strkwargs(hookargs)) + repo.hook(b"changegroup", **pycompat.strkwargs(hookargs)) for n in added: args = hookargs.copy() - args["node"] = hex(n) - del args["node_last"] - repo.hook("incoming", **pycompat.strkwargs(args)) + args[b"node"] = hex(n) + del args[b"node_last"] + repo.hook(b"incoming", **pycompat.strkwargs(args)) newheads = [h for h in repo.heads() if h not in oldheads] repo.ui.log( - "incoming", - "%d incoming changes - new heads: %s\n", + b"incoming", + b"%d incoming changes - new heads: %s\n", len(added), - ", ".join([hex(c[:6]) for c in newheads]), + b", ".join([hex(c[:6]) for c in newheads]), ) tr.addpostclose( - "changegroup-runhooks-%020i" % clstart, + b"changegroup-runhooks-%020i" % clstart, lambda tr: repo._afterlock(runhooks), ) finally: @@ -494,7 +494,7 @@ deltaheader = _CHANGEGROUPV2_DELTA_HEADER deltaheadersize = deltaheader.size - version = "02" + version = b"02" def _deltaheader(self, headertuple, prevnode): node, p1, p2, deltabase, cs = headertuple @@ -512,7 +512,7 @@ deltaheader = _CHANGEGROUPV3_DELTA_HEADER deltaheadersize = deltaheader.size - version = "03" + version = b"03" _grouplistcount = 2 # One list of manifests and one list of files def _deltaheader(self, headertuple, prevnode): @@ -523,11 +523,11 @@ super(cg3unpacker, self)._unpackmanifests(repo, revmap, trp, prog) for chunkdata in iter(self.filelogheader, {}): # If we get here, there are directory manifests in the changegroup - d = chunkdata["filename"] - repo.ui.debug("adding %s revisions\n" % d) + d = chunkdata[b"filename"] + repo.ui.debug(b"adding %s revisions\n" % d) deltas = self.deltaiter() if not repo.manifestlog.getstorage(d).addgroup(deltas, revmap, trp): - raise error.Abort(_("received dir revlog group is empty")) + raise error.Abort(_(b"received dir revlog group is empty")) class headerlessfixup(object): @@ -663,8 +663,8 @@ # We failed to resolve a parent for this node, so # we crash the changegroup construction. raise error.Abort( - "unable to resolve parent while packing %r %r" - " for changeset %r" % (store.indexfile, rev, clrev) + b"unable to resolve parent while packing %r %r" + b" for changeset %r" % (store.indexfile, rev, clrev) ) return nullrev @@ -710,10 +710,10 @@ if ischangelog: # `hg log` shows changesets in storage order. To preserve order # across clones, send out changesets in storage order. - nodesorder = "storage" + nodesorder = b"storage" elif ellipses: nodes = _sortnodesellipsis(store, nodes, cl, lookup) - nodesorder = "nodes" + nodesorder = b"nodes" else: nodesorder = None @@ -777,20 +777,20 @@ progress = None if topic is not None: progress = repo.ui.makeprogress( - topic, unit=_("chunks"), total=len(nodes) + topic, unit=_(b"chunks"), total=len(nodes) ) - configtarget = repo.ui.config("devel", "bundle.delta") - if configtarget not in ("", "p1", "full"): + configtarget = repo.ui.config(b"devel", b"bundle.delta") + if configtarget not in (b"", b"p1", b"full"): msg = _("""config "devel.bundle.delta" as unknown value: %s""") repo.ui.warn(msg % configtarget) deltamode = repository.CG_DELTAMODE_STD if forcedeltaparentprev: deltamode = repository.CG_DELTAMODE_PREV - elif configtarget == "p1": + elif configtarget == b"p1": deltamode = repository.CG_DELTAMODE_P1 - elif configtarget == "full": + elif configtarget == b"full": deltamode = repository.CG_DELTAMODE_FULL revisions = store.emitrevisions( @@ -910,7 +910,7 @@ repo = self._repo cl = repo.changelog - self._verbosenote(_("uncompressed size of bundle content:\n")) + self._verbosenote(_(b"uncompressed size of bundle content:\n")) size = 0 clstate, deltas = self._generatechangelog( @@ -925,11 +925,11 @@ size += len(close) yield closechunk() - self._verbosenote(_("%8.i (changelog)\n") % size) + self._verbosenote(_(b"%8.i (changelog)\n") % size) - clrevorder = clstate["clrevorder"] - manifests = clstate["manifests"] - changedfiles = clstate["changedfiles"] + clrevorder = clstate[b"clrevorder"] + manifests = clstate[b"manifests"] + changedfiles = clstate[b"changedfiles"] # We need to make sure that the linkrev in the changegroup refers to # the first changeset that introduced the manifest or file revision. @@ -950,7 +950,7 @@ # either, because we don't discover which directory nodes to # send along with files. This could probably be fixed. fastpathlinkrev = fastpathlinkrev and ( - "treemanifest" not in repo.requirements + b"treemanifest" not in repo.requirements ) fnodes = {} # needed file nodes @@ -963,7 +963,7 @@ manifests, fnodes, source, - clstate["clrevtomanifestrev"], + clstate[b"clrevtomanifestrev"], ) for tree, deltas in it: @@ -983,7 +983,7 @@ size += len(close) yield close - self._verbosenote(_("%8.i (manifests)\n") % size) + self._verbosenote(_(b"%8.i (manifests)\n") % size) yield self._manifestsend mfdicts = None @@ -1021,12 +1021,12 @@ size += len(close) yield close - self._verbosenote(_("%8.i %s\n") % (size, path)) + self._verbosenote(_(b"%8.i %s\n") % (size, path)) yield closechunk() if clnodes: - repo.hook("outgoing", node=hex(clnodes[0]), source=source) + repo.hook(b"outgoing", node=hex(clnodes[0]), source=source) def _generatechangelog(self, cl, nodes, generate=True): """Generate data for changelog chunks. @@ -1045,10 +1045,10 @@ clrevtomanifestrev = {} state = { - "clrevorder": clrevorder, - "manifests": manifests, - "changedfiles": changedfiles, - "clrevtomanifestrev": clrevtomanifestrev, + b"clrevorder": clrevorder, + b"manifests": manifests, + b"changedfiles": changedfiles, + b"clrevtomanifestrev": clrevtomanifestrev, } if not (generate or self._ellipses): @@ -1116,7 +1116,7 @@ lookupcl, self._forcedeltaparentprev, ellipses=self._ellipses, - topic=_("changesets"), + topic=_(b"changesets"), clrevtolocalrev={}, fullclnodes=self._fullclnodes, precomputedellipsis=self._precomputedellipsis, @@ -1141,7 +1141,7 @@ """ repo = self._repo mfl = repo.manifestlog - tmfnodes = {"": manifests} + tmfnodes = {b"": manifests} # Callback for the manifest, used to collect linkrevs for filelog # revisions. @@ -1170,8 +1170,8 @@ clnode = nodes[x] mdata = mfl.get(tree, x).readfast(shallow=True) for p, n, fl in mdata.iterentries(): - if fl == "t": # subdirectory manifest - subtree = tree + p + "/" + if fl == b"t": # subdirectory manifest + subtree = tree + p + b"/" tmfclnodes = tmfnodes.setdefault(subtree, {}) tmfclnode = tmfclnodes.setdefault(n, clnode) if clrevorder[clnode] < clrevorder[tmfclnode]: @@ -1220,7 +1220,7 @@ lookupfn, self._forcedeltaparentprev, ellipses=self._ellipses, - topic=_("manifests"), + topic=_(b"manifests"), clrevtolocalrev=clrevtolocalrev, fullclnodes=self._fullclnodes, precomputedellipsis=self._precomputedellipsis, @@ -1316,13 +1316,13 @@ repo = self._repo progress = repo.ui.makeprogress( - _("files"), unit=_("files"), total=len(changedfiles) + _(b"files"), unit=_(b"files"), total=len(changedfiles) ) for i, fname in enumerate(sorted(changedfiles)): filerevlog = repo.file(fname) if not filerevlog: raise error.Abort( - _("empty or missing file data for %s") % fname + _(b"empty or missing file data for %s") % fname ) clrevtolocalrev.clear() @@ -1454,22 +1454,22 @@ _packermap = { - "01": (_makecg1packer, cg1unpacker), + b"01": (_makecg1packer, cg1unpacker), # cg2 adds support for exchanging generaldelta - "02": (_makecg2packer, cg2unpacker), + b"02": (_makecg2packer, cg2unpacker), # cg3 adds support for exchanging revlog flags and treemanifests - "03": (_makecg3packer, cg3unpacker), + b"03": (_makecg3packer, cg3unpacker), } def allsupportedversions(repo): versions = set(_packermap.keys()) if not ( - repo.ui.configbool("experimental", "changegroup3") - or repo.ui.configbool("experimental", "treemanifest") - or "treemanifest" in repo.requirements + repo.ui.configbool(b"experimental", b"changegroup3") + or repo.ui.configbool(b"experimental", b"treemanifest") + or b"treemanifest" in repo.requirements ): - versions.discard("03") + versions.discard(b"03") return versions @@ -1481,24 +1481,24 @@ # Changegroup versions that can be created from the repo def supportedoutgoingversions(repo): versions = allsupportedversions(repo) - if "treemanifest" in repo.requirements: + if b"treemanifest" in repo.requirements: # Versions 01 and 02 support only flat manifests and it's just too # expensive to convert between the flat manifest and tree manifest on # the fly. Since tree manifests are hashed differently, all of history # would have to be converted. Instead, we simply don't even pretend to # support versions 01 and 02. - versions.discard("01") - versions.discard("02") + versions.discard(b"01") + versions.discard(b"02") if repository.NARROW_REQUIREMENT in repo.requirements: # Versions 01 and 02 don't support revlog flags, and we need to # support that for stripping and unbundling to work. - versions.discard("01") - versions.discard("02") + versions.discard(b"01") + versions.discard(b"02") if LFS_REQUIREMENT in repo.requirements: # Versions 01 and 02 don't support revlog flags, and we need to # mark LFS entries with REVIDX_EXTSTORED. - versions.discard("01") - versions.discard("02") + versions.discard(b"01") + versions.discard(b"02") return versions @@ -1514,8 +1514,8 @@ # will support. For example, all hg versions that support generaldelta also # support changegroup 02. versions = supportedoutgoingversions(repo) - if "generaldelta" in repo.requirements: - versions.discard("01") + if b"generaldelta" in repo.requirements: + versions.discard(b"01") assert versions return min(versions) @@ -1538,16 +1538,16 @@ if oldmatcher is None: oldmatcher = matchmod.never() - if version == "01" and not matcher.always(): + if version == b"01" and not matcher.always(): raise error.ProgrammingError( - "version 01 changegroups do not support " "sparse file matchers" + b"version 01 changegroups do not support " b"sparse file matchers" ) if ellipses and version in (b"01", b"02"): raise error.Abort( _( - "ellipsis nodes require at least cg3 on client and server, " - "but negotiated version %s" + b"ellipsis nodes require at least cg3 on client and server, " + b"but negotiated version %s" ) % version ) @@ -1574,12 +1574,12 @@ def _changegroupinfo(repo, nodes, source): - if repo.ui.verbose or source == "bundle": - repo.ui.status(_("%d changesets found\n") % len(nodes)) + if repo.ui.verbose or source == b"bundle": + repo.ui.status(_(b"%d changesets found\n") % len(nodes)) if repo.ui.debugflag: - repo.ui.debug("list of changesets:\n") + repo.ui.debug(b"list of changesets:\n") for node in nodes: - repo.ui.debug("%s\n" % hex(node)) + repo.ui.debug(b"%s\n" % hex(node)) def makechangegroup( @@ -1597,7 +1597,7 @@ version, util.chunkbuffer(cgstream), None, - {"clcount": len(outgoing.missing)}, + {b"clcount": len(outgoing.missing)}, ) @@ -1624,7 +1624,7 @@ repo.filtername is None and heads == sorted(repo.heads()) ) - repo.hook("preoutgoing", throw=True, source=source) + repo.hook(b"preoutgoing", throw=True, source=source) _changegroupinfo(repo, csets, source) return bundler.generate(commonrevs, csets, fastpathlinkrev, source) @@ -1633,21 +1633,21 @@ revisions = 0 files = 0 progress = repo.ui.makeprogress( - _("files"), unit=_("files"), total=expectedfiles + _(b"files"), unit=_(b"files"), total=expectedfiles ) for chunkdata in iter(source.filelogheader, {}): files += 1 - f = chunkdata["filename"] - repo.ui.debug("adding %s revisions\n" % f) + f = chunkdata[b"filename"] + repo.ui.debug(b"adding %s revisions\n" % f) progress.increment() fl = repo.file(f) o = len(fl) try: deltas = source.deltaiter() if not fl.addgroup(deltas, revmap, trp): - raise error.Abort(_("received file revlog group is empty")) + raise error.Abort(_(b"received file revlog group is empty")) except error.CensoredBaseError as e: - raise error.Abort(_("received delta base is censored: %s") % e) + raise error.Abort(_(b"received delta base is censored: %s") % e) revisions += len(fl) - o if f in needfiles: needs = needfiles[f] @@ -1656,7 +1656,7 @@ if n in needs: needs.remove(n) else: - raise error.Abort(_("received spurious file revlog entry")) + raise error.Abort(_(b"received spurious file revlog entry")) if not needs: del needfiles[f] progress.complete() @@ -1668,7 +1668,7 @@ fl.rev(n) except error.LookupError: raise error.Abort( - _("missing file data for %s:%s - run hg verify") + _(b"missing file data for %s:%s - run hg verify") % (f, hex(n)) ) diff --git a/mercurial/changelog.py b/mercurial/changelog.py --- a/mercurial/changelog.py +++ b/mercurial/changelog.py @@ -27,7 +27,7 @@ stringutil, ) -_defaultextra = {"branch": "default"} +_defaultextra = {b"branch": b"default"} def _string_escape(text): @@ -42,16 +42,20 @@ True """ # subset of the string_escape codec - text = text.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r") - return text.replace("\0", "\\0") + text = ( + text.replace(b"\\", b"\\\\") + .replace(b"\n", b"\\n") + .replace(b"\r", b"\\r") + ) + return text.replace(b"\0", b"\\0") def _string_unescape(text): - if "\\0" in text: + if b"\\0" in text: # fix up \0 without getting into trouble with \\0 - text = text.replace("\\\\", "\\\\\n") - text = text.replace("\\0", "\0") - text = text.replace("\n", "") + text = text.replace(b"\\\\", b"\\\\\n") + text = text.replace(b"\\0", b"\0") + text = text.replace(b"\n", b"") return stringutil.unescapestr(text) @@ -67,9 +71,9 @@ [('baz', '\\\\\\x002'), ('branch', 'default'), ('foo', 'bar')] """ extra = _defaultextra.copy() - for l in text.split("\0"): + for l in text.split(b"\0"): if l: - k, v = _string_unescape(l).split(":", 1) + k, v = _string_unescape(l).split(b":", 1) extra[k] = v return extra @@ -77,19 +81,22 @@ def encodeextra(d): # keys must be sorted to produce a deterministic changelog entry items = [ - _string_escape("%s:%s" % (k, pycompat.bytestr(d[k]))) for k in sorted(d) + _string_escape(b"%s:%s" % (k, pycompat.bytestr(d[k]))) + for k in sorted(d) ] - return "\0".join(items) + return b"\0".join(items) def encodecopies(files, copies): items = [] for i, dst in enumerate(files): if dst in copies: - items.append("%d\0%s" % (i, copies[dst])) + items.append(b"%d\0%s" % (i, copies[dst])) if len(items) != len(copies): - raise error.ProgrammingError("some copy targets missing from file list") - return "\n".join(items) + raise error.ProgrammingError( + b"some copy targets missing from file list" + ) + return b"\n".join(items) def decodecopies(files, data): @@ -97,8 +104,8 @@ copies = {} if not data: return copies - for l in data.split("\n"): - strindex, src = l.split("\0") + for l in data.split(b"\n"): + strindex, src = l.split(b"\0") i = int(strindex) dst = files[i] copies[dst] = src @@ -114,8 +121,8 @@ indices = [] for i, f in enumerate(files): if f in subset: - indices.append("%d" % i) - return "\n".join(indices) + indices.append(b"%d" % i) + return b"\n".join(indices) def decodefileindices(files, data): @@ -123,7 +130,7 @@ subset = [] if not data: return subset - for strindex in data.split("\n"): + for strindex in data.split(b"\n"): i = int(strindex) if i < 0 or i >= len(files): return None @@ -137,7 +144,7 @@ def stripdesc(desc): """strip trailing whitespace and leading and trailing empty lines""" - return "\n".join([l.rstrip() for l in desc.splitlines()]).strip("\n") + return b"\n".join([l.rstrip() for l in desc.splitlines()]).strip(b"\n") class appender(object): @@ -181,7 +188,7 @@ def read(self, count=-1): """only trick here is reads that span real file and data""" - ret = "" + ret = b"" if self.offset < self.size: s = self.fp.read(count) ret = s @@ -190,7 +197,7 @@ count -= len(s) if count != 0: doff = self.offset - self.size - self.data.insert(0, "".join(self.data)) + self.data.insert(0, b"".join(self.data)) del self.data[1:] s = self.data[0][doff : doff + count] self.offset += len(s) @@ -213,10 +220,10 @@ def _divertopener(opener, target): """build an opener that writes in 'target.a' instead of 'target'""" - def _divert(name, mode="r", checkambig=False): + def _divert(name, mode=b"r", checkambig=False): if name != target: return opener(name, mode) - return opener(name + ".a", mode) + return opener(name + b".a", mode) return _divert @@ -224,7 +231,7 @@ def _delayopener(opener, target, buf): """build an opener that stores chunks in 'buf' instead of 'target'""" - def _delay(name, mode="r", checkambig=False): + def _delay(name, mode=b"r", checkambig=False): if name != target: return opener(name, mode) return appender(opener, name, mode, buf) @@ -238,14 +245,14 @@ # it in extra = attr.ib() manifest = attr.ib(default=nullid) - user = attr.ib(default="") + user = attr.ib(default=b"") date = attr.ib(default=(0, 0)) files = attr.ib(default=attr.Factory(list)) filesadded = attr.ib(default=None) filesremoved = attr.ib(default=None) p1copies = attr.ib(default=None) p2copies = attr.ib(default=None) - description = attr.ib(default="") + description = attr.ib(default=b"") class changelogrevision(object): @@ -280,16 +287,16 @@ # # changelog v0 doesn't use extra - nl1 = text.index("\n") - nl2 = text.index("\n", nl1 + 1) - nl3 = text.index("\n", nl2 + 1) + nl1 = text.index(b"\n") + nl2 = text.index(b"\n", nl1 + 1) + nl3 = text.index(b"\n", nl2 + 1) # The list of files may be empty. Which means nl3 is the first of the # double newline that precedes the description. - if text[nl3 + 1 : nl3 + 2] == "\n": + if text[nl3 + 1 : nl3 + 2] == b"\n": doublenl = nl3 else: - doublenl = text.index("\n\n", nl3 + 1) + doublenl = text.index(b"\n\n", nl3 + 1) self._offsets = (nl1, nl2, nl3, doublenl) self._text = text @@ -309,13 +316,13 @@ def _rawdate(self): off = self._offsets dateextra = self._text[off[1] + 1 : off[2]] - return dateextra.split(" ", 2)[0:2] + return dateextra.split(b" ", 2)[0:2] @property def _rawextra(self): off = self._offsets dateextra = self._text[off[1] + 1 : off[2]] - fields = dateextra.split(" ", 2) + fields = dateextra.split(b" ", 2) if len(fields) != 3: return None @@ -347,26 +354,26 @@ if off[2] == off[3]: return [] - return self._text[off[2] + 1 : off[3]].split("\n") + return self._text[off[2] + 1 : off[3]].split(b"\n") @property def filesadded(self): - rawindices = self.extra.get("filesadded") + rawindices = self.extra.get(b"filesadded") return rawindices and decodefileindices(self.files, rawindices) @property def filesremoved(self): - rawindices = self.extra.get("filesremoved") + rawindices = self.extra.get(b"filesremoved") return rawindices and decodefileindices(self.files, rawindices) @property def p1copies(self): - rawcopies = self.extra.get("p1copies") + rawcopies = self.extra.get(b"p1copies") return rawcopies and decodecopies(self.files, rawcopies) @property def p2copies(self): - rawcopies = self.extra.get("p2copies") + rawcopies = self.extra.get(b"p2copies") return rawcopies and decodecopies(self.files, rawcopies) @property @@ -385,12 +392,12 @@ It exists in a separate file to facilitate readers (such as hooks processes) accessing data before a transaction is finalized. """ - if trypending and opener.exists("00changelog.i.a"): - indexfile = "00changelog.i.a" + if trypending and opener.exists(b"00changelog.i.a"): + indexfile = b"00changelog.i.a" else: - indexfile = "00changelog.i" + indexfile = b"00changelog.i" - datafile = "00changelog.d" + datafile = b"00changelog.d" revlog.revlog.__init__( self, opener, @@ -416,7 +423,7 @@ self._delaybuf = None self._divert = False self.filteredrevs = frozenset() - self._copiesstorage = opener.options.get("copies-storage") + self._copiesstorage = opener.options.get(b"copies-storage") def tiprev(self): for i in pycompat.xrange(len(self) - 1, -2, -1): @@ -494,7 +501,7 @@ r = super(changelog, self).rev(node) if r in self.filteredrevs: raise error.FilteredLookupError( - hex(node), self.indexfile, _("filtered node") + hex(node), self.indexfile, _(b"filtered node") ) return r @@ -523,13 +530,13 @@ return super(changelog, self).flags(rev) def delayupdate(self, tr): - "delay visibility of index updates to other readers" + b"delay visibility of index updates to other readers" if not self._delayed: if len(self) == 0: self._divert = True - if self._realopener.exists(self.indexfile + ".a"): - self._realopener.unlink(self.indexfile + ".a") + if self._realopener.exists(self.indexfile + b".a"): + self._realopener.unlink(self.indexfile + b".a") self.opener = _divertopener(self._realopener, self.indexfile) else: self._delaybuf = [] @@ -537,23 +544,23 @@ self._realopener, self.indexfile, self._delaybuf ) self._delayed = True - tr.addpending("cl-%i" % id(self), self._writepending) - tr.addfinalize("cl-%i" % id(self), self._finalize) + tr.addpending(b"cl-%i" % id(self), self._writepending) + tr.addfinalize(b"cl-%i" % id(self), self._finalize) def _finalize(self, tr): - "finalize index updates" + b"finalize index updates" self._delayed = False self.opener = self._realopener # move redirected index data back into place if self._divert: assert not self._delaybuf - tmpname = self.indexfile + ".a" + tmpname = self.indexfile + b".a" nfile = self.opener.open(tmpname) nfile.close() self.opener.rename(tmpname, self.indexfile, checkambig=True) elif self._delaybuf: - fp = self.opener(self.indexfile, "a", checkambig=True) - fp.write("".join(self._delaybuf)) + fp = self.opener(self.indexfile, b"a", checkambig=True) + fp.write(b"".join(self._delaybuf)) fp.close() self._delaybuf = None self._divert = False @@ -561,18 +568,18 @@ self._enforceinlinesize(tr) def _writepending(self, tr): - "create a file containing the unfinalized state for pretxnchangegroup" + b"create a file containing the unfinalized state for pretxnchangegroup" if self._delaybuf: # make a temporary copy of the index fp1 = self._realopener(self.indexfile) - pendingfilename = self.indexfile + ".a" + pendingfilename = self.indexfile + b".a" # register as a temp file to ensure cleanup on failure tr.registertmp(pendingfilename) # write existing data - fp2 = self._realopener(pendingfilename, "w") + fp2 = self._realopener(pendingfilename, b"w") fp2.write(fp1.read()) # add pending data - fp2.write("".join(self._delaybuf)) + fp2.write(b"".join(self._delaybuf)) fp2.close() # switch modes so finalize can simply rename self._delaybuf = None @@ -618,8 +625,8 @@ text = self.revision(node) if not text: return [] - last = text.index("\n\n") - l = text[:last].split("\n") + last = text.index(b"\n\n") + l = text[:last].split(b"\n") return l[3:] def add( @@ -648,29 +655,34 @@ # revision text contain two "\n\n" sequences -> corrupt # repository since read cannot unpack the revision. if not user: - raise error.StorageError(_("empty username")) - if "\n" in user: + raise error.StorageError(_(b"empty username")) + if b"\n" in user: raise error.StorageError( - _("username %r contains a newline") % pycompat.bytestr(user) + _(b"username %r contains a newline") % pycompat.bytestr(user) ) desc = stripdesc(desc) if date: - parseddate = "%d %d" % dateutil.parsedate(date) + parseddate = b"%d %d" % dateutil.parsedate(date) else: - parseddate = "%d %d" % dateutil.makedate() + parseddate = b"%d %d" % dateutil.makedate() if extra: - branch = extra.get("branch") - if branch in ("default", ""): - del extra["branch"] - elif branch in (".", "null", "tip"): + branch = extra.get(b"branch") + if branch in (b"default", b""): + del extra[b"branch"] + elif branch in (b".", b"null", b"tip"): raise error.StorageError( - _("the name '%s' is reserved") % branch + _(b"the name '%s' is reserved") % branch ) sortedfiles = sorted(files) if extra is not None: - for name in ("p1copies", "p2copies", "filesadded", "filesremoved"): + for name in ( + b"p1copies", + b"p2copies", + b"filesadded", + b"filesremoved", + ): extra.pop(name, None) if p1copies is not None: p1copies = encodecopies(sortedfiles, p1copies) @@ -680,24 +692,24 @@ filesadded = encodefileindices(sortedfiles, filesadded) if filesremoved is not None: filesremoved = encodefileindices(sortedfiles, filesremoved) - if self._copiesstorage == "extra": + if self._copiesstorage == b"extra": extrasentries = p1copies, p2copies, filesadded, filesremoved if extra is None and any(x is not None for x in extrasentries): extra = {} if p1copies is not None: - extra["p1copies"] = p1copies + extra[b"p1copies"] = p1copies if p2copies is not None: - extra["p2copies"] = p2copies + extra[b"p2copies"] = p2copies if filesadded is not None: - extra["filesadded"] = filesadded + extra[b"filesadded"] = filesadded if filesremoved is not None: - extra["filesremoved"] = filesremoved + extra[b"filesremoved"] = filesremoved if extra: extra = encodeextra(extra) - parseddate = "%s %s" % (parseddate, extra) - l = [hex(manifest), user, parseddate] + sortedfiles + ["", desc] - text = "\n".join(l) + parseddate = b"%s %s" % (parseddate, extra) + l = [hex(manifest), user, parseddate] + sortedfiles + [b"", desc] + text = b"\n".join(l) return self.addrevision(text, transaction, len(self), p1, p2) def branchinfo(self, rev): @@ -706,11 +718,11 @@ This function exists because creating a changectx object just to access this is costly.""" extra = self.read(rev)[5] - return encoding.tolocal(extra.get("branch")), "close" in extra + return encoding.tolocal(extra.get(b"branch")), b"close" in extra def _nodeduplicatecallback(self, transaction, node): # keep track of revisions that got "re-added", eg: unbunde of know rev. # # We track them in a list to preserve their order from the source bundle - duplicates = transaction.changes.setdefault("revduplicates", []) + duplicates = transaction.changes.setdefault(b"revduplicates", []) duplicates.append(self.rev(node)) diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -75,14 +75,14 @@ # sensitive config sections affecting confighash _configsections = [ - "alias", # affects global state commands.table - "eol", # uses setconfig('eol', ...) - "extdiff", # uisetup will register new commands - "extensions", + b"alias", # affects global state commands.table + b"eol", # uses setconfig('eol', ...) + b"extdiff", # uisetup will register new commands + b"extensions", ] _configsectionitems = [ - ("commands", "show.aliasprefix"), # show.py reads it in extsetup + (b"commands", b"show.aliasprefix"), # show.py reads it in extsetup ] # sensitive environment variables affecting confighash @@ -121,8 +121,8 @@ sectionitems.append(ui.config(section, item)) sectionhash = _hashlist(sectionitems) # If $CHGHG is set, the change to $HG should not trigger a new chg server - if "CHGHG" in encoding.environ: - ignored = {"HG"} + if b"CHGHG" in encoding.environ: + ignored = {b"HG"} else: ignored = set() envitems = [ @@ -204,8 +204,8 @@ confighash = _confighash(ui) mtimehash = _mtimehash(mtimepaths) ui.log( - "cmdserver", - "confighash = %s mtimehash = %s\n", + b"cmdserver", + b"confighash = %s mtimehash = %s\n", confighash, mtimehash, ) @@ -229,7 +229,7 @@ # will behave differently (i.e. write to stdout). if ( out is not self.fout - or not util.safehasattr(self.fout, "fileno") + or not util.safehasattr(self.fout, b"fileno") or self.fout.fileno() != procutil.stdout.fileno() or self._finoutredirected ): @@ -241,8 +241,8 @@ self._csystem( cmd, procutil.shellenviron(env), - type="pager", - cmdtable={"attachio": attachio}, + type=b"pager", + cmdtable={b"attachio": attachio}, ) return True @@ -253,27 +253,27 @@ from . import dispatch # avoid cycle newui = srcui.__class__.load() - for a in ["fin", "fout", "ferr", "environ"]: + for a in [b"fin", b"fout", b"ferr", b"environ"]: setattr(newui, a, getattr(srcui, a)) - if util.safehasattr(srcui, "_csystem"): + if util.safehasattr(srcui, b"_csystem"): newui._csystem = srcui._csystem # command line args options = dispatch._earlyparseopts(newui, args) - dispatch._parseconfig(newui, options["config"]) + dispatch._parseconfig(newui, options[b"config"]) # stolen from tortoisehg.util.copydynamicconfig() for section, name, value in srcui.walkconfig(): source = srcui.configsource(section, name) - if ":" in source or source == "--config" or source.startswith("$"): + if b":" in source or source == b"--config" or source.startswith(b"$"): # path:line or command line, or environ continue newui.setconfig(section, name, value, source) # load wd and repo config, copied from dispatch.py - cwd = options["cwd"] + cwd = options[b"cwd"] cwd = cwd and os.path.realpath(cwd) or None - rpath = options["repository"] + rpath = options[b"repository"] path, newlui = dispatch._getlocal(newui, rpath, wd=cwd) extensions.populateui(newui) @@ -311,22 +311,22 @@ self.out = out self.channel = channel - def __call__(self, cmd, environ, cwd=None, type="system", cmdtable=None): - args = [type, procutil.quotecommand(cmd), os.path.abspath(cwd or ".")] - args.extend("%s=%s" % (k, v) for k, v in environ.iteritems()) - data = "\0".join(args) - self.out.write(struct.pack(">cI", self.channel, len(data))) + def __call__(self, cmd, environ, cwd=None, type=b"system", cmdtable=None): + args = [type, procutil.quotecommand(cmd), os.path.abspath(cwd or b".")] + args.extend(b"%s=%s" % (k, v) for k, v in environ.iteritems()) + data = b"\0".join(args) + self.out.write(struct.pack(b">cI", self.channel, len(data))) self.out.write(data) self.out.flush() - if type == "system": + if type == b"system": length = self.in_.read(4) - (length,) = struct.unpack(">I", length) + (length,) = struct.unpack(b">I", length) if length != 4: - raise error.Abort(_("invalid response")) - (rc,) = struct.unpack(">i", self.in_.read(4)) + raise error.Abort(_(b"invalid response")) + (rc,) = struct.unpack(b">i", self.in_.read(4)) return rc - elif type == "pager": + elif type == b"pager": while True: cmd = self.in_.readline()[:-1] if not cmd: @@ -334,16 +334,16 @@ if cmdtable and cmd in cmdtable: cmdtable[cmd]() else: - raise error.Abort(_("unexpected command: %s") % cmd) + raise error.Abort(_(b"unexpected command: %s") % cmd) else: - raise error.ProgrammingError("invalid S channel type: %s" % type) + raise error.ProgrammingError(b"invalid S channel type: %s" % type) _iochannels = [ # server.ch, ui.fp, mode - ("cin", "fin", r"rb"), - ("cout", "fout", r"wb"), - ("cerr", "ferr", r"wb"), + (b"cin", b"fin", r"rb"), + (b"cout", b"fout", r"wb"), + (b"cerr", b"ferr", r"wb"), ] @@ -352,7 +352,7 @@ self, ui, repo, fin, fout, sock, prereposetups, hashstate, baseaddress ): super(chgcmdserver, self).__init__( - _newchgui(ui, channeledsystem(fin, fout, "S"), self.attachio), + _newchgui(ui, channeledsystem(fin, fout, b"S"), self.attachio), repo, fin, fout, @@ -365,7 +365,7 @@ self.baseaddress = baseaddress if hashstate is not None: self.capabilities = self.capabilities.copy() - self.capabilities["validate"] = chgcmdserver.validate + self.capabilities[b"validate"] = chgcmdserver.validate def cleanup(self): super(chgcmdserver, self).cleanup() @@ -381,9 +381,9 @@ """ # tell client to sendmsg() with 1-byte payload, which makes it # distinctive from "attachio\n" command consumed by client.read() - self.clientsock.sendall(struct.pack(">cI", "I", 1)) + self.clientsock.sendall(struct.pack(b">cI", b"I", 1)) clientfds = util.recvfds(self.clientsock.fileno()) - self.ui.log("chgserver", "received fds: %r\n", clientfds) + self.ui.log(b"chgserver", b"received fds: %r\n", clientfds) ui = self.ui ui.flush() @@ -399,7 +399,7 @@ # to see output immediately on pager, the mode stays unchanged # when client re-attached. ferr is unchanged because it should # be unbuffered no matter if it is a tty or not. - if fn == "ferr": + if fn == b"ferr": newfp = fp else: # make it line buffered explicitly because the default is @@ -413,7 +413,7 @@ setattr(self, cn, newfp) self._ioattached = True - self.cresult.write(struct.pack(">i", len(clientfds))) + self.cresult.write(struct.pack(b">i", len(clientfds))) def _saveio(self): if self._oldios: @@ -468,29 +468,29 @@ except error.ParseError as inst: dispatch._formatparse(self.ui.warn, inst) self.ui.flush() - self.cresult.write("exit 255") + self.cresult.write(b"exit 255") return except error.Abort as inst: - self.ui.error(_("abort: %s\n") % inst) + self.ui.error(_(b"abort: %s\n") % inst) if inst.hint: - self.ui.error(_("(%s)\n") % inst.hint) + self.ui.error(_(b"(%s)\n") % inst.hint) self.ui.flush() - self.cresult.write("exit 255") + self.cresult.write(b"exit 255") return newhash = hashstate.fromui(lui, self.hashstate.mtimepaths) insts = [] if newhash.mtimehash != self.hashstate.mtimehash: addr = _hashaddress(self.baseaddress, self.hashstate.confighash) - insts.append("unlink %s" % addr) + insts.append(b"unlink %s" % addr) # mtimehash is empty if one or more extensions fail to load. # to be compatible with hg, still serve the client this time. if self.hashstate.mtimehash: - insts.append("reconnect") + insts.append(b"reconnect") if newhash.confighash != self.hashstate.confighash: addr = _hashaddress(self.baseaddress, newhash.confighash) - insts.append("redirect %s" % addr) - self.ui.log("chgserver", "validate: %s\n", stringutil.pprint(insts)) - self.cresult.write("\0".join(insts) or "\0") + insts.append(b"redirect %s" % addr) + self.ui.log(b"chgserver", b"validate: %s\n", stringutil.pprint(insts)) + self.cresult.write(b"\0".join(insts) or b"\0") def chdir(self): """Change current directory @@ -501,7 +501,7 @@ path = self._readstr() if not path: return - self.ui.log("chgserver", "chdir to %r\n", path) + self.ui.log(b"chgserver", b"chdir to %r\n", path) os.chdir(path) def setumask(self): @@ -514,12 +514,12 @@ """Change umask""" data = self._readstr() if len(data) != 4: - raise ValueError("invalid mask length in setumask2 request") + raise ValueError(b"invalid mask length in setumask2 request") self._setumask(data) def _setumask(self, data): - mask = struct.unpack(">I", data)[0] - self.ui.log("chgserver", "setumask %r\n", mask) + mask = struct.unpack(b">I", data)[0] + self.ui.log(b"chgserver", b"setumask %r\n", mask) os.umask(mask) def runcommand(self): @@ -541,38 +541,38 @@ """ l = self._readlist() try: - newenv = dict(s.split("=", 1) for s in l) + newenv = dict(s.split(b"=", 1) for s in l) except ValueError: - raise ValueError("unexpected value in setenv request") - self.ui.log("chgserver", "setenv: %r\n", sorted(newenv.keys())) + raise ValueError(b"unexpected value in setenv request") + self.ui.log(b"chgserver", b"setenv: %r\n", sorted(newenv.keys())) encoding.environ.clear() encoding.environ.update(newenv) capabilities = commandserver.server.capabilities.copy() capabilities.update( { - "attachio": attachio, - "chdir": chdir, - "runcommand": runcommand, - "setenv": setenv, - "setumask": setumask, - "setumask2": setumask2, + b"attachio": attachio, + b"chdir": chdir, + b"runcommand": runcommand, + b"setenv": setenv, + b"setumask": setumask, + b"setumask2": setumask2, } ) - if util.safehasattr(procutil, "setprocname"): + if util.safehasattr(procutil, b"setprocname"): def setprocname(self): """Change process title""" name = self._readstr() - self.ui.log("chgserver", "setprocname: %r\n", name) + self.ui.log(b"chgserver", b"setprocname: %r\n", name) procutil.setprocname(name) - capabilities["setprocname"] = setprocname + capabilities[b"setprocname"] = setprocname def _tempaddress(address): - return "%s.%d.tmp" % (address, os.getpid()) + return b"%s.%d.tmp" % (address, os.getpid()) def _hashaddress(address, hashstr): @@ -580,8 +580,8 @@ # makes it possible for the client to pass 'server.tmp$PID' and follow by # an atomic rename to avoid locking when spawning new servers. dirname, basename = os.path.split(address) - basename = basename.split(".", 1)[0] - return "%s-%s" % (os.path.join(dirname, basename), hashstr) + basename = basename.split(b".", 1)[0] + return b"%s-%s" % (os.path.join(dirname, basename), hashstr) class chgunixservicehandler(object): @@ -591,7 +591,7 @@ def __init__(self, ui): self.ui = ui - self._idletimeout = ui.configint("chgserver", "idletimeout") + self._idletimeout = ui.configint(b"chgserver", b"idletimeout") self._lastactive = time.time() def bindsocket(self, sock, address): @@ -603,7 +603,7 @@ def _inithashstate(self, address): self._baseaddress = address - if self.ui.configbool("chgserver", "skiphash"): + if self.ui.configbool(b"chgserver", b"skiphash"): self._hashstate = None self._realaddress = address return @@ -617,7 +617,7 @@ # one or more extensions failed to load. mtimehash becomes # meaningless because we do not know the paths of those extensions. # set mtimehash to an illegal hash value to invalidate the server. - self._hashstate.mtimehash = "" + self._hashstate.mtimehash = b"" def _bind(self, sock): # use a unique temp address so we can stat the file and do ownership @@ -689,11 +689,11 @@ # demandimport or detecting chg client started by chg client. When executed # here, CHGINTERNALMARK is no longer useful and hence dropped to make # environ cleaner. - if "CHGINTERNALMARK" in encoding.environ: - del encoding.environ["CHGINTERNALMARK"] + if b"CHGINTERNALMARK" in encoding.environ: + del encoding.environ[b"CHGINTERNALMARK"] if repo: # one chgserver can serve multiple repos. drop repo information - ui.setconfig("bundle", "mainreporoot", "", "repo") + ui.setconfig(b"bundle", b"mainreporoot", b"", b"repo") h = chgunixservicehandler(ui) return commandserver.unixforkingservice(ui, repo=None, opts=opts, handler=h) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -61,55 +61,67 @@ # templates of common command options dryrunopts = [ - ("n", "dry-run", None, _("do not perform actions, just print output")), + (b"n", b"dry-run", None, _(b"do not perform actions, just print output")), ] confirmopts = [ - ("", "confirm", None, _("ask before applying actions")), + (b"", b"confirm", None, _(b"ask before applying actions")), ] remoteopts = [ - ("e", "ssh", "", _("specify ssh command to use"), _("CMD")), + (b"e", b"ssh", b"", _(b"specify ssh command to use"), _(b"CMD")), ( - "", - "remotecmd", - "", - _("specify hg command to run on the remote side"), - _("CMD"), + b"", + b"remotecmd", + b"", + _(b"specify hg command to run on the remote side"), + _(b"CMD"), ), ( - "", - "insecure", + b"", + b"insecure", None, - _("do not verify server certificate (ignoring web.cacerts config)"), + _(b"do not verify server certificate (ignoring web.cacerts config)"), ), ] walkopts = [ ( - "I", - "include", + b"I", + b"include", [], - _("include names matching the given patterns"), - _("PATTERN"), + _(b"include names matching the given patterns"), + _(b"PATTERN"), ), ( - "X", - "exclude", + b"X", + b"exclude", [], - _("exclude names matching the given patterns"), - _("PATTERN"), + _(b"exclude names matching the given patterns"), + _(b"PATTERN"), ), ] commitopts = [ - ("m", "message", "", _("use text as commit message"), _("TEXT")), - ("l", "logfile", "", _("read commit message from file"), _("FILE")), + (b"m", b"message", b"", _(b"use text as commit message"), _(b"TEXT")), + (b"l", b"logfile", b"", _(b"read commit message from file"), _(b"FILE")), ] commitopts2 = [ - ("d", "date", "", _("record the specified date as commit date"), _("DATE")), - ("u", "user", "", _("record the specified user as committer"), _("USER")), + ( + b"d", + b"date", + b"", + _(b"record the specified date as commit date"), + _(b"DATE"), + ), + ( + b"u", + b"user", + b"", + _(b"record the specified user as committer"), + _(b"USER"), + ), ] commitopts3 = [ @@ -118,107 +130,119 @@ ] formatteropts = [ - ("T", "template", "", _("display with template"), _("TEMPLATE")), + (b"T", b"template", b"", _(b"display with template"), _(b"TEMPLATE")), ] templateopts = [ ( - "", - "style", - "", - _("display using template map file (DEPRECATED)"), - _("STYLE"), + b"", + b"style", + b"", + _(b"display using template map file (DEPRECATED)"), + _(b"STYLE"), ), - ("T", "template", "", _("display with template"), _("TEMPLATE")), + (b"T", b"template", b"", _(b"display with template"), _(b"TEMPLATE")), ] logopts = [ - ("p", "patch", None, _("show patch")), - ("g", "git", None, _("use git extended diff format")), - ("l", "limit", "", _("limit number of changes displayed"), _("NUM")), - ("M", "no-merges", None, _("do not show merges")), - ("", "stat", None, _("output diffstat-style summary of changes")), - ("G", "graph", None, _("show the revision DAG")), + (b"p", b"patch", None, _(b"show patch")), + (b"g", b"git", None, _(b"use git extended diff format")), + (b"l", b"limit", b"", _(b"limit number of changes displayed"), _(b"NUM")), + (b"M", b"no-merges", None, _(b"do not show merges")), + (b"", b"stat", None, _(b"output diffstat-style summary of changes")), + (b"G", b"graph", None, _(b"show the revision DAG")), ] + templateopts diffopts = [ - ("a", "text", None, _("treat all files as text")), - ("g", "git", None, _("use git extended diff format")), - ("", "binary", None, _("generate binary diffs in git mode (default)")), - ("", "nodates", None, _("omit dates from diff headers")), + (b"a", b"text", None, _(b"treat all files as text")), + (b"g", b"git", None, _(b"use git extended diff format")), + (b"", b"binary", None, _(b"generate binary diffs in git mode (default)")), + (b"", b"nodates", None, _(b"omit dates from diff headers")), ] diffwsopts = [ ( - "w", - "ignore-all-space", + b"w", + b"ignore-all-space", None, - _("ignore white space when comparing lines"), + _(b"ignore white space when comparing lines"), ), ( - "b", - "ignore-space-change", + b"b", + b"ignore-space-change", None, - _("ignore changes in the amount of white space"), + _(b"ignore changes in the amount of white space"), ), ( - "B", - "ignore-blank-lines", + b"B", + b"ignore-blank-lines", None, - _("ignore changes whose lines are all blank"), + _(b"ignore changes whose lines are all blank"), ), ( - "Z", - "ignore-space-at-eol", + b"Z", + b"ignore-space-at-eol", None, - _("ignore changes in whitespace at EOL"), + _(b"ignore changes in whitespace at EOL"), ), ] diffopts2 = ( [ - ("", "noprefix", None, _("omit a/ and b/ prefixes from filenames")), + (b"", b"noprefix", None, _(b"omit a/ and b/ prefixes from filenames")), ( - "p", - "show-function", + b"p", + b"show-function", None, - _("show which function each change is in"), + _(b"show which function each change is in"), ), - ("", "reverse", None, _("produce a diff that undoes the changes")), + (b"", b"reverse", None, _(b"produce a diff that undoes the changes")), ] + diffwsopts + [ - ("U", "unified", "", _("number of lines of context to show"), _("NUM")), - ("", "stat", None, _("output diffstat-style summary of changes")), - ("", "root", "", _("produce diffs relative to subdirectory"), _("DIR")), + ( + b"U", + b"unified", + b"", + _(b"number of lines of context to show"), + _(b"NUM"), + ), + (b"", b"stat", None, _(b"output diffstat-style summary of changes")), + ( + b"", + b"root", + b"", + _(b"produce diffs relative to subdirectory"), + _(b"DIR"), + ), ] ) mergetoolopts = [ - ("t", "tool", "", _("specify merge tool"), _("TOOL")), + (b"t", b"tool", b"", _(b"specify merge tool"), _(b"TOOL")), ] similarityopts = [ ( - "s", - "similarity", - "", - _("guess renamed files by similarity (0<=s<=100)"), - _("SIMILARITY"), + b"s", + b"similarity", + b"", + _(b"guess renamed files by similarity (0<=s<=100)"), + _(b"SIMILARITY"), ) ] -subrepoopts = [("S", "subrepos", None, _("recurse into subrepositories"))] +subrepoopts = [(b"S", b"subrepos", None, _(b"recurse into subrepositories"))] debugrevlogopts = [ - ("c", "changelog", False, _("open changelog")), - ("m", "manifest", False, _("open manifest")), - ("", "dir", "", _("open directory manifest")), + (b"c", b"changelog", False, _(b"open changelog")), + (b"m", b"manifest", False, _(b"open manifest")), + (b"", b"dir", b"", _(b"open directory manifest")), ] # special string such that everything below this line will be ingored in the # editor text -_linebelow = "^HG: ------------------------ >8 ------------------------$" +_linebelow = b"^HG: ------------------------ >8 ------------------------$" def resolvecommitoptions(ui, opts): @@ -227,13 +251,13 @@ The return value indicates that ``rewrite.update-timestamp`` is the reason the ``date`` option is set. """ - if opts.get("date") and opts.get("currentdate"): + if opts.get(b"date") and opts.get(b"currentdate"): raise error.Abort( - _("--date and --currentdate are mutually " "exclusive") + _(b"--date and --currentdate are mutually " b"exclusive") ) if opts.get(b"user") and opts.get(b"currentuser"): raise error.Abort( - _("--user and --currentuser are mutually " "exclusive") + _(b"--user and --currentuser are mutually " b"exclusive") ) datemaydiffer = False # date-only change should be ignored? @@ -241,9 +265,9 @@ if opts.get(b"currentdate"): opts[b"date"] = b"%d %d" % dateutil.makedate() elif ( - not opts.get("date") - and ui.configbool("rewrite", "update-timestamp") - and opts.get("currentdate") is None + not opts.get(b"date") + and ui.configbool(b"rewrite", b"update-timestamp") + and opts.get(b"currentdate") is None ): opts[b"date"] = b"%d %d" % dateutil.makedate() datemaydiffer = True @@ -257,7 +281,7 @@ def checknotesize(ui, opts): """ make sure note is of valid format """ - note = opts.get("note") + note = opts.get(b"note") if not note: return @@ -289,13 +313,13 @@ def parsealiases(cmd): - return cmd.split("|") + return cmd.split(b"|") def setupwrapcolorwrite(ui): # wrap ui.write so diff output can be labeled/colorized def wrapwrite(orig, *args, **kw): - label = kw.pop(r"label", "") + label = kw.pop(r"label", b"") for chunk, l in patch.difflabel(lambda: args): orig(chunk, label=label + l) @@ -322,8 +346,8 @@ ui, originalhunks, recordfn, operation ) except crecordmod.fallbackerror as e: - ui.warn("%s\n" % e.message) - ui.warn(_("falling back to text mode\n")) + ui.warn(b"%s\n" % e.message) + ui.warn(_(b"falling back to text mode\n")) return patch.filterpatch(ui, originalhunks, match, operation) @@ -336,7 +360,7 @@ (see patch.filterpatch). """ usecurses = crecordmod.checkcurses(ui) - testfile = ui.config("experimental", "crecordtest") + testfile = ui.config(b"experimental", b"crecordtest") oldwrite = setupwrapcolorwrite(ui) try: newchunks, newopts = filterchunks( @@ -353,13 +377,13 @@ opts = pycompat.byteskwargs(opts) if not ui.interactive(): if cmdsuggest: - msg = _("running non-interactively, use %s instead") % cmdsuggest + msg = _(b"running non-interactively, use %s instead") % cmdsuggest else: - msg = _("running non-interactively") + msg = _(b"running non-interactively") raise error.Abort(msg) # make sure username is set before going interactive - if not opts.get("user"): + if not opts.get(b"user"): ui.username() # raise exception, username not provided def recordfunc(ui, repo, message, match, opts): @@ -376,22 +400,22 @@ In the end we'll record interesting changes, and everything else will be left in place, so the user can continue working. """ - if not opts.get("interactive-unshelve"): + if not opts.get(b"interactive-unshelve"): checkunfinished(repo, commit=True) wctx = repo[None] merge = len(wctx.parents()) > 1 if merge: raise error.Abort( _( - "cannot partially commit a merge " - '(use "hg commit" instead)' + b"cannot partially commit a merge " + b'(use "hg commit" instead)' ) ) def fail(f, msg): - raise error.Abort("%s: %s" % (f, msg)) - - force = opts.get("force") + raise error.Abort(b"%s: %s" % (f, msg)) + + force = opts.get(b"force") if not force: vdirs = [] match = matchmod.badmatch(match, fail) @@ -428,8 +452,8 @@ ui, opts=opts, whitespace=True, - section="commands", - configprefix="commit.interactive.", + section=b"commands", + configprefix=b"commit.interactive.", ) diffopts.nodates = True diffopts.git = True @@ -442,7 +466,7 @@ try: chunks, newopts = filterfn(ui, originalchunks, match) except error.PatchError as err: - raise error.Abort(_("error parsing patch: %s") % err) + raise error.Abort(_(b"error parsing patch: %s") % err) opts.update(newopts) # We need to keep a backup of files that have been newly added and @@ -463,7 +487,7 @@ changed = status.modified + status.added + status.removed newfiles = [f for f in changed if f in contenders] if not newfiles: - ui.status(_("no changes to record\n")) + ui.status(_(b"no changes to record\n")) return 0 modified = set(status.modified) @@ -480,7 +504,7 @@ ] backups = {} if tobackup: - backupdir = repo.vfs.join("record-backups") + backupdir = repo.vfs.join(b"record-backups") try: os.mkdir(backupdir) except OSError as err: @@ -490,10 +514,10 @@ # backup continues for f in tobackup: fd, tmpname = pycompat.mkstemp( - prefix=f.replace("/", "_") + ".", dir=backupdir + prefix=f.replace(b"/", b"_") + b".", dir=backupdir ) os.close(fd) - ui.debug("backup %r as %r\n" % (f, tmpname)) + ui.debug(b"backup %r as %r\n" % (f, tmpname)) util.copyfile(repo.wjoin(f), tmpname, copystat=True) backups[f] = tmpname @@ -506,14 +530,14 @@ fp.seek(0) # 2.5 optionally review / modify patch in text editor - if opts.get("review", False): + if opts.get(b"review", False): patchtext = ( crecordmod.diffhelptext + crecordmod.patchhelptext + fp.read() ) reviewedpatch = ui.edit( - patchtext, "", action="diff", repopath=repo.path + patchtext, b"", action=b"diff", repopath=repo.path ) fp.truncate(0) fp.write(reviewedpatch) @@ -535,7 +559,7 @@ # 3b. (apply) if dopatch: try: - ui.debug("applying patch\n") + ui.debug(b"applying patch\n") ui.debug(fp.getvalue()) patch.internalpatch(ui, repo, fp, 1, eolmode=None) except error.PatchError as err: @@ -554,9 +578,9 @@ try: dirstate = repo.dirstate for realname, tmpname in backups.iteritems(): - ui.debug("restoring %r to %r\n" % (tmpname, realname)) - - if dirstate[realname] == "n": + ui.debug(b"restoring %r to %r\n" % (tmpname, realname)) + + if dirstate[realname] == b"n": # without normallookup, restoring timestamp # may cause partially committed files # to be treated as unmodified @@ -618,8 +642,8 @@ # the filename contains a path separator, it means it's not the direct # child of this directory - if "/" in filename: - subdir, filep = filename.split("/", 1) + if b"/" in filename: + subdir, filep = filename.split(b"/", 1) # does the dirnode object for subdir exists if subdir not in self.subdirs: @@ -669,7 +693,7 @@ # Making sure we terse only when the status abbreviation is # passed as terse argument if onlyst in terseargs: - yield onlyst, self.path + "/" + yield onlyst, self.path + b"/" return # add the files to status list @@ -696,23 +720,23 @@ directory or not. """ # the order matters here as that is used to produce final list - allst = ("m", "a", "r", "d", "u", "i", "c") + allst = (b"m", b"a", b"r", b"d", b"u", b"i", b"c") # checking the argument validity for s in pycompat.bytestr(terseargs): if s not in allst: - raise error.Abort(_("'%s' not recognized") % s) + raise error.Abort(_(b"'%s' not recognized") % s) # creating a dirnode object for the root of the repo - rootobj = dirnode("") + rootobj = dirnode(b"") pstatus = ( - "modified", - "added", - "deleted", - "clean", - "unknown", - "ignored", - "removed", + b"modified", + b"added", + b"deleted", + b"clean", + b"unknown", + b"ignored", + b"removed", ) tersedict = {} @@ -742,8 +766,8 @@ def _commentlines(raw): """Surround lineswith a comment char and a new line""" lines = raw.splitlines() - commentedlines = ["# %s" % line for line in lines] - return "\n".join(commentedlines) + "\n" + commentedlines = [b"# %s" % line for line in lines] + return b"\n".join(commentedlines) + b"\n" def _conflictsmsg(repo): @@ -754,9 +778,9 @@ m = scmutil.match(repo[None]) unresolvedlist = [f for f in mergestate.unresolved() if m(f)] if unresolvedlist: - mergeliststr = "\n".join( + mergeliststr = b"\n".join( [ - " %s" % util.pathto(repo.root, encoding.getcwd(), path) + b" %s" % util.pathto(repo.root, encoding.getcwd(), path) for path in sorted(unresolvedlist) ] ) @@ -771,23 +795,23 @@ % mergeliststr ) else: - msg = _("No unresolved merge conflicts.") + msg = _(b"No unresolved merge conflicts.") return _commentlines(msg) def morestatus(repo, fm): statetuple = statemod.getrepostate(repo) - label = "status.morestatus" + label = b"status.morestatus" if statetuple: state, helpfulmsg = statetuple - statemsg = _("The repository is in an unfinished *%s* state.") % state - fm.plain("%s\n" % _commentlines(statemsg), label=label) + statemsg = _(b"The repository is in an unfinished *%s* state.") % state + fm.plain(b"%s\n" % _commentlines(statemsg), label=label) conmsg = _conflictsmsg(repo) if conmsg: - fm.plain("%s\n" % conmsg, label=label) + fm.plain(b"%s\n" % conmsg, label=label) if helpfulmsg: - fm.plain("%s\n" % _commentlines(helpfulmsg), label=label) + fm.plain(b"%s\n" % _commentlines(helpfulmsg), label=label) def findpossible(cmd, table, strict=False): @@ -818,7 +842,7 @@ found = a break if found is not None: - if aliases[0].startswith("debug") or found.startswith("debug"): + if aliases[0].startswith(b"debug") or found.startswith(b"debug"): debugchoice[found] = (aliases, table[e]) else: choice[found] = (aliases, table[e]) @@ -849,28 +873,32 @@ def changebranch(ui, repo, revs, label): """ Change the branch name of given revs to label """ - with repo.wlock(), repo.lock(), repo.transaction("branches"): + with repo.wlock(), repo.lock(), repo.transaction(b"branches"): # abort in case of uncommitted merge or dirty wdir bailifchanged(repo) revs = scmutil.revrange(repo, revs) if not revs: - raise error.Abort("empty revision set") - roots = repo.revs("roots(%ld)", revs) + raise error.Abort(b"empty revision set") + roots = repo.revs(b"roots(%ld)", revs) if len(roots) > 1: - raise error.Abort(_("cannot change branch of non-linear revisions")) - rewriteutil.precheck(repo, revs, "change branch of") + raise error.Abort( + _(b"cannot change branch of non-linear revisions") + ) + rewriteutil.precheck(repo, revs, b"change branch of") root = repo[roots.first()] rpb = {parent.branch() for parent in root.parents()} if label not in rpb and label in repo.branchmap(): - raise error.Abort(_("a branch of the same name already exists")) - - if repo.revs("obsolete() and %ld", revs): - raise error.Abort(_("cannot change branch of a obsolete changeset")) + raise error.Abort(_(b"a branch of the same name already exists")) + + if repo.revs(b"obsolete() and %ld", revs): + raise error.Abort( + _(b"cannot change branch of a obsolete changeset") + ) # make sure only topological heads - if repo.revs("heads(%ld) - head()", revs): - raise error.Abort(_("cannot change branch in middle of a stack")) + if repo.revs(b"heads(%ld) - head()", revs): + raise error.Abort(_(b"cannot change branch in middle of a stack")) replacements = {} # avoid import cycle mercurial.cmdutil -> mercurial.context -> @@ -891,11 +919,11 @@ return None ui.debug( - "changing branch of '%s' from '%s' to '%s'\n" + b"changing branch of '%s' from '%s' to '%s'\n" % (hex(ctx.node()), oldbranch, label) ) extra = ctx.extra() - extra["branch_change"] = hex(ctx.node()) + extra[b"branch_change"] = hex(ctx.node()) # While changing branch of set of linear commits, make sure that # we base our commits on new parent rather than old parent which # was obsoleted while changing the branch @@ -920,10 +948,12 @@ newnode = repo.commitctx(mc) replacements[ctx.node()] = (newnode,) - ui.debug("new node id is %s\n" % hex(newnode)) + ui.debug(b"new node id is %s\n" % hex(newnode)) # create obsmarkers and move bookmarks - scmutil.cleanupnodes(repo, replacements, "branch-change", fixphase=True) + scmutil.cleanupnodes( + repo, replacements, b"branch-change", fixphase=True + ) # move the working copy too wctx = repo[None] @@ -937,11 +967,11 @@ hg.update(repo, newid[0], quietempty=True) - ui.status(_("changed branch on %d changesets\n") % len(replacements)) + ui.status(_(b"changed branch on %d changesets\n") % len(replacements)) def findrepo(p): - while not os.path.isdir(os.path.join(p, ".hg")): + while not os.path.isdir(os.path.join(p, b".hg")): oldp, p = p, os.path.dirname(p) if p == oldp: return None @@ -959,10 +989,10 @@ """ if merge and repo.dirstate.p2() != nullid: - raise error.Abort(_("outstanding uncommitted merge"), hint=hint) + raise error.Abort(_(b"outstanding uncommitted merge"), hint=hint) modified, added, removed, deleted = repo.status()[:4] if modified or added or removed or deleted: - raise error.Abort(_("uncommitted changes"), hint=hint) + raise error.Abort(_(b"uncommitted changes"), hint=hint) ctx = repo[None] for s in sorted(ctx.substate): ctx.sub(s).bailifchanged(hint=hint) @@ -970,22 +1000,22 @@ def logmessage(ui, opts): """ get the log message according to -m and -l option """ - message = opts.get("message") - logfile = opts.get("logfile") + message = opts.get(b"message") + logfile = opts.get(b"logfile") if message and logfile: raise error.Abort( - _("options --message and --logfile are mutually " "exclusive") + _(b"options --message and --logfile are mutually " b"exclusive") ) if not message and logfile: try: if isstdiofilename(logfile): message = ui.fin.read() else: - message = "\n".join(util.readfile(logfile).splitlines()) + message = b"\n".join(util.readfile(logfile).splitlines()) except IOError as inst: raise error.Abort( - _("can't read commit message '%s': %s") + _(b"can't read commit message '%s': %s") % (logfile, encoding.strtolocal(inst.strerror)) ) return message @@ -1002,15 +1032,15 @@ """ if isinstance(ctxorbool, bool): if ctxorbool: - return baseformname + ".merge" + return baseformname + b".merge" elif len(ctxorbool.parents()) > 1: - return baseformname + ".merge" - - return baseformname + ".normal" + return baseformname + b".merge" + + return baseformname + b".normal" def getcommiteditor( - edit=False, finishdesc=None, extramsg=None, editform="", **opts + edit=False, finishdesc=None, extramsg=None, editform=b"", **opts ): """get appropriate commit message editor according to '--edit' option @@ -1081,7 +1111,7 @@ t = formatter.maketemplater( repo.ui, tmpl, defaults=templatekw.keywords, resources=tres ) - mapping = {"ctx": ctx} + mapping = {b"ctx": ctx} if props: mapping.update(props) return t.renderdefault(mapping) @@ -1145,7 +1175,7 @@ newname.append(stringutil.escapestr(pat[i:n])) if n + 2 > end: raise error.Abort( - _("incomplete format spec in output " "filename") + _(b"incomplete format spec in output " b"filename") ) c = pat[n + 1 : n + 2] i = n + 2 @@ -1153,9 +1183,9 @@ newname.append(expander[c]) except KeyError: raise error.Abort( - _("invalid format spec '%%%s' in output " "filename") % c + _(b"invalid format spec '%%%s' in output " b"filename") % c ) - return "".join(newname) + return b"".join(newname) def makefilename(ctx, pat, **props): @@ -1170,7 +1200,7 @@ def isstdiofilename(pat): """True if the given pat looks like a filename denoting stdin/stdout""" - return not pat or pat == "-" + return not pat or pat == b"-" class _unclosablefile(object): @@ -1193,8 +1223,8 @@ pass -def makefileobj(ctx, pat, mode="wb", **props): - writable = mode not in ("r", "rb") +def makefileobj(ctx, pat, mode=b"wb", **props): + writable = mode not in (b"r", b"rb") if isstdiofilename(pat): repo = ctx.repo() @@ -1209,21 +1239,21 @@ def openstorage(repo, cmd, file_, opts, returnrevlog=False): """opens the changelog, manifest, a filelog or a given revlog""" - cl = opts["changelog"] - mf = opts["manifest"] - dir = opts["dir"] + cl = opts[b"changelog"] + mf = opts[b"manifest"] + dir = opts[b"dir"] msg = None if cl and mf: - msg = _("cannot specify --changelog and --manifest at the same time") + msg = _(b"cannot specify --changelog and --manifest at the same time") elif cl and dir: - msg = _("cannot specify --changelog and --dir at the same time") + msg = _(b"cannot specify --changelog and --dir at the same time") elif cl or mf or dir: if file_: - msg = _("cannot specify filename with --changelog or --manifest") + msg = _(b"cannot specify filename with --changelog or --manifest") elif not repo: msg = _( - "cannot specify --changelog or --manifest or --dir " - "without a repository" + b"cannot specify --changelog or --manifest or --dir " + b"without a repository" ) if msg: raise error.Abort(msg) @@ -1233,15 +1263,15 @@ if cl: r = repo.unfiltered().changelog elif dir: - if "treemanifest" not in repo.requirements: + if b"treemanifest" not in repo.requirements: raise error.Abort( _( - "--dir can only be used on repos with " - "treemanifest enabled" + b"--dir can only be used on repos with " + b"treemanifest enabled" ) ) - if not dir.endswith("/"): - dir = dir + "/" + if not dir.endswith(b"/"): + dir = dir + b"/" dirlog = repo.manifestlog.getstorage(dir) if len(dirlog): r = dirlog @@ -1257,21 +1287,21 @@ if returnrevlog: if isinstance(r, revlog.revlog): pass - elif util.safehasattr(r, "_revlog"): + elif util.safehasattr(r, b"_revlog"): r = r._revlog elif r is not None: - raise error.Abort(_("%r does not appear to be a revlog") % r) + raise error.Abort(_(b"%r does not appear to be a revlog") % r) if not r: if not returnrevlog: - raise error.Abort(_("cannot give path to non-revlog")) + raise error.Abort(_(b"cannot give path to non-revlog")) if not file_: - raise error.CommandError(cmd, _("invalid arguments")) + raise error.CommandError(cmd, _(b"invalid arguments")) if not os.path.isfile(file_): - raise error.Abort(_("revlog '%s' not found") % file_) + raise error.Abort(_(b"revlog '%s' not found") % file_) r = revlog.revlog( - vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + ".i" + vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i" ) return r @@ -1296,8 +1326,8 @@ # ossep => pathname that uses os.sep to separate directories cwd = repo.getcwd() targets = {} - after = opts.get("after") - dryrun = opts.get("dry_run") + after = opts.get(b"after") + dryrun = opts.get(b"dry_run") wctx = repo[None] uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) @@ -1305,22 +1335,22 @@ def walkpat(pat): srcs = [] if after: - badstates = "?" + badstates = b"?" else: - badstates = "?r" + badstates = b"?r" m = scmutil.match(wctx, [pat], opts, globbed=True) for abs in wctx.walk(m): state = repo.dirstate[abs] rel = uipathfn(abs) exact = m.exact(abs) if state in badstates: - if exact and state == "?": - ui.warn(_("%s: not copying - file is not managed\n") % rel) - if exact and state == "r": + if exact and state == b"?": + ui.warn(_(b"%s: not copying - file is not managed\n") % rel) + if exact and state == b"r": ui.warn( _( - "%s: not copying - file has been marked for" - " remove\n" + b"%s: not copying - file has been marked for" + b" remove\n" ) % rel ) @@ -1335,11 +1365,11 @@ # otarget: ossep def copyfile(abssrc, relsrc, otarget, exact): abstarget = pathutil.canonpath(repo.root, cwd, otarget) - if "/" in abstarget: + if b"/" in abstarget: # We cannot normalize abstarget itself, this would prevent # case only renames, like a => A. - abspath, absname = abstarget.rsplit("/", 1) - abstarget = repo.dirstate.normalize(abspath) + "/" + absname + abspath, absname = abstarget.rsplit(b"/", 1) + abstarget = repo.dirstate.normalize(abspath) + b"/" + absname reltarget = repo.pathto(abstarget, cwd) target = repo.wjoin(abstarget) src = repo.wjoin(abssrc) @@ -1351,7 +1381,7 @@ prevsrc = targets.get(abstarget) if prevsrc is not None: ui.warn( - _("%s: not overwriting - %s collides with %s\n") + _(b"%s: not overwriting - %s collides with %s\n") % ( reltarget, repo.pathto(abssrc, cwd), @@ -1368,41 +1398,43 @@ abstarget ): if not rename: - ui.warn(_("%s: can't copy - same file\n") % reltarget) + ui.warn(_(b"%s: can't copy - same file\n") % reltarget) return True # report a failure exists = False samefile = True - if not after and exists or after and state in "mn": - if not opts["force"]: - if state in "mn": - msg = _("%s: not overwriting - file already committed\n") + if not after and exists or after and state in b"mn": + if not opts[b"force"]: + if state in b"mn": + msg = _(b"%s: not overwriting - file already committed\n") if after: - flags = "--after --force" + flags = b"--after --force" else: - flags = "--force" + flags = b"--force" if rename: hint = ( _( - "('hg rename %s' to replace the file by " - "recording a rename)\n" + b"('hg rename %s' to replace the file by " + b"recording a rename)\n" ) % flags ) else: hint = ( _( - "('hg copy %s' to replace the file by " - "recording a copy)\n" + b"('hg copy %s' to replace the file by " + b"recording a copy)\n" ) % flags ) else: - msg = _("%s: not overwriting - file exists\n") + msg = _(b"%s: not overwriting - file exists\n") if rename: - hint = _("('hg rename --after' to record the rename)\n") + hint = _( + b"('hg rename --after' to record the rename)\n" + ) else: - hint = _("('hg copy --after' to record the copy)\n") + hint = _(b"('hg copy --after' to record the copy)\n") ui.warn(msg % reltarget) ui.warn(hint) return True # report a failure @@ -1411,12 +1443,12 @@ if not exists: if rename: ui.warn( - _("%s: not recording move - %s does not exist\n") + _(b"%s: not recording move - %s does not exist\n") % (relsrc, reltarget) ) else: ui.warn( - _("%s: not recording copy - %s does not exist\n") + _(b"%s: not recording copy - %s does not exist\n") % (relsrc, reltarget) ) return True # report a failure @@ -1424,11 +1456,11 @@ try: if exists: os.unlink(target) - targetdir = os.path.dirname(target) or "." + targetdir = os.path.dirname(target) or b"." if not os.path.isdir(targetdir): os.makedirs(targetdir) if samefile: - tmp = target + "~hgrename" + tmp = target + b"~hgrename" os.rename(src, tmp) os.rename(tmp, target) else: @@ -1438,20 +1470,20 @@ srcexists = True except IOError as inst: if inst.errno == errno.ENOENT: - ui.warn(_("%s: deleted in working directory\n") % relsrc) + ui.warn(_(b"%s: deleted in working directory\n") % relsrc) srcexists = False else: ui.warn( - _("%s: cannot copy - %s\n") + _(b"%s: cannot copy - %s\n") % (relsrc, encoding.strtolocal(inst.strerror)) ) return True # report a failure if ui.verbose or not exact: if rename: - ui.status(_("moving %s to %s\n") % (relsrc, reltarget)) + ui.status(_(b"moving %s to %s\n") % (relsrc, reltarget)) else: - ui.status(_("copying %s to %s\n") % (relsrc, reltarget)) + ui.status(_(b"copying %s to %s\n") % (relsrc, reltarget)) targets[abstarget] = abssrc @@ -1461,7 +1493,7 @@ ) if rename and not dryrun: if not after and srcexists and not samefile: - rmdir = repo.ui.configbool("experimental", "removeemptydirs") + rmdir = repo.ui.configbool(b"experimental", b"removeemptydirs") repo.wvfs.unlinkpath(abssrc, rmdir=rmdir) wctx.forget([abssrc]) @@ -1535,21 +1567,21 @@ pats = scmutil.expandpats(pats) if not pats: - raise error.Abort(_("no source or destination specified")) + raise error.Abort(_(b"no source or destination specified")) if len(pats) == 1: - raise error.Abort(_("no destination specified")) + raise error.Abort(_(b"no destination specified")) dest = pats.pop() destdirexists = os.path.isdir(dest) and not os.path.islink(dest) if not destdirexists: if len(pats) > 1 or matchmod.patkind(pats[0]): raise error.Abort( _( - "with multiple sources, destination must be an " - "existing directory" + b"with multiple sources, destination must be an " + b"existing directory" ) ) if util.endswithsep(dest): - raise error.Abort(_("destination %s is not a directory") % dest) + raise error.Abort(_(b"destination %s is not a directory") % dest) tfn = targetpathfn if after: @@ -1561,7 +1593,7 @@ continue copylist.append((tfn(pat, dest, srcs), srcs)) if not copylist: - raise error.Abort(_("no files to copy")) + raise error.Abort(_(b"no files to copy")) errors = 0 for targetpath, srcs in copylist: @@ -1615,21 +1647,21 @@ # avoid cycle context -> subrepo -> cmdutil from . import context - tmpname = patchdata.get("filename") - message = patchdata.get("message") - user = opts.get("user") or patchdata.get("user") - date = opts.get("date") or patchdata.get("date") - branch = patchdata.get("branch") - nodeid = patchdata.get("nodeid") - p1 = patchdata.get("p1") - p2 = patchdata.get("p2") - - nocommit = opts.get("no_commit") - importbranch = opts.get("import_branch") - update = not opts.get("bypass") - strip = opts["strip"] - prefix = opts["prefix"] - sim = float(opts.get("similarity") or 0) + tmpname = patchdata.get(b"filename") + message = patchdata.get(b"message") + user = opts.get(b"user") or patchdata.get(b"user") + date = opts.get(b"date") or patchdata.get(b"date") + branch = patchdata.get(b"branch") + nodeid = patchdata.get(b"nodeid") + p1 = patchdata.get(b"p1") + p2 = patchdata.get(b"p2") + + nocommit = opts.get(b"no_commit") + importbranch = opts.get(b"import_branch") + update = not opts.get(b"bypass") + strip = opts[b"strip"] + prefix = opts[b"prefix"] + sim = float(opts.get(b"similarity") or 0) if not tmpname: return None, None, False @@ -1646,13 +1678,13 @@ else: # launch the editor message = None - ui.debug("message:\n%s\n" % (message or "")) + ui.debug(b"message:\n%s\n" % (message or b"")) if len(parents) == 1: parents.append(repo[nullid]) - if opts.get("exact"): + if opts.get(b"exact"): if not nodeid or not p1: - raise error.Abort(_("not a Mercurial patch")) + raise error.Abort(_(b"not a Mercurial patch")) p1 = repo[p1] p2 = repo[p2 or nullid] elif p2: @@ -1670,8 +1702,8 @@ if p2.node() == nullid: ui.warn( _( - "warning: import the patch as a normal revision\n" - "(use --exact to import the patch as a merge)\n" + b"warning: import the patch as a normal revision\n" + b"(use --exact to import the patch as a merge)\n" ) ) else: @@ -1684,10 +1716,10 @@ if p2 != parents[1]: repo.setparents(p1.node(), p2.node()) - if opts.get("exact") or importbranch: - repo.dirstate.setbranch(branch or "default") - - partial = opts.get("partial", False) + if opts.get(b"exact") or importbranch: + repo.dirstate.setbranch(branch or b"default") + + partial = opts.get(b"partial", False) files = set() try: patch.patch( @@ -1711,15 +1743,15 @@ if message: msgs.append(message) else: - if opts.get("exact") or p2: + if opts.get(b"exact") or p2: # If you got here, you either use --force and know what # you are doing or used --exact or a merge patch while # being updated to its first parent. m = None else: m = scmutil.matchfiles(repo, files or []) - editform = mergeeditform(repo[None], "import.normal") - if opts.get("exact"): + editform = mergeeditform(repo[None], b"import.normal") + if opts.get(b"exact"): editor = None else: editor = getcommiteditor( @@ -1730,16 +1762,16 @@ extrapreimportmap[idfunc](repo, patchdata, extra, opts) overrides = {} if partial: - overrides[("ui", "allowemptycommit")] = True - with repo.ui.configoverride(overrides, "import"): + overrides[(b"ui", b"allowemptycommit")] = True + with repo.ui.configoverride(overrides, b"import"): n = repo.commit( message, user, date, match=m, editor=editor, extra=extra ) for idfunc in extrapostimport: extrapostimportmap[idfunc](repo[n]) else: - if opts.get("exact") or importbranch: - branch = branch or "default" + if opts.get(b"exact") or importbranch: + branch = branch or b"default" else: branch = p1.branch() store = patch.filestore() @@ -1759,10 +1791,10 @@ ) except error.PatchError as e: raise error.Abort(stringutil.forcebytestr(e)) - if opts.get("exact"): + if opts.get(b"exact"): editor = None else: - editor = getcommiteditor(editform="import.bypass") + editor = getcommiteditor(editform=b"import.bypass") memctx = context.memctx( repo, (p1.node(), p2.node()), @@ -1777,16 +1809,16 @@ n = memctx.commit() finally: store.close() - if opts.get("exact") and nocommit: + if opts.get(b"exact") and nocommit: # --exact with --no-commit is still useful in that it does merge # and branch bits - ui.warn(_("warning: can't check exact import with --no-commit\n")) - elif opts.get("exact") and (not n or hex(n) != nodeid): - raise error.Abort(_("patch is damaged or loses information")) - msg = _("applied to working directory") + ui.warn(_(b"warning: can't check exact import with --no-commit\n")) + elif opts.get(b"exact") and (not n or hex(n) != nodeid): + raise error.Abort(_(b"patch is damaged or loses information")) + msg = _(b"applied to working directory") if n: # i18n: refers to a short changeset id - msg = _("created %s") % short(n) + msg = _(b"created %s") % short(n) return msg, n, rejects @@ -1812,27 +1844,27 @@ prev = nullid fm.context(ctx=ctx) - fm.plain("# HG changeset patch\n") - fm.write("user", "# User %s\n", ctx.user()) - fm.plain("# Date %d %d\n" % ctx.date()) - fm.write("date", "# %s\n", fm.formatdate(ctx.date())) + fm.plain(b"# HG changeset patch\n") + fm.write(b"user", b"# User %s\n", ctx.user()) + fm.plain(b"# Date %d %d\n" % ctx.date()) + fm.write(b"date", b"# %s\n", fm.formatdate(ctx.date())) fm.condwrite( - branch and branch != "default", "branch", "# Branch %s\n", branch + branch and branch != b"default", b"branch", b"# Branch %s\n", branch ) - fm.write("node", "# Node ID %s\n", hex(node)) - fm.plain("# Parent %s\n" % hex(prev)) + fm.write(b"node", b"# Node ID %s\n", hex(node)) + fm.plain(b"# Parent %s\n" % hex(prev)) if len(parents) > 1: - fm.plain("# Parent %s\n" % hex(parents[1])) - fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), name="node")) + fm.plain(b"# Parent %s\n" % hex(parents[1])) + fm.data(parents=fm.formatlist(pycompat.maplist(hex, parents), name=b"node")) # TODO: redesign extraexportmap function to support formatter for headerid in extraexport: header = extraexportmap[headerid](seqno, ctx) if header is not None: - fm.plain("# %s\n" % header) - - fm.write("desc", "%s\n", ctx.description().rstrip()) - fm.plain("\n") + fm.plain(b"# %s\n" % header) + + fm.write(b"desc", b"%s\n", ctx.description().rstrip()) + fm.plain(b"\n") if fm.isplain(): chunkiter = patch.diffui(repo, prev, node, match, opts=diffopts) @@ -1848,8 +1880,8 @@ """Export changesets to stdout or a single file""" for seqno, rev in enumerate(revs, 1): ctx = repo[rev] - if not dest.startswith("<"): - repo.ui.note("%s\n" % dest) + if not dest.startswith(b"<"): + repo.ui.note(b"%s\n" % dest) fm.startitem() _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts) @@ -1871,7 +1903,7 @@ for dest in filemap: with formatter.maybereopen(basefm, dest) as fm: - repo.ui.note("%s\n" % dest) + repo.ui.note(b"%s\n" % dest) for seqno, rev in filemap[dest]: fm.startitem() ctx = repo[rev] @@ -1893,7 +1925,7 @@ repo, revs, basefm, - fntemplate="hg-%h.patch", + fntemplate=b"hg-%h.patch", switch_parent=False, opts=None, match=None, @@ -1923,7 +1955,9 @@ _prefetchchangedfiles(repo, revs, match) if not fntemplate: - _exportfile(repo, revs, basefm, "", switch_parent, opts, match) + _exportfile( + repo, revs, basefm, b"", switch_parent, opts, match + ) else: _exportfntemplate( repo, revs, basefm, fntemplate, switch_parent, opts, match @@ -1934,8 +1968,8 @@ """Export changesets to the given file stream""" _prefetchchangedfiles(repo, revs, match) - dest = getattr(fp, "name", "") - with formatter.formatter(repo.ui, fp, "export", {}) as fm: + dest = getattr(fp, "name", b"") + with formatter.formatter(repo.ui, fp, b"export", {}) as fm: _exportfile(repo, revs, fm, dest, switch_parent, opts, match) @@ -1944,26 +1978,31 @@ To be used by debug function.""" if index is not None: - fm.write("index", "%i ", index) - fm.write("prednode", "%s ", hex(marker.prednode())) + fm.write(b"index", b"%i ", index) + fm.write(b"prednode", b"%s ", hex(marker.prednode())) succs = marker.succnodes() fm.condwrite( - succs, "succnodes", "%s ", fm.formatlist(map(hex, succs), name="node") + succs, + b"succnodes", + b"%s ", + fm.formatlist(map(hex, succs), name=b"node"), ) - fm.write("flag", "%X ", marker.flags()) + fm.write(b"flag", b"%X ", marker.flags()) parents = marker.parentnodes() if parents is not None: fm.write( - "parentnodes", - "{%s} ", - fm.formatlist(map(hex, parents), name="node", sep=", "), + b"parentnodes", + b"{%s} ", + fm.formatlist(map(hex, parents), name=b"node", sep=b", "), ) - fm.write("date", "(%s) ", fm.formatdate(marker.date())) + fm.write(b"date", b"(%s) ", fm.formatdate(marker.date())) meta = marker.metadata().copy() - meta.pop("date", None) + meta.pop(b"date", None) smeta = pycompat.rapply(pycompat.maybebytestr, meta) - fm.write("metadata", "{%s}", fm.formatdict(smeta, fmt="%r: %r", sep=", ")) - fm.plain("\n") + fm.write( + b"metadata", b"{%s}", fm.formatdict(smeta, fmt=b"%r: %r", sep=b", ") + ) + fm.plain(b"\n") def finddate(ui, repo, date): @@ -1978,16 +2017,16 @@ if df(d[0]): results[ctx.rev()] = d - for ctx in walkchangerevs(repo, m, {"rev": None}, prep): + for ctx in walkchangerevs(repo, m, {b"rev": None}, prep): rev = ctx.rev() if rev in results: ui.status( - _("found revision %s from %s\n") + _(b"found revision %s from %s\n") % (rev, dateutil.datestr(results[rev])) ) - return "%d" % rev - - raise error.Abort(_("revision matching date not found")) + return b"%d" % rev + + raise error.Abort(_(b"revision matching date not found")) def increasingwindows(windowsize=8, sizelimit=512): @@ -2000,13 +2039,13 @@ def _walkrevs(repo, opts): # Default --rev value depends on --follow but --follow behavior # depends on revisions resolved from --rev... - follow = opts.get("follow") or opts.get("follow_first") - if opts.get("rev"): - revs = scmutil.revrange(repo, opts["rev"]) + follow = opts.get(b"follow") or opts.get(b"follow_first") + if opts.get(b"rev"): + revs = scmutil.revrange(repo, opts[b"rev"]) elif follow and repo.dirstate.p1() == nullid: revs = smartset.baseset() elif follow: - revs = repo.revs("reverse(:.)") + revs = repo.revs(b"reverse(:.)") else: revs = smartset.spanset(repo) revs.reverse() @@ -2060,12 +2099,15 @@ return reversed(revs) def iterfiles(): - pctx = repo["."] + pctx = repo[b"."] for filename in match.files(): if follow: if filename not in pctx: raise error.Abort( - _("cannot follow file not in parent " 'revision: "%s"') + _( + b"cannot follow file not in parent " + b'revision: "%s"' + ) % filename ) yield filename, pctx[filename].filenode() @@ -2082,9 +2124,9 @@ # try to find matching entries on the slow path. if follow: raise error.Abort( - _('cannot follow nonexistent file: "%s"') % file_ + _(b'cannot follow nonexistent file: "%s"') % file_ ) - raise FileWalkError("Cannot walk via filelog") + raise FileWalkError(b"Cannot walk via filelog") else: continue @@ -2176,13 +2218,13 @@ yielding each context, the iterator will first call the prepare function on each context in the window in forward order.""" - allfiles = opts.get("all_files") - follow = opts.get("follow") or opts.get("follow_first") + allfiles = opts.get(b"all_files") + follow = opts.get(b"follow") or opts.get(b"follow_first") revs = _walkrevs(repo, opts) if not revs: return [] wanted = set() - slowpath = match.anypats() or (not match.always() and opts.get("removed")) + slowpath = match.anypats() or (not match.always() and opts.get(b"removed")) fncache = {} change = repo.__getitem__ @@ -2206,7 +2248,7 @@ # of the paths was not a file. Check to see if at least one of them # existed in history, otherwise simply return for path in match.files(): - if path == "." or path in repo.store: + if path == b"." or path in repo.store: break else: return [] @@ -2217,7 +2259,7 @@ if follow: raise error.Abort( - _("can only follow copies/renames for explicit " "filenames") + _(b"can only follow copies/renames for explicit " b"filenames") ) # The slow path checks files modified in every changeset. @@ -2255,7 +2297,7 @@ # it might be worthwhile to do this in the iterator if the rev range # is descending and the prune args are all within that range - for rev in opts.get("prune", ()): + for rev in opts.get(b"prune", ()): rev = repo[rev].rev() ff = _followfilter(repo) stop = min(revs[0], revs[-1]) @@ -2267,7 +2309,7 @@ # revision range, yielding only revisions in wanted. def iterate(): if follow and match.always(): - ff = _followfilter(repo, onlyfirst=opts.get("follow_first")) + ff = _followfilter(repo, onlyfirst=opts.get(b"follow_first")) def want(rev): return ff.match(rev) and rev in wanted @@ -2345,7 +2387,7 @@ names.append(f) if ui.verbose or not exact: ui.status( - _("adding %s\n") % uipathfn(f), label="ui.addremove.added" + _(b"adding %s\n") % uipathfn(f), label=b"ui.addremove.added" ) for subpath in sorted(wctx.substate): @@ -2364,7 +2406,7 @@ ) except error.LookupError: ui.status( - _("skipping missing subrepository: %s\n") % uipathfn(subpath) + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) if not opts.get(r"dry_run"): @@ -2375,9 +2417,9 @@ def addwebdirpath(repo, serverpath, webconf): webconf[serverpath] = repo.root - repo.ui.debug("adding %s = %s\n" % (serverpath, repo.root)) - - for r in repo.revs('filelog("path:.hgsub")'): + repo.ui.debug(b"adding %s = %s\n" % (serverpath, repo.root)) + + for r in repo.revs(b'filelog("path:.hgsub")'): ctx = repo[r] for subpath in ctx.substate: ctx.sub(subpath).addwebdirpath(serverpath, webconf) @@ -2387,7 +2429,7 @@ ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive ): if dryrun and interactive: - raise error.Abort(_("cannot specify both --dry-run and --interactive")) + raise error.Abort(_(b"cannot specify both --dry-run and --interactive")) bad = [] badfn = lambda x, y: bad.append(x) or match.bad(x, y) wctx = repo[None] @@ -2411,11 +2453,11 @@ dryrun=dryrun, interactive=interactive, ) - bad.extend([subpath + "/" + f for f in subbad]) - forgot.extend([subpath + "/" + f for f in subforgot]) + bad.extend([subpath + b"/" + f for f in subbad]) + forgot.extend([subpath + b"/" + f for f in subforgot]) except error.LookupError: ui.status( - _("skipping missing subrepository: %s\n") % uipathfn(subpath) + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) if not explicitonly: @@ -2430,30 +2472,33 @@ if repo.dirstate.normalize(f) in repo.dirstate: continue ui.warn( - _("not removing %s: " "file is already untracked\n") + _( + b"not removing %s: " + b"file is already untracked\n" + ) % uipathfn(f) ) bad.append(f) if interactive: responses = _( - "[Ynsa?]" - "$$ &Yes, forget this file" - "$$ &No, skip this file" - "$$ &Skip remaining files" - "$$ Include &all remaining files" - "$$ &? (display help)" + b"[Ynsa?]" + b"$$ &Yes, forget this file" + b"$$ &No, skip this file" + b"$$ &Skip remaining files" + b"$$ Include &all remaining files" + b"$$ &? (display help)" ) for filename in forget[:]: r = ui.promptchoice( - _("forget %s %s") % (uipathfn(filename), responses) + _(b"forget %s %s") % (uipathfn(filename), responses) ) if r == 4: # ? while r == 4: for c, t in ui.extractchoices(responses)[1]: - ui.write("%s - %s\n" % (c, encoding.lower(t))) + ui.write(b"%s - %s\n" % (c, encoding.lower(t))) r = ui.promptchoice( - _("forget %s %s") % (uipathfn(filename), responses) + _(b"forget %s %s") % (uipathfn(filename), responses) ) if r == 0: # yes continue @@ -2469,7 +2514,7 @@ for f in forget: if ui.verbose or not match.exact(f) or interactive: ui.status( - _("removing %s\n") % uipathfn(f), label="ui.addremove.removed" + _(b"removing %s\n") % uipathfn(f), label=b"ui.addremove.removed" ) if not dryrun: @@ -2482,13 +2527,13 @@ def files(ui, ctx, m, uipathfn, fm, fmt, subrepos): ret = 1 - needsfctx = ui.verbose or {"size", "flags"} & fm.datahint() + needsfctx = ui.verbose or {b"size", b"flags"} & fm.datahint() for f in ctx.matches(m): fm.startitem() fm.context(ctx=ctx) if needsfctx: fc = ctx[f] - fm.write("size flags", "% 10d % 1s ", fc.size(), fc.flags()) + fm.write(b"size flags", b"% 10d % 1s ", fc.size(), fc.flags()) fm.data(path=f) fm.plain(fmt % uipathfn(f)) ret = 0 @@ -2507,7 +2552,7 @@ ret = 0 except error.LookupError: ui.status( - _("skipping missing subrepository: %s\n") + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) @@ -2531,7 +2576,7 @@ subs = sorted(wctx.substate) progress = ui.makeprogress( - _("searching"), total=len(subs), unit=_("subrepos") + _(b"searching"), total=len(subs), unit=_(b"subrepos") ) for subpath in subs: submatch = matchmod.subdirmatcher(subpath, m) @@ -2554,7 +2599,7 @@ ret = 1 except error.LookupError: warnings.append( - _("skipping missing subrepository: %s\n") + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) progress.complete() @@ -2562,28 +2607,30 @@ # warn about failure to delete explicit files/dirs deleteddirs = util.dirs(deleted) files = m.files() - progress = ui.makeprogress(_("deleting"), total=len(files), unit=_("files")) + progress = ui.makeprogress( + _(b"deleting"), total=len(files), unit=_(b"files") + ) for f in files: def insubrepo(): for subpath in wctx.substate: - if f.startswith(subpath + "/"): + if f.startswith(subpath + b"/"): return True return False progress.increment() isdir = f in deleteddirs or wctx.hasdir(f) - if f in repo.dirstate or isdir or f == "." or insubrepo() or f in subs: + if f in repo.dirstate or isdir or f == b"." or insubrepo() or f in subs: continue if repo.wvfs.exists(f): if repo.wvfs.isdir(f): warnings.append( - _("not removing %s: no tracked files\n") % uipathfn(f) + _(b"not removing %s: no tracked files\n") % uipathfn(f) ) else: warnings.append( - _("not removing %s: file is untracked\n") % uipathfn(f) + _(b"not removing %s: file is untracked\n") % uipathfn(f) ) # missing files will generate a warning elsewhere ret = 1 @@ -2595,27 +2642,27 @@ list = deleted remaining = modified + added + clean progress = ui.makeprogress( - _("skipping"), total=len(remaining), unit=_("files") + _(b"skipping"), total=len(remaining), unit=_(b"files") ) for f in remaining: progress.increment() if ui.verbose or (f in files): warnings.append( - _("not removing %s: file still exists\n") % uipathfn(f) + _(b"not removing %s: file still exists\n") % uipathfn(f) ) ret = 1 progress.complete() else: list = deleted + clean progress = ui.makeprogress( - _("skipping"), total=(len(modified) + len(added)), unit=_("files") + _(b"skipping"), total=(len(modified) + len(added)), unit=_(b"files") ) for f in modified: progress.increment() warnings.append( _( - "not removing %s: file is modified (use -f" - " to force removal)\n" + b"not removing %s: file is modified (use -f" + b" to force removal)\n" ) % uipathfn(f) ) @@ -2624,8 +2671,8 @@ progress.increment() warnings.append( _( - "not removing %s: file has been marked for add" - " (use 'hg forget' to undo add)\n" + b"not removing %s: file has been marked for add" + b" (use 'hg forget' to undo add)\n" ) % uipathfn(f) ) @@ -2633,12 +2680,14 @@ progress.complete() list = sorted(list) - progress = ui.makeprogress(_("deleting"), total=len(list), unit=_("files")) + progress = ui.makeprogress( + _(b"deleting"), total=len(list), unit=_(b"files") + ) for f in list: if ui.verbose or not m.exact(f): progress.increment() ui.status( - _("removing %s\n") % uipathfn(f), label="ui.addremove.removed" + _(b"removing %s\n") % uipathfn(f), label=b"ui.addremove.removed" ) progress.complete() @@ -2649,7 +2698,7 @@ if f in added: continue # we never unlink added files on remove rmdir = repo.ui.configbool( - "experimental", "removeemptydirs" + b"experimental", b"removeemptydirs" ) repo.wvfs.unlinkpath(f, ignoremissing=True, rmdir=rmdir) repo[None].forget(list) @@ -2662,7 +2711,7 @@ def _catfmtneedsdata(fm): - return not fm.datahint() or "data" in fm.datahint() + return not fm.datahint() or b"data" in fm.datahint() def _updatecatformatter(fm, ctx, matcher, path, decode): @@ -2680,7 +2729,7 @@ data = ctx.repo().wwritedata(path, data) fm.startitem() fm.context(ctx=ctx) - fm.write("data", "%s", data) + fm.write(b"data", b"%s", data) fm.data(path=path) @@ -2700,7 +2749,7 @@ except OSError: pass with formatter.maybereopen(basefm, filename) as fm: - _updatecatformatter(fm, ctx, matcher, path, opts.get("decode")) + _updatecatformatter(fm, ctx, matcher, path, opts.get(b"decode")) # Automation often uses hg cat on single files, so special case it # for performance to avoid the cost of parsing the manifest. @@ -2740,7 +2789,7 @@ err = 0 except error.RepoLookupError: ui.status( - _("skipping missing subrepository: %s\n") % uipathfn(subpath) + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) return err @@ -2748,24 +2797,24 @@ def commit(ui, repo, commitfunc, pats, opts): """commit the specified files or all outstanding changes""" - date = opts.get("date") + date = opts.get(b"date") if date: - opts["date"] = dateutil.parsedate(date) + opts[b"date"] = dateutil.parsedate(date) message = logmessage(ui, opts) matcher = scmutil.match(repo[None], pats, opts) dsguard = None # extract addremove carefully -- this function can be called from a command # that doesn't support addremove - if opts.get("addremove"): - dsguard = dirstateguard.dirstateguard(repo, "commit") + if opts.get(b"addremove"): + dsguard = dirstateguard.dirstateguard(repo, b"commit") with dsguard or util.nullcontextmanager(): if dsguard: relative = scmutil.anypats(pats, opts) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative) - if scmutil.addremove(repo, matcher, "", uipathfn, opts) != 0: + if scmutil.addremove(repo, matcher, b"", uipathfn, opts) != 0: raise error.Abort( - _("failed to mark all new/missing files as added/removed") + _(b"failed to mark all new/missing files as added/removed") ) return commitfunc(ui, repo, message, matcher, opts) @@ -2792,10 +2841,10 @@ if obsolete.isenabled(repo, obsolete.createmarkersopt): ui.username() # raise exception if username not set - ui.note(_("amending changeset %s\n") % old) + ui.note(_(b"amending changeset %s\n") % old) base = old.p1() - with repo.wlock(), repo.lock(), repo.transaction("amend"): + with repo.wlock(), repo.lock(), repo.transaction(b"amend"): # Participating changesets: # # wctx o - workingctx that contains changes from working copy @@ -2819,9 +2868,9 @@ datemaydiffer = resolvecommitoptions(ui, opts) date = old.date() - if opts.get("date"): - date = dateutil.parsedate(opts.get("date")) - user = opts.get("user") or old.user() + if opts.get(b"date"): + date = dateutil.parsedate(opts.get(b"date")) + user = opts.get(b"user") or old.user() if len(old.parents()) > 1: # ctx.files() isn't reliable for merges, so fall back to the @@ -2835,17 +2884,17 @@ matcher = scmutil.match(wctx, pats, opts) relative = scmutil.anypats(pats, opts) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative) - if opts.get("addremove") and scmutil.addremove( - repo, matcher, "", uipathfn, opts + if opts.get(b"addremove") and scmutil.addremove( + repo, matcher, b"", uipathfn, opts ): raise error.Abort( - _("failed to mark all new/missing files as added/removed") + _(b"failed to mark all new/missing files as added/removed") ) # Check subrepos. This depends on in-place wctx._status update in # subrepo.precommit(). To minimize the risk of this hack, we do # nothing if .hgsub does not exist. - if ".hgsub" in wctx or ".hgsub" in old: + if b".hgsub" in wctx or b".hgsub" in old: subs, commitsubs, newsubstate = subrepoutil.precommit( ui, wctx, wctx._status, matcher ) @@ -2900,8 +2949,8 @@ ctx_, fctx.path(), fctx.data(), - islink="l" in flags, - isexec="x" in flags, + islink=b"l" in flags, + isexec=b"x" in flags, copysource=copied.get(path), ) return mctx @@ -2909,7 +2958,7 @@ return None else: - ui.note(_("copying changeset %s to %s\n") % (old, base)) + ui.note(_(b"copying changeset %s to %s\n") % (old, base)) # Use version of files as in the old cset def filectxfn(repo, ctx_, path): @@ -2922,22 +2971,22 @@ # the message of the changeset to amend. message = logmessage(ui, opts) - editform = mergeeditform(old, "commit.amend") + editform = mergeeditform(old, b"commit.amend") if not message: message = old.description() # Default if message isn't provided and --edit is not passed is to # invoke editor, but allow --no-edit. If somehow we don't have any # description, let's always start the editor. - doedit = not message or opts.get("edit") in [True, None] + doedit = not message or opts.get(b"edit") in [True, None] else: # Default if message is provided is to not invoke editor, but allow # --edit. - doedit = opts.get("edit") is True + doedit = opts.get(b"edit") is True editor = getcommiteditor(edit=doedit, editform=editform) pureextra = extra.copy() - extra["amend_source"] = old.hex() + extra[b"amend_source"] = old.hex() new = context.memctx( repo, @@ -2966,7 +3015,7 @@ return old.node() commitphase = None - if opts.get("secret"): + if opts.get(b"secret"): commitphase = phases.secret newid = repo.commitctx(new) @@ -2974,13 +3023,13 @@ repo.setparents(newid, nullid) mapping = {old.node(): (newid,)} obsmetadata = None - if opts.get("note"): - obsmetadata = {"note": encoding.fromlocal(opts["note"])} - backup = ui.configbool("rewrite", "backup-bundle") + if opts.get(b"note"): + obsmetadata = {b"note": encoding.fromlocal(opts[b"note"])} + backup = ui.configbool(b"rewrite", b"backup-bundle") scmutil.cleanupnodes( repo, mapping, - "amend", + b"amend", metadata=obsmetadata, fixphase=True, targetphase=commitphase, @@ -3009,7 +3058,7 @@ return newid -def commiteditor(repo, ctx, subs, editform=""): +def commiteditor(repo, ctx, subs, editform=b""): if ctx.description(): return ctx.description() return commitforceeditor( @@ -3023,18 +3072,18 @@ subs, finishdesc=None, extramsg=None, - editform="", + editform=b"", unchangedmessagedetection=False, ): if not extramsg: - extramsg = _("Leave message empty to abort commit.") - - forms = [e for e in editform.split(".") if e] - forms.insert(0, "changeset") + extramsg = _(b"Leave message empty to abort commit.") + + forms = [e for e in editform.split(b".") if e] + forms.insert(0, b"changeset") templatetext = None while forms: - ref = ".".join(forms) - if repo.ui.config("committemplate", ref): + ref = b".".join(forms) + if repo.ui.config(b"committemplate", ref): templatetext = committext = buildcommittemplate( repo, ctx, subs, extramsg, ref ) @@ -3059,7 +3108,7 @@ editform=editform, pending=pending, repopath=repo.path, - action="commit", + action=b"commit", ) text = editortext @@ -3069,15 +3118,15 @@ if stripbelow: text = text[: stripbelow.start()] - text = re.sub("(?m)^HG:.*(\n|$)", "", text) + text = re.sub(b"(?m)^HG:.*(\n|$)", b"", text) os.chdir(olddir) if finishdesc: text = finishdesc(text) if not text.strip(): - raise error.Abort(_("empty commit message")) + raise error.Abort(_(b"empty commit message")) if unchangedmessagedetection and editortext == templatetext: - raise error.Abort(_("commit message unchanged")) + raise error.Abort(_(b"commit message unchanged")) return text @@ -3088,11 +3137,11 @@ t = logcmdutil.changesettemplater(ui, repo, spec) t.t.cache.update( (k, templater.unquotestring(v)) - for k, v in repo.ui.configitems("committemplate") + for k, v in repo.ui.configitems(b"committemplate") ) if not extramsg: - extramsg = "" # ensure that extramsg is string + extramsg = b"" # ensure that extramsg is string ui.pushbuffer() t.show(ctx, extramsg=extramsg) @@ -3100,7 +3149,7 @@ def hgprefix(msg): - return "\n".join(["HG: %s" % a for a in msg.split("\n") if a]) + return b"\n".join([b"HG: %s" % a for a in msg.split(b"\n") if a]) def buildcommittext(repo, ctx, subs, extramsg): @@ -3108,34 +3157,34 @@ modified, added, removed = ctx.modified(), ctx.added(), ctx.removed() if ctx.description(): edittext.append(ctx.description()) - edittext.append("") - edittext.append("") # Empty line between message and comments. + edittext.append(b"") + edittext.append(b"") # Empty line between message and comments. edittext.append( hgprefix( _( - "Enter commit message." - " Lines beginning with 'HG:' are removed." + b"Enter commit message." + b" Lines beginning with 'HG:' are removed." ) ) ) edittext.append(hgprefix(extramsg)) - edittext.append("HG: --") - edittext.append(hgprefix(_("user: %s") % ctx.user())) + edittext.append(b"HG: --") + edittext.append(hgprefix(_(b"user: %s") % ctx.user())) if ctx.p2(): - edittext.append(hgprefix(_("branch merge"))) + edittext.append(hgprefix(_(b"branch merge"))) if ctx.branch(): - edittext.append(hgprefix(_("branch '%s'") % ctx.branch())) + edittext.append(hgprefix(_(b"branch '%s'") % ctx.branch())) if bookmarks.isactivewdirparent(repo): - edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark)) - edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs]) - edittext.extend([hgprefix(_("added %s") % f) for f in added]) - edittext.extend([hgprefix(_("changed %s") % f) for f in modified]) - edittext.extend([hgprefix(_("removed %s") % f) for f in removed]) + edittext.append(hgprefix(_(b"bookmark '%s'") % repo._activebookmark)) + edittext.extend([hgprefix(_(b"subrepo %s") % s) for s in subs]) + edittext.extend([hgprefix(_(b"added %s") % f) for f in added]) + edittext.extend([hgprefix(_(b"changed %s") % f) for f in modified]) + edittext.extend([hgprefix(_(b"removed %s") % f) for f in removed]) if not added and not modified and not removed: - edittext.append(hgprefix(_("no files changed"))) - edittext.append("") - - return "\n".join(edittext) + edittext.append(hgprefix(_(b"no files changed"))) + edittext.append(b"") + + return b"\n".join(edittext) def commitstatus(repo, node, branch, bheads=None, opts=None): @@ -3145,14 +3194,14 @@ parents = ctx.parents() if ( - not opts.get("amend") + not opts.get(b"amend") and bheads and node not in bheads and not [ x for x in parents if x.node() in bheads and x.branch() == branch ] ): - repo.ui.status(_("created new head\n")) + repo.ui.status(_(b"created new head\n")) # The message is not printed for initial roots. For the other # changesets, it is printed in the following situations: # @@ -3182,15 +3231,19 @@ # # H H n head merge: head count decreases - if not opts.get("close_branch"): + if not opts.get(b"close_branch"): for r in parents: if r.closesbranch() and r.branch() == branch: - repo.ui.status(_("reopening closed branch head %d\n") % r.rev()) + repo.ui.status( + _(b"reopening closed branch head %d\n") % r.rev() + ) if repo.ui.debugflag: - repo.ui.write(_("committed changeset %d:%s\n") % (ctx.rev(), ctx.hex())) + repo.ui.write( + _(b"committed changeset %d:%s\n") % (ctx.rev(), ctx.hex()) + ) elif repo.ui.verbose: - repo.ui.write(_("committed changeset %d:%s\n") % (ctx.rev(), ctx)) + repo.ui.write(_(b"committed changeset %d:%s\n") % (ctx.rev(), ctx)) def postcommitstatus(repo, pats, opts): @@ -3222,7 +3275,7 @@ ## filling of the `names` mapping # walk dirstate to fill `names` - interactive = opts.get("interactive", False) + interactive = opts.get(b"interactive", False) wctx = repo[None] m = scmutil.match(wctx, pats, opts) @@ -3241,11 +3294,11 @@ return if path in ctx.substate: return - path_ = path + "/" + path_ = path + b"/" for f in names: if f.startswith(path_): return - ui.warn("%s: %s\n" % (uipathfn(path), msg)) + ui.warn(b"%s: %s\n" % (uipathfn(path), msg)) for abs in ctx.walk(matchmod.badmatch(m, badfn)): if abs not in names: @@ -3326,7 +3379,7 @@ for f in localchanges: src = repo.dirstate.copied(f) # XXX should we check for rename down to target node? - if src and src not in names and repo.dirstate[src] == "r": + if src and src not in names and repo.dirstate[src] == b"r": dsremoved.add(src) names[src] = True @@ -3340,12 +3393,12 @@ # distinguish between file to forget and the other added = set() for abs in dsadded: - if repo.dirstate[abs] != "a": + if repo.dirstate[abs] != b"a": added.add(abs) dsadded -= added for abs in deladded: - if repo.dirstate[abs] == "a": + if repo.dirstate[abs] == b"a": dsadded.add(abs) deladded -= dsadded @@ -3370,14 +3423,14 @@ # action to be actually performed by revert # (, message>) tuple actions = { - "revert": ([], _("reverting %s\n")), - "add": ([], _("adding %s\n")), - "remove": ([], _("removing %s\n")), - "drop": ([], _("removing %s\n")), - "forget": ([], _("forgetting %s\n")), - "undelete": ([], _("undeleting %s\n")), - "noop": (None, _("no changes needed to %s\n")), - "unknown": (None, _("file not managed: %s\n")), + b"revert": ([], _(b"reverting %s\n")), + b"add": ([], _(b"adding %s\n")), + b"remove": ([], _(b"removing %s\n")), + b"drop": ([], _(b"removing %s\n")), + b"forget": ([], _(b"forgetting %s\n")), + b"undelete": ([], _(b"undeleting %s\n")), + b"noop": (None, _(b"no changes needed to %s\n")), + b"unknown": (None, _(b"file not managed: %s\n")), } # "constant" that convey the backup strategy. @@ -3388,7 +3441,7 @@ backup = 2 # unconditionally do backup check = 1 # check if the existing file differs from target discard = 0 # never do backup - if opts.get("no_backup"): + if opts.get(b"no_backup"): backupinteractive = backup = check = discard if interactive: dsmodifiedbackup = backupinteractive @@ -3396,9 +3449,9 @@ dsmodifiedbackup = backup tobackup = set() - backupanddel = actions["remove"] - if not opts.get("no_backup"): - backupanddel = actions["drop"] + backupanddel = actions[b"remove"] + if not opts.get(b"no_backup"): + backupanddel = actions[b"drop"] disptable = ( # dispatch table: @@ -3407,32 +3460,32 @@ # make backup ## Sets that results that will change file on disk # Modified compared to target, no local change - (modified, actions["revert"], discard), + (modified, actions[b"revert"], discard), # Modified compared to target, but local file is deleted - (deleted, actions["revert"], discard), + (deleted, actions[b"revert"], discard), # Modified compared to target, local change - (dsmodified, actions["revert"], dsmodifiedbackup), + (dsmodified, actions[b"revert"], dsmodifiedbackup), # Added since target - (added, actions["remove"], discard), + (added, actions[b"remove"], discard), # Added in working directory - (dsadded, actions["forget"], discard), + (dsadded, actions[b"forget"], discard), # Added since target, have local modification (modadded, backupanddel, backup), # Added since target but file is missing in working directory - (deladded, actions["drop"], discard), + (deladded, actions[b"drop"], discard), # Removed since target, before working copy parent - (removed, actions["add"], discard), + (removed, actions[b"add"], discard), # Same as `removed` but an unknown file exists at the same path - (removunk, actions["add"], check), + (removunk, actions[b"add"], check), # Removed since targe, marked as such in working copy parent - (dsremoved, actions["undelete"], discard), + (dsremoved, actions[b"undelete"], discard), # Same as `dsremoved` but an unknown file exists at the same path - (dsremovunk, actions["undelete"], check), + (dsremovunk, actions[b"undelete"], check), ## the following sets does not result in any file changes # File with no modification - (clean, actions["noop"], discard), + (clean, actions[b"noop"], discard), # Existing file, not tracked anywhere - (unknown, actions["unknown"], discard), + (unknown, actions[b"unknown"], discard), ) for abs, exact in sorted(names.items()): @@ -3457,23 +3510,23 @@ absbakname, start=repo.root ) ui.note( - _("saving current version of %s as %s\n") + _(b"saving current version of %s as %s\n") % (uipathfn(abs), uipathfn(bakname)) ) - if not opts.get("dry_run"): + if not opts.get(b"dry_run"): if interactive: util.copyfile(target, absbakname) else: util.rename(target, absbakname) - if opts.get("dry_run"): + if opts.get(b"dry_run"): if ui.verbose or not exact: ui.status(msg % uipathfn(abs)) elif exact: ui.warn(msg % uipathfn(abs)) break - if not opts.get("dry_run"): - needdata = ("revert", "add", "undelete") + if not opts.get(b"dry_run"): + needdata = (b"revert", b"add", b"undelete") oplist = [actions[name][0] for name in needdata] prefetch = scmutil.prefetchfiles matchfiles = scmutil.matchfiles @@ -3504,7 +3557,7 @@ ) except KeyError: raise error.Abort( - "subrepository '%s' does not exist in %s!" + b"subrepository '%s' does not exist in %s!" % (sub, short(ctx.node())) ) @@ -3537,7 +3590,7 @@ def doremove(f): try: - rmdir = repo.ui.configbool("experimental", "removeemptydirs") + rmdir = repo.ui.configbool(b"experimental", b"removeemptydirs") repo.wvfs.unlinkpath(f, rmdir=rmdir) except OSError: pass @@ -3549,36 +3602,36 @@ repo.ui.status(actions[action][1] % uipathfn(f)) audit_path = pathutil.pathauditor(repo.root, cached=True) - for f in actions["forget"][0]: + for f in actions[b"forget"][0]: if interactive: choice = repo.ui.promptchoice( - _("forget added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f) + _(b"forget added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f) ) if choice == 0: - prntstatusmsg("forget", f) + prntstatusmsg(b"forget", f) repo.dirstate.drop(f) else: excluded_files.append(f) else: - prntstatusmsg("forget", f) + prntstatusmsg(b"forget", f) repo.dirstate.drop(f) - for f in actions["remove"][0]: + for f in actions[b"remove"][0]: audit_path(f) if interactive: choice = repo.ui.promptchoice( - _("remove added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f) + _(b"remove added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f) ) if choice == 0: - prntstatusmsg("remove", f) + prntstatusmsg(b"remove", f) doremove(f) else: excluded_files.append(f) else: - prntstatusmsg("remove", f) + prntstatusmsg(b"remove", f) doremove(f) - for f in actions["drop"][0]: + for f in actions[b"drop"][0]: audit_path(f) - prntstatusmsg("drop", f) + prntstatusmsg(b"drop", f) repo.dirstate.remove(f) normal = None @@ -3594,26 +3647,26 @@ newlyaddedandmodifiedfiles = set() if interactive: # Prompt the user for changes to revert - torevert = [f for f in actions["revert"][0] if f not in excluded_files] + torevert = [f for f in actions[b"revert"][0] if f not in excluded_files] m = scmutil.matchfiles(repo, torevert) diffopts = patch.difffeatureopts( repo.ui, whitespace=True, - section="commands", - configprefix="revert.interactive.", + section=b"commands", + configprefix=b"revert.interactive.", ) diffopts.nodates = True diffopts.git = True - operation = "apply" + operation = b"apply" if node == parent: if repo.ui.configbool( - "experimental", "revert.interactive.select-to-keep" + b"experimental", b"revert.interactive.select-to-keep" ): - operation = "keep" + operation = b"keep" else: - operation = "discard" - - if operation == "apply": + operation = b"discard" + + if operation == b"apply": diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts) else: diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts) @@ -3624,11 +3677,11 @@ chunks, opts = recordfilter( repo.ui, originalchunks, match, operation=operation ) - if operation == "discard": + if operation == b"discard": chunks = patch.reversehunks(chunks) except error.PatchError as err: - raise error.Abort(_("error parsing patch: %s") % err) + raise error.Abort(_(b"error parsing patch: %s") % err) # FIXME: when doing an interactive revert of a copy, there's no way of # performing a partial revert of the added file, the only option is @@ -3644,7 +3697,7 @@ fp = stringio() # chunks are serialized per file, but files aren't sorted for f in sorted(set(c.header.filename() for c in chunks if ishunk(c))): - prntstatusmsg("revert", f) + prntstatusmsg(b"revert", f) files = set() for c in chunks: if ishunk(c): @@ -3657,7 +3710,7 @@ tobackup.remove(abs) if abs not in files: files.add(abs) - if operation == "keep": + if operation == b"keep": checkout(abs) c.write(fp) dopatch = fp.tell() @@ -3669,41 +3722,43 @@ raise error.Abort(pycompat.bytestr(err)) del fp else: - for f in actions["revert"][0]: - prntstatusmsg("revert", f) + for f in actions[b"revert"][0]: + prntstatusmsg(b"revert", f) checkout(f) if normal: normal(f) - for f in actions["add"][0]: + for f in actions[b"add"][0]: # Don't checkout modified files, they are already created by the diff if f not in newlyaddedandmodifiedfiles: - prntstatusmsg("add", f) + prntstatusmsg(b"add", f) checkout(f) repo.dirstate.add(f) normal = repo.dirstate.normallookup if node == parent and p2 == nullid: normal = repo.dirstate.normal - for f in actions["undelete"][0]: + for f in actions[b"undelete"][0]: if interactive: choice = repo.ui.promptchoice( - _("add back removed file %s (Yn)?$$ &Yes $$ &No") % f + _(b"add back removed file %s (Yn)?$$ &Yes $$ &No") % f ) if choice == 0: - prntstatusmsg("undelete", f) + prntstatusmsg(b"undelete", f) checkout(f) normal(f) else: excluded_files.append(f) else: - prntstatusmsg("undelete", f) + prntstatusmsg(b"undelete", f) checkout(f) normal(f) copied = copies.pathcopies(repo[parent], ctx) - for f in actions["add"][0] + actions["undelete"][0] + actions["revert"][0]: + for f in ( + actions[b"add"][0] + actions[b"undelete"][0] + actions[b"revert"][0] + ): if f in copied: repo.dirstate.copy(copied[f], f) @@ -3748,7 +3803,7 @@ if ( not s._clearable or (commit and s._allowcommit) - or (s._opname == "merge" and skipmerge) + or (s._opname == b"merge" and skipmerge) or s._reportonly ): continue @@ -3767,7 +3822,7 @@ raise error.Abort(state.msg(), hint=state.hint()) for s in statemod._unfinishedstates: - if s._opname == "merge" or state._reportonly: + if s._opname == b"merge" or state._reportonly: continue if s._clearable and s.isunfinished(repo): util.unlink(repo.vfs.join(s._fname)) @@ -3793,14 +3848,14 @@ Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is a boolean. """ - contmsg = _("continue: %s") + contmsg = _(b"continue: %s") for state in statemod._unfinishedstates: if not state._continueflag: continue if state.isunfinished(repo): return contmsg % state.continuemsg(), True if repo[None].dirty(missing=True, merge=False, branch=False): - return contmsg % _("hg commit"), False + return contmsg % _(b"hg commit"), False return None, None @@ -3815,9 +3870,9 @@ msg, warning = howtocontinue(repo) if msg is not None: if warning: - repo.ui.warn("%s\n" % msg) + repo.ui.warn(b"%s\n" % msg) else: - repo.ui.note("%s\n" % msg) + repo.ui.note(b"%s\n" % msg) def wrongtooltocontinue(repo, task): @@ -3833,26 +3888,26 @@ hint = None if after[1]: hint = after[0] - raise error.Abort(_("no %s in progress") % task, hint=hint) + raise error.Abort(_(b"no %s in progress") % task, hint=hint) def abortgraft(ui, repo, graftstate): """abort the interrupted graft and rollbacks to the state before interrupted graft""" if not graftstate.exists(): - raise error.Abort(_("no interrupted graft to abort")) + raise error.Abort(_(b"no interrupted graft to abort")) statedata = readgraftstate(repo, graftstate) - newnodes = statedata.get("newnodes") + newnodes = statedata.get(b"newnodes") if newnodes is None: # and old graft state which does not have all the data required to abort # the graft - raise error.Abort(_("cannot abort using an old graftstate")) + raise error.Abort(_(b"cannot abort using an old graftstate")) # changeset from which graft operation was started if len(newnodes) > 0: startctx = repo[newnodes[0]].p1() else: - startctx = repo["."] + startctx = repo[b"."] # whether to strip or not cleanup = False from . import hg @@ -3864,9 +3919,9 @@ immutable = [c for c in newnodes if not repo[c].mutable()] if immutable: repo.ui.warn( - _("cannot clean up public changesets %s\n") - % ", ".join(bytes(repo[r]) for r in immutable), - hint=_("see 'hg help phases' for details"), + _(b"cannot clean up public changesets %s\n") + % b", ".join(bytes(repo[r]) for r in immutable), + hint=_(b"see 'hg help phases' for details"), ) cleanup = False @@ -3875,8 +3930,8 @@ if desc - set(newnodes): repo.ui.warn( _( - "new changesets detected on destination " - "branch, can't strip\n" + b"new changesets detected on destination " + b"branch, can't strip\n" ) ) cleanup = False @@ -3886,17 +3941,17 @@ hg.updaterepo(repo, startctx.node(), overwrite=True) # stripping the new nodes created strippoints = [ - c.node() for c in repo.set("roots(%ld)", newnodes) + c.node() for c in repo.set(b"roots(%ld)", newnodes) ] repair.strip(repo.ui, repo, strippoints, backup=False) if not cleanup: # we don't update to the startnode if we can't strip - startctx = repo["."] + startctx = repo[b"."] hg.updaterepo(repo, startctx.node(), overwrite=True) - ui.status(_("graft aborted\n")) - ui.status(_("working directory is now at %s\n") % startctx.hex()[:12]) + ui.status(_(b"graft aborted\n")) + ui.status(_(b"working directory is now at %s\n") % startctx.hex()[:12]) graftstate.delete() return 0 @@ -3906,12 +3961,12 @@ try: return graftstate.read() except error.CorruptedState: - nodes = repo.vfs.read("graftstate").splitlines() - return {"nodes": nodes} + nodes = repo.vfs.read(b"graftstate").splitlines() + return {b"nodes": nodes} def hgabortgraft(ui, repo): """ abort logic for aborting graft using 'hg abort'""" with repo.wlock(): - graftstate = statemod.cmdstate(repo, "graftstate") + graftstate = statemod.cmdstate(repo, b"graftstate") return abortgraft(ui, repo, graftstate) diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -24,24 +24,24 @@ # Mapping from effect name to terminfo attribute name (or raw code) or # color number. This will also force-load the curses module. _baseterminfoparams = { - "none": (True, "sgr0", ""), - "standout": (True, "smso", ""), - "underline": (True, "smul", ""), - "reverse": (True, "rev", ""), - "inverse": (True, "rev", ""), - "blink": (True, "blink", ""), - "dim": (True, "dim", ""), - "bold": (True, "bold", ""), - "invisible": (True, "invis", ""), - "italic": (True, "sitm", ""), - "black": (False, curses.COLOR_BLACK, ""), - "red": (False, curses.COLOR_RED, ""), - "green": (False, curses.COLOR_GREEN, ""), - "yellow": (False, curses.COLOR_YELLOW, ""), - "blue": (False, curses.COLOR_BLUE, ""), - "magenta": (False, curses.COLOR_MAGENTA, ""), - "cyan": (False, curses.COLOR_CYAN, ""), - "white": (False, curses.COLOR_WHITE, ""), + b"none": (True, b"sgr0", b""), + b"standout": (True, b"smso", b""), + b"underline": (True, b"smul", b""), + b"reverse": (True, b"rev", b""), + b"inverse": (True, b"rev", b""), + b"blink": (True, b"blink", b""), + b"dim": (True, b"dim", b""), + b"bold": (True, b"bold", b""), + b"invisible": (True, b"invis", b""), + b"italic": (True, b"sitm", b""), + b"black": (False, curses.COLOR_BLACK, b""), + b"red": (False, curses.COLOR_RED, b""), + b"green": (False, curses.COLOR_GREEN, b""), + b"yellow": (False, curses.COLOR_YELLOW, b""), + b"blue": (False, curses.COLOR_BLUE, b""), + b"magenta": (False, curses.COLOR_MAGENTA, b""), + b"cyan": (False, curses.COLOR_CYAN, b""), + b"white": (False, curses.COLOR_WHITE, b""), } except ImportError: curses = None @@ -49,101 +49,101 @@ # start and stop parameters for effects _effects = { - "none": 0, - "black": 30, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36, - "white": 37, - "bold": 1, - "italic": 3, - "underline": 4, - "inverse": 7, - "dim": 2, - "black_background": 40, - "red_background": 41, - "green_background": 42, - "yellow_background": 43, - "blue_background": 44, - "purple_background": 45, - "cyan_background": 46, - "white_background": 47, + b"none": 0, + b"black": 30, + b"red": 31, + b"green": 32, + b"yellow": 33, + b"blue": 34, + b"magenta": 35, + b"cyan": 36, + b"white": 37, + b"bold": 1, + b"italic": 3, + b"underline": 4, + b"inverse": 7, + b"dim": 2, + b"black_background": 40, + b"red_background": 41, + b"green_background": 42, + b"yellow_background": 43, + b"blue_background": 44, + b"purple_background": 45, + b"cyan_background": 46, + b"white_background": 47, } _defaultstyles = { - "grep.match": "red bold", - "grep.linenumber": "green", - "grep.rev": "blue", - "grep.sep": "cyan", - "grep.filename": "magenta", - "grep.user": "magenta", - "grep.date": "magenta", - "grep.inserted": "green bold", - "grep.deleted": "red bold", - "bookmarks.active": "green", - "branches.active": "none", - "branches.closed": "black bold", - "branches.current": "green", - "branches.inactive": "none", - "diff.changed": "white", - "diff.deleted": "red", - "diff.deleted.changed": "red bold underline", - "diff.deleted.unchanged": "red", - "diff.diffline": "bold", - "diff.extended": "cyan bold", - "diff.file_a": "red bold", - "diff.file_b": "green bold", - "diff.hunk": "magenta", - "diff.inserted": "green", - "diff.inserted.changed": "green bold underline", - "diff.inserted.unchanged": "green", - "diff.tab": "", - "diff.trailingwhitespace": "bold red_background", - "changeset.public": "", - "changeset.draft": "", - "changeset.secret": "", - "diffstat.deleted": "red", - "diffstat.inserted": "green", - "formatvariant.name.mismatchconfig": "red", - "formatvariant.name.mismatchdefault": "yellow", - "formatvariant.name.uptodate": "green", - "formatvariant.repo.mismatchconfig": "red", - "formatvariant.repo.mismatchdefault": "yellow", - "formatvariant.repo.uptodate": "green", - "formatvariant.config.special": "yellow", - "formatvariant.config.default": "green", - "formatvariant.default": "", - "histedit.remaining": "red bold", - "ui.addremove.added": "green", - "ui.addremove.removed": "red", - "ui.error": "red", - "ui.prompt": "yellow", - "log.changeset": "yellow", - "patchbomb.finalsummary": "", - "patchbomb.from": "magenta", - "patchbomb.to": "cyan", - "patchbomb.subject": "green", - "patchbomb.diffstats": "", - "rebase.rebased": "blue", - "rebase.remaining": "red bold", - "resolve.resolved": "green bold", - "resolve.unresolved": "red bold", - "shelve.age": "cyan", - "shelve.newest": "green bold", - "shelve.name": "blue bold", - "status.added": "green bold", - "status.clean": "none", - "status.copied": "none", - "status.deleted": "cyan bold underline", - "status.ignored": "black bold", - "status.modified": "blue bold", - "status.removed": "red bold", - "status.unknown": "magenta bold underline", - "tags.normal": "green", - "tags.local": "black bold", + b"grep.match": b"red bold", + b"grep.linenumber": b"green", + b"grep.rev": b"blue", + b"grep.sep": b"cyan", + b"grep.filename": b"magenta", + b"grep.user": b"magenta", + b"grep.date": b"magenta", + b"grep.inserted": b"green bold", + b"grep.deleted": b"red bold", + b"bookmarks.active": b"green", + b"branches.active": b"none", + b"branches.closed": b"black bold", + b"branches.current": b"green", + b"branches.inactive": b"none", + b"diff.changed": b"white", + b"diff.deleted": b"red", + b"diff.deleted.changed": b"red bold underline", + b"diff.deleted.unchanged": b"red", + b"diff.diffline": b"bold", + b"diff.extended": b"cyan bold", + b"diff.file_a": b"red bold", + b"diff.file_b": b"green bold", + b"diff.hunk": b"magenta", + b"diff.inserted": b"green", + b"diff.inserted.changed": b"green bold underline", + b"diff.inserted.unchanged": b"green", + b"diff.tab": b"", + b"diff.trailingwhitespace": b"bold red_background", + b"changeset.public": b"", + b"changeset.draft": b"", + b"changeset.secret": b"", + b"diffstat.deleted": b"red", + b"diffstat.inserted": b"green", + b"formatvariant.name.mismatchconfig": b"red", + b"formatvariant.name.mismatchdefault": b"yellow", + b"formatvariant.name.uptodate": b"green", + b"formatvariant.repo.mismatchconfig": b"red", + b"formatvariant.repo.mismatchdefault": b"yellow", + b"formatvariant.repo.uptodate": b"green", + b"formatvariant.config.special": b"yellow", + b"formatvariant.config.default": b"green", + b"formatvariant.default": b"", + b"histedit.remaining": b"red bold", + b"ui.addremove.added": b"green", + b"ui.addremove.removed": b"red", + b"ui.error": b"red", + b"ui.prompt": b"yellow", + b"log.changeset": b"yellow", + b"patchbomb.finalsummary": b"", + b"patchbomb.from": b"magenta", + b"patchbomb.to": b"cyan", + b"patchbomb.subject": b"green", + b"patchbomb.diffstats": b"", + b"rebase.rebased": b"blue", + b"rebase.remaining": b"red bold", + b"resolve.resolved": b"green bold", + b"resolve.unresolved": b"red bold", + b"shelve.age": b"cyan", + b"shelve.newest": b"green bold", + b"shelve.name": b"blue bold", + b"status.added": b"green bold", + b"status.clean": b"none", + b"status.copied": b"none", + b"status.deleted": b"cyan bold underline", + b"status.ignored": b"black bold", + b"status.modified": b"blue bold", + b"status.removed": b"red bold", + b"status.unknown": b"magenta bold underline", + b"tags.normal": b"green", + b"tags.local": b"black bold", } @@ -158,16 +158,16 @@ if curses is None: return # Otherwise, see what the config file says. - if mode not in ("auto", "terminfo"): + if mode not in (b"auto", b"terminfo"): return ui._terminfoparams.update(_baseterminfoparams) - for key, val in ui.configitems("color"): - if key.startswith("color."): - newval = (False, int(val), "") + for key, val in ui.configitems(b"color"): + if key.startswith(b"color."): + newval = (False, int(val), b"") ui._terminfoparams[key[6:]] = newval - elif key.startswith("terminfo."): - newval = (True, "", val.replace("\\E", "\x1b")) + elif key.startswith(b"terminfo."): + newval = (True, b"", val.replace(b"\\E", b"\x1b")) ui._terminfoparams[key[9:]] = newval try: curses.setupterm() @@ -181,16 +181,16 @@ if not c and not curses.tigetstr(pycompat.sysstr(e)): # Most terminals don't support dim, invis, etc, so don't be # noisy and use ui.debug(). - ui.debug("no terminfo entry for %s\n" % e) + ui.debug(b"no terminfo entry for %s\n" % e) del ui._terminfoparams[key] if not curses.tigetstr(r"setaf") or not curses.tigetstr(r"setab"): # Only warn about missing terminfo entries if we explicitly asked for # terminfo mode and we're in a formatted terminal. - if mode == "terminfo" and formatted: + if mode == b"terminfo" and formatted: ui.warn( _( - "no terminfo entry for setab/setaf: reverting to " - "ECMA-48 color\n" + b"no terminfo entry for setab/setaf: reverting to " + b"ECMA-48 color\n" ) ) ui._terminfoparams.clear() @@ -203,23 +203,26 @@ the configuration looking for custom colors and effect definitions.""" mode = _modesetup(ui) ui._colormode = mode - if mode and mode != "debug": + if mode and mode != b"debug": configstyles(ui) def _modesetup(ui): - if ui.plain("color"): + if ui.plain(b"color"): return None - config = ui.config("ui", "color") - if config == "debug": - return "debug" + config = ui.config(b"ui", b"color") + if config == b"debug": + return b"debug" - auto = config == "auto" + auto = config == b"auto" always = False if not auto and stringutil.parsebool(config): # We want the config to behave like a boolean, "on" is actually auto, # but "always" value is treated as a special case to reduce confusion. - if ui.configsource("ui", "color") == "--color" or config == "always": + if ( + ui.configsource(b"ui", b"color") == b"--color" + or config == b"always" + ): always = True else: auto = True @@ -228,64 +231,64 @@ return None formatted = always or ( - encoding.environ.get("TERM") != "dumb" and ui.formatted() + encoding.environ.get(b"TERM") != b"dumb" and ui.formatted() ) - mode = ui.config("color", "mode") + mode = ui.config(b"color", b"mode") # If pager is active, color.pagermode overrides color.mode. if getattr(ui, "pageractive", False): - mode = ui.config("color", "pagermode", mode) + mode = ui.config(b"color", b"pagermode", mode) realmode = mode if pycompat.iswindows: from . import win32 - term = encoding.environ.get("TERM") + term = encoding.environ.get(b"TERM") # TERM won't be defined in a vanilla cmd.exe environment. # UNIX-like environments on Windows such as Cygwin and MSYS will # set TERM. They appear to make a best effort attempt at setting it # to something appropriate. However, not all environments with TERM # defined support ANSI. - ansienviron = term and "xterm" in term + ansienviron = term and b"xterm" in term - if mode == "auto": + if mode == b"auto": # Since "ansi" could result in terminal gibberish, we error on the # side of selecting "win32". However, if w32effects is not defined, # we almost certainly don't support "win32", so don't even try. # w32effects is not populated when stdout is redirected, so checking # it first avoids win32 calls in a state known to error out. if ansienviron or not w32effects or win32.enablevtmode(): - realmode = "ansi" + realmode = b"ansi" else: - realmode = "win32" + realmode = b"win32" # An empty w32effects is a clue that stdout is redirected, and thus # cannot enable VT mode. - elif mode == "ansi" and w32effects and not ansienviron: + elif mode == b"ansi" and w32effects and not ansienviron: win32.enablevtmode() - elif mode == "auto": - realmode = "ansi" + elif mode == b"auto": + realmode = b"ansi" def modewarn(): # only warn if color.mode was explicitly set and we're in # a formatted terminal if mode == realmode and formatted: - ui.warn(_("warning: failed to set color mode to %s\n") % mode) + ui.warn(_(b"warning: failed to set color mode to %s\n") % mode) - if realmode == "win32": + if realmode == b"win32": ui._terminfoparams.clear() if not w32effects: modewarn() return None - elif realmode == "ansi": + elif realmode == b"ansi": ui._terminfoparams.clear() - elif realmode == "terminfo": + elif realmode == b"terminfo": _terminfosetup(ui, mode, formatted) if not ui._terminfoparams: ## FIXME Shouldn't we return None in this case too? modewarn() - realmode = "ansi" + realmode = b"ansi" else: return None @@ -296,10 +299,10 @@ def configstyles(ui): ui._styles.update(_defaultstyles) - for status, cfgeffects in ui.configitems("color"): - if "." not in status or status.startswith(("color.", "terminfo.")): + for status, cfgeffects in ui.configitems(b"color"): + if b"." not in status or status.startswith((b"color.", b"terminfo.")): continue - cfgeffects = ui.configlist("color", status) + cfgeffects = ui.configlist(b"color", status) if cfgeffects: good = [] for e in cfgeffects: @@ -308,17 +311,17 @@ else: ui.warn( _( - "ignoring unknown color/effect %s " - "(configured in color.%s)\n" + b"ignoring unknown color/effect %s " + b"(configured in color.%s)\n" ) % (stringutil.pprint(e), status) ) - ui._styles[status] = " ".join(good) + ui._styles[status] = b" ".join(good) def _activeeffects(ui): """Return the effects map for the color mode set on the ui.""" - if ui._colormode == "win32": + if ui._colormode == b"win32": return w32effects elif ui._colormode is not None: return _effects @@ -326,7 +329,7 @@ def valideffect(ui, effect): - "Determine if the effect is valid or not." + b"Determine if the effect is valid or not." return (not ui._terminfoparams and effect in _activeeffects(ui)) or ( effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams ) @@ -336,13 +339,13 @@ """Helper function for render_effects().""" bg = False - if effect.endswith("_background"): + if effect.endswith(b"_background"): bg = True effect = effect[:-11] try: attr, val, termcode = ui._terminfoparams[effect] except KeyError: - return "" + return b"" if attr: if termcode: return termcode @@ -369,26 +372,26 @@ if not t: continue parts.extend([start, t, stop]) - return "".join(parts) + return b"".join(parts) def _render_effects(ui, text, effects): - "Wrap text in commands to turn on each effect." + b"Wrap text in commands to turn on each effect." if not text: return text if ui._terminfoparams: - start = "".join( - _effect_str(ui, effect) for effect in ["none"] + effects.split() + start = b"".join( + _effect_str(ui, effect) for effect in [b"none"] + effects.split() ) - stop = _effect_str(ui, "none") + stop = _effect_str(ui, b"none") else: activeeffects = _activeeffects(ui) start = [ pycompat.bytestr(activeeffects[e]) - for e in ["none"] + effects.split() + for e in [b"none"] + effects.split() ] - start = "\033[" + ";".join(start) + "m" - stop = "\033[" + pycompat.bytestr(activeeffects["none"]) + "m" + start = b"\033[" + b";".join(start) + b"m" + stop = b"\033[" + pycompat.bytestr(activeeffects[b"none"]) + b"m" return _mergeeffects(text, start, stop) @@ -397,29 +400,32 @@ def stripeffects(text): """Strip ANSI control codes which could be inserted by colorlabel()""" - return _ansieffectre.sub("", text) + return _ansieffectre.sub(b"", text) def colorlabel(ui, msg, label): """add color control code according to the mode""" - if ui._colormode == "debug": + if ui._colormode == b"debug": if label and msg: - if msg.endswith("\n"): - msg = "[%s|%s]\n" % (label, msg[:-1]) + if msg.endswith(b"\n"): + msg = b"[%s|%s]\n" % (label, msg[:-1]) else: - msg = "[%s|%s]" % (label, msg) + msg = b"[%s|%s]" % (label, msg) elif ui._colormode is not None: effects = [] for l in label.split(): - s = ui._styles.get(l, "") + s = ui._styles.get(l, b"") if s: effects.append(s) elif valideffect(ui, l): effects.append(l) - effects = " ".join(effects) + effects = b" ".join(effects) if effects: - msg = "\n".join( - [_render_effects(ui, line, effects) for line in msg.split("\n")] + msg = b"\n".join( + [ + _render_effects(ui, line, effects) + for line in msg.split(b"\n") + ] ) return msg @@ -472,29 +478,29 @@ # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx w32effects = { - "none": -1, - "black": 0, - "red": _FOREGROUND_RED, - "green": _FOREGROUND_GREEN, - "yellow": _FOREGROUND_RED | _FOREGROUND_GREEN, - "blue": _FOREGROUND_BLUE, - "magenta": _FOREGROUND_BLUE | _FOREGROUND_RED, - "cyan": _FOREGROUND_BLUE | _FOREGROUND_GREEN, - "white": _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, - "bold": _FOREGROUND_INTENSITY, - "black_background": 0x100, # unused value > 0x0f - "red_background": _BACKGROUND_RED, - "green_background": _BACKGROUND_GREEN, - "yellow_background": _BACKGROUND_RED | _BACKGROUND_GREEN, - "blue_background": _BACKGROUND_BLUE, - "purple_background": _BACKGROUND_BLUE | _BACKGROUND_RED, - "cyan_background": _BACKGROUND_BLUE | _BACKGROUND_GREEN, - "white_background": ( + b"none": -1, + b"black": 0, + b"red": _FOREGROUND_RED, + b"green": _FOREGROUND_GREEN, + b"yellow": _FOREGROUND_RED | _FOREGROUND_GREEN, + b"blue": _FOREGROUND_BLUE, + b"magenta": _FOREGROUND_BLUE | _FOREGROUND_RED, + b"cyan": _FOREGROUND_BLUE | _FOREGROUND_GREEN, + b"white": _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, + b"bold": _FOREGROUND_INTENSITY, + b"black_background": 0x100, # unused value > 0x0f + b"red_background": _BACKGROUND_RED, + b"green_background": _BACKGROUND_GREEN, + b"yellow_background": _BACKGROUND_RED | _BACKGROUND_GREEN, + b"blue_background": _BACKGROUND_BLUE, + b"purple_background": _BACKGROUND_BLUE | _BACKGROUND_RED, + b"cyan_background": _BACKGROUND_BLUE | _BACKGROUND_GREEN, + b"white_background": ( _BACKGROUND_RED | _BACKGROUND_GREEN | _BACKGROUND_BLUE ), - "bold_background": _BACKGROUND_INTENSITY, - "underline": _COMMON_LVB_UNDERSCORE, # double-byte charsets only - "inverse": _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only + b"bold_background": _BACKGROUND_INTENSITY, + b"underline": _COMMON_LVB_UNDERSCORE, # double-byte charsets only + b"inverse": _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only } passthrough = { @@ -522,7 +528,7 @@ ) def win32print(ui, writefunc, text, **opts): - label = opts.get(r"label", "") + label = opts.get(r"label", b"") attr = origattr def mapcolor(val, attr): @@ -537,7 +543,7 @@ # determine console attributes based on labels for l in label.split(): - style = ui._styles.get(l, "") + style = ui._styles.get(l, b"") for effect in style.split(): try: attr = mapcolor(w32effects[effect], attr) diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -81,65 +81,67 @@ globalopts = [ ( - "R", - "repository", - "", - _("repository root directory or name of overlay bundle file"), - _("REPO"), + b"R", + b"repository", + b"", + _(b"repository root directory or name of overlay bundle file"), + _(b"REPO"), ), - ("", "cwd", "", _("change working directory"), _("DIR")), + (b"", b"cwd", b"", _(b"change working directory"), _(b"DIR")), ( - "y", - "noninteractive", + b"y", + b"noninteractive", None, - _("do not prompt, automatically pick the first choice for all prompts"), + _( + b"do not prompt, automatically pick the first choice for all prompts" + ), ), - ("q", "quiet", None, _("suppress output")), - ("v", "verbose", None, _("enable additional output")), + (b"q", b"quiet", None, _(b"suppress output")), + (b"v", b"verbose", None, _(b"enable additional output")), ( - "", - "color", - "", + b"", + b"color", + b"", # i18n: 'always', 'auto', 'never', and 'debug' are keywords # and should not be translated - _("when to colorize (boolean, always, auto, never, or debug)"), - _("TYPE"), + _(b"when to colorize (boolean, always, auto, never, or debug)"), + _(b"TYPE"), ), ( - "", - "config", + b"", + b"config", [], - _("set/override config option (use 'section.name=value')"), - _("CONFIG"), + _(b"set/override config option (use 'section.name=value')"), + _(b"CONFIG"), ), - ("", "debug", None, _("enable debugging output")), - ("", "debugger", None, _("start debugger")), + (b"", b"debug", None, _(b"enable debugging output")), + (b"", b"debugger", None, _(b"start debugger")), ( - "", - "encoding", + b"", + b"encoding", encoding.encoding, - _("set the charset encoding"), - _("ENCODE"), + _(b"set the charset encoding"), + _(b"ENCODE"), ), ( - "", - "encodingmode", + b"", + b"encodingmode", encoding.encodingmode, - _("set the charset encoding mode"), - _("MODE"), + _(b"set the charset encoding mode"), + _(b"MODE"), ), - ("", "traceback", None, _("always print a traceback on exception")), - ("", "time", None, _("time how long the command takes")), - ("", "profile", None, _("print command execution profile")), - ("", "version", None, _("output version information and exit")), - ("h", "help", None, _("display help and exit")), - ("", "hidden", False, _("consider hidden changesets")), + (b"", b"traceback", None, _(b"always print a traceback on exception")), + (b"", b"time", None, _(b"time how long the command takes")), + (b"", b"profile", None, _(b"print command execution profile")), + (b"", b"version", None, _(b"output version information and exit")), + (b"h", b"help", None, _(b"display help and exit")), + (b"", b"hidden", False, _(b"consider hidden changesets")), ( - "", - "pager", - "auto", - _("when to paginate (boolean, always, auto, or never)"), - _("TYPE"), + b"", + b"pager", + b"auto", + _(b"when to paginate (boolean, always, auto, or never)"), + _(b"TYPE"), ), ] @@ -164,7 +166,7 @@ @command( - "abort", + b"abort", dryrunopts, helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True, @@ -180,25 +182,27 @@ dryrun = opts.get(r"dry_run") abortstate = cmdutil.getunfinishedstate(repo) if not abortstate: - raise error.Abort(_("no operation in progress")) + raise error.Abort(_(b"no operation in progress")) if not abortstate.abortfunc: raise error.Abort( ( - _("%s in progress but does not support 'hg abort'") + _(b"%s in progress but does not support 'hg abort'") % (abortstate._opname) ), hint=abortstate.hint(), ) if dryrun: - ui.status(_("%s in progress, will be aborted\n") % (abortstate._opname)) + ui.status( + _(b"%s in progress, will be aborted\n") % (abortstate._opname) + ) return return abortstate.abortfunc(ui, repo) @command( - "add", + b"add", walkopts + subrepoopts + dryrunopts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, inferrepo=True, @@ -248,14 +252,14 @@ m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts)) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) - rejected = cmdutil.add(ui, repo, m, "", uipathfn, False, **opts) + rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts) return rejected and 1 or 0 @command( - "addremove", + b"addremove", similarityopts + subrepoopts + walkopts + dryrunopts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, inferrepo=True, ) @@ -322,43 +326,49 @@ Returns 0 if all files are successfully added. """ opts = pycompat.byteskwargs(opts) - if not opts.get("similarity"): - opts["similarity"] = "100" + if not opts.get(b"similarity"): + opts[b"similarity"] = b"100" matcher = scmutil.match(repo[None], pats, opts) relative = scmutil.anypats(pats, opts) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative) - return scmutil.addremove(repo, matcher, "", uipathfn, opts) + return scmutil.addremove(repo, matcher, b"", uipathfn, opts) @command( - "annotate|blame", + b"annotate|blame", [ - ("r", "rev", "", _("annotate the specified revision"), _("REV")), + (b"r", b"rev", b"", _(b"annotate the specified revision"), _(b"REV")), ( - "", - "follow", + b"", + b"follow", None, - _("follow copies/renames and list the filename (DEPRECATED)"), + _(b"follow copies/renames and list the filename (DEPRECATED)"), ), - ("", "no-follow", None, _("don't follow copies and renames")), - ("a", "text", None, _("treat all files as text")), - ("u", "user", None, _("list the author (long with -v)")), - ("f", "file", None, _("list the filename")), - ("d", "date", None, _("list the date (short with -q)")), - ("n", "number", None, _("list the revision number (default)")), - ("c", "changeset", None, _("list the changeset")), + (b"", b"no-follow", None, _(b"don't follow copies and renames")), + (b"a", b"text", None, _(b"treat all files as text")), + (b"u", b"user", None, _(b"list the author (long with -v)")), + (b"f", b"file", None, _(b"list the filename")), + (b"d", b"date", None, _(b"list the date (short with -q)")), + (b"n", b"number", None, _(b"list the revision number (default)")), + (b"c", b"changeset", None, _(b"list the changeset")), ( - "l", - "line-number", + b"l", + b"line-number", None, - _("show line number at the first appearance"), + _(b"show line number at the first appearance"), ), - ("", "skip", [], _("revision to not display (EXPERIMENTAL)"), _("REV")), + ( + b"", + b"skip", + [], + _(b"revision to not display (EXPERIMENTAL)"), + _(b"REV"), + ), ] + diffwsopts + walkopts + formatteropts, - _("[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE..."), + _(b"[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE..."), helpcategory=command.CATEGORY_FILE_CONTENTS, helpbasic=True, inferrepo=True, @@ -403,32 +413,36 @@ """ opts = pycompat.byteskwargs(opts) if not pats: - raise error.Abort(_("at least one filename or pattern is required")) - - if opts.get("follow"): + raise error.Abort(_(b"at least one filename or pattern is required")) + + if opts.get(b"follow"): # --follow is deprecated and now just an alias for -f/--file # to mimic the behavior of Mercurial before version 1.5 - opts["file"] = True + opts[b"file"] = True if ( - not opts.get("user") - and not opts.get("changeset") - and not opts.get("date") - and not opts.get("file") + not opts.get(b"user") + and not opts.get(b"changeset") + and not opts.get(b"date") + and not opts.get(b"file") ): - opts["number"] = True - - linenumber = opts.get("line_number") is not None - if linenumber and (not opts.get("changeset")) and (not opts.get("number")): - raise error.Abort(_("at least one of -n/-c is required for -l")) - - rev = opts.get("rev") + opts[b"number"] = True + + linenumber = opts.get(b"line_number") is not None + if ( + linenumber + and (not opts.get(b"changeset")) + and (not opts.get(b"number")) + ): + raise error.Abort(_(b"at least one of -n/-c is required for -l")) + + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev) - ui.pager("annotate") - rootfm = ui.formatter("annotate", opts) + ui.pager(b"annotate") + rootfm = ui.formatter(b"annotate", opts) if ui.debugflag: shorthex = pycompat.identity else: @@ -441,45 +455,45 @@ else: datefunc = dateutil.datestr if ctx.rev() is None: - if opts.get("changeset"): + if opts.get(b"changeset"): # omit "+" suffix which is appended to node hex def formatrev(rev): if rev == wdirrev: - return "%d" % ctx.p1().rev() + return b"%d" % ctx.p1().rev() else: - return "%d" % rev + return b"%d" % rev else: def formatrev(rev): if rev == wdirrev: - return "%d+" % ctx.p1().rev() + return b"%d+" % ctx.p1().rev() else: - return "%d " % rev + return b"%d " % rev def formathex(h): if h == wdirhex: - return "%s+" % shorthex(hex(ctx.p1().node())) + return b"%s+" % shorthex(hex(ctx.p1().node())) else: - return "%s " % shorthex(h) + return b"%s " % shorthex(h) else: formatrev = b"%d".__mod__ formathex = shorthex opmap = [ - ("user", " ", lambda x: x.fctx.user(), ui.shortuser), - ("rev", " ", lambda x: scmutil.intrev(x.fctx), formatrev), - ("node", " ", lambda x: hex(scmutil.binnode(x.fctx)), formathex), - ("date", " ", lambda x: x.fctx.date(), util.cachefunc(datefunc)), - ("path", " ", lambda x: x.fctx.path(), pycompat.bytestr), - ("lineno", ":", lambda x: x.lineno, pycompat.bytestr), + (b"user", b" ", lambda x: x.fctx.user(), ui.shortuser), + (b"rev", b" ", lambda x: scmutil.intrev(x.fctx), formatrev), + (b"node", b" ", lambda x: hex(scmutil.binnode(x.fctx)), formathex), + (b"date", b" ", lambda x: x.fctx.date(), util.cachefunc(datefunc)), + (b"path", b" ", lambda x: x.fctx.path(), pycompat.bytestr), + (b"lineno", b":", lambda x: x.lineno, pycompat.bytestr), ] opnamemap = { - "rev": "number", - "node": "changeset", - "path": "file", - "lineno": "line_number", + b"rev": b"number", + b"node": b"changeset", + b"path": b"file", + b"lineno": b"line_number", } if rootfm.isplain(): @@ -498,23 +512,23 @@ for fn, sep, get, fmt in opmap if opts.get(opnamemap.get(fn, fn)) or fn in datahint ] - funcmap[0] = (funcmap[0][0], "") # no separator in front of first column - fields = " ".join( + funcmap[0] = (funcmap[0][0], b"") # no separator in front of first column + fields = b" ".join( fn for fn, sep, get, fmt in opmap if opts.get(opnamemap.get(fn, fn)) or fn in datahint ) def bad(x, y): - raise error.Abort("%s: %s" % (x, y)) + raise error.Abort(b"%s: %s" % (x, y)) m = scmutil.match(ctx, pats, opts, badfn=bad) - follow = not opts.get("no_follow") + follow = not opts.get(b"no_follow") diffopts = patch.difffeatureopts( - ui, opts, section="annotate", whitespace=True + ui, opts, section=b"annotate", whitespace=True ) - skiprevs = opts.get("skip") + skiprevs = opts.get(b"skip") if skiprevs: skiprevs = scmutil.revrange(repo, skiprevs) @@ -523,11 +537,11 @@ fctx = ctx[abs] rootfm.startitem() rootfm.data(path=abs) - if not opts.get("text") and fctx.isbinary(): - rootfm.plain(_("%s: binary file\n") % uipathfn(abs)) + if not opts.get(b"text") and fctx.isbinary(): + rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs)) continue - fm = rootfm.nested("lines", tmpl="{rev}: {line}") + fm = rootfm.nested(b"lines", tmpl=b"{rev}: {line}") lines = fctx.annotate( follow=follow, skiprevs=skiprevs, diffopts=diffopts ) @@ -542,45 +556,45 @@ if fm.isplain(): sizes = [encoding.colwidth(x) for x in l] ml = max(sizes) - formats.append([sep + " " * (ml - w) + "%s" for w in sizes]) + formats.append([sep + b" " * (ml - w) + b"%s" for w in sizes]) else: - formats.append(["%s" for x in l]) + formats.append([b"%s" for x in l]) pieces.append(l) for f, p, n in zip(zip(*formats), zip(*pieces), lines): fm.startitem() fm.context(fctx=n.fctx) - fm.write(fields, "".join(f), *p) + fm.write(fields, b"".join(f), *p) if n.skip: - fmt = "* %s" + fmt = b"* %s" else: - fmt = ": %s" - fm.write("line", fmt, n.text) - - if not lines[-1].text.endswith("\n"): - fm.plain("\n") + fmt = b": %s" + fm.write(b"line", fmt, n.text) + + if not lines[-1].text.endswith(b"\n"): + fm.plain(b"\n") fm.end() rootfm.end() @command( - "archive", + b"archive", [ - ("", "no-decode", None, _("do not pass files through decoders")), + (b"", b"no-decode", None, _(b"do not pass files through decoders")), ( - "p", - "prefix", - "", - _("directory prefix for files in archive"), - _("PREFIX"), + b"p", + b"prefix", + b"", + _(b"directory prefix for files in archive"), + _(b"PREFIX"), ), - ("r", "rev", "", _("revision to distribute"), _("REV")), - ("t", "type", "", _("type of distribution to create"), _("TYPE")), + (b"r", b"rev", b"", _(b"revision to distribute"), _(b"REV")), + (b"t", b"type", b"", _(b"type of distribution to create"), _(b"TYPE")), ] + subrepoopts + walkopts, - _("[OPTION]... DEST"), + _(b"[OPTION]... DEST"), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def archive(ui, repo, dest, **opts): @@ -626,26 +640,26 @@ """ opts = pycompat.byteskwargs(opts) - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev) if not ctx: - raise error.Abort(_("no working directory: please specify a revision")) + raise error.Abort(_(b"no working directory: please specify a revision")) node = ctx.node() dest = cmdutil.makefilename(ctx, dest) if os.path.realpath(dest) == repo.root: - raise error.Abort(_("repository root cannot be destination")) - - kind = opts.get("type") or archival.guesskind(dest) or "files" - prefix = opts.get("prefix") - - if dest == "-": - if kind == "files": - raise error.Abort(_("cannot archive plain files to stdout")) + raise error.Abort(_(b"repository root cannot be destination")) + + kind = opts.get(b"type") or archival.guesskind(dest) or b"files" + prefix = opts.get(b"prefix") + + if dest == b"-": + if kind == b"files": + raise error.Abort(_(b"cannot archive plain files to stdout")) dest = cmdutil.makefileobj(ctx, dest) if not prefix: - prefix = os.path.basename(repo.root) + "-%h" + prefix = os.path.basename(repo.root) + b"-%h" prefix = cmdutil.makefilename(ctx, prefix) match = scmutil.match(ctx, [], opts) @@ -654,39 +668,44 @@ dest, node, kind, - not opts.get("no_decode"), + not opts.get(b"no_decode"), match, prefix, - subrepos=opts.get("subrepos"), + subrepos=opts.get(b"subrepos"), ) @command( - "backout", + b"backout", [ - ("", "merge", None, _("merge with old dirstate parent after backout")), ( - "", - "commit", + b"", + b"merge", None, - _("commit if no conflicts were encountered (DEPRECATED)"), + _(b"merge with old dirstate parent after backout"), ), - ("", "no-commit", None, _("do not commit")), + ( + b"", + b"commit", + None, + _(b"commit if no conflicts were encountered (DEPRECATED)"), + ), + (b"", b"no-commit", None, _(b"do not commit")), ( - "", - "parent", - "", - _("parent to choose when backing out merge (DEPRECATED)"), - _("REV"), + b"", + b"parent", + b"", + _(b"parent to choose when backing out merge (DEPRECATED)"), + _(b"REV"), ), - ("r", "rev", "", _("revision to backout"), _("REV")), - ("e", "edit", False, _("invoke editor on commit messages")), + (b"r", b"rev", b"", _(b"revision to backout"), _(b"REV")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), ] + mergetoolopts + walkopts + commitopts + commitopts2, - _("[OPTION]... [-r] REV"), + _(b"[OPTION]... [-r] REV"), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def backout(ui, repo, node=None, rev=None, **opts): @@ -747,23 +766,23 @@ def _dobackout(ui, repo, node=None, rev=None, **opts): opts = pycompat.byteskwargs(opts) - if opts.get("commit") and opts.get("no_commit"): - raise error.Abort(_("cannot use --commit with --no-commit")) - if opts.get("merge") and opts.get("no_commit"): - raise error.Abort(_("cannot use --merge with --no-commit")) + if opts.get(b"commit") and opts.get(b"no_commit"): + raise error.Abort(_(b"cannot use --commit with --no-commit")) + if opts.get(b"merge") and opts.get(b"no_commit"): + raise error.Abort(_(b"cannot use --merge with --no-commit")) if rev and node: - raise error.Abort(_("please specify just one revision")) + raise error.Abort(_(b"please specify just one revision")) if not rev: rev = node if not rev: - raise error.Abort(_("please specify a revision to backout")) - - date = opts.get("date") + raise error.Abort(_(b"please specify a revision to backout")) + + date = opts.get(b"date") if date: - opts["date"] = dateutil.parsedate(date) + opts[b"date"] = dateutil.parsedate(date) cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) @@ -771,33 +790,33 @@ op1, op2 = repo.dirstate.parents() if not repo.changelog.isancestor(node, op1): - raise error.Abort(_("cannot backout change that is not an ancestor")) + raise error.Abort(_(b"cannot backout change that is not an ancestor")) p1, p2 = repo.changelog.parents(node) if p1 == nullid: - raise error.Abort(_("cannot backout a change with no parents")) + raise error.Abort(_(b"cannot backout a change with no parents")) if p2 != nullid: - if not opts.get("parent"): - raise error.Abort(_("cannot backout a merge changeset")) - p = repo.lookup(opts["parent"]) + if not opts.get(b"parent"): + raise error.Abort(_(b"cannot backout a merge changeset")) + p = repo.lookup(opts[b"parent"]) if p not in (p1, p2): raise error.Abort( - _("%s is not a parent of %s") % (short(p), short(node)) + _(b"%s is not a parent of %s") % (short(p), short(node)) ) parent = p else: - if opts.get("parent"): - raise error.Abort(_("cannot use --parent on non-merge changeset")) + if opts.get(b"parent"): + raise error.Abort(_(b"cannot use --parent on non-merge changeset")) parent = p1 # the backout should appear on the same branch branch = repo.dirstate.branch() bheads = repo.branchheads(branch) rctx = scmutil.revsingle(repo, hex(parent)) - if not opts.get("merge") and op1 != node: - with dirstateguard.dirstateguard(repo, "backout"): - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "backout"): + if not opts.get(b"merge") and op1 != node: + with dirstateguard.dirstateguard(repo, b"backout"): + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"backout"): stats = mergemod.update( repo, parent, @@ -810,7 +829,7 @@ hg._showstats(repo, stats) if stats.unresolvedcount: repo.ui.status( - _("use 'hg resolve' to retry unresolved " "file merges\n") + _(b"use 'hg resolve' to retry unresolved " b"file merges\n") ) return 1 else: @@ -818,64 +837,66 @@ repo.dirstate.setbranch(branch) cmdutil.revert(ui, repo, rctx, repo.dirstate.parents()) - if opts.get("no_commit"): - msg = _("changeset %s backed out, " "don't forget to commit.\n") + if opts.get(b"no_commit"): + msg = _(b"changeset %s backed out, " b"don't forget to commit.\n") ui.status(msg % short(node)) return 0 def commitfunc(ui, repo, message, match, opts): - editform = "backout" + editform = b"backout" e = cmdutil.getcommiteditor( editform=editform, **pycompat.strkwargs(opts) ) if not message: # we don't translate commit messages - message = "Backed out changeset %s" % short(node) + message = b"Backed out changeset %s" % short(node) e = cmdutil.getcommiteditor(edit=True, editform=editform) return repo.commit( - message, opts.get("user"), opts.get("date"), match, editor=e + message, opts.get(b"user"), opts.get(b"date"), match, editor=e ) newnode = cmdutil.commit(ui, repo, commitfunc, [], opts) if not newnode: - ui.status(_("nothing changed\n")) + ui.status(_(b"nothing changed\n")) return 1 cmdutil.commitstatus(repo, newnode, branch, bheads) def nice(node): - return "%d:%s" % (repo.changelog.rev(node), short(node)) + return b"%d:%s" % (repo.changelog.rev(node), short(node)) ui.status( - _("changeset %s backs out changeset %s\n") + _(b"changeset %s backs out changeset %s\n") % (nice(repo.changelog.tip()), nice(node)) ) - if opts.get("merge") and op1 != node: + if opts.get(b"merge") and op1 != node: hg.clean(repo, op1, show_stats=False) - ui.status(_("merging with changeset %s\n") % nice(repo.changelog.tip())) - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "backout"): + ui.status( + _(b"merging with changeset %s\n") % nice(repo.changelog.tip()) + ) + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"backout"): return hg.merge(repo, hex(repo.changelog.tip())) return 0 @command( - "bisect", + b"bisect", [ - ("r", "reset", False, _("reset bisect state")), - ("g", "good", False, _("mark changeset good")), - ("b", "bad", False, _("mark changeset bad")), - ("s", "skip", False, _("skip testing changeset")), - ("e", "extend", False, _("extend the bisect range")), + (b"r", b"reset", False, _(b"reset bisect state")), + (b"g", b"good", False, _(b"mark changeset good")), + (b"b", b"bad", False, _(b"mark changeset bad")), + (b"s", b"skip", False, _(b"skip testing changeset")), + (b"e", b"extend", False, _(b"extend the bisect range")), ( - "c", - "command", - "", - _("use command to check changeset state"), - _("CMD"), + b"c", + b"command", + b"", + _(b"use command to check changeset state"), + _(b"CMD"), ), - ("U", "noupdate", False, _("do not update to target")), + (b"U", b"noupdate", False, _(b"do not update to target")), ], - _("[-gbsr] [-U] [-c CMD] [REV]"), + _(b"[-gbsr] [-U] [-c CMD] [REV]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, ) def bisect( @@ -973,32 +994,32 @@ Returns 0 on success. """ # backward compatibility - if rev in "good bad reset init".split(): - ui.warn(_("(use of 'hg bisect ' is deprecated)\n")) + if rev in b"good bad reset init".split(): + ui.warn(_(b"(use of 'hg bisect ' is deprecated)\n")) cmd, rev, extra = rev, extra, None - if cmd == "good": + if cmd == b"good": good = True - elif cmd == "bad": + elif cmd == b"bad": bad = True else: reset = True elif extra: - raise error.Abort(_("incompatible arguments")) + raise error.Abort(_(b"incompatible arguments")) incompatibles = { - "--bad": bad, - "--command": bool(command), - "--extend": extend, - "--good": good, - "--reset": reset, - "--skip": skip, + b"--bad": bad, + b"--command": bool(command), + b"--extend": extend, + b"--good": good, + b"--reset": reset, + b"--skip": skip, } enabled = [x for x in incompatibles if incompatibles[x]] if len(enabled) > 1: raise error.Abort( - _("%s and %s are incompatible") % tuple(sorted(enabled)[0:2]) + _(b"%s and %s are incompatible") % tuple(sorted(enabled)[0:2]) ) if reset: @@ -1012,15 +1033,15 @@ if rev: nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])] else: - nodes = [repo.lookup(".")] + nodes = [repo.lookup(b".")] if good: - state["good"] += nodes + state[b"good"] += nodes elif bad: - state["bad"] += nodes + state[b"bad"] += nodes elif skip: - state["skip"] += nodes + state[b"skip"] += nodes hbisect.save_state(repo, state) - if not (state["good"] and state["bad"]): + if not (state[b"good"] and state[b"bad"]): return def mayupdate(repo, node, show_stats=True): @@ -1037,45 +1058,45 @@ changesets = 1 if noupdate: try: - node = state["current"][0] + node = state[b"current"][0] except LookupError: raise error.Abort( _( - "current bisect revision is unknown - " - "start a new bisect to fix" + b"current bisect revision is unknown - " + b"start a new bisect to fix" ) ) else: node, p2 = repo.dirstate.parents() if p2 != nullid: - raise error.Abort(_("current bisect revision is a merge")) + raise error.Abort(_(b"current bisect revision is a merge")) if rev: node = repo[scmutil.revsingle(repo, rev, node)].node() try: while changesets: # update state - state["current"] = [node] + state[b"current"] = [node] hbisect.save_state(repo, state) status = ui.system( command, - environ={"HG_NODE": hex(node)}, - blockedtag="bisect_check", + environ={b"HG_NODE": hex(node)}, + blockedtag=b"bisect_check", ) if status == 125: - transition = "skip" + transition = b"skip" elif status == 0: - transition = "good" + transition = b"good" # status < 0 means process was killed elif status == 127: - raise error.Abort(_("failed to execute %s") % command) + raise error.Abort(_(b"failed to execute %s") % command) elif status < 0: - raise error.Abort(_("%s killed") % command) + raise error.Abort(_(b"%s killed") % command) else: - transition = "bad" + transition = b"bad" state[transition].append(node) ctx = repo[node] ui.status( - _("changeset %d:%s: %s\n") % (ctx.rev(), ctx, transition) + _(b"changeset %d:%s: %s\n") % (ctx.rev(), ctx, transition) ) hbisect.checkstate(state) # bisect @@ -1084,7 +1105,7 @@ node = nodes[0] mayupdate(repo, node, show_stats=False) finally: - state["current"] = [node] + state[b"current"] = [node] hbisect.save_state(repo, state) hbisect.printresult(ui, repo, state, displayer, nodes, bgood) return @@ -1098,13 +1119,13 @@ extendnode = hbisect.extendrange(repo, state, nodes, good) if extendnode is not None: ui.write( - _("Extending search to changeset %d:%s\n") + _(b"Extending search to changeset %d:%s\n") % (extendnode.rev(), extendnode) ) - state["current"] = [extendnode.node()] + state[b"current"] = [extendnode.node()] hbisect.save_state(repo, state) return mayupdate(repo, extendnode.node()) - raise error.Abort(_("nothing to extend")) + raise error.Abort(_(b"nothing to extend")) if changesets == 0: hbisect.printresult(ui, repo, state, displayer, nodes, good) @@ -1118,28 +1139,28 @@ rev = repo.changelog.rev(node) ui.write( _( - "Testing changeset %d:%s " - "(%d changesets remaining, ~%d tests)\n" + b"Testing changeset %d:%s " + b"(%d changesets remaining, ~%d tests)\n" ) % (rev, short(node), changesets, tests) ) - state["current"] = [node] + state[b"current"] = [node] hbisect.save_state(repo, state) return mayupdate(repo, node) @command( - "bookmarks|bookmark", + b"bookmarks|bookmark", [ - ("f", "force", False, _("force")), - ("r", "rev", "", _("revision for bookmark action"), _("REV")), - ("d", "delete", False, _("delete a given bookmark")), - ("m", "rename", "", _("rename a given bookmark"), _("OLD")), - ("i", "inactive", False, _("mark a bookmark inactive")), - ("l", "list", False, _("list existing bookmarks")), + (b"f", b"force", False, _(b"force")), + (b"r", b"rev", b"", _(b"revision for bookmark action"), _(b"REV")), + (b"d", b"delete", False, _(b"delete a given bookmark")), + (b"m", b"rename", b"", _(b"rename a given bookmark"), _(b"OLD")), + (b"i", b"inactive", False, _(b"mark a bookmark inactive")), + (b"l", b"list", False, _(b"list existing bookmarks")), ] + formatteropts, - _("hg bookmarks [OPTIONS]... [NAME]..."), + _(b"hg bookmarks [OPTIONS]... [NAME]..."), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def bookmark(ui, repo, *names, **opts): @@ -1203,73 +1224,78 @@ hg book -ql . """ opts = pycompat.byteskwargs(opts) - force = opts.get("force") - rev = opts.get("rev") - inactive = opts.get("inactive") # meaning add/rename to inactive bookmark - - selactions = [k for k in ["delete", "rename", "list"] if opts.get(k)] + force = opts.get(b"force") + rev = opts.get(b"rev") + inactive = opts.get(b"inactive") # meaning add/rename to inactive bookmark + + selactions = [k for k in [b"delete", b"rename", b"list"] if opts.get(k)] if len(selactions) > 1: raise error.Abort( - _("--%s and --%s are incompatible") % tuple(selactions[:2]) + _(b"--%s and --%s are incompatible") % tuple(selactions[:2]) ) if selactions: action = selactions[0] elif names or rev: - action = "add" + action = b"add" elif inactive: - action = "inactive" # meaning deactivate + action = b"inactive" # meaning deactivate else: - action = "list" - - if rev and action in {"delete", "rename", "list"}: - raise error.Abort(_("--rev is incompatible with --%s") % action) - if inactive and action in {"delete", "list"}: - raise error.Abort(_("--inactive is incompatible with --%s") % action) - if not names and action in {"add", "delete"}: - raise error.Abort(_("bookmark name required")) - - if action in {"add", "delete", "rename", "inactive"}: - with repo.wlock(), repo.lock(), repo.transaction("bookmark") as tr: - if action == "delete": + action = b"list" + + if rev and action in {b"delete", b"rename", b"list"}: + raise error.Abort(_(b"--rev is incompatible with --%s") % action) + if inactive and action in {b"delete", b"list"}: + raise error.Abort(_(b"--inactive is incompatible with --%s") % action) + if not names and action in {b"add", b"delete"}: + raise error.Abort(_(b"bookmark name required")) + + if action in {b"add", b"delete", b"rename", b"inactive"}: + with repo.wlock(), repo.lock(), repo.transaction(b"bookmark") as tr: + if action == b"delete": names = pycompat.maplist(repo._bookmarks.expandname, names) bookmarks.delete(repo, tr, names) - elif action == "rename": + elif action == b"rename": if not names: - raise error.Abort(_("new bookmark name required")) + raise error.Abort(_(b"new bookmark name required")) elif len(names) > 1: - raise error.Abort(_("only one new bookmark name allowed")) - oldname = repo._bookmarks.expandname(opts["rename"]) + raise error.Abort(_(b"only one new bookmark name allowed")) + oldname = repo._bookmarks.expandname(opts[b"rename"]) bookmarks.rename(repo, tr, oldname, names[0], force, inactive) - elif action == "add": + elif action == b"add": bookmarks.addbookmarks(repo, tr, names, rev, force, inactive) - elif action == "inactive": + elif action == b"inactive": if len(repo._bookmarks) == 0: - ui.status(_("no bookmarks set\n")) + ui.status(_(b"no bookmarks set\n")) elif not repo._activebookmark: - ui.status(_("no active bookmark\n")) + ui.status(_(b"no active bookmark\n")) else: bookmarks.deactivate(repo) - elif action == "list": + elif action == b"list": names = pycompat.maplist(repo._bookmarks.expandname, names) - with ui.formatter("bookmarks", opts) as fm: + with ui.formatter(b"bookmarks", opts) as fm: bookmarks.printbookmarks(ui, repo, fm, names) else: - raise error.ProgrammingError("invalid action: %s" % action) + raise error.ProgrammingError(b"invalid action: %s" % action) @command( - "branch", + b"branch", [ ( - "f", - "force", + b"f", + b"force", None, - _("set branch name even if it shadows an existing branch"), + _(b"set branch name even if it shadows an existing branch"), ), - ("C", "clean", None, _("reset branch name to parent branch name")), - ("r", "rev", [], _("change branches of the given revs (EXPERIMENTAL)")), + (b"C", b"clean", None, _(b"reset branch name to parent branch name")), + ( + b"r", + b"rev", + [], + _(b"change branches of the given revs (EXPERIMENTAL)"), + ), ], - _("[-fC] [NAME]"), + _(b"[-fC] [NAME]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def branch(ui, repo, label=None, **opts): @@ -1302,64 +1328,64 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - revs = opts.get("rev") + revs = opts.get(b"rev") if label: label = label.strip() - if not opts.get("clean") and not label: + if not opts.get(b"clean") and not label: if revs: - raise error.Abort(_("no branch name specified for the revisions")) - ui.write("%s\n" % repo.dirstate.branch()) + raise error.Abort(_(b"no branch name specified for the revisions")) + ui.write(b"%s\n" % repo.dirstate.branch()) return with repo.wlock(): - if opts.get("clean"): - label = repo["."].branch() + if opts.get(b"clean"): + label = repo[b"."].branch() repo.dirstate.setbranch(label) - ui.status(_("reset working directory to branch %s\n") % label) + ui.status(_(b"reset working directory to branch %s\n") % label) elif label: - scmutil.checknewlabel(repo, label, "branch") + scmutil.checknewlabel(repo, label, b"branch") if revs: return cmdutil.changebranch(ui, repo, revs, label) - if not opts.get("force") and label in repo.branchmap(): + if not opts.get(b"force") and label in repo.branchmap(): if label not in [p.branch() for p in repo[None].parents()]: raise error.Abort( - _("a branch of the same name already" " exists"), + _(b"a branch of the same name already" b" exists"), # i18n: "it" refers to an existing branch - hint=_("use 'hg update' to switch to it"), + hint=_(b"use 'hg update' to switch to it"), ) repo.dirstate.setbranch(label) - ui.status(_("marked working directory as branch %s\n") % label) + ui.status(_(b"marked working directory as branch %s\n") % label) # find any open named branches aside from default for n, h, t, c in repo.branchmap().iterbranches(): - if n != "default" and not c: + if n != b"default" and not c: return 0 ui.status( _( - "(branches are permanent and global, " - "did you want a bookmark?)\n" + b"(branches are permanent and global, " + b"did you want a bookmark?)\n" ) ) @command( - "branches", + b"branches", [ ( - "a", - "active", + b"a", + b"active", False, - _("show only branches that have unmerged heads (DEPRECATED)"), + _(b"show only branches that have unmerged heads (DEPRECATED)"), ), - ("c", "closed", False, _("show normal and closed branches")), - ("r", "rev", [], _("show branch name(s) of the given rev")), + (b"c", b"closed", False, _(b"show normal and closed branches")), + (b"r", b"rev", [], _(b"show branch name(s) of the given rev")), ] + formatteropts, - _("[-c]"), + _(b"[-c]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, intents={INTENT_READONLY}, ) @@ -1388,15 +1414,15 @@ """ opts = pycompat.byteskwargs(opts) - revs = opts.get("rev") + revs = opts.get(b"rev") selectedbranches = None if revs: revs = scmutil.revrange(repo, revs) getbi = repo.revbranchcache().branchinfo selectedbranches = {getbi(r)[0] for r in revs} - ui.pager("branches") - fm = ui.formatter("branches", opts) + ui.pager(b"branches") + fm = ui.formatter(b"branches", opts) hexfunc = fm.hexfunc allheads = set(repo.heads()) @@ -1415,71 +1441,82 @@ if active and not isactive: continue if isactive: - label = "branches.active" - notice = "" + label = b"branches.active" + notice = b"" elif not isopen: if not closed: continue - label = "branches.closed" - notice = _(" (closed)") + label = b"branches.closed" + notice = _(b" (closed)") else: - label = "branches.inactive" - notice = _(" (inactive)") + label = b"branches.inactive" + notice = _(b" (inactive)") current = tag == repo.dirstate.branch() if current: - label = "branches.current" + label = b"branches.current" fm.startitem() - fm.write("branch", "%s", tag, label=label) + fm.write(b"branch", b"%s", tag, label=label) rev = ctx.rev() - padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0) - fmt = " " * padsize + " %d:%s" + padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0) + fmt = b" " * padsize + b" %d:%s" fm.condwrite( not ui.quiet, - "rev node", + b"rev node", fmt, rev, hexfunc(ctx.node()), - label="log.changeset changeset.%s" % ctx.phasestr(), + label=b"log.changeset changeset.%s" % ctx.phasestr(), ) fm.context(ctx=ctx) fm.data(active=isactive, closed=not isopen, current=current) if not ui.quiet: fm.plain(notice) - fm.plain("\n") + fm.plain(b"\n") fm.end() @command( - "bundle", + b"bundle", [ - ("f", "force", None, _("run even when the destination is unrelated")), ( - "r", - "rev", + b"f", + b"force", + None, + _(b"run even when the destination is unrelated"), + ), + ( + b"r", + b"rev", [], - _("a changeset intended to be added to the destination"), - _("REV"), + _(b"a changeset intended to be added to the destination"), + _(b"REV"), ), ( - "b", - "branch", + b"b", + b"branch", [], - _("a specific branch you would like to bundle"), - _("BRANCH"), + _(b"a specific branch you would like to bundle"), + _(b"BRANCH"), ), ( - "", - "base", + b"", + b"base", [], - _("a base changeset assumed to be available at the destination"), - _("REV"), + _(b"a base changeset assumed to be available at the destination"), + _(b"REV"), ), - ("a", "all", None, _("bundle all changesets in the repository")), - ("t", "type", "bzip2", _("bundle compression type to use"), _("TYPE")), + (b"a", b"all", None, _(b"bundle all changesets in the repository")), + ( + b"t", + b"type", + b"bzip2", + _(b"bundle compression type to use"), + _(b"TYPE"), + ), ] + remoteopts, - _("[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]"), + _(b"[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]"), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def bundle(ui, repo, fname, dest=None, **opts): @@ -1512,78 +1549,82 @@ """ opts = pycompat.byteskwargs(opts) revs = None - if "rev" in opts: - revstrings = opts["rev"] + if b"rev" in opts: + revstrings = opts[b"rev"] revs = scmutil.revrange(repo, revstrings) if revstrings and not revs: - raise error.Abort(_("no commits to bundle")) - - bundletype = opts.get("type", "bzip2").lower() + raise error.Abort(_(b"no commits to bundle")) + + bundletype = opts.get(b"type", b"bzip2").lower() try: bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False) except error.UnsupportedBundleSpecification as e: raise error.Abort( pycompat.bytestr(e), hint=_( - "see 'hg help bundlespec' for supported " "values for --type" + b"see 'hg help bundlespec' for supported " b"values for --type" ), ) - cgversion = bundlespec.contentopts["cg.version"] + cgversion = bundlespec.contentopts[b"cg.version"] # Packed bundles are a pseudo bundle format for now. - if cgversion == "s1": + if cgversion == b"s1": raise error.Abort( - _('packed bundles cannot be produced by "hg bundle"'), - hint=_("use 'hg debugcreatestreamclonebundle'"), + _(b'packed bundles cannot be produced by "hg bundle"'), + hint=_(b"use 'hg debugcreatestreamclonebundle'"), ) - if opts.get("all"): + if opts.get(b"all"): if dest: raise error.Abort( - _("--all is incompatible with specifying " "a destination") + _(b"--all is incompatible with specifying " b"a destination") ) - if opts.get("base"): - ui.warn(_("ignoring --base because --all was specified\n")) + if opts.get(b"base"): + ui.warn(_(b"ignoring --base because --all was specified\n")) base = [nullrev] else: - base = scmutil.revrange(repo, opts.get("base")) + base = scmutil.revrange(repo, opts.get(b"base")) if cgversion not in changegroup.supportedoutgoingversions(repo): raise error.Abort( - _("repository does not support bundle version %s") % cgversion + _(b"repository does not support bundle version %s") % cgversion ) if base: if dest: raise error.Abort( - _("--base is incompatible with specifying " "a destination") + _(b"--base is incompatible with specifying " b"a destination") ) common = [repo[rev].node() for rev in base] heads = [repo[r].node() for r in revs] if revs else None outgoing = discovery.outgoing(repo, common, heads) else: - dest = ui.expandpath(dest or "default-push", dest or "default") - dest, branches = hg.parseurl(dest, opts.get("branch")) + dest = ui.expandpath(dest or b"default-push", dest or b"default") + dest, branches = hg.parseurl(dest, opts.get(b"branch")) other = hg.peer(repo, opts, dest) revs = [repo[r].hex() for r in revs] revs, checkout = hg.addbranchrevs(repo, repo, branches, revs) heads = revs and pycompat.maplist(repo.lookup, revs) or revs outgoing = discovery.findcommonoutgoing( - repo, other, onlyheads=heads, force=opts.get("force"), portable=True + repo, + other, + onlyheads=heads, + force=opts.get(b"force"), + portable=True, ) if not outgoing.missing: scmutil.nochangesfound(ui, repo, not base and outgoing.excluded) return 1 - if cgversion == "01": # bundle1 - bversion = "HG10" + bundlespec.wirecompression + if cgversion == b"01": # bundle1 + bversion = b"HG10" + bundlespec.wirecompression bcompression = None - elif cgversion in ("02", "03"): - bversion = "HG20" + elif cgversion in (b"02", b"03"): + bversion = b"HG20" bcompression = bundlespec.wirecompression else: raise error.ProgrammingError( - "bundle: unexpected changegroup version %s" % cgversion + b"bundle: unexpected changegroup version %s" % cgversion ) # TODO compression options should be derived from bundlespec parsing. @@ -1592,24 +1633,24 @@ # b) introducing a command flag. compopts = {} complevel = ui.configint( - "experimental", "bundlecomplevel." + bundlespec.compression + b"experimental", b"bundlecomplevel." + bundlespec.compression ) if complevel is None: - complevel = ui.configint("experimental", "bundlecomplevel") + complevel = ui.configint(b"experimental", b"bundlecomplevel") if complevel is not None: - compopts["level"] = complevel + compopts[b"level"] = complevel # Allow overriding the bundling of obsmarker in phases through # configuration while we don't have a bundle version that include them - if repo.ui.configbool("experimental", "evolution.bundle-obsmarker"): - bundlespec.contentopts["obsolescence"] = True - if repo.ui.configbool("experimental", "bundle-phases"): - bundlespec.contentopts["phases"] = True + if repo.ui.configbool(b"experimental", b"evolution.bundle-obsmarker"): + bundlespec.contentopts[b"obsolescence"] = True + if repo.ui.configbool(b"experimental", b"bundle-phases"): + bundlespec.contentopts[b"phases"] = True bundle2.writenewbundle( ui, repo, - "bundle", + b"bundle", fname, bversion, outgoing, @@ -1620,21 +1661,21 @@ @command( - "cat", + b"cat", [ ( - "o", - "output", - "", - _("print output to file with formatted name"), - _("FORMAT"), + b"o", + b"output", + b"", + _(b"print output to file with formatted name"), + _(b"FORMAT"), ), - ("r", "rev", "", _("print the given revision"), _("REV")), - ("", "decode", None, _("apply any matching decode filter")), + (b"r", b"rev", b"", _(b"print the given revision"), _(b"REV")), + (b"", b"decode", None, _(b"apply any matching decode filter")), ] + walkopts + formatteropts, - _("[OPTION]... FILE..."), + _(b"[OPTION]... FILE..."), helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, intents={INTENT_READONLY}, @@ -1674,71 +1715,71 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev) m = scmutil.match(ctx, (file1,) + pats, opts) - fntemplate = opts.pop("output", "") + fntemplate = opts.pop(b"output", b"") if cmdutil.isstdiofilename(fntemplate): - fntemplate = "" + fntemplate = b"" if fntemplate: - fm = formatter.nullformatter(ui, "cat", opts) + fm = formatter.nullformatter(ui, b"cat", opts) else: - ui.pager("cat") - fm = ui.formatter("cat", opts) + ui.pager(b"cat") + fm = ui.formatter(b"cat", opts) with fm: return cmdutil.cat( - ui, repo, ctx, m, fm, fntemplate, "", **pycompat.strkwargs(opts) + ui, repo, ctx, m, fm, fntemplate, b"", **pycompat.strkwargs(opts) ) @command( - "clone", + b"clone", [ ( - "U", - "noupdate", + b"U", + b"noupdate", None, _( - "the clone will include an empty working " - "directory (only a repository)" + b"the clone will include an empty working " + b"directory (only a repository)" ), ), ( - "u", - "updaterev", - "", - _("revision, tag, or branch to check out"), - _("REV"), + b"u", + b"updaterev", + b"", + _(b"revision, tag, or branch to check out"), + _(b"REV"), ), ( - "r", - "rev", + b"r", + b"rev", [], _( - "do not clone everything, but include this changeset" - " and its ancestors" + b"do not clone everything, but include this changeset" + b" and its ancestors" ), - _("REV"), + _(b"REV"), ), ( - "b", - "branch", + b"b", + b"branch", [], _( - "do not clone everything, but include this branch's" - " changesets and their ancestors" + b"do not clone everything, but include this branch's" + b" changesets and their ancestors" ), - _("BRANCH"), + _(b"BRANCH"), ), - ("", "pull", None, _("use pull protocol to copy metadata")), - ("", "uncompressed", None, _("an alias to --stream (DEPRECATED)")), - ("", "stream", None, _("clone with minimal data processing")), + (b"", b"pull", None, _(b"use pull protocol to copy metadata")), + (b"", b"uncompressed", None, _(b"an alias to --stream (DEPRECATED)")), + (b"", b"stream", None, _(b"clone with minimal data processing")), ] + remoteopts, - _("[OPTION]... SOURCE [DEST]"), + _(b"[OPTION]... SOURCE [DEST]"), helpcategory=command.CATEGORY_REPO_CREATION, helpbasic=True, norepo=True, @@ -1852,68 +1893,68 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - if opts.get("noupdate") and opts.get("updaterev"): - raise error.Abort(_("cannot specify both --noupdate and --updaterev")) + if opts.get(b"noupdate") and opts.get(b"updaterev"): + raise error.Abort(_(b"cannot specify both --noupdate and --updaterev")) # --include/--exclude can come from narrow or sparse. includepats, excludepats = None, None # hg.clone() differentiates between None and an empty set. So make sure # patterns are sets if narrow is requested without patterns. - if opts.get("narrow"): + if opts.get(b"narrow"): includepats = set() excludepats = set() - if opts.get("include"): - includepats = narrowspec.parsepatterns(opts.get("include")) - if opts.get("exclude"): - excludepats = narrowspec.parsepatterns(opts.get("exclude")) + if opts.get(b"include"): + includepats = narrowspec.parsepatterns(opts.get(b"include")) + if opts.get(b"exclude"): + excludepats = narrowspec.parsepatterns(opts.get(b"exclude")) r = hg.clone( ui, opts, source, dest, - pull=opts.get("pull"), - stream=opts.get("stream") or opts.get("uncompressed"), - revs=opts.get("rev"), - update=opts.get("updaterev") or not opts.get("noupdate"), - branch=opts.get("branch"), - shareopts=opts.get("shareopts"), + pull=opts.get(b"pull"), + stream=opts.get(b"stream") or opts.get(b"uncompressed"), + revs=opts.get(b"rev"), + update=opts.get(b"updaterev") or not opts.get(b"noupdate"), + branch=opts.get(b"branch"), + shareopts=opts.get(b"shareopts"), storeincludepats=includepats, storeexcludepats=excludepats, - depth=opts.get("depth") or None, + depth=opts.get(b"depth") or None, ) return r is None @command( - "commit|ci", + b"commit|ci", [ ( - "A", - "addremove", + b"A", + b"addremove", None, - _("mark new/missing files as added/removed before committing"), + _(b"mark new/missing files as added/removed before committing"), ), - ("", "close-branch", None, _("mark a branch head as closed")), - ("", "amend", None, _("amend the parent of the working directory")), - ("s", "secret", None, _("use the secret phase for committing")), - ("e", "edit", None, _("invoke editor on commit messages")), + (b"", b"close-branch", None, _(b"mark a branch head as closed")), + (b"", b"amend", None, _(b"amend the parent of the working directory")), + (b"s", b"secret", None, _(b"use the secret phase for committing")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), ( - "", - "force-close-branch", + b"", + b"force-close-branch", None, - _("forcibly close branch from a non-head changeset (ADVANCED)"), + _(b"forcibly close branch from a non-head changeset (ADVANCED)"), ), - ("i", "interactive", None, _("use interactive mode")), + (b"i", b"interactive", None, _(b"use interactive mode")), ] + walkopts + commitopts + commitopts2 + subrepoopts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_COMMITTING, helpbasic=True, inferrepo=True, @@ -1989,11 +2030,11 @@ return 1 if ret == 0 else ret opts = pycompat.byteskwargs(opts) - if opts.get("subrepos"): - if opts.get("amend"): - raise error.Abort(_("cannot amend with --subrepos")) + if opts.get(b"subrepos"): + if opts.get(b"amend"): + raise error.Abort(_(b"cannot amend with --subrepos")) # Let --subrepos on the command line override config setting. - ui.setconfig("ui", "commitsubrepos", True, "commit") + ui.setconfig(b"ui", b"commitsubrepos", True, b"commit") cmdutil.checkunfinished(repo, commit=True) @@ -2001,38 +2042,38 @@ bheads = repo.branchheads(branch) extra = {} - if opts.get("close_branch") or opts.get("force_close_branch"): - extra["close"] = "1" - - if repo["."].closesbranch(): + if opts.get(b"close_branch") or opts.get(b"force_close_branch"): + extra[b"close"] = b"1" + + if repo[b"."].closesbranch(): raise error.Abort( - _("current revision is already a branch closing" " head") + _(b"current revision is already a branch closing" b" head") ) elif not bheads: - raise error.Abort(_('branch "%s" has no heads to close') % branch) + raise error.Abort(_(b'branch "%s" has no heads to close') % branch) elif ( - branch == repo["."].branch() - and repo["."].node() not in bheads - and not opts.get("force_close_branch") + branch == repo[b"."].branch() + and repo[b"."].node() not in bheads + and not opts.get(b"force_close_branch") ): hint = _( - "use --force-close-branch to close branch from a non-head" - " changeset" + b"use --force-close-branch to close branch from a non-head" + b" changeset" ) - raise error.Abort(_("can only close branch heads"), hint=hint) - elif opts.get("amend"): + raise error.Abort(_(b"can only close branch heads"), hint=hint) + elif opts.get(b"amend"): if ( - repo["."].p1().branch() != branch - and repo["."].p2().branch() != branch + repo[b"."].p1().branch() != branch + and repo[b"."].p2().branch() != branch ): - raise error.Abort(_("can only close branch heads")) - - if opts.get("amend"): - if ui.configbool("ui", "commitsubrepos"): - raise error.Abort(_("cannot amend with ui.commitsubrepos enabled")) - - old = repo["."] - rewriteutil.precheck(repo, [old.rev()], "amend") + raise error.Abort(_(b"can only close branch heads")) + + if opts.get(b"amend"): + if ui.configbool(b"ui", b"commitsubrepos"): + raise error.Abort(_(b"cannot amend with ui.commitsubrepos enabled")) + + old = repo[b"."] + rewriteutil.precheck(repo, [old.rev()], b"amend") # Currently histedit gets confused if an amend happens while histedit # is in progress. Since we have a checkunfinished command, we are @@ -2045,28 +2086,28 @@ node = cmdutil.amend(ui, repo, old, extra, pats, opts) if node == old.node(): - ui.status(_("nothing changed\n")) + ui.status(_(b"nothing changed\n")) return 1 else: def commitfunc(ui, repo, message, match, opts): overrides = {} - if opts.get("secret"): - overrides[("phases", "new-commit")] = "secret" + if opts.get(b"secret"): + overrides[(b"phases", b"new-commit")] = b"secret" baseui = repo.baseui - with baseui.configoverride(overrides, "commit"): - with ui.configoverride(overrides, "commit"): + with baseui.configoverride(overrides, b"commit"): + with ui.configoverride(overrides, b"commit"): editform = cmdutil.mergeeditform( - repo[None], "commit.normal" + repo[None], b"commit.normal" ) editor = cmdutil.getcommiteditor( editform=editform, **pycompat.strkwargs(opts) ) return repo.commit( message, - opts.get("user"), - opts.get("date"), + opts.get(b"user"), + opts.get(b"date"), match, editor=editor, extra=extra, @@ -2079,18 +2120,18 @@ if stat[3]: ui.status( _( - "nothing changed (%d missing files, see " - "'hg status')\n" + b"nothing changed (%d missing files, see " + b"'hg status')\n" ) % len(stat[3]) ) else: - ui.status(_("nothing changed\n")) + ui.status(_(b"nothing changed\n")) return 1 cmdutil.commitstatus(repo, node, branch, bheads, opts) - if not ui.quiet and ui.configbool("commands", "commit.post-status"): + if not ui.quiet and ui.configbool(b"commands", b"commit.post-status"): status( ui, repo, @@ -2099,20 +2140,20 @@ removed=True, deleted=True, unknown=True, - subrepos=opts.get("subrepos"), + subrepos=opts.get(b"subrepos"), ) @command( - "config|showconfig|debugconfig", + b"config|showconfig|debugconfig", [ - ("u", "untrusted", None, _("show untrusted configuration options")), - ("e", "edit", None, _("edit user config")), - ("l", "local", None, _("edit repository config")), - ("g", "global", None, _("edit global config")), + (b"u", b"untrusted", None, _(b"show untrusted configuration options")), + (b"e", b"edit", None, _(b"edit user config")), + (b"l", b"local", None, _(b"edit repository config")), + (b"g", b"global", None, _(b"edit global config")), ] + formatteropts, - _("[-u] [NAME]..."), + _(b"[-u] [NAME]..."), helpcategory=command.CATEGORY_HELP, optionalrepo=True, intents={INTENT_READONLY}, @@ -2152,15 +2193,15 @@ """ opts = pycompat.byteskwargs(opts) - if opts.get("edit") or opts.get("local") or opts.get("global"): - if opts.get("local") and opts.get("global"): - raise error.Abort(_("can't use --local and --global together")) - - if opts.get("local"): + if opts.get(b"edit") or opts.get(b"local") or opts.get(b"global"): + if opts.get(b"local") and opts.get(b"global"): + raise error.Abort(_(b"can't use --local and --global together")) + + if opts.get(b"local"): if not repo: - raise error.Abort(_("can't use --local outside a repository")) - paths = [repo.vfs.join("hgrc")] - elif opts.get("global"): + raise error.Abort(_(b"can't use --local outside a repository")) + paths = [repo.vfs.join(b"hgrc")] + elif opts.get(b"global"): paths = rcutil.systemrcpath() else: paths = rcutil.userrcpath() @@ -2169,42 +2210,42 @@ if os.path.exists(f): break else: - if opts.get("global"): - samplehgrc = uimod.samplehgrcs["global"] - elif opts.get("local"): - samplehgrc = uimod.samplehgrcs["local"] + if opts.get(b"global"): + samplehgrc = uimod.samplehgrcs[b"global"] + elif opts.get(b"local"): + samplehgrc = uimod.samplehgrcs[b"local"] else: - samplehgrc = uimod.samplehgrcs["user"] + samplehgrc = uimod.samplehgrcs[b"user"] f = paths[0] - fp = open(f, "wb") + fp = open(f, b"wb") fp.write(util.tonativeeol(samplehgrc)) fp.close() editor = ui.geteditor() ui.system( - '%s "%s"' % (editor, f), + b'%s "%s"' % (editor, f), onerr=error.Abort, - errprefix=_("edit failed"), - blockedtag="config_edit", + errprefix=_(b"edit failed"), + blockedtag=b"config_edit", ) return - ui.pager("config") - fm = ui.formatter("config", opts) + ui.pager(b"config") + fm = ui.formatter(b"config", opts) for t, f in rcutil.rccomponents(): - if t == "path": - ui.debug("read config from: %s\n" % f) - elif t == "items": + if t == b"path": + ui.debug(b"read config from: %s\n" % f) + elif t == b"items": for section, name, value, source in f: - ui.debug("set config by: %s\n" % source) + ui.debug(b"set config by: %s\n" % source) else: - raise error.ProgrammingError("unknown rctype: %s" % t) - untrusted = bool(opts.get("untrusted")) + raise error.ProgrammingError(b"unknown rctype: %s" % t) + untrusted = bool(opts.get(b"untrusted")) selsections = selentries = [] if values: - selsections = [v for v in values if "." not in v] - selentries = [v for v in values if "." in v] + selsections = [v for v in values if b"." not in v] + selentries = [v for v in values if b"." in v] uniquesel = len(selentries) == 1 and not selsections selsections = set(selsections) selentries = set(selentries) @@ -2215,18 +2256,18 @@ value = pycompat.bytestr(value) defaultvalue = ui.configdefault(section, name) if fm.isplain(): - source = source or "none" - value = value.replace("\n", "\\n") - entryname = section + "." + name + source = source or b"none" + value = value.replace(b"\n", b"\\n") + entryname = section + b"." + name if values and not (section in selsections or entryname in selentries): continue fm.startitem() - fm.condwrite(ui.debugflag, "source", "%s: ", source) + fm.condwrite(ui.debugflag, b"source", b"%s: ", source) if uniquesel: fm.data(name=entryname) - fm.write("value", "%s\n", value) + fm.write(b"value", b"%s\n", value) else: - fm.write("name value", "%s=%s\n", entryname, value) + fm.write(b"name value", b"%s=%s\n", entryname, value) fm.data(defaultvalue=defaultvalue) matched = True fm.end() @@ -2236,7 +2277,7 @@ @command( - "continue", + b"continue", dryrunopts, helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True, @@ -2252,30 +2293,35 @@ dryrun = opts.get(r"dry_run") contstate = cmdutil.getunfinishedstate(repo) if not contstate: - raise error.Abort(_("no operation in progress")) + raise error.Abort(_(b"no operation in progress")) if not contstate.continuefunc: raise error.Abort( ( - _("%s in progress but does not support " "'hg continue'") + _(b"%s in progress but does not support " b"'hg continue'") % (contstate._opname) ), hint=contstate.continuemsg(), ) if dryrun: - ui.status(_("%s in progress, will be resumed\n") % (contstate._opname)) + ui.status(_(b"%s in progress, will be resumed\n") % (contstate._opname)) return return contstate.continuefunc(ui, repo) @command( - "copy|cp", + b"copy|cp", [ - ("A", "after", None, _("record a copy that has already occurred")), - ("f", "force", None, _("forcibly copy over an existing managed file")), + (b"A", b"after", None, _(b"record a copy that has already occurred")), + ( + b"f", + b"force", + None, + _(b"forcibly copy over an existing managed file"), + ), ] + walkopts + dryrunopts, - _("[OPTION]... SOURCE... DEST"), + _(b"[OPTION]... SOURCE... DEST"), helpcategory=command.CATEGORY_FILE_CONTENTS, ) def copy(ui, repo, *pats, **opts): @@ -2300,28 +2346,28 @@ @command( - "debugcommands", + b"debugcommands", [], - _("[COMMAND]"), + _(b"[COMMAND]"), helpcategory=command.CATEGORY_HELP, norepo=True, ) -def debugcommands(ui, cmd="", *args): +def debugcommands(ui, cmd=b"", *args): """list all available commands and options""" for cmd, vals in sorted(table.iteritems()): - cmd = cmd.split("|")[0] - opts = ", ".join([i[1] for i in vals[1]]) - ui.write("%s: %s\n" % (cmd, opts)) + cmd = cmd.split(b"|")[0] + opts = b", ".join([i[1] for i in vals[1]]) + ui.write(b"%s: %s\n" % (cmd, opts)) @command( - "debugcomplete", - [("o", "options", None, _("show the command options"))], - _("[-o] CMD"), + b"debugcomplete", + [(b"o", b"options", None, _(b"show the command options"))], + _(b"[-o] CMD"), helpcategory=command.CATEGORY_HELP, norepo=True, ) -def debugcomplete(ui, cmd="", **opts): +def debugcomplete(ui, cmd=b"", **opts): """returns the completion list associated with the given command""" if opts.get(r"options"): @@ -2332,31 +2378,31 @@ otables.append(entry[1]) for t in otables: for o in t: - if "(DEPRECATED)" in o[3]: + if b"(DEPRECATED)" in o[3]: continue if o[0]: - options.append("-%s" % o[0]) - options.append("--%s" % o[1]) - ui.write("%s\n" % "\n".join(options)) + options.append(b"-%s" % o[0]) + options.append(b"--%s" % o[1]) + ui.write(b"%s\n" % b"\n".join(options)) return cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table) if ui.verbose: - cmdlist = [" ".join(c[0]) for c in cmdlist.values()] - ui.write("%s\n" % "\n".join(sorted(cmdlist))) + cmdlist = [b" ".join(c[0]) for c in cmdlist.values()] + ui.write(b"%s\n" % b"\n".join(sorted(cmdlist))) @command( - "diff", + b"diff", [ - ("r", "rev", [], _("revision"), _("REV")), - ("c", "change", "", _("change made by revision"), _("REV")), + (b"r", b"rev", [], _(b"revision"), _(b"REV")), + (b"c", b"change", b"", _(b"change made by revision"), _(b"REV")), ] + diffopts + diffopts2 + walkopts + subrepoopts, - _("[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]..."), + _(b"[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]..."), helpcategory=command.CATEGORY_FILE_CONTENTS, helpbasic=True, inferrepo=True, @@ -2421,20 +2467,20 @@ """ opts = pycompat.byteskwargs(opts) - revs = opts.get("rev") - change = opts.get("change") - stat = opts.get("stat") - reverse = opts.get("reverse") + revs = opts.get(b"rev") + change = opts.get(b"change") + stat = opts.get(b"stat") + reverse = opts.get(b"reverse") if revs and change: - msg = _("cannot specify --rev and --change at the same time") + msg = _(b"cannot specify --rev and --change at the same time") raise error.Abort(msg) elif change: - repo = scmutil.unhidehashlikerevs(repo, [change], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [change], b"nowarn") ctx2 = scmutil.revsingle(repo, change, None) ctx1 = ctx2.p1() else: - repo = scmutil.unhidehashlikerevs(repo, revs, "nowarn") + repo = scmutil.unhidehashlikerevs(repo, revs, b"nowarn") ctx1, ctx2 = scmutil.revpair(repo, revs) node1, node2 = ctx1.node(), ctx2.node() @@ -2444,7 +2490,7 @@ diffopts = patch.diffallopts(ui, opts) m = scmutil.match(ctx2, pats, opts) m = repo.narrowmatch(m) - ui.pager("diff") + ui.pager(b"diff") logcmdutil.diffordiffstat( ui, repo, @@ -2453,34 +2499,34 @@ node2, m, stat=stat, - listsubrepos=opts.get("subrepos"), - root=opts.get("root"), + listsubrepos=opts.get(b"subrepos"), + root=opts.get(b"root"), ) @command( - "export", + b"export", [ ( - "B", - "bookmark", - "", - _("export changes only reachable by given bookmark"), - _("BOOKMARK"), + b"B", + b"bookmark", + b"", + _(b"export changes only reachable by given bookmark"), + _(b"BOOKMARK"), ), ( - "o", - "output", - "", - _("print output to file with formatted name"), - _("FORMAT"), + b"o", + b"output", + b"", + _(b"print output to file with formatted name"), + _(b"FORMAT"), ), - ("", "switch-parent", None, _("diff against the second parent")), - ("r", "rev", [], _("revisions to export"), _("REV")), + (b"", b"switch-parent", None, _(b"diff against the second parent")), + (b"r", b"rev", [], _(b"revisions to export"), _(b"REV")), ] + diffopts + formatteropts, - _("[OPTION]... [-o OUTFILESPEC] [-r] [REV]..."), + _(b"[OPTION]... [-o OUTFILESPEC] [-r] [REV]..."), helpcategory=command.CATEGORY_IMPORT_EXPORT, helpbasic=True, intents={INTENT_READONLY}, @@ -2560,61 +2606,72 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - bookmark = opts.get("bookmark") - changesets += tuple(opts.get("rev", [])) + bookmark = opts.get(b"bookmark") + changesets += tuple(opts.get(b"rev", [])) if bookmark and changesets: - raise error.Abort(_("-r and -B are mutually exclusive")) + raise error.Abort(_(b"-r and -B are mutually exclusive")) if bookmark: if bookmark not in repo._bookmarks: - raise error.Abort(_("bookmark '%s' not found") % bookmark) + raise error.Abort(_(b"bookmark '%s' not found") % bookmark) revs = scmutil.bookmarkrevs(repo, bookmark) else: if not changesets: - changesets = ["."] - - repo = scmutil.unhidehashlikerevs(repo, changesets, "nowarn") + changesets = [b"."] + + repo = scmutil.unhidehashlikerevs(repo, changesets, b"nowarn") revs = scmutil.revrange(repo, changesets) if not revs: - raise error.Abort(_("export requires at least one changeset")) + raise error.Abort(_(b"export requires at least one changeset")) if len(revs) > 1: - ui.note(_("exporting patches:\n")) + ui.note(_(b"exporting patches:\n")) else: - ui.note(_("exporting patch:\n")) - - fntemplate = opts.get("output") + ui.note(_(b"exporting patch:\n")) + + fntemplate = opts.get(b"output") if cmdutil.isstdiofilename(fntemplate): - fntemplate = "" + fntemplate = b"" if fntemplate: - fm = formatter.nullformatter(ui, "export", opts) + fm = formatter.nullformatter(ui, b"export", opts) else: - ui.pager("export") - fm = ui.formatter("export", opts) + ui.pager(b"export") + fm = ui.formatter(b"export", opts) with fm: cmdutil.export( repo, revs, fm, fntemplate=fntemplate, - switch_parent=opts.get("switch_parent"), + switch_parent=opts.get(b"switch_parent"), opts=patch.diffallopts(ui, opts), ) @command( - "files", + b"files", [ - ("r", "rev", "", _("search the repository as it is in REV"), _("REV")), - ("0", "print0", None, _("end filenames with NUL, for use with xargs")), + ( + b"r", + b"rev", + b"", + _(b"search the repository as it is in REV"), + _(b"REV"), + ), + ( + b"0", + b"print0", + None, + _(b"end filenames with NUL, for use with xargs"), + ), ] + walkopts + formatteropts + subrepoopts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, intents={INTENT_READONLY}, ) @@ -2673,31 +2730,31 @@ """ opts = pycompat.byteskwargs(opts) - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev, None) - end = "\n" - if opts.get("print0"): - end = "\0" - fmt = "%s" + end + end = b"\n" + if opts.get(b"print0"): + end = b"\0" + fmt = b"%s" + end m = scmutil.match(ctx, pats, opts) - ui.pager("files") + ui.pager(b"files") uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True) - with ui.formatter("files", opts) as fm: + with ui.formatter(b"files", opts) as fm: return cmdutil.files( - ui, ctx, m, uipathfn, fm, fmt, opts.get("subrepos") + ui, ctx, m, uipathfn, fm, fmt, opts.get(b"subrepos") ) @command( - "forget", - [("i", "interactive", None, _("use interactive mode")),] + b"forget", + [(b"i", b"interactive", None, _(b"use interactive mode")),] + walkopts + dryrunopts, - _("[OPTION]... FILE..."), + _(b"[OPTION]... FILE..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, inferrepo=True, @@ -2733,16 +2790,16 @@ opts = pycompat.byteskwargs(opts) if not pats: - raise error.Abort(_("no files specified")) + raise error.Abort(_(b"no files specified")) m = scmutil.match(repo[None], pats, opts) - dryrun, interactive = opts.get("dry_run"), opts.get("interactive") + dryrun, interactive = opts.get(b"dry_run"), opts.get(b"interactive") uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) rejected = cmdutil.forget( ui, repo, m, - prefix="", + prefix=b"", uipathfn=uipathfn, explicitonly=False, dryrun=dryrun, @@ -2752,40 +2809,45 @@ @command( - "graft", + b"graft", [ - ("r", "rev", [], _("revisions to graft"), _("REV")), + (b"r", b"rev", [], _(b"revisions to graft"), _(b"REV")), ( - "", - "base", - "", - _("base revision when doing the graft merge (ADVANCED)"), - _("REV"), + b"", + b"base", + b"", + _(b"base revision when doing the graft merge (ADVANCED)"), + _(b"REV"), ), - ("c", "continue", False, _("resume interrupted graft")), - ("", "stop", False, _("stop interrupted graft")), - ("", "abort", False, _("abort interrupted graft")), - ("e", "edit", False, _("invoke editor on commit messages")), - ("", "log", None, _("append graft info to log message")), + (b"c", b"continue", False, _(b"resume interrupted graft")), + (b"", b"stop", False, _(b"stop interrupted graft")), + (b"", b"abort", False, _(b"abort interrupted graft")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), + (b"", b"log", None, _(b"append graft info to log message")), ( - "", - "no-commit", + b"", + b"no-commit", None, - _("don't commit, just apply the changes in working directory"), + _(b"don't commit, just apply the changes in working directory"), ), - ("f", "force", False, _("force graft")), + (b"f", b"force", False, _(b"force graft")), ( - "D", - "currentdate", + b"D", + b"currentdate", False, - _("record the current date as commit date"), + _(b"record the current date as commit date"), ), - ("U", "currentuser", False, _("record the current user as committer")), + ( + b"U", + b"currentuser", + False, + _(b"record the current user as committer"), + ), ] + commitopts2 + mergetoolopts + dryrunopts, - _("[OPTION]... [-r REV]... REV..."), + _(b"[OPTION]... [-r REV]... REV..."), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def graft(ui, repo, *revs, **opts): @@ -2889,120 +2951,122 @@ def _dograft(ui, repo, *revs, **opts): opts = pycompat.byteskwargs(opts) - if revs and opts.get("rev"): + if revs and opts.get(b"rev"): ui.warn( _( - "warning: inconsistent use of --rev might give unexpected " - "revision ordering!\n" + b"warning: inconsistent use of --rev might give unexpected " + b"revision ordering!\n" ) ) revs = list(revs) - revs.extend(opts.get("rev")) + revs.extend(opts.get(b"rev")) basectx = None - if opts.get("base"): - basectx = scmutil.revsingle(repo, opts["base"], None) + if opts.get(b"base"): + basectx = scmutil.revsingle(repo, opts[b"base"], None) # a dict of data to be stored in state file statedata = {} # list of new nodes created by ongoing graft - statedata["newnodes"] = [] - - if opts.get("user") and opts.get("currentuser"): - raise error.Abort(_("--user and --currentuser are mutually exclusive")) - if opts.get("date") and opts.get("currentdate"): - raise error.Abort(_("--date and --currentdate are mutually exclusive")) - if not opts.get("user") and opts.get("currentuser"): - opts["user"] = ui.username() - if not opts.get("date") and opts.get("currentdate"): - opts["date"] = "%d %d" % dateutil.makedate() + statedata[b"newnodes"] = [] + + if opts.get(b"user") and opts.get(b"currentuser"): + raise error.Abort(_(b"--user and --currentuser are mutually exclusive")) + if opts.get(b"date") and opts.get(b"currentdate"): + raise error.Abort(_(b"--date and --currentdate are mutually exclusive")) + if not opts.get(b"user") and opts.get(b"currentuser"): + opts[b"user"] = ui.username() + if not opts.get(b"date") and opts.get(b"currentdate"): + opts[b"date"] = b"%d %d" % dateutil.makedate() editor = cmdutil.getcommiteditor( - editform="graft", **pycompat.strkwargs(opts) + editform=b"graft", **pycompat.strkwargs(opts) ) cont = False - if opts.get("no_commit"): - if opts.get("edit"): + if opts.get(b"no_commit"): + if opts.get(b"edit"): raise error.Abort( - _("cannot specify --no-commit and " "--edit together") + _(b"cannot specify --no-commit and " b"--edit together") ) - if opts.get("currentuser"): + if opts.get(b"currentuser"): raise error.Abort( - _("cannot specify --no-commit and " "--currentuser together") + _(b"cannot specify --no-commit and " b"--currentuser together") ) - if opts.get("currentdate"): + if opts.get(b"currentdate"): raise error.Abort( - _("cannot specify --no-commit and " "--currentdate together") + _(b"cannot specify --no-commit and " b"--currentdate together") ) - if opts.get("log"): + if opts.get(b"log"): raise error.Abort( - _("cannot specify --no-commit and " "--log together") + _(b"cannot specify --no-commit and " b"--log together") ) - graftstate = statemod.cmdstate(repo, "graftstate") - - if opts.get("stop"): - if opts.get("continue"): + graftstate = statemod.cmdstate(repo, b"graftstate") + + if opts.get(b"stop"): + if opts.get(b"continue"): raise error.Abort( - _("cannot use '--continue' and " "'--stop' together") + _(b"cannot use '--continue' and " b"'--stop' together") ) - if opts.get("abort"): - raise error.Abort(_("cannot use '--abort' and '--stop' together")) + if opts.get(b"abort"): + raise error.Abort(_(b"cannot use '--abort' and '--stop' together")) if any( ( - opts.get("edit"), - opts.get("log"), - opts.get("user"), - opts.get("date"), - opts.get("currentdate"), - opts.get("currentuser"), - opts.get("rev"), + opts.get(b"edit"), + opts.get(b"log"), + opts.get(b"user"), + opts.get(b"date"), + opts.get(b"currentdate"), + opts.get(b"currentuser"), + opts.get(b"rev"), ) ): - raise error.Abort(_("cannot specify any other flag with '--stop'")) + raise error.Abort(_(b"cannot specify any other flag with '--stop'")) return _stopgraft(ui, repo, graftstate) - elif opts.get("abort"): - if opts.get("continue"): + elif opts.get(b"abort"): + if opts.get(b"continue"): raise error.Abort( - _("cannot use '--continue' and " "'--abort' together") + _(b"cannot use '--continue' and " b"'--abort' together") ) if any( ( - opts.get("edit"), - opts.get("log"), - opts.get("user"), - opts.get("date"), - opts.get("currentdate"), - opts.get("currentuser"), - opts.get("rev"), + opts.get(b"edit"), + opts.get(b"log"), + opts.get(b"user"), + opts.get(b"date"), + opts.get(b"currentdate"), + opts.get(b"currentuser"), + opts.get(b"rev"), ) ): - raise error.Abort(_("cannot specify any other flag with '--abort'")) + raise error.Abort( + _(b"cannot specify any other flag with '--abort'") + ) return cmdutil.abortgraft(ui, repo, graftstate) - elif opts.get("continue"): + elif opts.get(b"continue"): cont = True if revs: - raise error.Abort(_("can't specify --continue and revisions")) + raise error.Abort(_(b"can't specify --continue and revisions")) # read in unfinished revisions if graftstate.exists(): statedata = cmdutil.readgraftstate(repo, graftstate) - if statedata.get("date"): - opts["date"] = statedata["date"] - if statedata.get("user"): - opts["user"] = statedata["user"] - if statedata.get("log"): - opts["log"] = True - if statedata.get("no_commit"): - opts["no_commit"] = statedata.get("no_commit") - nodes = statedata["nodes"] + if statedata.get(b"date"): + opts[b"date"] = statedata[b"date"] + if statedata.get(b"user"): + opts[b"user"] = statedata[b"user"] + if statedata.get(b"log"): + opts[b"log"] = True + if statedata.get(b"no_commit"): + opts[b"no_commit"] = statedata.get(b"no_commit") + nodes = statedata[b"nodes"] revs = [repo[node].rev() for node in nodes] else: - cmdutil.wrongtooltocontinue(repo, _("graft")) + cmdutil.wrongtooltocontinue(repo, _(b"graft")) else: if not revs: - raise error.Abort(_("no revisions specified")) + raise error.Abort(_(b"no revisions specified")) cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) revs = scmutil.revrange(repo, revs) @@ -3010,14 +3074,14 @@ skipped = set() if basectx is None: # check for merges - for rev in repo.revs("%ld and merge()", revs): - ui.warn(_("skipping ungraftable merge revision %d\n") % rev) + for rev in repo.revs(b"%ld and merge()", revs): + ui.warn(_(b"skipping ungraftable merge revision %d\n") % rev) skipped.add(rev) revs = [r for r in revs if r not in skipped] if not revs: return -1 if basectx is not None and len(revs) != 1: - raise error.Abort(_("only one revision allowed with --base ")) + raise error.Abort(_(b"only one revision allowed with --base ")) # Don't check in the --continue case, in effect retaining --force across # --continues. That's because without --force, any revisions we decided to @@ -3025,16 +3089,16 @@ # way to the graftstate. With --force, any revisions we would have otherwise # skipped would not have been filtered out, and if they hadn't been applied # already, they'd have been in the graftstate. - if not (cont or opts.get("force")) and basectx is None: + if not (cont or opts.get(b"force")) and basectx is None: # check for ancestors of dest branch - crev = repo["."].rev() + crev = repo[b"."].rev() ancestors = repo.changelog.ancestors([crev], inclusive=True) # XXX make this lazy in the future # don't mutate while iterating, create a copy for rev in list(revs): if rev in ancestors: ui.warn( - _("skipping ancestor revision %d:%s\n") % (rev, repo[rev]) + _(b"skipping ancestor revision %d:%s\n") % (rev, repo[rev]) ) # XXX remove on list is slow revs.remove(rev) @@ -3043,20 +3107,20 @@ # analyze revs for earlier grafts ids = {} - for ctx in repo.set("%ld", revs): + for ctx in repo.set(b"%ld", revs): ids[ctx.hex()] = ctx.rev() - n = ctx.extra().get("source") + n = ctx.extra().get(b"source") if n: ids[n] = ctx.rev() # check ancestors for earlier grafts - ui.debug("scanning for duplicate grafts\n") + ui.debug(b"scanning for duplicate grafts\n") # The only changesets we can be sure doesn't contain grafts of any # revs, are the ones that are common ancestors of *all* revs: - for rev in repo.revs("only(%d,ancestor(%ld))", crev, revs): + for rev in repo.revs(b"only(%d,ancestor(%ld))", crev, revs): ctx = repo[rev] - n = ctx.extra().get("source") + n = ctx.extra().get(b"source") if n in ids: try: r = repo[n].rev() @@ -3065,8 +3129,8 @@ if r in revs: ui.warn( _( - "skipping revision %d:%s " - "(already grafted to %d:%s)\n" + b"skipping revision %d:%s " + b"(already grafted to %d:%s)\n" ) % (r, repo[r], rev, ctx) ) @@ -3075,16 +3139,16 @@ if r is None: ui.warn( _( - "skipping already grafted revision %d:%s " - "(%d:%s also has unknown origin %s)\n" + b"skipping already grafted revision %d:%s " + b"(%d:%s also has unknown origin %s)\n" ) % (ids[n], repo[ids[n]], rev, ctx, n[:12]) ) else: ui.warn( _( - "skipping already grafted revision %d:%s " - "(%d:%s also has origin %d:%s)\n" + b"skipping already grafted revision %d:%s " + b"(%d:%s also has origin %d:%s)\n" ) % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]) ) @@ -3094,8 +3158,8 @@ if r in revs: ui.warn( _( - "skipping already grafted revision %d:%s " - "(was grafted from %d:%s)\n" + b"skipping already grafted revision %d:%s " + b"(was grafted from %d:%s)\n" ) % (r, repo[r], rev, ctx) ) @@ -3103,78 +3167,78 @@ if not revs: return -1 - if opts.get("no_commit"): - statedata["no_commit"] = True - for pos, ctx in enumerate(repo.set("%ld", revs)): - desc = '%d:%s "%s"' % ( + if opts.get(b"no_commit"): + statedata[b"no_commit"] = True + for pos, ctx in enumerate(repo.set(b"%ld", revs)): + desc = b'%d:%s "%s"' % ( ctx.rev(), ctx, - ctx.description().split("\n", 1)[0], + ctx.description().split(b"\n", 1)[0], ) names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) if names: - desc += " (%s)" % " ".join(names) - ui.status(_("grafting %s\n") % desc) - if opts.get("dry_run"): + desc += b" (%s)" % b" ".join(names) + ui.status(_(b"grafting %s\n") % desc) + if opts.get(b"dry_run"): continue - source = ctx.extra().get("source") + source = ctx.extra().get(b"source") extra = {} if source: - extra["source"] = source - extra["intermediate-source"] = ctx.hex() + extra[b"source"] = source + extra[b"intermediate-source"] = ctx.hex() else: - extra["source"] = ctx.hex() + extra[b"source"] = ctx.hex() user = ctx.user() - if opts.get("user"): - user = opts["user"] - statedata["user"] = user + if opts.get(b"user"): + user = opts[b"user"] + statedata[b"user"] = user date = ctx.date() - if opts.get("date"): - date = opts["date"] - statedata["date"] = date + if opts.get(b"date"): + date = opts[b"date"] + statedata[b"date"] = date message = ctx.description() - if opts.get("log"): - message += "\n(grafted from %s)" % ctx.hex() - statedata["log"] = True + if opts.get(b"log"): + message += b"\n(grafted from %s)" % ctx.hex() + statedata[b"log"] = True # we don't merge the first commit when continuing if not cont: # perform the graft merge with p1(rev) as 'ancestor' - overrides = {("ui", "forcemerge"): opts.get("tool", "")} + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} base = ctx.p1() if basectx is None else basectx - with ui.configoverride(overrides, "graft"): - stats = mergemod.graft(repo, ctx, base, ["local", "graft"]) + with ui.configoverride(overrides, b"graft"): + stats = mergemod.graft(repo, ctx, base, [b"local", b"graft"]) # report any conflicts if stats.unresolvedcount > 0: # write out state for --continue nodes = [repo[rev].hex() for rev in revs[pos:]] - statedata["nodes"] = nodes + statedata[b"nodes"] = nodes stateversion = 1 graftstate.save(stateversion, statedata) - hint = _("use 'hg resolve' and 'hg graft --continue'") + hint = _(b"use 'hg resolve' and 'hg graft --continue'") raise error.Abort( - _("unresolved conflicts, can't continue"), hint=hint + _(b"unresolved conflicts, can't continue"), hint=hint ) else: cont = False # commit if --no-commit is false - if not opts.get("no_commit"): + if not opts.get(b"no_commit"): node = repo.commit( text=message, user=user, date=date, extra=extra, editor=editor ) if node is None: ui.warn( - _("note: graft of %d:%s created no changes to commit\n") + _(b"note: graft of %d:%s created no changes to commit\n") % (ctx.rev(), ctx) ) # checking that newnodes exist because old state files won't have it - elif statedata.get("newnodes") is not None: - statedata["newnodes"].append(node) + elif statedata.get(b"newnodes") is not None: + statedata[b"newnodes"].append(node) # remove state when we complete successfully - if not opts.get("dry_run"): + if not opts.get(b"dry_run"): graftstate.delete() return 0 @@ -3183,76 +3247,79 @@ def _stopgraft(ui, repo, graftstate): """stop the interrupted graft""" if not graftstate.exists(): - raise error.Abort(_("no interrupted graft found")) - pctx = repo["."] + raise error.Abort(_(b"no interrupted graft found")) + pctx = repo[b"."] hg.updaterepo(repo, pctx.node(), overwrite=True) graftstate.delete() - ui.status(_("stopped the interrupted graft\n")) - ui.status(_("working directory is now at %s\n") % pctx.hex()[:12]) + ui.status(_(b"stopped the interrupted graft\n")) + ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12]) return 0 statemod.addunfinished( - "graft", - fname="graftstate", + b"graft", + fname=b"graftstate", clearable=True, stopflag=True, continueflag=True, abortfunc=cmdutil.hgabortgraft, - cmdhint=_("use 'hg graft --continue' or 'hg graft --stop' to stop"), + cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"), ) @command( - "grep", + b"grep", [ - ("0", "print0", None, _("end fields with NUL")), - ("", "all", None, _("print all revisions that match (DEPRECATED) ")), + (b"0", b"print0", None, _(b"end fields with NUL")), + (b"", b"all", None, _(b"print all revisions that match (DEPRECATED) ")), ( - "", - "diff", - None, - _("print all revisions when the term was introduced " "or removed"), - ), - ("a", "text", None, _("treat all files as text")), - ( - "f", - "follow", + b"", + b"diff", None, _( - "follow changeset history," - " or file history across copies and renames" + b"print all revisions when the term was introduced " + b"or removed" + ), + ), + (b"a", b"text", None, _(b"treat all files as text")), + ( + b"f", + b"follow", + None, + _( + b"follow changeset history," + b" or file history across copies and renames" ), ), - ("i", "ignore-case", None, _("ignore case when matching")), + (b"i", b"ignore-case", None, _(b"ignore case when matching")), ( - "l", - "files-with-matches", + b"l", + b"files-with-matches", None, - _("print only filenames and revisions that match"), + _(b"print only filenames and revisions that match"), ), - ("n", "line-number", None, _("print matching line numbers")), + (b"n", b"line-number", None, _(b"print matching line numbers")), ( - "r", - "rev", + b"r", + b"rev", [], - _("only search files changed within revision range"), - _("REV"), + _(b"only search files changed within revision range"), + _(b"REV"), ), ( - "", - "all-files", + b"", + b"all-files", None, _( - "include all files in the changeset while grepping (EXPERIMENTAL)" + b"include all files in the changeset while grepping (EXPERIMENTAL)" ), ), - ("u", "user", None, _("list the author (long with -v)")), - ("d", "date", None, _("list the date (short with -q)")), + (b"u", b"user", None, _(b"list the author (long with -v)")), + (b"d", b"date", None, _(b"list the date (short with -q)")), ] + formatteropts + walkopts, - _("[OPTION]... PATTERN [FILE]..."), + _(b"[OPTION]... PATTERN [FILE]..."), helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, intents={INTENT_READONLY}, @@ -3299,29 +3366,31 @@ Returns 0 if a match is found, 1 otherwise. """ opts = pycompat.byteskwargs(opts) - diff = opts.get("all") or opts.get("diff") - all_files = opts.get("all_files") - if diff and opts.get("all_files"): - raise error.Abort(_("--diff and --all-files are mutually exclusive")) + diff = opts.get(b"all") or opts.get(b"diff") + all_files = opts.get(b"all_files") + if diff and opts.get(b"all_files"): + raise error.Abort(_(b"--diff and --all-files are mutually exclusive")) # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working - if opts.get("all_files") is None and not opts.get("rev") and not diff: + if opts.get(b"all_files") is None and not opts.get(b"rev") and not diff: # experimental config: commands.grep.all-files - opts["all_files"] = ui.configbool("commands", "grep.all-files") - plaingrep = opts.get("all_files") and not opts.get("rev") + opts[b"all_files"] = ui.configbool(b"commands", b"grep.all-files") + plaingrep = opts.get(b"all_files") and not opts.get(b"rev") if plaingrep: - opts["rev"] = ["wdir()"] + opts[b"rev"] = [b"wdir()"] reflags = re.M - if opts.get("ignore_case"): + if opts.get(b"ignore_case"): reflags |= re.I try: regexp = util.re.compile(pattern, reflags) except re.error as inst: - ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)) + ui.warn( + _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst) + ) return 1 - sep, eol = ":", "\n" - if opts.get("print0"): - sep = eol = "\0" + sep, eol = b":", b"\n" + if opts.get(b"print0"): + sep = eol = b"\0" getfile = util.lrucachefunc(repo.file) @@ -3333,9 +3402,9 @@ if not match: break mstart, mend = match.span() - linenum += body.count("\n", begin, mstart) + 1 - lstart = body.rfind("\n", begin, mstart) + 1 or begin - begin = body.find("\n", mend) + 1 or len(body) + 1 + linenum += body.count(b"\n", begin, mstart) + 1 + lstart = body.rfind(b"\n", begin, mstart) + 1 or begin + begin = body.find(b"\n", mend) + 1 or len(body) + 1 lend = begin - 1 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend] @@ -3378,15 +3447,15 @@ for tag, alo, ahi, blo, bhi in sm.get_opcodes(): if tag == r"insert": for i in pycompat.xrange(blo, bhi): - yield ("+", b[i]) + yield (b"+", b[i]) elif tag == r"delete": for i in pycompat.xrange(alo, ahi): - yield ("-", a[i]) + yield (b"-", a[i]) elif tag == r"replace": for i in pycompat.xrange(alo, ahi): - yield ("-", a[i]) + yield (b"-", a[i]) for i in pycompat.xrange(blo, bhi): - yield ("+", b[i]) + yield (b"+", b[i]) uipathfn = scmutil.getuipathfn(repo) @@ -3397,9 +3466,9 @@ else: formatuser = pycompat.bytestr if ui.quiet: - datefmt = "%Y-%m-%d" + datefmt = b"%Y-%m-%d" else: - datefmt = "%a %b %d %H:%M:%S %Y %1%2" + datefmt = b"%a %b %d %H:%M:%S %Y %1%2" found = False @util.cachefunc @@ -3410,64 +3479,72 @@ except error.WdirUnsupported: return ctx[fn].isbinary() - fieldnamemap = {"linenumber": "lineno"} + fieldnamemap = {b"linenumber": b"lineno"} if diff: iter = difflinestates(pstates, states) else: - iter = [("", l) for l in states] + iter = [(b"", l) for l in states] for change, l in iter: fm.startitem() fm.context(ctx=ctx) fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn) - fm.plain(uipathfn(fn), label="grep.filename") + fm.plain(uipathfn(fn), label=b"grep.filename") cols = [ - ("rev", "%d", rev, not plaingrep, ""), - ("linenumber", "%d", l.linenum, opts.get("line_number"), ""), + (b"rev", b"%d", rev, not plaingrep, b""), + ( + b"linenumber", + b"%d", + l.linenum, + opts.get(b"line_number"), + b"", + ), ] if diff: cols.append( ( - "change", - "%s", + b"change", + b"%s", change, True, - "grep.inserted " if change == "+" else "grep.deleted ", + b"grep.inserted " + if change == b"+" + else b"grep.deleted ", ) ) cols.extend( [ ( - "user", - "%s", + b"user", + b"%s", formatuser(ctx.user()), - opts.get("user"), - "", + opts.get(b"user"), + b"", ), ( - "date", - "%s", + b"date", + b"%s", fm.formatdate(ctx.date(), datefmt), - opts.get("date"), - "", + opts.get(b"date"), + b"", ), ] ) for name, fmt, data, cond, extra_label in cols: if cond: - fm.plain(sep, label="grep.sep") + fm.plain(sep, label=b"grep.sep") field = fieldnamemap.get(name, name) - label = extra_label + ("grep.%s" % name) + label = extra_label + (b"grep.%s" % name) fm.condwrite(cond, field, fmt, data, label=label) - if not opts.get("files_with_matches"): - fm.plain(sep, label="grep.sep") - if not opts.get("text") and binary(): - fm.plain(_(" Binary file matches")) + if not opts.get(b"files_with_matches"): + fm.plain(sep, label=b"grep.sep") + if not opts.get(b"text") and binary(): + fm.plain(_(b" Binary file matches")) else: - displaymatches(fm.nested("texts", tmpl="{text}"), l) + displaymatches(fm.nested(b"texts", tmpl=b"{text}"), l) fm.plain(eol) found = True - if opts.get("files_with_matches"): + if opts.get(b"files_with_matches"): break return found @@ -3476,15 +3553,15 @@ for s, e in l.findpos(): if p < s: fm.startitem() - fm.write("text", "%s", l.line[p:s]) + fm.write(b"text", b"%s", l.line[p:s]) fm.data(matched=False) fm.startitem() - fm.write("text", "%s", l.line[s:e], label="grep.match") + fm.write(b"text", b"%s", l.line[s:e], label=b"grep.match") fm.data(matched=True) p = e if p < len(l.line): fm.startitem() - fm.write("text", "%s", l.line[p:]) + fm.write(b"text", b"%s", l.line[p:]) fm.data(matched=False) fm.end() @@ -3492,7 +3569,7 @@ revfiles = {} match = scmutil.match(repo[None], pats, opts) found = False - follow = opts.get("follow") + follow = opts.get(b"follow") getrenamed = scmutil.getrenamedfn(repo) @@ -3536,8 +3613,8 @@ except error.LookupError: pass - ui.pager("grep") - fm = ui.formatter("grep", opts) + ui.pager(b"grep") + fm = ui.formatter(b"grep", opts) for ctx in cmdutil.walkchangerevs(repo, match, opts, prep): rev = ctx.rev() parent = ctx.p1().rev() @@ -3567,21 +3644,26 @@ @command( - "heads", + b"heads", [ ( - "r", - "rev", - "", - _("show only heads which are descendants of STARTREV"), - _("STARTREV"), + b"r", + b"rev", + b"", + _(b"show only heads which are descendants of STARTREV"), + _(b"STARTREV"), ), - ("t", "topo", False, _("show topological heads only")), - ("a", "active", False, _("show active branchheads only (DEPRECATED)")), - ("c", "closed", False, _("show normal and closed branch heads")), + (b"t", b"topo", False, _(b"show topological heads only")), + ( + b"a", + b"active", + False, + _(b"show active branchheads only (DEPRECATED)"), + ), + (b"c", b"closed", False, _(b"show normal and closed branch heads")), ] + templateopts, - _("[-ct] [-r STARTREV] [REV]..."), + _(b"[-ct] [-r STARTREV] [REV]..."), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, intents={INTENT_READONLY}, ) @@ -3612,17 +3694,17 @@ opts = pycompat.byteskwargs(opts) start = None - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") start = scmutil.revsingle(repo, rev, None).node() - if opts.get("topo"): + if opts.get(b"topo"): heads = [repo[h] for h in repo.heads(start)] else: heads = [] for branch in repo.branchmap(): - heads += repo.branchheads(branch, start, opts.get("closed")) + heads += repo.branchheads(branch, start, opts.get(b"closed")) heads = [repo[h] for h in heads] if branchrevs: @@ -3631,23 +3713,23 @@ ) heads = [h for h in heads if h.branch() in branches] - if opts.get("active") and branchrevs: + if opts.get(b"active") and branchrevs: dagheads = repo.heads(start) heads = [h for h in heads if h.node() in dagheads] if branchrevs: haveheads = set(h.branch() for h in heads) if branches - haveheads: - headless = ", ".join(b for b in branches - haveheads) - msg = _("no open branch heads found on branches %s") - if opts.get("rev"): - msg += _(" (started at %s)") % opts["rev"] - ui.warn((msg + "\n") % headless) + headless = b", ".join(b for b in branches - haveheads) + msg = _(b"no open branch heads found on branches %s") + if opts.get(b"rev"): + msg += _(b" (started at %s)") % opts[b"rev"] + ui.warn((msg + b"\n") % headless) if not heads: return 1 - ui.pager("heads") + ui.pager(b"heads") heads = sorted(heads, key=lambda x: -(x.rev())) displayer = logcmdutil.changesetdisplayer(ui, repo, opts) for ctx in heads: @@ -3656,20 +3738,20 @@ @command( - "help", + b"help", [ - ("e", "extension", None, _("show only help for extensions")), - ("c", "command", None, _("show only help for commands")), - ("k", "keyword", None, _("show topics matching keyword")), + (b"e", b"extension", None, _(b"show only help for extensions")), + (b"c", b"command", None, _(b"show only help for commands")), + (b"k", b"keyword", None, _(b"show topics matching keyword")), ( - "s", - "system", + b"s", + b"system", [], - _("show help for specific platform(s)"), - _("PLATFORM"), + _(b"show help for specific platform(s)"), + _(b"PLATFORM"), ), ], - _("[-eck] [-s PLATFORM] [TOPIC]"), + _(b"[-eck] [-s PLATFORM] [TOPIC]"), helpcategory=command.CATEGORY_HELP, norepo=True, intents={INTENT_READONLY}, @@ -3687,37 +3769,37 @@ keep = opts.get(r"system") or [] if len(keep) == 0: - if pycompat.sysplatform.startswith("win"): - keep.append("windows") - elif pycompat.sysplatform == "OpenVMS": - keep.append("vms") - elif pycompat.sysplatform == "plan9": - keep.append("plan9") + if pycompat.sysplatform.startswith(b"win"): + keep.append(b"windows") + elif pycompat.sysplatform == b"OpenVMS": + keep.append(b"vms") + elif pycompat.sysplatform == b"plan9": + keep.append(b"plan9") else: - keep.append("unix") + keep.append(b"unix") keep.append(pycompat.sysplatform.lower()) if ui.verbose: - keep.append("verbose") + keep.append(b"verbose") commands = sys.modules[__name__] formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts) - ui.pager("help") + ui.pager(b"help") ui.write(formatted) @command( - "identify|id", + b"identify|id", [ - ("r", "rev", "", _("identify the specified revision"), _("REV")), - ("n", "num", None, _("show local revision number")), - ("i", "id", None, _("show global revision id")), - ("b", "branch", None, _("show branch")), - ("t", "tags", None, _("show tags")), - ("B", "bookmarks", None, _("show bookmarks")), + (b"r", b"rev", b"", _(b"identify the specified revision"), _(b"REV")), + (b"n", b"num", None, _(b"show local revision number")), + (b"i", b"id", None, _(b"show global revision id")), + (b"b", b"branch", None, _(b"show branch")), + (b"t", b"tags", None, _(b"show tags")), + (b"B", b"bookmarks", None, _(b"show bookmarks")), ] + remoteopts + formatteropts, - _("[-nibtB] [-r REV] [SOURCE]"), + _(b"[-nibtB] [-r REV] [SOURCE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, optionalrepo=True, intents={INTENT_READONLY}, @@ -3783,7 +3865,7 @@ opts = pycompat.byteskwargs(opts) if not repo and not source: raise error.Abort( - _("there is no Mercurial repository here " "(.hg not found)") + _(b"there is no Mercurial repository here " b"(.hg not found)") ) default = not (num or id or branch or tags or bookmarks) @@ -3796,18 +3878,18 @@ repo = peer.local() revs, checkout = hg.addbranchrevs(repo, peer, branches, None) - fm = ui.formatter("identify", opts) + fm = ui.formatter(b"identify", opts) fm.startitem() if not repo: if num or branch or tags: raise error.Abort( - _("can't query remote revision number, branch, or tags") + _(b"can't query remote revision number, branch, or tags") ) if not rev and revs: rev = revs[0] if not rev: - rev = "tip" + rev = b"tip" remoterev = peer.lookup(rev) hexrev = fm.hexfunc(remoterev) @@ -3819,11 +3901,11 @@ def getbms(): bms = [] - if "bookmarks" in peer.listkeys("namespaces"): + if b"bookmarks" in peer.listkeys(b"namespaces"): hexremoterev = hex(remoterev) bms = [ bm - for bm, bmr in peer.listkeys("bookmarks").iteritems() + for bm, bmr in peer.listkeys(b"bookmarks").iteritems() if bmr == hexremoterev ] @@ -3834,16 +3916,16 @@ output.extend(getbms()) elif default and not ui.quiet: # multiple bookmarks for a single parent separated by '/' - bm = "/".join(getbms()) + bm = b"/".join(getbms()) if bm: output.append(bm) else: fm.data(node=hex(remoterev)) - if bookmarks or "bookmarks" in fm.datahint(): - fm.data(bookmarks=fm.formatlist(getbms(), name="bookmark")) + if bookmarks or b"bookmarks" in fm.datahint(): + fm.data(bookmarks=fm.formatlist(getbms(), name=b"bookmark")) else: if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev, None) if ctx.rev() is None: @@ -3853,23 +3935,23 @@ for p in parents: taglist.extend(p.tags()) - dirty = "" + dirty = b"" if ctx.dirty(missing=True, merge=False, branch=False): - dirty = "+" + dirty = b"+" fm.data(dirty=dirty) hexoutput = [fm.hexfunc(p.node()) for p in parents] if default or id: - output = ["%s%s" % ("+".join(hexoutput), dirty)] - fm.data(id="%s%s" % ("+".join(hexoutput), dirty)) + output = [b"%s%s" % (b"+".join(hexoutput), dirty)] + fm.data(id=b"%s%s" % (b"+".join(hexoutput), dirty)) if num: - numoutput = ["%d" % p.rev() for p in parents] - output.append("%s%s" % ("+".join(numoutput), dirty)) + numoutput = [b"%d" % p.rev() for p in parents] + output.append(b"%s%s" % (b"+".join(numoutput), dirty)) fm.data( parents=fm.formatlist( - [fm.hexfunc(p.node()) for p in parents], name="node" + [fm.hexfunc(p.node()) for p in parents], name=b"node" ) ) else: @@ -3884,16 +3966,16 @@ if default and not ui.quiet: b = ctx.branch() - if b != "default": - output.append("(%s)" % b) + if b != b"default": + output.append(b"(%s)" % b) # multiple tags for a single parent separated by '/' - t = "/".join(taglist) + t = b"/".join(taglist) if t: output.append(t) # multiple bookmarks for a single parent separated by '/' - bm = "/".join(ctx.bookmarks()) + bm = b"/".join(ctx.bookmarks()) if bm: output.append(bm) else: @@ -3908,61 +3990,61 @@ fm.data(node=ctx.hex()) fm.data(branch=ctx.branch()) - fm.data(tags=fm.formatlist(taglist, name="tag", sep=":")) - fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name="bookmark")) + fm.data(tags=fm.formatlist(taglist, name=b"tag", sep=b":")) + fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b"bookmark")) fm.context(ctx=ctx) - fm.plain("%s\n" % " ".join(output)) + fm.plain(b"%s\n" % b" ".join(output)) fm.end() @command( - "import|patch", + b"import|patch", [ ( - "p", - "strip", + b"p", + b"strip", 1, _( - "directory strip option for patch. This has the same " - "meaning as the corresponding patch option" + b"directory strip option for patch. This has the same " + b"meaning as the corresponding patch option" ), - _("NUM"), + _(b"NUM"), ), - ("b", "base", "", _("base path (DEPRECATED)"), _("PATH")), - ("e", "edit", False, _("invoke editor on commit messages")), + (b"b", b"base", b"", _(b"base path (DEPRECATED)"), _(b"PATH")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), ( - "f", - "force", + b"f", + b"force", None, - _("skip check for outstanding uncommitted changes (DEPRECATED)"), + _(b"skip check for outstanding uncommitted changes (DEPRECATED)"), ), ( - "", - "no-commit", + b"", + b"no-commit", None, - _("don't commit, just update the working directory"), + _(b"don't commit, just update the working directory"), ), ( - "", - "bypass", + b"", + b"bypass", None, - _("apply patch without touching the working directory"), + _(b"apply patch without touching the working directory"), ), - ("", "partial", None, _("commit even if some hunks fail")), - ("", "exact", None, _("abort if patch would apply lossily")), - ("", "prefix", "", _("apply patch to subdirectory"), _("DIR")), + (b"", b"partial", None, _(b"commit even if some hunks fail")), + (b"", b"exact", None, _(b"abort if patch would apply lossily")), + (b"", b"prefix", b"", _(b"apply patch to subdirectory"), _(b"DIR")), ( - "", - "import-branch", + b"", + b"import-branch", None, - _("use any branch information in patch (implied by --exact)"), + _(b"use any branch information in patch (implied by --exact)"), ), ] + commitopts + commitopts2 + similarityopts, - _("[OPTION]... PATCH..."), + _(b"[OPTION]... PATCH..."), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def import_(ui, repo, patch1=None, *patches, **opts): @@ -4066,60 +4148,60 @@ opts = pycompat.byteskwargs(opts) if not patch1: - raise error.Abort(_("need at least one patch to import")) + raise error.Abort(_(b"need at least one patch to import")) patches = (patch1,) + patches - date = opts.get("date") + date = opts.get(b"date") if date: - opts["date"] = dateutil.parsedate(date) - - exact = opts.get("exact") - update = not opts.get("bypass") - if not update and opts.get("no_commit"): - raise error.Abort(_("cannot use --no-commit with --bypass")) + opts[b"date"] = dateutil.parsedate(date) + + exact = opts.get(b"exact") + update = not opts.get(b"bypass") + if not update and opts.get(b"no_commit"): + raise error.Abort(_(b"cannot use --no-commit with --bypass")) try: - sim = float(opts.get("similarity") or 0) + sim = float(opts.get(b"similarity") or 0) except ValueError: - raise error.Abort(_("similarity must be a number")) + raise error.Abort(_(b"similarity must be a number")) if sim < 0 or sim > 100: - raise error.Abort(_("similarity must be between 0 and 100")) + raise error.Abort(_(b"similarity must be between 0 and 100")) if sim and not update: - raise error.Abort(_("cannot use --similarity with --bypass")) + raise error.Abort(_(b"cannot use --similarity with --bypass")) if exact: - if opts.get("edit"): - raise error.Abort(_("cannot use --exact with --edit")) - if opts.get("prefix"): - raise error.Abort(_("cannot use --exact with --prefix")) - - base = opts["base"] + if opts.get(b"edit"): + raise error.Abort(_(b"cannot use --exact with --edit")) + if opts.get(b"prefix"): + raise error.Abort(_(b"cannot use --exact with --prefix")) + + base = opts[b"base"] msgs = [] ret = 0 with repo.wlock(): if update: cmdutil.checkunfinished(repo) - if exact or not opts.get("force"): + if exact or not opts.get(b"force"): cmdutil.bailifchanged(repo) - if not opts.get("no_commit"): + if not opts.get(b"no_commit"): lock = repo.lock - tr = lambda: repo.transaction("import") + tr = lambda: repo.transaction(b"import") dsguard = util.nullcontextmanager else: lock = util.nullcontextmanager tr = util.nullcontextmanager - dsguard = lambda: dirstateguard.dirstateguard(repo, "import") + dsguard = lambda: dirstateguard.dirstateguard(repo, b"import") with lock(), tr(), dsguard(): parents = repo[None].parents() for patchurl in patches: - if patchurl == "-": - ui.status(_("applying patch from stdin\n")) + if patchurl == b"-": + ui.status(_(b"applying patch from stdin\n")) patchfile = ui.fin - patchurl = "stdin" # for error message + patchurl = b"stdin" # for error message else: patchurl = os.path.join(base, patchurl) - ui.status(_("applying %s\n") % patchurl) + ui.status(_(b"applying %s\n") % patchurl) patchfile = hg.openpath(ui, patchurl, sendaccept=False) haspatch = False @@ -4130,59 +4212,64 @@ ) if msg: haspatch = True - ui.note(msg + "\n") + ui.note(msg + b"\n") if update or exact: parents = repo[None].parents() else: parents = [repo[node]] if rej: - ui.write_err(_("patch applied partially\n")) + ui.write_err(_(b"patch applied partially\n")) ui.write_err( _( - "(fix the .rej files and run " - "`hg commit --amend`)\n" + b"(fix the .rej files and run " + b"`hg commit --amend`)\n" ) ) ret = 1 break if not haspatch: - raise error.Abort(_("%s: no diffs found") % patchurl) + raise error.Abort(_(b"%s: no diffs found") % patchurl) if msgs: - repo.savecommitmessage("\n* * *\n".join(msgs)) + repo.savecommitmessage(b"\n* * *\n".join(msgs)) return ret @command( - "incoming|in", + b"incoming|in", [ - ("f", "force", None, _("run even if remote repository is unrelated")), - ("n", "newest-first", None, _("show newest record first")), - ("", "bundle", "", _("file to store the bundles into"), _("FILE")), ( - "r", - "rev", + b"f", + b"force", + None, + _(b"run even if remote repository is unrelated"), + ), + (b"n", b"newest-first", None, _(b"show newest record first")), + (b"", b"bundle", b"", _(b"file to store the bundles into"), _(b"FILE")), + ( + b"r", + b"rev", [], - _("a remote changeset intended to be added"), - _("REV"), + _(b"a remote changeset intended to be added"), + _(b"REV"), ), - ("B", "bookmarks", False, _("compare bookmarks")), + (b"B", b"bookmarks", False, _(b"compare bookmarks")), ( - "b", - "branch", + b"b", + b"branch", [], - _("a specific branch you would like to pull"), - _("BRANCH"), + _(b"a specific branch you would like to pull"), + _(b"BRANCH"), ), ] + logopts + remoteopts + subrepoopts, - _("[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]"), + _(b"[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, ) -def incoming(ui, repo, source="default", **opts): +def incoming(ui, repo, source=b"default", **opts): """show new changesets found in source Show new changesets found in the specified path/URL or the default @@ -4237,7 +4324,7 @@ Returns 0 if there are incoming changes, 1 otherwise. """ opts = pycompat.byteskwargs(opts) - if opts.get("graph"): + if opts.get(b"graph"): logcmdutil.checkunsupportedgraphflags([], opts) def display(other, chlist, displayer): @@ -4249,19 +4336,19 @@ hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True) return 0 - if opts.get("bundle") and opts.get("subrepos"): - raise error.Abort(_("cannot combine --bundle and --subrepos")) - - if opts.get("bookmarks"): + if opts.get(b"bundle") and opts.get(b"subrepos"): + raise error.Abort(_(b"cannot combine --bundle and --subrepos")) + + if opts.get(b"bookmarks"): source, branches = hg.parseurl( - ui.expandpath(source), opts.get("branch") + ui.expandpath(source), opts.get(b"branch") ) other = hg.peer(repo, opts, source) - if "bookmarks" not in other.listkeys("namespaces"): - ui.warn(_("remote doesn't support bookmarks\n")) + if b"bookmarks" not in other.listkeys(b"namespaces"): + ui.warn(_(b"remote doesn't support bookmarks\n")) return 0 - ui.pager("incoming") - ui.status(_("comparing with %s\n") % util.hidepassword(source)) + ui.pager(b"incoming") + ui.status(_(b"comparing with %s\n") % util.hidepassword(source)) return bookmarks.incoming(ui, repo, other) repo._subtoppath = ui.expandpath(source) @@ -4272,14 +4359,14 @@ @command( - "init", + b"init", remoteopts, - _("[-e CMD] [--remotecmd CMD] [DEST]"), + _(b"[-e CMD] [--remotecmd CMD] [DEST]"), helpcategory=command.CATEGORY_REPO_CREATION, helpbasic=True, norepo=True, ) -def init(ui, dest=".", **opts): +def init(ui, dest=b".", **opts): """create a new repository in the given directory Initialize a new repository in the given directory. If the given @@ -4297,19 +4384,30 @@ @command( - "locate", + b"locate", [ - ("r", "rev", "", _("search the repository as it is in REV"), _("REV")), - ("0", "print0", None, _("end filenames with NUL, for use with xargs")), + ( + b"r", + b"rev", + b"", + _(b"search the repository as it is in REV"), + _(b"REV"), + ), ( - "f", - "fullpath", + b"0", + b"print0", None, - _("print complete paths from the filesystem root"), + _(b"end filenames with NUL, for use with xargs"), + ), + ( + b"f", + b"fullpath", + None, + _(b"print complete paths from the filesystem root"), ), ] + walkopts, - _("[OPTION]... [PATTERN]..."), + _(b"[OPTION]... [PATTERN]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def locate(ui, repo, *pats, **opts): @@ -4335,18 +4433,18 @@ Returns 0 if a match is found, 1 otherwise. """ opts = pycompat.byteskwargs(opts) - if opts.get("print0"): - end = "\0" + if opts.get(b"print0"): + end = b"\0" else: - end = "\n" - ctx = scmutil.revsingle(repo, opts.get("rev"), None) + end = b"\n" + ctx = scmutil.revsingle(repo, opts.get(b"rev"), None) ret = 1 m = scmutil.match( - ctx, pats, opts, default="relglob", badfn=lambda x, y: False + ctx, pats, opts, default=b"relglob", badfn=lambda x, y: False ) - ui.pager("locate") + ui.pager(b"locate") if ctx.rev() is None: # When run on the working copy, "locate" includes removed files, so # we get the list of files from the dirstate. @@ -4355,7 +4453,7 @@ filesgen = ctx.matches(m) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats)) for abs in filesgen: - if opts.get("fullpath"): + if opts.get(b"fullpath"): ui.write(repo.wjoin(abs), end) else: ui.write(uipathfn(abs), end) @@ -4365,74 +4463,91 @@ @command( - "log|history", + b"log|history", [ ( - "f", - "follow", + b"f", + b"follow", None, _( - "follow changeset history, or file history across copies and renames" + b"follow changeset history, or file history across copies and renames" ), ), ( - "", - "follow-first", + b"", + b"follow-first", None, - _("only follow the first parent of merge changesets (DEPRECATED)"), + _(b"only follow the first parent of merge changesets (DEPRECATED)"), ), - ("d", "date", "", _("show revisions matching date spec"), _("DATE")), - ("C", "copies", None, _("show copied files")), ( - "k", - "keyword", + b"d", + b"date", + b"", + _(b"show revisions matching date spec"), + _(b"DATE"), + ), + (b"C", b"copies", None, _(b"show copied files")), + ( + b"k", + b"keyword", [], - _("do case-insensitive search for a given text"), - _("TEXT"), + _(b"do case-insensitive search for a given text"), + _(b"TEXT"), ), - ("r", "rev", [], _("show the specified revision or revset"), _("REV")), ( - "L", - "line-range", + b"r", + b"rev", [], - _("follow line range of specified file (EXPERIMENTAL)"), - _("FILE,RANGE"), + _(b"show the specified revision or revset"), + _(b"REV"), ), - ("", "removed", None, _("include revisions where files were removed")), + ( + b"L", + b"line-range", + [], + _(b"follow line range of specified file (EXPERIMENTAL)"), + _(b"FILE,RANGE"), + ), ( - "m", - "only-merges", + b"", + b"removed", None, - _('show only merges (DEPRECATED) (use -r "merge()" instead)'), + _(b"include revisions where files were removed"), ), - ("u", "user", [], _("revisions committed by user"), _("USER")), ( - "", - "only-branch", + b"m", + b"only-merges", + None, + _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'), + ), + (b"u", b"user", [], _(b"revisions committed by user"), _(b"USER")), + ( + b"", + b"only-branch", [], _( - "show only changesets within the given named branch (DEPRECATED)" + b"show only changesets within the given named branch (DEPRECATED)" ), - _("BRANCH"), + _(b"BRANCH"), ), ( - "b", - "branch", + b"b", + b"branch", [], - _("show changesets within the given named branch"), - _("BRANCH"), + _(b"show changesets within the given named branch"), + _(b"BRANCH"), ), ( - "P", - "prune", + b"P", + b"prune", [], - _("do not display revision or any of its ancestors"), - _("REV"), + _(b"do not display revision or any of its ancestors"), + _(b"REV"), ), ] + logopts + walkopts, - _("[OPTION]... [FILE]"), + _(b"[OPTION]... [FILE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, helpbasic=True, inferrepo=True, @@ -4567,18 +4682,18 @@ """ opts = pycompat.byteskwargs(opts) - linerange = opts.get("line_range") - - if linerange and not opts.get("follow"): - raise error.Abort(_("--line-range requires --follow")) + linerange = opts.get(b"line_range") + + if linerange and not opts.get(b"follow"): + raise error.Abort(_(b"--line-range requires --follow")) if linerange and pats: # TODO: take pats as patterns with no line-range filter raise error.Abort( - _("FILE arguments are not compatible with --line-range option") + _(b"FILE arguments are not compatible with --line-range option") ) - repo = scmutil.unhidehashlikerevs(repo, opts.get("rev"), "nowarn") + repo = scmutil.unhidehashlikerevs(repo, opts.get(b"rev"), b"nowarn") revs, differ = logcmdutil.getrevs(repo, pats, opts) if linerange: # TODO: should follow file history from logcmdutil._initialrevs(), @@ -4586,17 +4701,17 @@ revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts) getcopies = None - if opts.get("copies"): + if opts.get(b"copies"): endrev = None if revs: endrev = revs.max() + 1 getcopies = scmutil.getcopiesfn(repo, endrev=endrev) - ui.pager("log") + ui.pager(b"log") displayer = logcmdutil.changesetdisplayer( ui, repo, opts, differ, buffered=True ) - if opts.get("graph"): + if opts.get(b"graph"): displayfn = logcmdutil.displaygraphrevs else: displayfn = logcmdutil.displayrevs @@ -4604,13 +4719,13 @@ @command( - "manifest", + b"manifest", [ - ("r", "rev", "", _("revision to display"), _("REV")), - ("", "all", False, _("list files from all revisions")), + (b"r", b"rev", b"", _(b"revision to display"), _(b"REV")), + (b"", b"all", False, _(b"list files from all revisions")), ] + formatteropts, - _("[-r REV]"), + _(b"[-r REV]"), helpcategory=command.CATEGORY_MAINTENANCE, intents={INTENT_READONLY}, ) @@ -4630,67 +4745,67 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - fm = ui.formatter("manifest", opts) - - if opts.get("all"): + fm = ui.formatter(b"manifest", opts) + + if opts.get(b"all"): if rev or node: - raise error.Abort(_("can't specify a revision with --all")) + raise error.Abort(_(b"can't specify a revision with --all")) res = set() for rev in repo: ctx = repo[rev] res |= set(ctx.files()) - ui.pager("manifest") + ui.pager(b"manifest") for f in sorted(res): fm.startitem() - fm.write("path", "%s\n", f) + fm.write(b"path", b"%s\n", f) fm.end() return if rev and node: - raise error.Abort(_("please specify just one revision")) + raise error.Abort(_(b"please specify just one revision")) if not node: node = rev - char = {"l": "@", "x": "*", "": "", "t": "d"} - mode = {"l": "644", "x": "755", "": "644", "t": "755"} + char = {b"l": b"@", b"x": b"*", b"": b"", b"t": b"d"} + mode = {b"l": b"644", b"x": b"755", b"": b"644", b"t": b"755"} if node: - repo = scmutil.unhidehashlikerevs(repo, [node], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [node], b"nowarn") ctx = scmutil.revsingle(repo, node) mf = ctx.manifest() - ui.pager("manifest") + ui.pager(b"manifest") for f in ctx: fm.startitem() fm.context(ctx=ctx) fl = ctx[f].flags() - fm.condwrite(ui.debugflag, "hash", "%s ", hex(mf[f])) - fm.condwrite(ui.verbose, "mode type", "%s %1s ", mode[fl], char[fl]) - fm.write("path", "%s\n", f) + fm.condwrite(ui.debugflag, b"hash", b"%s ", hex(mf[f])) + fm.condwrite(ui.verbose, b"mode type", b"%s %1s ", mode[fl], char[fl]) + fm.write(b"path", b"%s\n", f) fm.end() @command( - "merge", + b"merge", [ ( - "f", - "force", + b"f", + b"force", None, - _("force a merge including outstanding changes (DEPRECATED)"), + _(b"force a merge including outstanding changes (DEPRECATED)"), ), - ("r", "rev", "", _("revision to merge"), _("REV")), + (b"r", b"rev", b"", _(b"revision to merge"), _(b"REV")), ( - "P", - "preview", + b"P", + b"preview", None, - _("review revisions to merge (no merge is performed)"), + _(b"review revisions to merge (no merge is performed)"), ), - ("", "abort", None, _("abort the ongoing merge")), + (b"", b"abort", None, _(b"abort the ongoing merge")), ] + mergetoolopts, - _("[-P] [[-r] REV]"), + _(b"[-P] [[-r] REV]"), helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True, ) @@ -4724,26 +4839,26 @@ """ opts = pycompat.byteskwargs(opts) - abort = opts.get("abort") + abort = opts.get(b"abort") if abort and repo.dirstate.p2() == nullid: - cmdutil.wrongtooltocontinue(repo, _("merge")) + cmdutil.wrongtooltocontinue(repo, _(b"merge")) if abort: state = cmdutil.getunfinishedstate(repo) - if state and state._opname != "merge": + if state and state._opname != b"merge": raise error.Abort( - _("cannot abort merge with %s in progress") % (state._opname), + _(b"cannot abort merge with %s in progress") % (state._opname), hint=state.hint(), ) if node: - raise error.Abort(_("cannot specify a node with --abort")) - if opts.get("rev"): - raise error.Abort(_("cannot specify both --rev and --abort")) - if opts.get("preview"): - raise error.Abort(_("cannot specify --preview with --abort")) - if opts.get("rev") and node: - raise error.Abort(_("please specify just one revision")) + raise error.Abort(_(b"cannot specify a node with --abort")) + if opts.get(b"rev"): + raise error.Abort(_(b"cannot specify both --rev and --abort")) + if opts.get(b"preview"): + raise error.Abort(_(b"cannot specify --preview with --abort")) + if opts.get(b"rev") and node: + raise error.Abort(_(b"please specify just one revision")) if not node: - node = opts.get("rev") + node = opts.get(b"rev") if node: node = scmutil.revsingle(repo, node).node() @@ -4751,9 +4866,9 @@ if not node and not abort: node = repo[destutil.destmerge(repo)].node() - if opts.get("preview"): + if opts.get(b"preview"): # find nodes that are ancestors of p2 but not of p1 - p1 = repo.lookup(".") + p1 = repo.lookup(b".") p2 = node nodes = repo.changelog.findmissing(common=[p1], heads=[p2]) @@ -4764,10 +4879,10 @@ return 0 # ui.forcemerge is an internal variable, do not document - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "merge"): - force = opts.get("force") - labels = ["working copy", "merge rev"] + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"merge"): + force = opts.get(b"force") + labels = [b"working copy", b"merge rev"] return hg.merge( repo, node, @@ -4779,44 +4894,49 @@ statemod.addunfinished( - "merge", + b"merge", fname=None, clearable=True, allowcommit=True, - cmdmsg=_("outstanding uncommitted merge"), + cmdmsg=_(b"outstanding uncommitted merge"), abortfunc=hg.abortmerge, statushint=_( - "To continue: hg commit\n" "To abort: hg merge --abort" + b"To continue: hg commit\n" b"To abort: hg merge --abort" ), - cmdhint=_("use 'hg commit' or 'hg merge --abort'"), + cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"), ) @command( - "outgoing|out", + b"outgoing|out", [ - ("f", "force", None, _("run even when the destination is unrelated")), ( - "r", - "rev", + b"f", + b"force", + None, + _(b"run even when the destination is unrelated"), + ), + ( + b"r", + b"rev", [], - _("a changeset intended to be included in the destination"), - _("REV"), + _(b"a changeset intended to be included in the destination"), + _(b"REV"), ), - ("n", "newest-first", None, _("show newest record first")), - ("B", "bookmarks", False, _("compare bookmarks")), + (b"n", b"newest-first", None, _(b"show newest record first")), + (b"B", b"bookmarks", False, _(b"compare bookmarks")), ( - "b", - "branch", + b"b", + b"branch", [], - _("a specific branch you would like to push"), - _("BRANCH"), + _(b"a specific branch you would like to push"), + _(b"BRANCH"), ), ] + logopts + remoteopts + subrepoopts, - _("[-M] [-p] [-n] [-f] [-r REV]... [DEST]"), + _(b"[-M] [-p] [-n] [-f] [-r REV]... [DEST]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, ) def outgoing(ui, repo, dest=None, **opts): @@ -4857,15 +4977,15 @@ """ # hg._outgoing() needs to re-resolve the path in order to handle #branch # style URLs, so don't overwrite dest. - path = ui.paths.getpath(dest, default=("default-push", "default")) + path = ui.paths.getpath(dest, default=(b"default-push", b"default")) if not path: raise error.Abort( - _("default repository not configured!"), - hint=_("see 'hg help config.paths'"), + _(b"default repository not configured!"), + hint=_(b"see 'hg help config.paths'"), ) opts = pycompat.byteskwargs(opts) - if opts.get("graph"): + if opts.get(b"graph"): logcmdutil.checkunsupportedgraphflags([], opts) o, other = hg._outgoing(ui, repo, dest, opts) if not o: @@ -4873,7 +4993,7 @@ return revdag = logcmdutil.graphrevs(repo, o, opts) - ui.pager("outgoing") + ui.pager(b"outgoing") displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True) logcmdutil.displaygraph( ui, repo, revdag, displayer, graphmod.asciiedges @@ -4881,14 +5001,14 @@ cmdutil.outgoinghooks(ui, repo, other, opts, o) return 0 - if opts.get("bookmarks"): + if opts.get(b"bookmarks"): dest = path.pushloc or path.loc other = hg.peer(repo, opts, dest) - if "bookmarks" not in other.listkeys("namespaces"): - ui.warn(_("remote doesn't support bookmarks\n")) + if b"bookmarks" not in other.listkeys(b"namespaces"): + ui.warn(_(b"remote doesn't support bookmarks\n")) return 0 - ui.status(_("comparing with %s\n") % util.hidepassword(dest)) - ui.pager("outgoing") + ui.status(_(b"comparing with %s\n") % util.hidepassword(dest)) + ui.pager(b"outgoing") return bookmarks.outgoing(ui, repo, other) repo._subtoppath = path.pushloc or path.loc @@ -4899,10 +5019,18 @@ @command( - "parents", - [("r", "rev", "", _("show parents of the specified revision"), _("REV")),] + b"parents", + [ + ( + b"r", + b"rev", + b"", + _(b"show parents of the specified revision"), + _(b"REV"), + ), + ] + templateopts, - _("[-r REV] [FILE]"), + _(b"[-r REV] [FILE]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, inferrepo=True, ) @@ -4928,15 +5056,15 @@ """ opts = pycompat.byteskwargs(opts) - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev, None) if file_: m = scmutil.match(ctx, (file_,), opts) if m.anypats() or len(m.files()) != 1: - raise error.Abort(_("can only specify an explicit filename")) + raise error.Abort(_(b"can only specify an explicit filename")) file_ = m.files()[0] filenodes = [] for cp in ctx.parents(): @@ -4947,7 +5075,7 @@ except error.LookupError: pass if not filenodes: - raise error.Abort(_("'%s' not found in manifest!") % file_) + raise error.Abort(_(b"'%s' not found in manifest!") % file_) p = [] for fn in filenodes: fctx = repo.filectx(file_, fileid=fn) @@ -4963,9 +5091,9 @@ @command( - "paths", + b"paths", formatteropts, - _("[NAME]"), + _(b"[NAME]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, optionalrepo=True, intents={INTENT_READONLY}, @@ -5013,7 +5141,7 @@ """ opts = pycompat.byteskwargs(opts) - ui.pager("paths") + ui.pager(b"paths") if search: pathitems = [ (name, path) @@ -5023,47 +5151,47 @@ else: pathitems = sorted(ui.paths.iteritems()) - fm = ui.formatter("paths", opts) + fm = ui.formatter(b"paths", opts) if fm.isplain(): hidepassword = util.hidepassword else: hidepassword = bytes if ui.quiet: - namefmt = "%s\n" + namefmt = b"%s\n" else: - namefmt = "%s = " + namefmt = b"%s = " showsubopts = not search and not ui.quiet for name, path in pathitems: fm.startitem() - fm.condwrite(not search, "name", namefmt, name) - fm.condwrite(not ui.quiet, "url", "%s\n", hidepassword(path.rawloc)) + fm.condwrite(not search, b"name", namefmt, name) + fm.condwrite(not ui.quiet, b"url", b"%s\n", hidepassword(path.rawloc)) for subopt, value in sorted(path.suboptions.items()): - assert subopt not in ("name", "url") + assert subopt not in (b"name", b"url") if showsubopts: - fm.plain("%s:%s = " % (name, subopt)) - fm.condwrite(showsubopts, subopt, "%s\n", value) + fm.plain(b"%s:%s = " % (name, subopt)) + fm.condwrite(showsubopts, subopt, b"%s\n", value) fm.end() if search and not pathitems: if not ui.quiet: - ui.warn(_("not found!\n")) + ui.warn(_(b"not found!\n")) return 1 else: return 0 @command( - "phase", + b"phase", [ - ("p", "public", False, _("set changeset phase to public")), - ("d", "draft", False, _("set changeset phase to draft")), - ("s", "secret", False, _("set changeset phase to secret")), - ("f", "force", False, _("allow to move boundary backward")), - ("r", "rev", [], _("target revision"), _("REV")), + (b"p", b"public", False, _(b"set changeset phase to public")), + (b"d", b"draft", False, _(b"set changeset phase to draft")), + (b"s", b"secret", False, _(b"set changeset phase to secret")), + (b"f", b"force", False, _(b"allow to move boundary backward")), + (b"r", b"rev", [], _(b"target revision"), _(b"REV")), ], - _("[-p|-d|-s] [-f] [-r] [REV...]"), + _(b"[-p|-d|-s] [-f] [-r] [REV...]"), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def phase(ui, repo, *revs, **opts): @@ -5089,12 +5217,12 @@ for idx, name in enumerate(phases.cmdphasenames): if opts[name]: if targetphase is not None: - raise error.Abort(_("only one phase can be specified")) + raise error.Abort(_(b"only one phase can be specified")) targetphase = idx # look for specified revision revs = list(revs) - revs.extend(opts["rev"]) + revs.extend(opts[b"rev"]) if not revs: # display both parents as the second parent phase can influence # the phase of a merge commit @@ -5107,12 +5235,12 @@ # display for r in revs: ctx = repo[r] - ui.write("%i: %s\n" % (ctx.rev(), ctx.phasestr())) + ui.write(b"%i: %s\n" % (ctx.rev(), ctx.phasestr())) else: - with repo.lock(), repo.transaction("phase") as tr: + with repo.lock(), repo.transaction(b"phase") as tr: # set phase if not revs: - raise error.Abort(_("empty revision set")) + raise error.Abort(_(b"empty revision set")) nodes = [repo[r].node() for r in revs] # moving revision from public to draft may hide them # We have to check result on an unfiltered repository @@ -5120,7 +5248,7 @@ getphase = unfi._phasecache.phase olddata = [getphase(unfi, r) for r in unfi] phases.advanceboundary(repo, tr, targetphase, nodes) - if opts["force"]: + if opts[b"force"]: phases.retractboundary(repo, tr, targetphase, nodes) getphase = unfi._phasecache.phase newdata = [getphase(unfi, r) for r in unfi] @@ -5130,20 +5258,20 @@ if rejected: ui.warn( _( - "cannot move %i changesets to a higher " - "phase, use --force\n" + b"cannot move %i changesets to a higher " + b"phase, use --force\n" ) % len(rejected) ) ret = 1 if changes: - msg = _("phase changed for %i changesets\n") % changes + msg = _(b"phase changed for %i changesets\n") % changes if ret: ui.status(msg) else: ui.note(msg) else: - ui.warn(_("no phases changed\n")) + ui.warn(_(b"no phases changed\n")) return ret @@ -5163,55 +5291,62 @@ try: return hg.updatetotally(ui, repo, checkout, brev) except error.UpdateAbort as inst: - msg = _("not updating: %s") % stringutil.forcebytestr(inst) + msg = _(b"not updating: %s") % stringutil.forcebytestr(inst) hint = inst.hint raise error.UpdateAbort(msg, hint=hint) if modheads is not None and modheads > 1: currentbranchheads = len(repo.branchheads()) if currentbranchheads == modheads: - ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n")) + ui.status( + _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n") + ) elif currentbranchheads > 1: ui.status( - _("(run 'hg heads .' to see heads, 'hg merge' to " "merge)\n") + _(b"(run 'hg heads .' to see heads, 'hg merge' to " b"merge)\n") ) else: - ui.status(_("(run 'hg heads' to see heads)\n")) - elif not ui.configbool("commands", "update.requiredest"): - ui.status(_("(run 'hg update' to get a working copy)\n")) + ui.status(_(b"(run 'hg heads' to see heads)\n")) + elif not ui.configbool(b"commands", b"update.requiredest"): + ui.status(_(b"(run 'hg update' to get a working copy)\n")) @command( - "pull", + b"pull", [ ( - "u", - "update", + b"u", + b"update", None, - _("update to new branch head if new descendants were pulled"), + _(b"update to new branch head if new descendants were pulled"), ), - ("f", "force", None, _("run even when remote repository is unrelated")), ( - "r", - "rev", + b"f", + b"force", + None, + _(b"run even when remote repository is unrelated"), + ), + ( + b"r", + b"rev", [], - _("a remote changeset intended to be added"), - _("REV"), + _(b"a remote changeset intended to be added"), + _(b"REV"), ), - ("B", "bookmark", [], _("bookmark to pull"), _("BOOKMARK")), + (b"B", b"bookmark", [], _(b"bookmark to pull"), _(b"BOOKMARK")), ( - "b", - "branch", + b"b", + b"branch", [], - _("a specific branch you would like to pull"), - _("BRANCH"), + _(b"a specific branch you would like to pull"), + _(b"BRANCH"), ), ] + remoteopts, - _("[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]"), + _(b"[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, helpbasic=True, ) -def pull(ui, repo, source="default", **opts): +def pull(ui, repo, source=b"default", **opts): """pull changes from the specified source Pull changes from a remote repository to a local one. @@ -5242,23 +5377,25 @@ """ opts = pycompat.byteskwargs(opts) - if ui.configbool("commands", "update.requiredest") and opts.get("update"): - msg = _("update destination required by configuration") - hint = _("use hg pull followed by hg update DEST") + if ui.configbool(b"commands", b"update.requiredest") and opts.get( + b"update" + ): + msg = _(b"update destination required by configuration") + hint = _(b"use hg pull followed by hg update DEST") raise error.Abort(msg, hint=hint) - source, branches = hg.parseurl(ui.expandpath(source), opts.get("branch")) - ui.status(_("pulling from %s\n") % util.hidepassword(source)) + source, branches = hg.parseurl(ui.expandpath(source), opts.get(b"branch")) + ui.status(_(b"pulling from %s\n") % util.hidepassword(source)) other = hg.peer(repo, opts, source) try: revs, checkout = hg.addbranchrevs( - repo, other, branches, opts.get("rev") + repo, other, branches, opts.get(b"rev") ) pullopargs = {} nodes = None - if opts.get("bookmark") or revs: + if opts.get(b"bookmark") or revs: # The list of bookmark used here is the same used to actually update # the bookmark names, to avoid the race from issue 4689 and we do # all lookup and bookmark queries in one go so they see the same @@ -5266,25 +5403,25 @@ nodes = [] fnodes = [] revs = revs or [] - if revs and not other.capable("lookup"): + if revs and not other.capable(b"lookup"): err = _( - "other repository doesn't support revision lookup, " - "so a rev cannot be specified." + b"other repository doesn't support revision lookup, " + b"so a rev cannot be specified." ) raise error.Abort(err) with other.commandexecutor() as e: fremotebookmarks = e.callcommand( - "listkeys", {"namespace": "bookmarks"} + b"listkeys", {b"namespace": b"bookmarks"} ) for r in revs: - fnodes.append(e.callcommand("lookup", {"key": r})) + fnodes.append(e.callcommand(b"lookup", {b"key": r})) remotebookmarks = fremotebookmarks.result() remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks) - pullopargs["remotebookmarks"] = remotebookmarks - for b in opts.get("bookmark", []): + pullopargs[b"remotebookmarks"] = remotebookmarks + for b in opts.get(b"bookmark", []): b = repo._bookmarks.expandname(b) if b not in remotebookmarks: - raise error.Abort(_("remote bookmark %s not found!") % b) + raise error.Abort(_(b"remote bookmark %s not found!") % b) nodes.append(remotebookmarks[b]) for i, rev in enumerate(revs): node = fnodes[i].result() @@ -5293,16 +5430,16 @@ checkout = node wlock = util.nullcontextmanager() - if opts.get("update"): + if opts.get(b"update"): wlock = repo.wlock() with wlock: - pullopargs.update(opts.get("opargs", {})) + pullopargs.update(opts.get(b"opargs", {})) modheads = exchange.pull( repo, other, heads=nodes, - force=opts.get("force"), - bookmarks=opts.get("bookmark", ()), + force=opts.get(b"force"), + bookmarks=opts.get(b"bookmark", ()), opargs=pullopargs, ).cgresult @@ -5317,19 +5454,19 @@ # order below depends on implementation of # hg.addbranchrevs(). opts['bookmark'] is ignored, # because 'checkout' is determined without it. - if opts.get("rev"): - brev = opts["rev"][0] - elif opts.get("branch"): - brev = opts["branch"][0] + if opts.get(b"rev"): + brev = opts[b"rev"][0] + elif opts.get(b"branch"): + brev = opts[b"branch"][0] else: brev = branches[0] repo._subtoppath = source try: ret = postincoming( - ui, repo, modheads, opts.get("update"), checkout, brev + ui, repo, modheads, opts.get(b"update"), checkout, brev ) except error.FilteredRepoLookupError as exc: - msg = _("cannot update to target: %s") % exc.args[0] + msg = _(b"cannot update to target: %s") % exc.args[0] exc.args = (msg,) + exc.args[1:] raise finally: @@ -5341,40 +5478,40 @@ @command( - "push", + b"push", [ - ("f", "force", None, _("force push")), + (b"f", b"force", None, _(b"force push")), ( - "r", - "rev", + b"r", + b"rev", [], - _("a changeset intended to be included in the destination"), - _("REV"), + _(b"a changeset intended to be included in the destination"), + _(b"REV"), ), - ("B", "bookmark", [], _("bookmark to push"), _("BOOKMARK")), + (b"B", b"bookmark", [], _(b"bookmark to push"), _(b"BOOKMARK")), ( - "b", - "branch", + b"b", + b"branch", [], - _("a specific branch you would like to push"), - _("BRANCH"), + _(b"a specific branch you would like to push"), + _(b"BRANCH"), ), - ("", "new-branch", False, _("allow pushing a new branch")), + (b"", b"new-branch", False, _(b"allow pushing a new branch")), ( - "", - "pushvars", + b"", + b"pushvars", [], - _("variables that can be sent to server (ADVANCED)"), + _(b"variables that can be sent to server (ADVANCED)"), ), ( - "", - "publish", + b"", + b"publish", False, - _("push the changeset as public (EXPERIMENTAL)"), + _(b"push the changeset as public (EXPERIMENTAL)"), ), ] + remoteopts, - _("[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]"), + _(b"[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]"), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, helpbasic=True, ) @@ -5436,52 +5573,52 @@ """ opts = pycompat.byteskwargs(opts) - if opts.get("bookmark"): - ui.setconfig("bookmarks", "pushing", opts["bookmark"], "push") - for b in opts["bookmark"]: + if opts.get(b"bookmark"): + ui.setconfig(b"bookmarks", b"pushing", opts[b"bookmark"], b"push") + for b in opts[b"bookmark"]: # translate -B options to -r so changesets get pushed b = repo._bookmarks.expandname(b) if b in repo._bookmarks: - opts.setdefault("rev", []).append(b) + opts.setdefault(b"rev", []).append(b) else: # if we try to push a deleted bookmark, translate it to null # this lets simultaneous -r, -b options continue working - opts.setdefault("rev", []).append("null") - - path = ui.paths.getpath(dest, default=("default-push", "default")) + opts.setdefault(b"rev", []).append(b"null") + + path = ui.paths.getpath(dest, default=(b"default-push", b"default")) if not path: raise error.Abort( - _("default repository not configured!"), - hint=_("see 'hg help config.paths'"), + _(b"default repository not configured!"), + hint=_(b"see 'hg help config.paths'"), ) dest = path.pushloc or path.loc - branches = (path.branch, opts.get("branch") or []) - ui.status(_("pushing to %s\n") % util.hidepassword(dest)) - revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get("rev")) + branches = (path.branch, opts.get(b"branch") or []) + ui.status(_(b"pushing to %s\n") % util.hidepassword(dest)) + revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b"rev")) other = hg.peer(repo, opts, dest) if revs: revs = [repo[r].node() for r in scmutil.revrange(repo, revs)] if not revs: raise error.Abort( - _("specified revisions evaluate to an empty set"), - hint=_("use different revision arguments"), + _(b"specified revisions evaluate to an empty set"), + hint=_(b"use different revision arguments"), ) elif path.pushrev: # It doesn't make any sense to specify ancestor revisions. So limit # to DAG heads to make discovery simpler. - expr = revsetlang.formatspec("heads(%r)", path.pushrev) + expr = revsetlang.formatspec(b"heads(%r)", path.pushrev) revs = scmutil.revrange(repo, [expr]) revs = [repo[rev].node() for rev in revs] if not revs: raise error.Abort( - _("default push revset for path evaluates to an " "empty set") + _(b"default push revset for path evaluates to an " b"empty set") ) repo._subtoppath = dest try: # push subrepos depth-first for coherent ordering - c = repo["."] + c = repo[b"."] subs = c.substate # only repos that are committed for s in sorted(subs): result = c.sub(s).push(opts) @@ -5490,17 +5627,17 @@ finally: del repo._subtoppath - opargs = dict(opts.get("opargs", {})) # copy opargs since we may mutate it - opargs.setdefault("pushvars", []).extend(opts.get("pushvars", [])) + opargs = dict(opts.get(b"opargs", {})) # copy opargs since we may mutate it + opargs.setdefault(b"pushvars", []).extend(opts.get(b"pushvars", [])) pushop = exchange.push( repo, other, - opts.get("force"), + opts.get(b"force"), revs=revs, - newbranch=opts.get("new_branch"), - bookmarks=opts.get("bookmark", ()), - publish=opts.get("publish"), + newbranch=opts.get(b"new_branch"), + bookmarks=opts.get(b"bookmark", ()), + publish=opts.get(b"publish"), opargs=opargs, ) @@ -5516,8 +5653,8 @@ @command( - "recover", - [("", "verify", True, "run `hg verify` after succesful recover"),], + b"recover", + [(b"", b"verify", True, b"run `hg verify` after succesful recover"),], helpcategory=command.CATEGORY_MAINTENANCE, ) def recover(ui, repo, **opts): @@ -5537,8 +5674,8 @@ return hg.verify(repo) else: msg = _( - "(verify step skipped, run `hg verify` to check your " - "repository content)\n" + b"(verify step skipped, run `hg verify` to check your " + b"repository content)\n" ) ui.warn(msg) return 0 @@ -5546,15 +5683,15 @@ @command( - "remove|rm", + b"remove|rm", [ - ("A", "after", None, _("record delete for missing files")), - ("f", "force", None, _("forget added files, delete modified files")), + (b"A", b"after", None, _(b"record delete for missing files")), + (b"f", b"force", None, _(b"forget added files, delete modified files")), ] + subrepoopts + walkopts + dryrunopts, - _("[OPTION]... FILE..."), + _(b"[OPTION]... FILE..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, inferrepo=True, @@ -5599,28 +5736,33 @@ """ opts = pycompat.byteskwargs(opts) - after, force = opts.get("after"), opts.get("force") - dryrun = opts.get("dry_run") + after, force = opts.get(b"after"), opts.get(b"force") + dryrun = opts.get(b"dry_run") if not pats and not after: - raise error.Abort(_("no files specified")) + raise error.Abort(_(b"no files specified")) m = scmutil.match(repo[None], pats, opts) - subrepos = opts.get("subrepos") + subrepos = opts.get(b"subrepos") uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) return cmdutil.remove( - ui, repo, m, "", uipathfn, after, force, subrepos, dryrun=dryrun + ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun ) @command( - "rename|move|mv", + b"rename|move|mv", [ - ("A", "after", None, _("record a rename that has already occurred")), - ("f", "force", None, _("forcibly move over an existing managed file")), + (b"A", b"after", None, _(b"record a rename that has already occurred")), + ( + b"f", + b"force", + None, + _(b"forcibly move over an existing managed file"), + ), ] + walkopts + dryrunopts, - _("[OPTION]... SOURCE... DEST"), + _(b"[OPTION]... SOURCE... DEST"), helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def rename(ui, repo, *pats, **opts): @@ -5645,19 +5787,19 @@ @command( - "resolve", + b"resolve", [ - ("a", "all", None, _("select all unresolved files")), - ("l", "list", None, _("list state of files needing merge")), - ("m", "mark", None, _("mark files as resolved")), - ("u", "unmark", None, _("mark files as unresolved")), - ("n", "no-status", None, _("hide status prefix")), - ("", "re-merge", None, _("re-merge files")), + (b"a", b"all", None, _(b"select all unresolved files")), + (b"l", b"list", None, _(b"list state of files needing merge")), + (b"m", b"mark", None, _(b"mark files as resolved")), + (b"u", b"unmark", None, _(b"mark files as unresolved")), + (b"n", b"no-status", None, _(b"hide status prefix")), + (b"", b"re-merge", None, _(b"re-merge files")), ] + mergetoolopts + walkopts + formatteropts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, inferrepo=True, ) @@ -5714,24 +5856,24 @@ """ opts = pycompat.byteskwargs(opts) - confirm = ui.configbool("commands", "resolve.confirm") - flaglist = "all mark unmark list no_status re_merge".split() + confirm = ui.configbool(b"commands", b"resolve.confirm") + flaglist = b"all mark unmark list no_status re_merge".split() all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist] actioncount = len(list(filter(None, [show, mark, unmark, remerge]))) if actioncount > 1: - raise error.Abort(_("too many actions specified")) + raise error.Abort(_(b"too many actions specified")) elif actioncount == 0 and ui.configbool( - "commands", "resolve.explicit-re-merge" + b"commands", b"resolve.explicit-re-merge" ): - hint = _("use --mark, --unmark, --list or --re-merge") - raise error.Abort(_("no action specified"), hint=hint) + hint = _(b"use --mark, --unmark, --list or --re-merge") + raise error.Abort(_(b"no action specified"), hint=hint) if pats and all: - raise error.Abort(_("can't specify --all and patterns")) + raise error.Abort(_(b"can't specify --all and patterns")) if not (all or pats or show or mark or unmark): raise error.Abort( - _("no files or directories specified"), - hint="use --all to re-merge all unresolved files", + _(b"no files or directories specified"), + hint=b"use --all to re-merge all unresolved files", ) if confirm: @@ -5739,7 +5881,7 @@ if ui.promptchoice( _(b"re-merge all unresolved files (yn)?" b"$$ &Yes $$ &No") ): - raise error.Abort(_("user quit")) + raise error.Abort(_(b"user quit")) if mark and not pats: if ui.promptchoice( _( @@ -5747,7 +5889,7 @@ b"$$ &Yes $$ &No" ) ): - raise error.Abort(_("user quit")) + raise error.Abort(_(b"user quit")) if unmark and not pats: if ui.promptchoice( _( @@ -5755,13 +5897,13 @@ b"$$ &Yes $$ &No" ) ): - raise error.Abort(_("user quit")) + raise error.Abort(_(b"user quit")) uipathfn = scmutil.getuipathfn(repo) if show: - ui.pager("resolve") - fm = ui.formatter("resolve", opts) + ui.pager(b"resolve") + fm = ui.formatter(b"resolve", opts) ms = mergemod.mergestate.read(repo) wctx = repo[None] m = scmutil.match(wctx, pats, opts) @@ -5770,13 +5912,16 @@ # as 'P'. Resolved path conflicts show as 'R', the same as normal # resolved conflicts. mergestateinfo = { - mergemod.MERGE_RECORD_UNRESOLVED: ("resolve.unresolved", "U"), - mergemod.MERGE_RECORD_RESOLVED: ("resolve.resolved", "R"), - mergemod.MERGE_RECORD_UNRESOLVED_PATH: ("resolve.unresolved", "P"), - mergemod.MERGE_RECORD_RESOLVED_PATH: ("resolve.resolved", "R"), + mergemod.MERGE_RECORD_UNRESOLVED: (b"resolve.unresolved", b"U"), + mergemod.MERGE_RECORD_RESOLVED: (b"resolve.resolved", b"R"), + mergemod.MERGE_RECORD_UNRESOLVED_PATH: ( + b"resolve.unresolved", + b"P", + ), + mergemod.MERGE_RECORD_RESOLVED_PATH: (b"resolve.resolved", b"R"), mergemod.MERGE_RECORD_DRIVER_RESOLVED: ( - "resolve.driverresolved", - "D", + b"resolve.driverresolved", + b"D", ), } @@ -5787,9 +5932,9 @@ label, key = mergestateinfo[ms[f]] fm.startitem() fm.context(ctx=wctx) - fm.condwrite(not nostatus, "mergestatus", "%s ", key, label=label) + fm.condwrite(not nostatus, b"mergestatus", b"%s ", key, label=label) fm.data(path=f) - fm.plain("%s\n" % uipathfn(f), label=label) + fm.plain(b"%s\n" % uipathfn(f), label=label) fm.end() return 0 @@ -5798,7 +5943,7 @@ if not (ms.active() or repo.dirstate.p2() != nullid): raise error.Abort( - _("resolve command not applicable when not merging") + _(b"resolve command not applicable when not merging") ) wctx = repo[None] @@ -5821,8 +5966,8 @@ tocomplete = [] hasconflictmarkers = [] if mark: - markcheck = ui.config("commands", "resolve.mark-check") - if markcheck not in ["warn", "abort"]: + markcheck = ui.config(b"commands", b"resolve.mark-check") + if markcheck not in [b"warn", b"abort"]: # Treat all invalid / unrecognized values as 'none'. markcheck = False for f in ms: @@ -5838,13 +5983,13 @@ if mark: if exact: ui.warn( - _("not marking %s as it is driver-resolved\n") + _(b"not marking %s as it is driver-resolved\n") % uipathfn(f) ) elif unmark: if exact: ui.warn( - _("not unmarking %s as it is driver-resolved\n") + _(b"not unmarking %s as it is driver-resolved\n") % uipathfn(f) ) else: @@ -5862,7 +6007,7 @@ ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH) elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH: ui.warn( - _("%s: path conflict must be resolved manually\n") + _(b"%s: path conflict must be resolved manually\n") % uipathfn(f) ) continue @@ -5882,15 +6027,15 @@ # backup pre-resolve (merge uses .orig for its own purposes) a = repo.wjoin(f) try: - util.copyfile(a, a + ".resolve") + util.copyfile(a, a + b".resolve") except (IOError, OSError) as inst: if inst.errno != errno.ENOENT: raise try: # preresolve file - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "resolve"): + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"resolve"): complete, r = ms.preresolve(f, wctx) if not complete: tocomplete.append(f) @@ -5904,7 +6049,7 @@ if complete: try: util.rename( - a + ".resolve", scmutil.backuppath(ui, repo, f) + a + b".resolve", scmutil.backuppath(ui, repo, f) ) except OSError as inst: if inst.errno != errno.ENOENT: @@ -5913,22 +6058,24 @@ if hasconflictmarkers: ui.warn( _( - "warning: the following files still have conflict " - "markers:\n" + b"warning: the following files still have conflict " + b"markers:\n" ) - + "".join(" " + uipathfn(f) + "\n" for f in hasconflictmarkers) + + b"".join( + b" " + uipathfn(f) + b"\n" for f in hasconflictmarkers + ) ) - if markcheck == "abort" and not all and not pats: + if markcheck == b"abort" and not all and not pats: raise error.Abort( - _("conflict markers detected"), - hint=_("use --all to mark anyway"), + _(b"conflict markers detected"), + hint=_(b"use --all to mark anyway"), ) for f in tocomplete: try: # resolve file - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "resolve"): + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"resolve"): r = ms.resolve(f, wctx) if r: ret = 1 @@ -5938,7 +6085,7 @@ # replace filemerge's .orig file with our resolve file a = repo.wjoin(f) try: - util.rename(a + ".resolve", scmutil.backuppath(ui, repo, f)) + util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f)) except OSError as inst: if inst.errno != errno.ENOENT: raise @@ -5948,28 +6095,28 @@ if not didwork and pats: hint = None - if not any([p for p in pats if p.find(":") >= 0]): - pats = ["path:%s" % p for p in pats] + if not any([p for p in pats if p.find(b":") >= 0]): + pats = [b"path:%s" % p for p in pats] m = scmutil.match(wctx, pats, opts) for f in ms: if not m(f): continue def flag(o): - if o == "re_merge": - return "--re-merge " - return "-%s " % o[0:1] - - flags = "".join([flag(o) for o in flaglist if opts.get(o)]) - hint = _("(try: hg resolve %s%s)\n") % ( + if o == b"re_merge": + return b"--re-merge " + return b"-%s " % o[0:1] + + flags = b"".join([flag(o) for o in flaglist if opts.get(o)]) + hint = _(b"(try: hg resolve %s%s)\n") % ( flags, - " ".join(pats), + b" ".join(pats), ) break - ui.warn(_("arguments do not match paths that need resolving\n")) + ui.warn(_(b"arguments do not match paths that need resolving\n")) if hint: ui.warn(hint) - elif ms.mergedriver and ms.mdstate() != "s": + elif ms.mergedriver and ms.mdstate() != b"s": # run conclude step when either a driver-resolved file is requested # or there are no driver-resolved files # we can't use 'ret' to determine whether any files are unresolved @@ -5986,13 +6133,13 @@ unresolvedf = list(ms.unresolved()) driverresolvedf = list(ms.driverresolved()) if not unresolvedf and not driverresolvedf: - ui.status(_("(no more unresolved files)\n")) + ui.status(_(b"(no more unresolved files)\n")) cmdutil.checkafterresolved(repo) elif not unresolvedf: ui.status( _( - "(no more unresolved files -- " - 'run "hg resolve --all" to conclude)\n' + b"(no more unresolved files -- " + b'run "hg resolve --all" to conclude)\n' ) ) @@ -6000,17 +6147,17 @@ @command( - "revert", + b"revert", [ - ("a", "all", None, _("revert all changes when no arguments given")), - ("d", "date", "", _("tipmost revision matching date"), _("DATE")), - ("r", "rev", "", _("revert to the specified revision"), _("REV")), - ("C", "no-backup", None, _("do not save backup copies of files")), - ("i", "interactive", None, _("interactively select the changes")), + (b"a", b"all", None, _(b"revert all changes when no arguments given")), + (b"d", b"date", b"", _(b"tipmost revision matching date"), _(b"DATE")), + (b"r", b"rev", b"", _(b"revert to the specified revision"), _(b"REV")), + (b"C", b"no-backup", None, _(b"do not save backup copies of files")), + (b"i", b"interactive", None, _(b"interactively select the changes")), ] + walkopts + dryrunopts, - _("[OPTION]... [-r REV] [NAME]..."), + _(b"[OPTION]... [-r REV] [NAME]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def revert(ui, repo, *pats, **opts): @@ -6051,36 +6198,36 @@ """ opts = pycompat.byteskwargs(opts) - if opts.get("date"): - if opts.get("rev"): - raise error.Abort(_("you can't specify a revision and a date")) - opts["rev"] = cmdutil.finddate(ui, repo, opts["date"]) + if opts.get(b"date"): + if opts.get(b"rev"): + raise error.Abort(_(b"you can't specify a revision and a date")) + opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"]) parent, p2 = repo.dirstate.parents() - if not opts.get("rev") and p2 != nullid: + if not opts.get(b"rev") and p2 != nullid: # revert after merge is a trap for new users (issue2915) raise error.Abort( - _("uncommitted merge with no revision specified"), - hint=_("use 'hg update' or see 'hg help revert'"), + _(b"uncommitted merge with no revision specified"), + hint=_(b"use 'hg update' or see 'hg help revert'"), ) - rev = opts.get("rev") + rev = opts.get(b"rev") if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev) if not ( pats - or opts.get("include") - or opts.get("exclude") - or opts.get("all") - or opts.get("interactive") + or opts.get(b"include") + or opts.get(b"exclude") + or opts.get(b"all") + or opts.get(b"interactive") ): - msg = _("no files or directories specified") + msg = _(b"no files or directories specified") if p2 != nullid: hint = _( - "uncommitted merge, use --all to discard all changes," - " or 'hg update -C .' to abort the merge" + b"uncommitted merge, use --all to discard all changes," + b" or 'hg update -C .' to abort the merge" ) raise error.Abort(msg, hint=hint) dirty = any(repo.status()) @@ -6089,23 +6236,23 @@ if dirty: hint = ( _( - "uncommitted changes, use --all to discard all" - " changes, or 'hg update %d' to update" + b"uncommitted changes, use --all to discard all" + b" changes, or 'hg update %d' to update" ) % ctx.rev() ) else: hint = ( _( - "use --all to revert all files," - " or 'hg update %d' to update" + b"use --all to revert all files," + b" or 'hg update %d' to update" ) % ctx.rev() ) elif dirty: - hint = _("uncommitted changes, use --all to discard all changes") + hint = _(b"uncommitted changes, use --all to discard all changes") else: - hint = _("use --all to revert all files") + hint = _(b"use --all to revert all files") raise error.Abort(msg, hint=hint) return cmdutil.revert( @@ -6114,8 +6261,8 @@ @command( - "rollback", - dryrunopts + [("f", "force", False, _("ignore safety measures"))], + b"rollback", + dryrunopts + [(b"f", b"force", False, _(b"ignore safety measures"))], helpcategory=command.CATEGORY_MAINTENANCE, ) def rollback(ui, repo, **opts): @@ -6163,16 +6310,16 @@ Returns 0 on success, 1 if no rollback data is available. """ - if not ui.configbool("ui", "rollback"): + if not ui.configbool(b"ui", b"rollback"): raise error.Abort( - _("rollback is disabled because it is unsafe"), - hint="see `hg help -v rollback` for information", + _(b"rollback is disabled because it is unsafe"), + hint=b"see `hg help -v rollback` for information", ) return repo.rollback(dryrun=opts.get(r"dry_run"), force=opts.get(r"force")) @command( - "root", + b"root", [] + formatteropts, intents={INTENT_READONLY}, helpcategory=command.CATEGORY_WORKING_DIRECTORY, @@ -6195,85 +6342,97 @@ Returns 0 on success. """ opts = pycompat.byteskwargs(opts) - with ui.formatter("root", opts) as fm: + with ui.formatter(b"root", opts) as fm: fm.startitem() - fm.write("reporoot", "%s\n", repo.root) + fm.write(b"reporoot", b"%s\n", repo.root) fm.data(hgpath=repo.path, storepath=repo.spath) @command( - "serve", + b"serve", [ ( - "A", - "accesslog", - "", - _("name of access log file to write to"), - _("FILE"), + b"A", + b"accesslog", + b"", + _(b"name of access log file to write to"), + _(b"FILE"), ), - ("d", "daemon", None, _("run server in background")), - ("", "daemon-postexec", [], _("used internally by daemon mode")), + (b"d", b"daemon", None, _(b"run server in background")), + (b"", b"daemon-postexec", [], _(b"used internally by daemon mode")), ( - "E", - "errorlog", - "", - _("name of error log file to write to"), - _("FILE"), + b"E", + b"errorlog", + b"", + _(b"name of error log file to write to"), + _(b"FILE"), ), # use string type, then we can check if something was passed - ("p", "port", "", _("port to listen on (default: 8000)"), _("PORT")), ( - "a", - "address", - "", - _("address to listen on (default: all interfaces)"), - _("ADDR"), + b"p", + b"port", + b"", + _(b"port to listen on (default: 8000)"), + _(b"PORT"), ), ( - "", - "prefix", - "", - _("prefix path to serve from (default: server root)"), - _("PREFIX"), + b"a", + b"address", + b"", + _(b"address to listen on (default: all interfaces)"), + _(b"ADDR"), + ), + ( + b"", + b"prefix", + b"", + _(b"prefix path to serve from (default: server root)"), + _(b"PREFIX"), ), ( - "n", - "name", - "", - _("name to show in web pages (default: working directory)"), - _("NAME"), + b"n", + b"name", + b"", + _(b"name to show in web pages (default: working directory)"), + _(b"NAME"), ), ( - "", - "web-conf", - "", - _("name of the hgweb config file (see 'hg help hgweb')"), - _("FILE"), + b"", + b"web-conf", + b"", + _(b"name of the hgweb config file (see 'hg help hgweb')"), + _(b"FILE"), + ), + ( + b"", + b"webdir-conf", + b"", + _(b"name of the hgweb config file (DEPRECATED)"), + _(b"FILE"), ), ( - "", - "webdir-conf", - "", - _("name of the hgweb config file (DEPRECATED)"), - _("FILE"), + b"", + b"pid-file", + b"", + _(b"name of file to write process ID to"), + _(b"FILE"), ), + (b"", b"stdio", None, _(b"for remote clients (ADVANCED)")), ( - "", - "pid-file", - "", - _("name of file to write process ID to"), - _("FILE"), + b"", + b"cmdserver", + b"", + _(b"for remote clients (ADVANCED)"), + _(b"MODE"), ), - ("", "stdio", None, _("for remote clients (ADVANCED)")), - ("", "cmdserver", "", _("for remote clients (ADVANCED)"), _("MODE")), - ("t", "templates", "", _("web templates to use"), _("TEMPLATE")), - ("", "style", "", _("template style to use"), _("STYLE")), - ("6", "ipv6", None, _("use IPv6 in addition to IPv4")), - ("", "certificate", "", _("SSL certificate file"), _("FILE")), - ("", "print-url", None, _("start and print only the URL")), + (b"t", b"templates", b"", _(b"web templates to use"), _(b"TEMPLATE")), + (b"", b"style", b"", _(b"template style to use"), _(b"STYLE")), + (b"6", b"ipv6", None, _(b"use IPv6 in addition to IPv4")), + (b"", b"certificate", b"", _(b"SSL certificate file"), _(b"FILE")), + (b"", b"print-url", None, _(b"start and print only the URL")), ] + subrepoopts, - _("[OPTION]..."), + _(b"[OPTION]..."), helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, helpbasic=True, optionalrepo=True, @@ -6304,15 +6463,15 @@ """ opts = pycompat.byteskwargs(opts) - if opts["stdio"] and opts["cmdserver"]: - raise error.Abort(_("cannot use --stdio with --cmdserver")) - if opts["print_url"] and ui.verbose: - raise error.Abort(_("cannot use --print-url with --verbose")) - - if opts["stdio"]: + if opts[b"stdio"] and opts[b"cmdserver"]: + raise error.Abort(_(b"cannot use --stdio with --cmdserver")) + if opts[b"print_url"] and ui.verbose: + raise error.Abort(_(b"cannot use --print-url with --verbose")) + + if opts[b"stdio"]: if repo is None: raise error.RepoError( - _("there is no Mercurial repository here" " (.hg not found)") + _(b"there is no Mercurial repository here" b" (.hg not found)") ) s = wireprotoserver.sshserver(ui, repo) s.serve_forever() @@ -6322,56 +6481,62 @@ @command( - "shelve", + b"shelve", [ ( - "A", - "addremove", + b"A", + b"addremove", None, - _("mark new/missing files as added/removed before shelving"), + _(b"mark new/missing files as added/removed before shelving"), ), - ("u", "unknown", None, _("store unknown files in the shelve")), - ("", "cleanup", None, _("delete all shelved changes")), - ("", "date", "", _("shelve with the specified commit date"), _("DATE")), - ("d", "delete", None, _("delete the named shelved change(s)")), - ("e", "edit", False, _("invoke editor on commit messages")), + (b"u", b"unknown", None, _(b"store unknown files in the shelve")), + (b"", b"cleanup", None, _(b"delete all shelved changes")), ( - "k", - "keep", - False, - _("shelve, but keep changes in the working directory"), + b"", + b"date", + b"", + _(b"shelve with the specified commit date"), + _(b"DATE"), ), - ("l", "list", None, _("list current shelves")), - ("m", "message", "", _("use text as shelve message"), _("TEXT")), + (b"d", b"delete", None, _(b"delete the named shelved change(s)")), + (b"e", b"edit", False, _(b"invoke editor on commit messages")), ( - "n", - "name", - "", - _("use the given name for the shelved commit"), - _("NAME"), + b"k", + b"keep", + False, + _(b"shelve, but keep changes in the working directory"), + ), + (b"l", b"list", None, _(b"list current shelves")), + (b"m", b"message", b"", _(b"use text as shelve message"), _(b"TEXT")), + ( + b"n", + b"name", + b"", + _(b"use the given name for the shelved commit"), + _(b"NAME"), ), ( - "p", - "patch", + b"p", + b"patch", None, _( - "output patches for changes (provide the names of the shelved " - "changes as positional arguments)" + b"output patches for changes (provide the names of the shelved " + b"changes as positional arguments)" ), ), - ("i", "interactive", None, _("interactive mode")), + (b"i", b"interactive", None, _(b"interactive mode")), ( - "", - "stat", + b"", + b"stat", None, _( - "output diffstat-style summary of changes (provide the names of " - "the shelved changes as positional arguments)" + b"output diffstat-style summary of changes (provide the names of " + b"the shelved changes as positional arguments)" ), ), ] + cmdutil.walkopts, - _("hg shelve [OPTION]... [FILE]..."), + _(b"hg shelve [OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def shelve(ui, repo, *pats, **opts): @@ -6409,18 +6574,18 @@ """ opts = pycompat.byteskwargs(opts) allowables = [ - ("addremove", {"create"}), # 'create' is pseudo action - ("unknown", {"create"}), - ("cleanup", {"cleanup"}), + (b"addremove", {b"create"}), # 'create' is pseudo action + (b"unknown", {b"create"}), + (b"cleanup", {b"cleanup"}), # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests - ("delete", {"delete"}), - ("edit", {"create"}), - ("keep", {"create"}), - ("list", {"list"}), - ("message", {"create"}), - ("name", {"create"}), - ("patch", {"patch", "list"}), - ("stat", {"stat", "list"}), + (b"delete", {b"delete"}), + (b"edit", {b"create"}), + (b"keep", {b"create"}), + (b"list", {b"list"}), + (b"message", {b"create"}), + (b"name", {b"create"}), + (b"patch", {b"patch", b"list"}), + (b"stat", {b"stat", b"list"}), ] def checkopt(opt): @@ -6429,52 +6594,63 @@ if opts[i] and opt not in allowable: raise error.Abort( _( - "options '--%s' and '--%s' may not be " - "used together" + b"options '--%s' and '--%s' may not be " + b"used together" ) % (opt, i) ) return True - if checkopt("cleanup"): + if checkopt(b"cleanup"): if pats: - raise error.Abort(_("cannot specify names when using '--cleanup'")) + raise error.Abort(_(b"cannot specify names when using '--cleanup'")) return shelvemod.cleanupcmd(ui, repo) - elif checkopt("delete"): + elif checkopt(b"delete"): return shelvemod.deletecmd(ui, repo, pats) - elif checkopt("list"): + elif checkopt(b"list"): return shelvemod.listcmd(ui, repo, pats, opts) - elif checkopt("patch") or checkopt("stat"): + elif checkopt(b"patch") or checkopt(b"stat"): return shelvemod.patchcmds(ui, repo, pats, opts) else: return shelvemod.createcmd(ui, repo, pats, opts) -_NOTTERSE = "nothing" +_NOTTERSE = b"nothing" @command( - "status|st", + b"status|st", [ - ("A", "all", None, _("show status of all files")), - ("m", "modified", None, _("show only modified files")), - ("a", "added", None, _("show only added files")), - ("r", "removed", None, _("show only removed files")), - ("d", "deleted", None, _("show only deleted (but tracked) files")), - ("c", "clean", None, _("show only files without changes")), - ("u", "unknown", None, _("show only unknown (not tracked) files")), - ("i", "ignored", None, _("show only ignored files")), - ("n", "no-status", None, _("hide status prefix")), - ("t", "terse", _NOTTERSE, _("show the terse output (EXPERIMENTAL)")), - ("C", "copies", None, _("show source of copied files")), - ("0", "print0", None, _("end filenames with NUL, for use with xargs")), - ("", "rev", [], _("show difference from revision"), _("REV")), - ("", "change", "", _("list the changed files of a revision"), _("REV")), + (b"A", b"all", None, _(b"show status of all files")), + (b"m", b"modified", None, _(b"show only modified files")), + (b"a", b"added", None, _(b"show only added files")), + (b"r", b"removed", None, _(b"show only removed files")), + (b"d", b"deleted", None, _(b"show only deleted (but tracked) files")), + (b"c", b"clean", None, _(b"show only files without changes")), + (b"u", b"unknown", None, _(b"show only unknown (not tracked) files")), + (b"i", b"ignored", None, _(b"show only ignored files")), + (b"n", b"no-status", None, _(b"hide status prefix")), + (b"t", b"terse", _NOTTERSE, _(b"show the terse output (EXPERIMENTAL)")), + (b"C", b"copies", None, _(b"show source of copied files")), + ( + b"0", + b"print0", + None, + _(b"end filenames with NUL, for use with xargs"), + ), + (b"", b"rev", [], _(b"show difference from revision"), _(b"REV")), + ( + b"", + b"change", + b"", + _(b"list the changed files of a revision"), + _(b"REV"), + ), ] + walkopts + subrepoopts + formatteropts, - _("[OPTION]... [FILE]..."), + _(b"[OPTION]... [FILE]..."), helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, inferrepo=True, @@ -6576,47 +6752,47 @@ """ opts = pycompat.byteskwargs(opts) - revs = opts.get("rev") - change = opts.get("change") - terse = opts.get("terse") + revs = opts.get(b"rev") + change = opts.get(b"change") + terse = opts.get(b"terse") if terse is _NOTTERSE: if revs: - terse = "" + terse = b"" else: - terse = ui.config("commands", "status.terse") + terse = ui.config(b"commands", b"status.terse") if revs and change: - msg = _("cannot specify --rev and --change at the same time") + msg = _(b"cannot specify --rev and --change at the same time") raise error.Abort(msg) elif revs and terse: - msg = _("cannot use --terse with --rev") + msg = _(b"cannot use --terse with --rev") raise error.Abort(msg) elif change: - repo = scmutil.unhidehashlikerevs(repo, [change], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [change], b"nowarn") ctx2 = scmutil.revsingle(repo, change, None) ctx1 = ctx2.p1() else: - repo = scmutil.unhidehashlikerevs(repo, revs, "nowarn") + repo = scmutil.unhidehashlikerevs(repo, revs, b"nowarn") ctx1, ctx2 = scmutil.revpair(repo, revs) forcerelativevalue = None - if ui.hasconfig("commands", "status.relative"): - forcerelativevalue = ui.configbool("commands", "status.relative") + if ui.hasconfig(b"commands", b"status.relative"): + forcerelativevalue = ui.configbool(b"commands", b"status.relative") uipathfn = scmutil.getuipathfn( repo, legacyrelativevalue=bool(pats), forcerelativevalue=forcerelativevalue, ) - if opts.get("print0"): - end = "\0" + if opts.get(b"print0"): + end = b"\0" else: - end = "\n" + end = b"\n" copy = {} - states = "modified added removed deleted unknown ignored clean".split() + states = b"modified added removed deleted unknown ignored clean".split() show = [k for k in states if opts.get(k)] - if opts.get("all"): - show += ui.quiet and (states[:4] + ["clean"]) or states + if opts.get(b"all"): + show += ui.quiet and (states[:4] + [b"clean"]) or states if not show: if ui.quiet: @@ -6631,10 +6807,10 @@ ctx1.node(), ctx2.node(), m, - "ignored" in show or "i" in terse, + b"ignored" in show or b"i" in terse, clean=True, unknown=True, - listsubrepos=opts.get("subrepos"), + listsubrepos=opts.get(b"subrepos"), ) stat = cmdutil.tersedir(stat, terse) @@ -6643,53 +6819,53 @@ ctx1.node(), ctx2.node(), m, - "ignored" in show, - "clean" in show, - "unknown" in show, - opts.get("subrepos"), + b"ignored" in show, + b"clean" in show, + b"unknown" in show, + opts.get(b"subrepos"), ) - changestates = zip(states, pycompat.iterbytestr("MAR!?IC"), stat) + changestates = zip(states, pycompat.iterbytestr(b"MAR!?IC"), stat) if ( - opts.get("all") - or opts.get("copies") - or ui.configbool("ui", "statuscopies") - ) and not opts.get("no_status"): + opts.get(b"all") + or opts.get(b"copies") + or ui.configbool(b"ui", b"statuscopies") + ) and not opts.get(b"no_status"): copy = copies.pathcopies(ctx1, ctx2, m) - ui.pager("status") - fm = ui.formatter("status", opts) - fmt = "%s" + end - showchar = not opts.get("no_status") + ui.pager(b"status") + fm = ui.formatter(b"status", opts) + fmt = b"%s" + end + showchar = not opts.get(b"no_status") for state, char, files in changestates: if state in show: - label = "status." + state + label = b"status." + state for f in files: fm.startitem() fm.context(ctx=ctx2) fm.data(path=f) - fm.condwrite(showchar, "status", "%s ", char, label=label) + fm.condwrite(showchar, b"status", b"%s ", char, label=label) fm.plain(fmt % uipathfn(f), label=label) if f in copy: fm.data(source=copy[f]) fm.plain( - (" %s" + end) % uipathfn(copy[f]), - label="status.copied", + (b" %s" + end) % uipathfn(copy[f]), + label=b"status.copied", ) if ( - ui.verbose or ui.configbool("commands", "status.verbose") + ui.verbose or ui.configbool(b"commands", b"status.verbose") ) and not ui.plain(): cmdutil.morestatus(repo, fm) fm.end() @command( - "summary|sum", - [("", "remote", None, _("check for push and pull"))], - "[--remote]", + b"summary|sum", + [(b"", b"remote", None, _(b"check for push and pull"))], + b"[--remote]", helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, intents={INTENT_READONLY}, @@ -6707,7 +6883,7 @@ """ opts = pycompat.byteskwargs(opts) - ui.pager("summary") + ui.pager(b"summary") ctx = repo[None] parents = ctx.parents() pnode = parents[0].node() @@ -6716,9 +6892,9 @@ try: ms = mergemod.mergestate.read(repo) except error.UnsupportedMergeRecords as e: - s = " ".join(e.recordtypes) + s = b" ".join(e.recordtypes) ui.warn( - _("warning: merge state has unsupported record types: %s\n") % s + _(b"warning: merge state has unsupported record types: %s\n") % s ) unresolved = [] else: @@ -6729,54 +6905,54 @@ # shows a working directory parent *changeset*: # i18n: column positioning for "hg summary" ui.write( - _("parent: %d:%s ") % (p.rev(), p), + _(b"parent: %d:%s ") % (p.rev(), p), label=logcmdutil.changesetlabels(p), ) - ui.write(" ".join(p.tags()), label="log.tag") + ui.write(b" ".join(p.tags()), label=b"log.tag") if p.bookmarks(): marks.extend(p.bookmarks()) if p.rev() == -1: if not len(repo): - ui.write(_(" (empty repository)")) + ui.write(_(b" (empty repository)")) else: - ui.write(_(" (no revision checked out)")) + ui.write(_(b" (no revision checked out)")) if p.obsolete(): - ui.write(_(" (obsolete)")) + ui.write(_(b" (obsolete)")) if p.isunstable(): instabilities = ( - ui.label(instability, "trouble.%s" % instability) + ui.label(instability, b"trouble.%s" % instability) for instability in p.instabilities() ) - ui.write(" (" + ", ".join(instabilities) + ")") - ui.write("\n") + ui.write(b" (" + b", ".join(instabilities) + b")") + ui.write(b"\n") if p.description(): ui.status( - " " + p.description().splitlines()[0].strip() + "\n", - label="log.summary", + b" " + p.description().splitlines()[0].strip() + b"\n", + label=b"log.summary", ) branch = ctx.branch() bheads = repo.branchheads(branch) # i18n: column positioning for "hg summary" - m = _("branch: %s\n") % branch - if branch != "default": - ui.write(m, label="log.branch") + m = _(b"branch: %s\n") % branch + if branch != b"default": + ui.write(m, label=b"log.branch") else: - ui.status(m, label="log.branch") + ui.status(m, label=b"log.branch") if marks: active = repo._activebookmark # i18n: column positioning for "hg summary" - ui.write(_("bookmarks:"), label="log.bookmark") + ui.write(_(b"bookmarks:"), label=b"log.bookmark") if active is not None: if active in marks: - ui.write(" *" + active, label=bookmarks.activebookmarklabel) + ui.write(b" *" + active, label=bookmarks.activebookmarklabel) marks.remove(active) else: - ui.write(" [%s]" % active, label=bookmarks.activebookmarklabel) + ui.write(b" [%s]" % active, label=bookmarks.activebookmarklabel) for m in marks: - ui.write(" " + m, label="log.bookmark") - ui.write("\n", label="log.bookmark") + ui.write(b" " + m, label=b"log.bookmark") + ui.write(b"\n", label=b"log.bookmark") status = repo.status(unknown=True) @@ -6794,36 +6970,36 @@ subs = [s for s in ctx.substate if ctx.sub(s).dirty()] labels = [ - (ui.label(_("%d modified"), "status.modified"), status.modified), - (ui.label(_("%d added"), "status.added"), status.added), - (ui.label(_("%d removed"), "status.removed"), status.removed), - (ui.label(_("%d renamed"), "status.copied"), renamed), - (ui.label(_("%d copied"), "status.copied"), copied), - (ui.label(_("%d deleted"), "status.deleted"), status.deleted), - (ui.label(_("%d unknown"), "status.unknown"), status.unknown), - (ui.label(_("%d unresolved"), "resolve.unresolved"), unresolved), - (ui.label(_("%d subrepos"), "status.modified"), subs), + (ui.label(_(b"%d modified"), b"status.modified"), status.modified), + (ui.label(_(b"%d added"), b"status.added"), status.added), + (ui.label(_(b"%d removed"), b"status.removed"), status.removed), + (ui.label(_(b"%d renamed"), b"status.copied"), renamed), + (ui.label(_(b"%d copied"), b"status.copied"), copied), + (ui.label(_(b"%d deleted"), b"status.deleted"), status.deleted), + (ui.label(_(b"%d unknown"), b"status.unknown"), status.unknown), + (ui.label(_(b"%d unresolved"), b"resolve.unresolved"), unresolved), + (ui.label(_(b"%d subrepos"), b"status.modified"), subs), ] t = [] for l, s in labels: if s: t.append(l % len(s)) - t = ", ".join(t) + t = b", ".join(t) cleanworkdir = False - if repo.vfs.exists("graftstate"): - t += _(" (graft in progress)") - if repo.vfs.exists("updatestate"): - t += _(" (interrupted update)") + if repo.vfs.exists(b"graftstate"): + t += _(b" (graft in progress)") + if repo.vfs.exists(b"updatestate"): + t += _(b" (interrupted update)") elif len(parents) > 1: - t += _(" (merge)") + t += _(b" (merge)") elif branch != parents[0].branch(): - t += _(" (new branch)") + t += _(b" (new branch)") elif parents[0].closesbranch() and pnode in repo.branchheads( branch, closed=True ): - t += _(" (head closed)") + t += _(b" (head closed)") elif not ( status.modified or status.added @@ -6832,10 +7008,10 @@ or copied or subs ): - t += _(" (clean)") + t += _(b" (clean)") cleanworkdir = True elif pnode not in bheads: - t += _(" (new branch head)") + t += _(b" (new branch head)") if parents: pendingphase = max(p.phase() for p in parents) @@ -6843,14 +7019,14 @@ pendingphase = phases.public if pendingphase > phases.newcommitphase(ui): - t += " (%s)" % phases.phasenames[pendingphase] + t += b" (%s)" % phases.phasenames[pendingphase] if cleanworkdir: # i18n: column positioning for "hg summary" - ui.status(_("commit: %s\n") % t.strip()) + ui.status(_(b"commit: %s\n") % t.strip()) else: # i18n: column positioning for "hg summary" - ui.write(_("commit: %s\n") % t.strip()) + ui.write(_(b"commit: %s\n") % t.strip()) # all ancestors of branch heads - all ancestors of parent = new csets new = len( @@ -6859,43 +7035,43 @@ if new == 0: # i18n: column positioning for "hg summary" - ui.status(_("update: (current)\n")) + ui.status(_(b"update: (current)\n")) elif pnode not in bheads: # i18n: column positioning for "hg summary" - ui.write(_("update: %d new changesets (update)\n") % new) + ui.write(_(b"update: %d new changesets (update)\n") % new) else: # i18n: column positioning for "hg summary" ui.write( - _("update: %d new changesets, %d branch heads (merge)\n") + _(b"update: %d new changesets, %d branch heads (merge)\n") % (new, len(bheads)) ) t = [] - draft = len(repo.revs("draft()")) + draft = len(repo.revs(b"draft()")) if draft: - t.append(_("%d draft") % draft) - secret = len(repo.revs("secret()")) + t.append(_(b"%d draft") % draft) + secret = len(repo.revs(b"secret()")) if secret: - t.append(_("%d secret") % secret) + t.append(_(b"%d secret") % secret) if draft or secret: - ui.status(_("phases: %s\n") % ", ".join(t)) + ui.status(_(b"phases: %s\n") % b", ".join(t)) if obsolete.isenabled(repo, obsolete.createmarkersopt): - for trouble in ("orphan", "contentdivergent", "phasedivergent"): - numtrouble = len(repo.revs(trouble + "()")) + for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"): + numtrouble = len(repo.revs(trouble + b"()")) # We write all the possibilities to ease translation troublemsg = { - "orphan": _("orphan: %d changesets"), - "contentdivergent": _("content-divergent: %d changesets"), - "phasedivergent": _("phase-divergent: %d changesets"), + b"orphan": _(b"orphan: %d changesets"), + b"contentdivergent": _(b"content-divergent: %d changesets"), + b"phasedivergent": _(b"phase-divergent: %d changesets"), } if numtrouble > 0: - ui.status(troublemsg[trouble] % numtrouble + "\n") + ui.status(troublemsg[trouble] % numtrouble + b"\n") cmdutil.summaryhooks(ui, repo) - if opts.get("remote"): + if opts.get(b"remote"): needsincoming, needsoutgoing = True, True else: needsincoming, needsoutgoing = False, False @@ -6908,18 +7084,18 @@ return def getincoming(): - source, branches = hg.parseurl(ui.expandpath("default")) + source, branches = hg.parseurl(ui.expandpath(b"default")) sbranch = branches[0] try: other = hg.peer(repo, {}, source) except error.RepoError: - if opts.get("remote"): + if opts.get(b"remote"): raise return source, sbranch, None, None, None revs, checkout = hg.addbranchrevs(repo, other, branches, None) if revs: revs = [other.lookup(rev) for rev in revs] - ui.debug("comparing with %s\n" % util.hidepassword(source)) + ui.debug(b"comparing with %s\n" % util.hidepassword(source)) repo.ui.pushbuffer() commoninc = discovery.findcommonincoming(repo, other, heads=revs) repo.ui.popbuffer() @@ -6931,17 +7107,17 @@ source = sbranch = sother = commoninc = incoming = None def getoutgoing(): - dest, branches = hg.parseurl(ui.expandpath("default-push", "default")) + dest, branches = hg.parseurl(ui.expandpath(b"default-push", b"default")) dbranch = branches[0] revs, checkout = hg.addbranchrevs(repo, repo, branches, None) if source != dest: try: dother = hg.peer(repo, {}, dest) except error.RepoError: - if opts.get("remote"): + if opts.get(b"remote"): raise return dest, dbranch, None, None - ui.debug("comparing with %s\n" % util.hidepassword(dest)) + ui.debug(b"comparing with %s\n" % util.hidepassword(dest)) elif sother is None: # there is no explicit destination peer, but source one is invalid return dest, dbranch, None, None @@ -6965,27 +7141,27 @@ else: dest = dbranch = dother = outgoing = None - if opts.get("remote"): + if opts.get(b"remote"): t = [] if incoming: - t.append(_("1 or more incoming")) + t.append(_(b"1 or more incoming")) o = outgoing.missing if o: - t.append(_("%d outgoing") % len(o)) + t.append(_(b"%d outgoing") % len(o)) other = dother or sother - if "bookmarks" in other.listkeys("namespaces"): + if b"bookmarks" in other.listkeys(b"namespaces"): counts = bookmarks.summary(repo, other) if counts[0] > 0: - t.append(_("%d incoming bookmarks") % counts[0]) + t.append(_(b"%d incoming bookmarks") % counts[0]) if counts[1] > 0: - t.append(_("%d outgoing bookmarks") % counts[1]) + t.append(_(b"%d outgoing bookmarks") % counts[1]) if t: # i18n: column positioning for "hg summary" - ui.write(_("remote: %s\n") % (", ".join(t))) + ui.write(_(b"remote: %s\n") % (b", ".join(t))) else: # i18n: column positioning for "hg summary" - ui.status(_("remote: (synced)\n")) + ui.status(_(b"remote: (synced)\n")) cmdutil.summaryremotehooks( ui, @@ -6999,18 +7175,18 @@ @command( - "tag", + b"tag", [ - ("f", "force", None, _("force tag")), - ("l", "local", None, _("make the tag local")), - ("r", "rev", "", _("revision to tag"), _("REV")), - ("", "remove", None, _("remove a tag")), + (b"f", b"force", None, _(b"force tag")), + (b"l", b"local", None, _(b"make the tag local")), + (b"r", b"rev", b"", _(b"revision to tag"), _(b"REV")), + (b"", b"remove", None, _(b"remove a tag")), # -l/--local is already there, commitopts cannot be used - ("e", "edit", None, _("invoke editor on commit messages")), - ("m", "message", "", _("use text as commit message"), _("TEXT")), + (b"e", b"edit", None, _(b"invoke editor on commit messages")), + (b"m", b"message", b"", _(b"use text as commit message"), _(b"TEXT")), ] + commitopts2, - _("[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME..."), + _(b"[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME..."), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def tag(ui, repo, name1, *names, **opts): @@ -7047,105 +7223,107 @@ """ opts = pycompat.byteskwargs(opts) with repo.wlock(), repo.lock(): - rev_ = "." + rev_ = b"." names = [t.strip() for t in (name1,) + names] if len(names) != len(set(names)): - raise error.Abort(_("tag names must be unique")) + raise error.Abort(_(b"tag names must be unique")) for n in names: - scmutil.checknewlabel(repo, n, "tag") + scmutil.checknewlabel(repo, n, b"tag") if not n: raise error.Abort( - _("tag names cannot consist entirely of " "whitespace") + _(b"tag names cannot consist entirely of " b"whitespace") ) - if opts.get("rev") and opts.get("remove"): - raise error.Abort(_("--rev and --remove are incompatible")) - if opts.get("rev"): - rev_ = opts["rev"] - message = opts.get("message") - if opts.get("remove"): - if opts.get("local"): - expectedtype = "local" + if opts.get(b"rev") and opts.get(b"remove"): + raise error.Abort(_(b"--rev and --remove are incompatible")) + if opts.get(b"rev"): + rev_ = opts[b"rev"] + message = opts.get(b"message") + if opts.get(b"remove"): + if opts.get(b"local"): + expectedtype = b"local" else: - expectedtype = "global" + expectedtype = b"global" for n in names: - if repo.tagtype(n) == "global": + if repo.tagtype(n) == b"global": alltags = tagsmod.findglobaltags(ui, repo) if alltags[n][0] == nullid: - raise error.Abort(_("tag '%s' is already removed") % n) + raise error.Abort(_(b"tag '%s' is already removed") % n) if not repo.tagtype(n): - raise error.Abort(_("tag '%s' does not exist") % n) + raise error.Abort(_(b"tag '%s' does not exist") % n) if repo.tagtype(n) != expectedtype: - if expectedtype == "global": - raise error.Abort(_("tag '%s' is not a global tag") % n) + if expectedtype == b"global": + raise error.Abort( + _(b"tag '%s' is not a global tag") % n + ) else: - raise error.Abort(_("tag '%s' is not a local tag") % n) - rev_ = "null" + raise error.Abort(_(b"tag '%s' is not a local tag") % n) + rev_ = b"null" if not message: # we don't translate commit messages - message = "Removed tag %s" % ", ".join(names) - elif not opts.get("force"): + message = b"Removed tag %s" % b", ".join(names) + elif not opts.get(b"force"): for n in names: if n in repo.tags(): raise error.Abort( - _("tag '%s' already exists " "(use -f to force)") % n + _(b"tag '%s' already exists " b"(use -f to force)") % n ) - if not opts.get("local"): + if not opts.get(b"local"): p1, p2 = repo.dirstate.parents() if p2 != nullid: - raise error.Abort(_("uncommitted merge")) + raise error.Abort(_(b"uncommitted merge")) bheads = repo.branchheads() - if not opts.get("force") and bheads and p1 not in bheads: + if not opts.get(b"force") and bheads and p1 not in bheads: raise error.Abort( _( - "working directory is not at a branch head " - "(use -f to force)" + b"working directory is not at a branch head " + b"(use -f to force)" ) ) node = scmutil.revsingle(repo, rev_).node() if not message: # we don't translate commit messages - message = "Added tag %s for changeset %s" % ( - ", ".join(names), + message = b"Added tag %s for changeset %s" % ( + b", ".join(names), short(node), ) - date = opts.get("date") + date = opts.get(b"date") if date: date = dateutil.parsedate(date) - if opts.get("remove"): - editform = "tag.remove" + if opts.get(b"remove"): + editform = b"tag.remove" else: - editform = "tag.add" + editform = b"tag.add" editor = cmdutil.getcommiteditor( editform=editform, **pycompat.strkwargs(opts) ) # don't allow tagging the null rev if ( - not opts.get("remove") + not opts.get(b"remove") and scmutil.revsingle(repo, rev_).rev() == nullrev ): - raise error.Abort(_("cannot tag null revision")) + raise error.Abort(_(b"cannot tag null revision")) tagsmod.tag( repo, names, node, message, - opts.get("local"), - opts.get("user"), + opts.get(b"local"), + opts.get(b"user"), date, editor=editor, ) @command( - "tags", + b"tags", formatteropts, - "", + b"", helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, intents={INTENT_READONLY}, ) @@ -7170,45 +7348,45 @@ """ opts = pycompat.byteskwargs(opts) - ui.pager("tags") - fm = ui.formatter("tags", opts) + ui.pager(b"tags") + fm = ui.formatter(b"tags", opts) hexfunc = fm.hexfunc for t, n in reversed(repo.tagslist()): hn = hexfunc(n) - label = "tags.normal" - tagtype = "" - if repo.tagtype(t) == "local": - label = "tags.local" - tagtype = "local" + label = b"tags.normal" + tagtype = b"" + if repo.tagtype(t) == b"local": + label = b"tags.local" + tagtype = b"local" fm.startitem() fm.context(repo=repo) - fm.write("tag", "%s", t, label=label) - fmt = " " * (30 - encoding.colwidth(t)) + " %5d:%s" + fm.write(b"tag", b"%s", t, label=label) + fmt = b" " * (30 - encoding.colwidth(t)) + b" %5d:%s" fm.condwrite( not ui.quiet, - "rev node", + b"rev node", fmt, repo.changelog.rev(n), hn, label=label, ) fm.condwrite( - ui.verbose and tagtype, "type", " %s", tagtype, label=label + ui.verbose and tagtype, b"type", b" %s", tagtype, label=label ) - fm.plain("\n") + fm.plain(b"\n") fm.end() @command( - "tip", + b"tip", [ - ("p", "patch", None, _("show patch")), - ("g", "git", None, _("use git extended diff format")), + (b"p", b"patch", None, _(b"show patch")), + (b"g", b"git", None, _(b"use git extended diff format")), ] + templateopts, - _("[-p] [-g]"), + _(b"[-p] [-g]"), helpcategory=command.CATEGORY_CHANGE_NAVIGATION, ) def tip(ui, repo, **opts): @@ -7229,21 +7407,21 @@ """ opts = pycompat.byteskwargs(opts) displayer = logcmdutil.changesetdisplayer(ui, repo, opts) - displayer.show(repo["tip"]) + displayer.show(repo[b"tip"]) displayer.close() @command( - "unbundle", + b"unbundle", [ ( - "u", - "update", + b"u", + b"update", None, - _("update to new branch head if changesets were unbundled"), + _(b"update to new branch head if changesets were unbundled"), ) ], - _("[-u] FILE..."), + _(b"[-u] FILE..."), helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def unbundle(ui, repo, fname1, *fnames, **opts): @@ -7261,25 +7439,28 @@ gen = exchange.readbundle(ui, f, fname) if isinstance(gen, streamclone.streamcloneapplier): raise error.Abort( - _("packed bundles cannot be applied with " '"hg unbundle"'), - hint=_('use "hg debugapplystreamclonebundle"'), + _( + b"packed bundles cannot be applied with " + b'"hg unbundle"' + ), + hint=_(b'use "hg debugapplystreamclonebundle"'), ) - url = "bundle:" + fname + url = b"bundle:" + fname try: - txnname = "unbundle" + txnname = b"unbundle" if not isinstance(gen, bundle2.unbundle20): - txnname = "unbundle\n%s" % util.hidepassword(url) + txnname = b"unbundle\n%s" % util.hidepassword(url) with repo.transaction(txnname) as tr: op = bundle2.applybundle( - repo, gen, tr, source="unbundle", url=url + repo, gen, tr, source=b"unbundle", url=url ) except error.BundleUnknownFeatureError as exc: raise error.Abort( - _("%s: unknown bundle feature, %s") % (fname, exc), + _(b"%s: unknown bundle feature, %s") % (fname, exc), hint=_( - "see https://mercurial-scm.org/" - "wiki/BundleFeature for more " - "information" + b"see https://mercurial-scm.org/" + b"wiki/BundleFeature for more " + b"information" ), ) modheads = bundle2.combinechangegroupresults(op) @@ -7288,29 +7469,34 @@ @command( - "unshelve", + b"unshelve", [ - ("a", "abort", None, _("abort an incomplete unshelve operation")), - ("c", "continue", None, _("continue an incomplete unshelve operation")), - ("i", "interactive", None, _("use interactive mode (EXPERIMENTAL)")), - ("k", "keep", None, _("keep shelve after unshelving")), + (b"a", b"abort", None, _(b"abort an incomplete unshelve operation")), + ( + b"c", + b"continue", + None, + _(b"continue an incomplete unshelve operation"), + ), + (b"i", b"interactive", None, _(b"use interactive mode (EXPERIMENTAL)")), + (b"k", b"keep", None, _(b"keep shelve after unshelving")), ( - "n", - "name", - "", - _("restore shelved change with given name"), - _("NAME"), + b"n", + b"name", + b"", + _(b"restore shelved change with given name"), + _(b"NAME"), ), - ("t", "tool", "", _("specify merge tool")), + (b"t", b"tool", b"", _(b"specify merge tool")), ( - "", - "date", - "", - _("set date for temporary commits (DEPRECATED)"), - _("DATE"), + b"", + b"date", + b"", + _(b"set date for temporary commits (DEPRECATED)"), + _(b"DATE"), ), ], - _("hg unshelve [OPTION]... [FILE]... [-n SHELVED]"), + _(b"hg unshelve [OPTION]... [FILE]... [-n SHELVED]"), helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def unshelve(ui, repo, *shelved, **opts): @@ -7362,26 +7548,26 @@ statemod.addunfinished( - "unshelve", - fname="shelvedstate", + b"unshelve", + fname=b"shelvedstate", continueflag=True, abortfunc=shelvemod.hgabortunshelve, continuefunc=shelvemod.hgcontinueunshelve, - cmdmsg=_("unshelve already in progress"), + cmdmsg=_(b"unshelve already in progress"), ) @command( - "update|up|checkout|co", + b"update|up|checkout|co", [ - ("C", "clean", None, _("discard uncommitted changes (no backup)")), - ("c", "check", None, _("require clean working directory")), - ("m", "merge", None, _("merge uncommitted changes")), - ("d", "date", "", _("tipmost revision matching date"), _("DATE")), - ("r", "rev", "", _("revision"), _("REV")), + (b"C", b"clean", None, _(b"discard uncommitted changes (no backup)")), + (b"c", b"check", None, _(b"require clean working directory")), + (b"m", b"merge", None, _(b"merge uncommitted changes")), + (b"d", b"date", b"", _(b"tipmost revision matching date"), _(b"DATE")), + (b"r", b"rev", b"", _(b"revision"), _(b"REV")), ] + mergetoolopts, - _("[-C|-c|-m] [-d DATE] [[-r] REV]"), + _(b"[-C|-c|-m] [-d DATE] [[-r] REV]"), helpcategory=command.CATEGORY_WORKING_DIRECTORY, helpbasic=True, ) @@ -7446,34 +7632,34 @@ check = opts.get(r"check") merge = opts.get(r"merge") if rev and node: - raise error.Abort(_("please specify just one revision")) - - if ui.configbool("commands", "update.requiredest"): + raise error.Abort(_(b"please specify just one revision")) + + if ui.configbool(b"commands", b"update.requiredest"): if not node and not rev and not date: raise error.Abort( - _("you must specify a destination"), - hint=_('for example: hg update ".::"'), + _(b"you must specify a destination"), + hint=_(b'for example: hg update ".::"'), ) - if rev is None or rev == "": + if rev is None or rev == b"": rev = node if date and rev is not None: - raise error.Abort(_("you can't specify a revision and a date")) + raise error.Abort(_(b"you can't specify a revision and a date")) if len([x for x in (clean, check, merge) if x]) > 1: raise error.Abort( _( - "can only specify one of -C/--clean, -c/--check, " - "or -m/--merge" + b"can only specify one of -C/--clean, -c/--check, " + b"or -m/--merge" ) ) updatecheck = None if check: - updatecheck = "abort" + updatecheck = b"abort" elif merge: - updatecheck = "none" + updatecheck = b"none" with repo.wlock(): cmdutil.clearunfinished(repo) @@ -7483,28 +7669,28 @@ # if we defined a bookmark, we have to remember the original name brev = rev if rev: - repo = scmutil.unhidehashlikerevs(repo, [rev], "nowarn") + repo = scmutil.unhidehashlikerevs(repo, [rev], b"nowarn") ctx = scmutil.revsingle(repo, rev, default=None) rev = ctx.rev() hidden = ctx.hidden() - overrides = {("ui", "forcemerge"): opts.get(r"tool", "")} - with ui.configoverride(overrides, "update"): + overrides = {(b"ui", b"forcemerge"): opts.get(r"tool", b"")} + with ui.configoverride(overrides, b"update"): ret = hg.updatetotally( ui, repo, rev, brev, clean=clean, updatecheck=updatecheck ) if hidden: ctxstr = ctx.hex()[:12] - ui.warn(_("updated to hidden changeset %s\n") % ctxstr) + ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr) if ctx.obsolete(): obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx) - ui.warn("(%s)\n" % obsfatemsg) + ui.warn(b"(%s)\n" % obsfatemsg) return ret @command( - "verify", - [("", "full", False, "perform more checks (EXPERIMENTAL)")], + b"verify", + [(b"", b"full", False, b"perform more checks (EXPERIMENTAL)")], helpcategory=command.CATEGORY_MAINTENANCE, ) def verify(ui, repo, **opts): @@ -7526,13 +7712,13 @@ opts = pycompat.byteskwargs(opts) level = None - if opts["full"]: + if opts[b"full"]: level = verifymod.VERIFY_FULL return hg.verify(repo, level) @command( - "version", + b"version", [] + formatteropts, helpcategory=command.CATEGORY_HELP, norepo=True, @@ -7558,24 +7744,24 @@ """ opts = pycompat.byteskwargs(opts) if ui.verbose: - ui.pager("version") - fm = ui.formatter("version", opts) + ui.pager(b"version") + fm = ui.formatter(b"version", opts) fm.startitem() fm.write( - "ver", _("Mercurial Distributed SCM (version %s)\n"), util.version() + b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version() ) license = _( - "(see https://mercurial-scm.org for more information)\n" - "\nCopyright (C) 2005-2019 Matt Mackall and others\n" - "This is free software; see the source for copying conditions. " - "There is NO\nwarranty; " - "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" + b"(see https://mercurial-scm.org for more information)\n" + b"\nCopyright (C) 2005-2019 Matt Mackall and others\n" + b"This is free software; see the source for copying conditions. " + b"There is NO\nwarranty; " + b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) if not ui.quiet: fm.plain(license) if ui.verbose: - fm.plain(_("\nEnabled extensions:\n\n")) + fm.plain(_(b"\nEnabled extensions:\n\n")) # format names and versions into columns names = [] vers = [] @@ -7584,19 +7770,19 @@ names.append(name) vers.append(extensions.moduleversion(module) or None) isinternals.append(extensions.ismoduleinternal(module)) - fn = fm.nested("extensions", tmpl="{name}\n") + fn = fm.nested(b"extensions", tmpl=b"{name}\n") if names: - namefmt = " %%-%ds " % max(len(n) for n in names) - places = [_("external"), _("internal")] + namefmt = b" %%-%ds " % max(len(n) for n in names) + places = [_(b"external"), _(b"internal")] for n, v, p in zip(names, vers, isinternals): fn.startitem() - fn.condwrite(ui.verbose, "name", namefmt, n) + fn.condwrite(ui.verbose, b"name", namefmt, n) if ui.verbose: - fn.plain("%s " % places[p]) + fn.plain(b"%s " % places[p]) fn.data(bundled=p) - fn.condwrite(ui.verbose and v, "ver", "%s", v) + fn.condwrite(ui.verbose and v, b"ver", b"%s", v) if ui.verbose: - fn.plain("\n") + fn.plain(b"\n") fn.end() fm.end() @@ -7607,7 +7793,7 @@ overrides = [cmd for cmd in cmdtable if cmd in table] if overrides: ui.warn( - _("extension '%s' overrides commands: %s\n") - % (name, " ".join(overrides)) + _(b"extension '%s' overrides commands: %s\n") + % (name, b" ".join(overrides)) ) table.update(cmdtable) diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py --- a/mercurial/commandserver.py +++ b/mercurial/commandserver.py @@ -53,13 +53,13 @@ @property def name(self): - return "<%c-channel>" % self.channel + return b"<%c-channel>" % self.channel def write(self, data): if not data: return # single write() to guarantee the same atomicity as the underlying file - self.out.write(struct.pack(">cI", self.channel, len(data)) + data) + self.out.write(struct.pack(b">cI", self.channel, len(data)) + data) self.out.flush() def __getattr__(self, attr): @@ -119,7 +119,7 @@ @property def name(self): - return "<%c-channel>" % self.channel + return b"<%c-channel>" % self.channel def read(self, size=-1): if size < 0: @@ -138,34 +138,34 @@ def _read(self, size, channel): if not size: - return "" + return b"" assert size > 0 # tell the client we need at most size bytes - self.out.write(struct.pack(">cI", channel, size)) + self.out.write(struct.pack(b">cI", channel, size)) self.out.flush() length = self.in_.read(4) - length = struct.unpack(">I", length)[0] + length = struct.unpack(b">I", length)[0] if not length: - return "" + return b"" else: return self.in_.read(length) def readline(self, size=-1): if size < 0: size = self.maxchunksize - s = self._read(size, "L") + s = self._read(size, b"L") buf = s # keep asking for more until there's either no more or # we got a full line - while s and s[-1] != "\n": - s = self._read(size, "L") + while s and s[-1] != b"\n": + s = self._read(size, b"L") buf += s return buf else: - return self._read(size, "L") + return self._read(size, b"L") def __iter__(self): return self @@ -221,11 +221,11 @@ self.repo = self.repoui = None self._prereposetups = prereposetups - self.cdebug = channeledoutput(fout, "d") - self.cerr = channeledoutput(fout, "e") - self.cout = channeledoutput(fout, "o") - self.cin = channeledinput(fin, fout, "I") - self.cresult = channeledoutput(fout, "r") + self.cdebug = channeledoutput(fout, b"d") + self.cerr = channeledoutput(fout, b"e") + self.cout = channeledoutput(fout, b"o") + self.cin = channeledinput(fin, fout, b"I") + self.cresult = channeledoutput(fout, b"r") if self.ui.config(b"cmdserver", b"log") == b"-": # switch log stream of server's ui to the 'd' (debug) channel @@ -248,7 +248,7 @@ def _read(self, size): if not size: - return "" + return b"" data = self.client.read(size) @@ -264,16 +264,16 @@ format: data length (uint32), data """ - length = struct.unpack(">I", self._read(4))[0] + length = struct.unpack(b">I", self._read(4))[0] if not length: - return "" + return b"" return self._read(length) def _readlist(self): """read a list of NULL separated strings from the channel""" s = self._readstr() if s: - return s.split("\0") + return s.split(b"\0") else: return [] @@ -302,8 +302,8 @@ # any kind of interaction must use server channels, but chg may # replace channels by fully functional tty files. so nontty is # enforced only if cin is a channel. - if not util.safehasattr(self.cin, "fileno"): - ui.setconfig("ui", "nontty", "true", "commandserver") + if not util.safehasattr(self.cin, b"fileno"): + ui.setconfig(b"ui", b"nontty", b"true", b"commandserver") req = dispatch.request( args[:], @@ -318,10 +318,10 @@ try: ret = dispatch.dispatch(req) & 255 - self.cresult.write(struct.pack(">i", int(ret))) + self.cresult.write(struct.pack(b">i", int(ret))) finally: # restore old cwd - if "--cwd" in args: + if b"--cwd" in args: os.chdir(self.cwd) def getencoding(self): @@ -337,23 +337,23 @@ else: # clients are expected to check what commands are supported by # looking at the servers capabilities - raise error.Abort(_("unknown command %s") % cmd) + raise error.Abort(_(b"unknown command %s") % cmd) - return cmd != "" + return cmd != b"" - capabilities = {"runcommand": runcommand, "getencoding": getencoding} + capabilities = {b"runcommand": runcommand, b"getencoding": getencoding} def serve(self): - hellomsg = "capabilities: " + " ".join(sorted(self.capabilities)) - hellomsg += "\n" - hellomsg += "encoding: " + encoding.encoding - hellomsg += "\n" + hellomsg = b"capabilities: " + b" ".join(sorted(self.capabilities)) + hellomsg += b"\n" + hellomsg += b"encoding: " + encoding.encoding + hellomsg += b"\n" if self.cmsg: - hellomsg += "message-encoding: %s\n" % self.cmsg.encoding - hellomsg += "pid: %d" % procutil.getpid() - if util.safehasattr(os, "getpgid"): - hellomsg += "\n" - hellomsg += "pgid: %d" % os.getpgid(0) + hellomsg += b"message-encoding: %s\n" % self.cmsg.encoding + hellomsg += b"pid: %d" % procutil.getpid() + if util.safehasattr(os, b"getpgid"): + hellomsg += b"\n" + hellomsg += b"pgid: %d" % os.getpgid(0) # write the hello msg in -one- chunk self.cout.write(hellomsg) @@ -459,7 +459,7 @@ # handle exceptions that may be raised by command server. most of # known exceptions are caught by dispatch. except error.Abort as inst: - ui.error(_("abort: %s\n") % inst) + ui.error(_(b"abort: %s\n") % inst) except IOError as inst: if inst.errno != errno.EPIPE: raise @@ -473,7 +473,7 @@ if sv: cerr = sv.cerr else: - cerr = channeledoutput(fout, "e") + cerr = channeledoutput(fout, b"e") cerr.write(encoding.strtolocal(traceback.format_exc())) raise finally: @@ -500,7 +500,7 @@ def bindsocket(self, sock, address): util.bindunixsocket(sock, address) sock.listen(socket.SOMAXCONN) - self.ui.status(_("listening at %s\n") % address) + self.ui.status(_(b"listening at %s\n") % address) self.ui.flush() # avoid buffering of status message def unlinksocket(self, address): @@ -527,11 +527,11 @@ def __init__(self, ui, repo, opts, handler=None): self.ui = ui self.repo = repo - self.address = opts["address"] - if not util.safehasattr(socket, "AF_UNIX"): - raise error.Abort(_("unsupported platform")) + self.address = opts[b"address"] + if not util.safehasattr(socket, b"AF_UNIX"): + raise error.Abort(_(b"unsupported platform")) if not self.address: - raise error.Abort(_("no socket path specified with --address")) + raise error.Abort(_(b"no socket path specified with --address")) self._servicehandler = handler or unixservicehandler(ui) self._sock = None self._mainipc = None @@ -542,7 +542,7 @@ # experimental config: cmdserver.max-repo-cache maxlen = ui.configint(b"cmdserver", b"max-repo-cache") if maxlen < 0: - raise error.Abort(_("negative max-repo-cache size not allowed")) + raise error.Abort(_(b"negative max-repo-cache size not allowed")) self._repoloader = repocache.repoloader(ui, maxlen) def init(self): @@ -553,7 +553,7 @@ o = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM) self._mainipc, self._workeripc = o self._servicehandler.bindsocket(self._sock, self.address) - if util.safehasattr(procutil, "unblocksignal"): + if util.safehasattr(procutil, b"unblocksignal"): procutil.unblocksignal(signal.SIGCHLD) o = signal.signal(signal.SIGCHLD, self._sigchldhandler) self._oldsigchldhandler = o diff --git a/mercurial/config.py b/mercurial/config.py --- a/mercurial/config.py +++ b/mercurial/config.py @@ -79,7 +79,7 @@ return (section, item) def source(self, section, item): - return self._source.get((section, item), "") + return self._source.get((section, item), b"") def sections(self): return sorted(self._data.keys()) @@ -87,17 +87,17 @@ def items(self, section): return list(self._data.get(section, {}).iteritems()) - def set(self, section, item, value, source=""): + def set(self, section, item, value, source=b""): if pycompat.ispy3: assert not isinstance( section, str - ), "config section may not be unicode strings on Python 3" + ), b"config section may not be unicode strings on Python 3" assert not isinstance( item, str - ), "config item may not be unicode strings on Python 3" + ), b"config item may not be unicode strings on Python 3" assert not isinstance( value, str - ), "config values may not be unicode strings on Python 3" + ), b"config values may not be unicode strings on Python 3" if section not in self: self._data[section] = util.cowsortdict() else: @@ -131,7 +131,7 @@ commentre = util.re.compile(br"(;|#)") unsetre = util.re.compile(br"%unset\s+(\S+)") includere = util.re.compile(br"%include\s+(\S|\S.*\S)\s*$") - section = "" + section = b"" item = None line = 0 cont = False @@ -141,7 +141,7 @@ for l in data.splitlines(True): line += 1 - if line == 1 and l.startswith("\xef\xbb\xbf"): + if line == 1 and l.startswith(b"\xef\xbb\xbf"): # Someone set us up the BOM l = l[3:] if cont: @@ -151,8 +151,8 @@ if m: if sections and section not in sections: continue - v = self.get(section, item) + "\n" + m.group(1) - self.set(section, item, v, "%s:%d" % (src, line)) + v = self.get(section, item) + b"\n" + m.group(1) + self.set(section, item, v, b"%s:%d" % (src, line)) continue item = None cont = False @@ -171,9 +171,9 @@ except IOError as inst: if inst.errno != errno.ENOENT: raise error.ParseError( - _("cannot include %s (%s)") + _(b"cannot include %s (%s)") % (inc, inst.strerror), - "%s:%d" % (src, line), + b"%s:%d" % (src, line), ) continue if emptyre.match(l): @@ -192,7 +192,7 @@ cont = True if sections and section not in sections: continue - self.set(section, item, m.group(2), "%s:%d" % (src, line)) + self.set(section, item, m.group(2), b"%s:%d" % (src, line)) continue m = unsetre.match(l) if m: @@ -205,14 +205,14 @@ self._unset.append((section, name)) continue - raise error.ParseError(l.rstrip(), ("%s:%d" % (src, line))) + raise error.ParseError(l.rstrip(), (b"%s:%d" % (src, line))) def read(self, path, fp=None, sections=None, remap=None): if not fp: - fp = util.posixfile(path, "rb") + fp = util.posixfile(path, b"rb") assert ( getattr(fp, "mode", r"rb") == r"rb" - ), "config files must be opened in binary mode, got fp=%r mode=%r" % ( + ), b"config files must be opened in binary mode, got fp=%r mode=%r" % ( fp, fp.mode, ) @@ -231,41 +231,41 @@ def _parse_plain(parts, s, offset): whitespace = False while offset < len(s) and ( - s[offset : offset + 1].isspace() or s[offset : offset + 1] == "," + s[offset : offset + 1].isspace() or s[offset : offset + 1] == b"," ): whitespace = True offset += 1 if offset >= len(s): return None, parts, offset if whitespace: - parts.append("") - if s[offset : offset + 1] == '"' and not parts[-1]: + parts.append(b"") + if s[offset : offset + 1] == b'"' and not parts[-1]: return _parse_quote, parts, offset + 1 - elif s[offset : offset + 1] == '"' and parts[-1][-1:] == "\\": + elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b"\\": parts[-1] = parts[-1][:-1] + s[offset : offset + 1] return _parse_plain, parts, offset + 1 parts[-1] += s[offset : offset + 1] return _parse_plain, parts, offset + 1 def _parse_quote(parts, s, offset): - if offset < len(s) and s[offset : offset + 1] == '"': # "" - parts.append("") + if offset < len(s) and s[offset : offset + 1] == b'"': # "" + parts.append(b"") offset += 1 while offset < len(s) and ( s[offset : offset + 1].isspace() - or s[offset : offset + 1] == "," + or s[offset : offset + 1] == b"," ): offset += 1 return _parse_plain, parts, offset - while offset < len(s) and s[offset : offset + 1] != '"': + while offset < len(s) and s[offset : offset + 1] != b'"': if ( - s[offset : offset + 1] == "\\" + s[offset : offset + 1] == b"\\" and offset + 1 < len(s) - and s[offset + 1 : offset + 2] == '"' + and s[offset + 1 : offset + 2] == b'"' ): offset += 1 - parts[-1] += '"' + parts[-1] += b'"' else: parts[-1] += s[offset : offset + 1] offset += 1 @@ -273,39 +273,39 @@ if offset >= len(s): real_parts = _configlist(parts[-1]) if not real_parts: - parts[-1] = '"' + parts[-1] = b'"' else: - real_parts[0] = '"' + real_parts[0] + real_parts[0] = b'"' + real_parts[0] parts = parts[:-1] parts.extend(real_parts) return None, parts, offset offset += 1 - while offset < len(s) and s[offset : offset + 1] in [" ", ","]: + while offset < len(s) and s[offset : offset + 1] in [b" ", b","]: offset += 1 if offset < len(s): - if offset + 1 == len(s) and s[offset : offset + 1] == '"': - parts[-1] += '"' + if offset + 1 == len(s) and s[offset : offset + 1] == b'"': + parts[-1] += b'"' offset += 1 else: - parts.append("") + parts.append(b"") else: return None, parts, offset return _parse_plain, parts, offset def _configlist(s): - s = s.rstrip(" ,") + s = s.rstrip(b" ,") if not s: return [] - parser, parts, offset = _parse_plain, [""], 0 + parser, parts, offset = _parse_plain, [b""], 0 while parser: parser, parts, offset = parser(parts, s, offset) return parts if value is not None and isinstance(value, bytes): - result = _configlist(value.lstrip(" ,\n")) + result = _configlist(value.lstrip(b" ,\n")) else: result = value return result or [] diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -23,9 +23,9 @@ knownkeys = set(knownitems) newkeys = set(items) for key in sorted(knownkeys & newkeys): - msg = "extension '%s' overwrite config item '%s.%s'" + msg = b"extension '%s' overwrite config item '%s.%s'" msg %= (extname, section, key) - ui.develwarn(msg, config="warn-config") + ui.develwarn(msg, config=b"warn-config") knownitems.update(items) @@ -110,7 +110,7 @@ item = configitem(*args, **kwargs) section = configtable.setdefault(item.section, itemregister()) if item.name in section: - msg = "duplicated config item registration for '%s.%s'" + msg = b"duplicated config item registration for '%s.%s'" raise error.ProgrammingError(msg % (item.section, item.name)) section[item.name] = item @@ -131,1401 +131,1404 @@ coreconfigitem = getitemregister(coreitems) -def _registerdiffopts(section, configprefix=""): +def _registerdiffopts(section, configprefix=b""): coreconfigitem( - section, configprefix + "nodates", default=False, + section, configprefix + b"nodates", default=False, ) coreconfigitem( - section, configprefix + "showfunc", default=False, + section, configprefix + b"showfunc", default=False, ) coreconfigitem( - section, configprefix + "unified", default=None, + section, configprefix + b"unified", default=None, ) coreconfigitem( - section, configprefix + "git", default=False, + section, configprefix + b"git", default=False, ) coreconfigitem( - section, configprefix + "ignorews", default=False, + section, configprefix + b"ignorews", default=False, ) coreconfigitem( - section, configprefix + "ignorewsamount", default=False, + section, configprefix + b"ignorewsamount", default=False, ) coreconfigitem( - section, configprefix + "ignoreblanklines", default=False, + section, configprefix + b"ignoreblanklines", default=False, ) coreconfigitem( - section, configprefix + "ignorewseol", default=False, + section, configprefix + b"ignorewseol", default=False, ) coreconfigitem( - section, configprefix + "nobinary", default=False, + section, configprefix + b"nobinary", default=False, ) coreconfigitem( - section, configprefix + "noprefix", default=False, + section, configprefix + b"noprefix", default=False, ) coreconfigitem( - section, configprefix + "word-diff", default=False, + section, configprefix + b"word-diff", default=False, ) coreconfigitem( - "alias", ".*", default=dynamicdefault, generic=True, + b"alias", b".*", default=dynamicdefault, generic=True, ) coreconfigitem( - "auth", "cookiefile", default=None, + b"auth", b"cookiefile", default=None, ) -_registerdiffopts(section="annotate") +_registerdiffopts(section=b"annotate") # bookmarks.pushing: internal hack for discovery coreconfigitem( - "bookmarks", "pushing", default=list, + b"bookmarks", b"pushing", default=list, ) # bundle.mainreporoot: internal hack for bundlerepo coreconfigitem( - "bundle", "mainreporoot", default="", + b"bundle", b"mainreporoot", default=b"", ) coreconfigitem( - "censor", "policy", default="abort", experimental=True, + b"censor", b"policy", default=b"abort", experimental=True, ) coreconfigitem( - "chgserver", "idletimeout", default=3600, + b"chgserver", b"idletimeout", default=3600, ) coreconfigitem( - "chgserver", "skiphash", default=False, + b"chgserver", b"skiphash", default=False, ) coreconfigitem( - "cmdserver", "log", default=None, + b"cmdserver", b"log", default=None, ) coreconfigitem( - "cmdserver", "max-log-files", default=7, + b"cmdserver", b"max-log-files", default=7, ) coreconfigitem( - "cmdserver", "max-log-size", default="1 MB", + b"cmdserver", b"max-log-size", default=b"1 MB", ) coreconfigitem( - "cmdserver", "max-repo-cache", default=0, experimental=True, + b"cmdserver", b"max-repo-cache", default=0, experimental=True, ) coreconfigitem( - "cmdserver", "message-encodings", default=list, experimental=True, + b"cmdserver", b"message-encodings", default=list, experimental=True, ) coreconfigitem( - "cmdserver", - "track-log", - default=lambda: ["chgserver", "cmdserver", "repocache"], + b"cmdserver", + b"track-log", + default=lambda: [b"chgserver", b"cmdserver", b"repocache"], ) coreconfigitem( - "color", ".*", default=None, generic=True, + b"color", b".*", default=None, generic=True, ) coreconfigitem( - "color", "mode", default="auto", + b"color", b"mode", default=b"auto", ) coreconfigitem( - "color", "pagermode", default=dynamicdefault, + b"color", b"pagermode", default=dynamicdefault, ) -_registerdiffopts(section="commands", configprefix="commit.interactive.") +_registerdiffopts(section=b"commands", configprefix=b"commit.interactive.") coreconfigitem( - "commands", "commit.post-status", default=False, + b"commands", b"commit.post-status", default=False, ) coreconfigitem( - "commands", "grep.all-files", default=False, experimental=True, + b"commands", b"grep.all-files", default=False, experimental=True, ) coreconfigitem( - "commands", "resolve.confirm", default=False, + b"commands", b"resolve.confirm", default=False, ) coreconfigitem( - "commands", "resolve.explicit-re-merge", default=False, + b"commands", b"resolve.explicit-re-merge", default=False, ) coreconfigitem( - "commands", "resolve.mark-check", default="none", + b"commands", b"resolve.mark-check", default=b"none", ) -_registerdiffopts(section="commands", configprefix="revert.interactive.") +_registerdiffopts(section=b"commands", configprefix=b"revert.interactive.") coreconfigitem( - "commands", "show.aliasprefix", default=list, + b"commands", b"show.aliasprefix", default=list, ) coreconfigitem( - "commands", "status.relative", default=False, + b"commands", b"status.relative", default=False, ) coreconfigitem( - "commands", "status.skipstates", default=[], experimental=True, + b"commands", b"status.skipstates", default=[], experimental=True, ) coreconfigitem( - "commands", "status.terse", default="", + b"commands", b"status.terse", default=b"", ) coreconfigitem( - "commands", "status.verbose", default=False, + b"commands", b"status.verbose", default=False, ) coreconfigitem( - "commands", "update.check", default=None, + b"commands", b"update.check", default=None, ) coreconfigitem( - "commands", "update.requiredest", default=False, + b"commands", b"update.requiredest", default=False, ) coreconfigitem( - "committemplate", ".*", default=None, generic=True, + b"committemplate", b".*", default=None, generic=True, ) coreconfigitem( - "convert", "bzr.saverev", default=True, + b"convert", b"bzr.saverev", default=True, ) coreconfigitem( - "convert", "cvsps.cache", default=True, + b"convert", b"cvsps.cache", default=True, ) coreconfigitem( - "convert", "cvsps.fuzz", default=60, + b"convert", b"cvsps.fuzz", default=60, ) coreconfigitem( - "convert", "cvsps.logencoding", default=None, + b"convert", b"cvsps.logencoding", default=None, ) coreconfigitem( - "convert", "cvsps.mergefrom", default=None, + b"convert", b"cvsps.mergefrom", default=None, ) coreconfigitem( - "convert", "cvsps.mergeto", default=None, + b"convert", b"cvsps.mergeto", default=None, ) coreconfigitem( - "convert", "git.committeractions", default=lambda: ["messagedifferent"], + b"convert", b"git.committeractions", default=lambda: [b"messagedifferent"], ) coreconfigitem( - "convert", "git.extrakeys", default=list, + b"convert", b"git.extrakeys", default=list, ) coreconfigitem( - "convert", "git.findcopiesharder", default=False, + b"convert", b"git.findcopiesharder", default=False, ) coreconfigitem( - "convert", "git.remoteprefix", default="remote", + b"convert", b"git.remoteprefix", default=b"remote", ) coreconfigitem( - "convert", "git.renamelimit", default=400, + b"convert", b"git.renamelimit", default=400, ) coreconfigitem( - "convert", "git.saverev", default=True, + b"convert", b"git.saverev", default=True, ) coreconfigitem( - "convert", "git.similarity", default=50, + b"convert", b"git.similarity", default=50, ) coreconfigitem( - "convert", "git.skipsubmodules", default=False, + b"convert", b"git.skipsubmodules", default=False, ) coreconfigitem( - "convert", "hg.clonebranches", default=False, + b"convert", b"hg.clonebranches", default=False, ) coreconfigitem( - "convert", "hg.ignoreerrors", default=False, + b"convert", b"hg.ignoreerrors", default=False, ) coreconfigitem( - "convert", "hg.preserve-hash", default=False, + b"convert", b"hg.preserve-hash", default=False, ) coreconfigitem( - "convert", "hg.revs", default=None, + b"convert", b"hg.revs", default=None, ) coreconfigitem( - "convert", "hg.saverev", default=False, + b"convert", b"hg.saverev", default=False, ) coreconfigitem( - "convert", "hg.sourcename", default=None, + b"convert", b"hg.sourcename", default=None, ) coreconfigitem( - "convert", "hg.startrev", default=None, + b"convert", b"hg.startrev", default=None, ) coreconfigitem( - "convert", "hg.tagsbranch", default="default", + b"convert", b"hg.tagsbranch", default=b"default", ) coreconfigitem( - "convert", "hg.usebranchnames", default=True, + b"convert", b"hg.usebranchnames", default=True, ) coreconfigitem( - "convert", "ignoreancestorcheck", default=False, experimental=True, + b"convert", b"ignoreancestorcheck", default=False, experimental=True, ) coreconfigitem( - "convert", "localtimezone", default=False, + b"convert", b"localtimezone", default=False, ) coreconfigitem( - "convert", "p4.encoding", default=dynamicdefault, + b"convert", b"p4.encoding", default=dynamicdefault, ) coreconfigitem( - "convert", "p4.startrev", default=0, + b"convert", b"p4.startrev", default=0, ) coreconfigitem( - "convert", "skiptags", default=False, + b"convert", b"skiptags", default=False, ) coreconfigitem( - "convert", "svn.debugsvnlog", default=True, + b"convert", b"svn.debugsvnlog", default=True, ) coreconfigitem( - "convert", "svn.trunk", default=None, + b"convert", b"svn.trunk", default=None, ) coreconfigitem( - "convert", "svn.tags", default=None, + b"convert", b"svn.tags", default=None, ) coreconfigitem( - "convert", "svn.branches", default=None, + b"convert", b"svn.branches", default=None, ) coreconfigitem( - "convert", "svn.startrev", default=0, + b"convert", b"svn.startrev", default=0, ) coreconfigitem( - "debug", "dirstate.delaywrite", default=0, + b"debug", b"dirstate.delaywrite", default=0, ) coreconfigitem( - "defaults", ".*", default=None, generic=True, + b"defaults", b".*", default=None, generic=True, ) coreconfigitem( - "devel", "all-warnings", default=False, + b"devel", b"all-warnings", default=False, ) coreconfigitem( - "devel", "bundle2.debug", default=False, + b"devel", b"bundle2.debug", default=False, ) coreconfigitem( - "devel", "bundle.delta", default="", + b"devel", b"bundle.delta", default=b"", ) coreconfigitem( - "devel", "cache-vfs", default=None, + b"devel", b"cache-vfs", default=None, ) coreconfigitem( - "devel", "check-locks", default=False, + b"devel", b"check-locks", default=False, ) coreconfigitem( - "devel", "check-relroot", default=False, + b"devel", b"check-relroot", default=False, ) coreconfigitem( - "devel", "default-date", default=None, + b"devel", b"default-date", default=None, ) coreconfigitem( - "devel", "deprec-warn", default=False, + b"devel", b"deprec-warn", default=False, ) coreconfigitem( - "devel", "disableloaddefaultcerts", default=False, + b"devel", b"disableloaddefaultcerts", default=False, ) coreconfigitem( - "devel", "warn-empty-changegroup", default=False, + b"devel", b"warn-empty-changegroup", default=False, ) coreconfigitem( - "devel", "legacy.exchange", default=list, + b"devel", b"legacy.exchange", default=list, ) coreconfigitem( - "devel", "servercafile", default="", + b"devel", b"servercafile", default=b"", ) coreconfigitem( - "devel", "serverexactprotocol", default="", + b"devel", b"serverexactprotocol", default=b"", ) coreconfigitem( - "devel", "serverrequirecert", default=False, + b"devel", b"serverrequirecert", default=False, ) coreconfigitem( - "devel", "strip-obsmarkers", default=True, + b"devel", b"strip-obsmarkers", default=True, ) coreconfigitem( - "devel", "warn-config", default=None, + b"devel", b"warn-config", default=None, ) coreconfigitem( - "devel", "warn-config-default", default=None, + b"devel", b"warn-config-default", default=None, ) coreconfigitem( - "devel", "user.obsmarker", default=None, + b"devel", b"user.obsmarker", default=None, ) coreconfigitem( - "devel", "warn-config-unknown", default=None, + b"devel", b"warn-config-unknown", default=None, ) coreconfigitem( - "devel", "debug.copies", default=False, + b"devel", b"debug.copies", default=False, ) coreconfigitem( - "devel", "debug.extensions", default=False, + b"devel", b"debug.extensions", default=False, ) coreconfigitem( - "devel", "debug.peer-request", default=False, + b"devel", b"debug.peer-request", default=False, ) coreconfigitem( - "devel", "discovery.randomize", default=True, + b"devel", b"discovery.randomize", default=True, ) -_registerdiffopts(section="diff") +_registerdiffopts(section=b"diff") coreconfigitem( - "email", "bcc", default=None, + b"email", b"bcc", default=None, ) coreconfigitem( - "email", "cc", default=None, + b"email", b"cc", default=None, ) coreconfigitem( - "email", "charsets", default=list, + b"email", b"charsets", default=list, ) coreconfigitem( - "email", "from", default=None, + b"email", b"from", default=None, ) coreconfigitem( - "email", "method", default="smtp", + b"email", b"method", default=b"smtp", ) coreconfigitem( - "email", "reply-to", default=None, + b"email", b"reply-to", default=None, ) coreconfigitem( - "email", "to", default=None, + b"email", b"to", default=None, ) coreconfigitem( - "experimental", "archivemetatemplate", default=dynamicdefault, + b"experimental", b"archivemetatemplate", default=dynamicdefault, ) coreconfigitem( - "experimental", "auto-publish", default="publish", + b"experimental", b"auto-publish", default=b"publish", ) coreconfigitem( - "experimental", "bundle-phases", default=False, + b"experimental", b"bundle-phases", default=False, ) coreconfigitem( - "experimental", "bundle2-advertise", default=True, + b"experimental", b"bundle2-advertise", default=True, ) coreconfigitem( - "experimental", "bundle2-output-capture", default=False, + b"experimental", b"bundle2-output-capture", default=False, ) coreconfigitem( - "experimental", "bundle2.pushback", default=False, + b"experimental", b"bundle2.pushback", default=False, ) coreconfigitem( - "experimental", "bundle2lazylocking", default=False, + b"experimental", b"bundle2lazylocking", default=False, ) coreconfigitem( - "experimental", "bundlecomplevel", default=None, + b"experimental", b"bundlecomplevel", default=None, ) coreconfigitem( - "experimental", "bundlecomplevel.bzip2", default=None, + b"experimental", b"bundlecomplevel.bzip2", default=None, ) coreconfigitem( - "experimental", "bundlecomplevel.gzip", default=None, + b"experimental", b"bundlecomplevel.gzip", default=None, ) coreconfigitem( - "experimental", "bundlecomplevel.none", default=None, + b"experimental", b"bundlecomplevel.none", default=None, ) coreconfigitem( - "experimental", "bundlecomplevel.zstd", default=None, + b"experimental", b"bundlecomplevel.zstd", default=None, ) coreconfigitem( - "experimental", "changegroup3", default=False, + b"experimental", b"changegroup3", default=False, ) coreconfigitem( - "experimental", "cleanup-as-archived", default=False, + b"experimental", b"cleanup-as-archived", default=False, ) coreconfigitem( - "experimental", "clientcompressionengines", default=list, + b"experimental", b"clientcompressionengines", default=list, ) coreconfigitem( - "experimental", "copytrace", default="on", + b"experimental", b"copytrace", default=b"on", ) coreconfigitem( - "experimental", "copytrace.movecandidateslimit", default=100, + b"experimental", b"copytrace.movecandidateslimit", default=100, ) coreconfigitem( - "experimental", "copytrace.sourcecommitlimit", default=100, + b"experimental", b"copytrace.sourcecommitlimit", default=100, ) coreconfigitem( - "experimental", "copies.read-from", default="filelog-only", + b"experimental", b"copies.read-from", default=b"filelog-only", ) coreconfigitem( - "experimental", "copies.write-to", default="filelog-only", + b"experimental", b"copies.write-to", default=b"filelog-only", ) coreconfigitem( - "experimental", "crecordtest", default=None, + b"experimental", b"crecordtest", default=None, ) coreconfigitem( - "experimental", "directaccess", default=False, + b"experimental", b"directaccess", default=False, ) coreconfigitem( - "experimental", "directaccess.revnums", default=False, + b"experimental", b"directaccess.revnums", default=False, ) coreconfigitem( - "experimental", "editortmpinhg", default=False, + b"experimental", b"editortmpinhg", default=False, ) coreconfigitem( - "experimental", "evolution", default=list, + b"experimental", b"evolution", default=list, ) coreconfigitem( - "experimental", - "evolution.allowdivergence", + b"experimental", + b"evolution.allowdivergence", default=False, - alias=[("experimental", "allowdivergence")], + alias=[(b"experimental", b"allowdivergence")], ) coreconfigitem( - "experimental", "evolution.allowunstable", default=None, + b"experimental", b"evolution.allowunstable", default=None, ) coreconfigitem( - "experimental", "evolution.createmarkers", default=None, + b"experimental", b"evolution.createmarkers", default=None, ) coreconfigitem( - "experimental", - "evolution.effect-flags", + b"experimental", + b"evolution.effect-flags", default=True, - alias=[("experimental", "effect-flags")], + alias=[(b"experimental", b"effect-flags")], ) coreconfigitem( - "experimental", "evolution.exchange", default=None, + b"experimental", b"evolution.exchange", default=None, ) coreconfigitem( - "experimental", "evolution.bundle-obsmarker", default=False, + b"experimental", b"evolution.bundle-obsmarker", default=False, ) coreconfigitem( - "experimental", "log.topo", default=False, + b"experimental", b"log.topo", default=False, ) coreconfigitem( - "experimental", "evolution.report-instabilities", default=True, + b"experimental", b"evolution.report-instabilities", default=True, ) coreconfigitem( - "experimental", "evolution.track-operation", default=True, + b"experimental", b"evolution.track-operation", default=True, ) # repo-level config to exclude a revset visibility # # The target use case is to use `share` to expose different subset of the same # repository, especially server side. See also `server.view`. coreconfigitem( - "experimental", "extra-filter-revs", default=None, + b"experimental", b"extra-filter-revs", default=None, ) coreconfigitem( - "experimental", "maxdeltachainspan", default=-1, + b"experimental", b"maxdeltachainspan", default=-1, ) coreconfigitem( - "experimental", "mergetempdirprefix", default=None, + b"experimental", b"mergetempdirprefix", default=None, ) coreconfigitem( - "experimental", "mmapindexthreshold", default=None, + b"experimental", b"mmapindexthreshold", default=None, ) coreconfigitem( - "experimental", "narrow", default=False, + b"experimental", b"narrow", default=False, ) coreconfigitem( - "experimental", "nonnormalparanoidcheck", default=False, + b"experimental", b"nonnormalparanoidcheck", default=False, ) coreconfigitem( - "experimental", "exportableenviron", default=list, + b"experimental", b"exportableenviron", default=list, ) coreconfigitem( - "experimental", "extendedheader.index", default=None, + b"experimental", b"extendedheader.index", default=None, ) coreconfigitem( - "experimental", "extendedheader.similarity", default=False, + b"experimental", b"extendedheader.similarity", default=False, ) coreconfigitem( - "experimental", "graphshorten", default=False, + b"experimental", b"graphshorten", default=False, ) coreconfigitem( - "experimental", "graphstyle.parent", default=dynamicdefault, + b"experimental", b"graphstyle.parent", default=dynamicdefault, ) coreconfigitem( - "experimental", "graphstyle.missing", default=dynamicdefault, + b"experimental", b"graphstyle.missing", default=dynamicdefault, ) coreconfigitem( - "experimental", "graphstyle.grandparent", default=dynamicdefault, + b"experimental", b"graphstyle.grandparent", default=dynamicdefault, ) coreconfigitem( - "experimental", "hook-track-tags", default=False, + b"experimental", b"hook-track-tags", default=False, ) coreconfigitem( - "experimental", "httppeer.advertise-v2", default=False, + b"experimental", b"httppeer.advertise-v2", default=False, ) coreconfigitem( - "experimental", "httppeer.v2-encoder-order", default=None, + b"experimental", b"httppeer.v2-encoder-order", default=None, ) coreconfigitem( - "experimental", "httppostargs", default=False, + b"experimental", b"httppostargs", default=False, ) coreconfigitem( - "experimental", "mergedriver", default=None, + b"experimental", b"mergedriver", default=None, ) -coreconfigitem("experimental", "nointerrupt", default=False) -coreconfigitem("experimental", "nointerrupt-interactiveonly", default=True) +coreconfigitem(b"experimental", b"nointerrupt", default=False) +coreconfigitem(b"experimental", b"nointerrupt-interactiveonly", default=True) coreconfigitem( - "experimental", "obsmarkers-exchange-debug", default=False, + b"experimental", b"obsmarkers-exchange-debug", default=False, ) coreconfigitem( - "experimental", "remotenames", default=False, + b"experimental", b"remotenames", default=False, ) coreconfigitem( - "experimental", "removeemptydirs", default=True, + b"experimental", b"removeemptydirs", default=True, ) coreconfigitem( - "experimental", "revert.interactive.select-to-keep", default=False, + b"experimental", b"revert.interactive.select-to-keep", default=False, ) coreconfigitem( - "experimental", "revisions.prefixhexnode", default=False, + b"experimental", b"revisions.prefixhexnode", default=False, ) coreconfigitem( - "experimental", "revlogv2", default=None, + b"experimental", b"revlogv2", default=None, ) coreconfigitem( - "experimental", "revisions.disambiguatewithin", default=None, + b"experimental", b"revisions.disambiguatewithin", default=None, ) coreconfigitem( - "experimental", "server.filesdata.recommended-batch-size", default=50000, + b"experimental", b"server.filesdata.recommended-batch-size", default=50000, ) coreconfigitem( - "experimental", - "server.manifestdata.recommended-batch-size", + b"experimental", + b"server.manifestdata.recommended-batch-size", default=100000, ) coreconfigitem( - "experimental", "server.stream-narrow-clones", default=False, + b"experimental", b"server.stream-narrow-clones", default=False, ) coreconfigitem( - "experimental", "single-head-per-branch", default=False, + b"experimental", b"single-head-per-branch", default=False, ) coreconfigitem( - "experimental", - "single-head-per-branch:account-closed-heads", + b"experimental", + b"single-head-per-branch:account-closed-heads", default=False, ) coreconfigitem( - "experimental", "sshserver.support-v2", default=False, + b"experimental", b"sshserver.support-v2", default=False, ) coreconfigitem( - "experimental", "sparse-read", default=False, + b"experimental", b"sparse-read", default=False, ) coreconfigitem( - "experimental", "sparse-read.density-threshold", default=0.50, + b"experimental", b"sparse-read.density-threshold", default=0.50, ) coreconfigitem( - "experimental", "sparse-read.min-gap-size", default="65K", + b"experimental", b"sparse-read.min-gap-size", default=b"65K", ) coreconfigitem( - "experimental", "treemanifest", default=False, + b"experimental", b"treemanifest", default=False, ) coreconfigitem( - "experimental", "update.atomic-file", default=False, + b"experimental", b"update.atomic-file", default=False, ) coreconfigitem( - "experimental", "sshpeer.advertise-v2", default=False, + b"experimental", b"sshpeer.advertise-v2", default=False, ) coreconfigitem( - "experimental", "web.apiserver", default=False, + b"experimental", b"web.apiserver", default=False, ) coreconfigitem( - "experimental", "web.api.http-v2", default=False, + b"experimental", b"web.api.http-v2", default=False, ) coreconfigitem( - "experimental", "web.api.debugreflect", default=False, + b"experimental", b"web.api.debugreflect", default=False, ) coreconfigitem( - "experimental", "worker.wdir-get-thread-safe", default=False, + b"experimental", b"worker.wdir-get-thread-safe", default=False, ) coreconfigitem( - "experimental", "xdiff", default=False, + b"experimental", b"xdiff", default=False, ) coreconfigitem( - "extensions", ".*", default=None, generic=True, + b"extensions", b".*", default=None, generic=True, ) coreconfigitem( - "extdata", ".*", default=None, generic=True, + b"extdata", b".*", default=None, generic=True, ) coreconfigitem( - "format", "bookmarks-in-store", default=False, + b"format", b"bookmarks-in-store", default=False, ) coreconfigitem( - "format", "chunkcachesize", default=None, experimental=True, + b"format", b"chunkcachesize", default=None, experimental=True, ) coreconfigitem( - "format", "dotencode", default=True, + b"format", b"dotencode", default=True, ) coreconfigitem( - "format", "generaldelta", default=False, experimental=True, + b"format", b"generaldelta", default=False, experimental=True, ) coreconfigitem( - "format", "manifestcachesize", default=None, experimental=True, + b"format", b"manifestcachesize", default=None, experimental=True, ) coreconfigitem( - "format", "maxchainlen", default=dynamicdefault, experimental=True, + b"format", b"maxchainlen", default=dynamicdefault, experimental=True, ) coreconfigitem( - "format", "obsstore-version", default=None, + b"format", b"obsstore-version", default=None, ) coreconfigitem( - "format", "sparse-revlog", default=True, + b"format", b"sparse-revlog", default=True, ) coreconfigitem( - "format", - "revlog-compression", - default="zlib", - alias=[("experimental", "format.compression")], + b"format", + b"revlog-compression", + default=b"zlib", + alias=[(b"experimental", b"format.compression")], ) coreconfigitem( - "format", "usefncache", default=True, + b"format", b"usefncache", default=True, +) +coreconfigitem( + b"format", b"usegeneraldelta", default=True, ) coreconfigitem( - "format", "usegeneraldelta", default=True, + b"format", b"usestore", default=True, ) coreconfigitem( - "format", "usestore", default=True, + b"format", b"use-side-data", default=False, experimental=True, ) coreconfigitem( - "format", "use-side-data", default=False, experimental=True, + b"format", b"internal-phase", default=False, experimental=True, ) coreconfigitem( - "format", "internal-phase", default=False, experimental=True, + b"fsmonitor", b"warn_when_unused", default=True, ) coreconfigitem( - "fsmonitor", "warn_when_unused", default=True, + b"fsmonitor", b"warn_update_file_count", default=50000, ) coreconfigitem( - "fsmonitor", "warn_update_file_count", default=50000, + b"help", br"hidden-command\..*", default=False, generic=True, ) coreconfigitem( - "help", br"hidden-command\..*", default=False, generic=True, + b"help", br"hidden-topic\..*", default=False, generic=True, ) coreconfigitem( - "help", br"hidden-topic\..*", default=False, generic=True, + b"hooks", b".*", default=dynamicdefault, generic=True, ) coreconfigitem( - "hooks", ".*", default=dynamicdefault, generic=True, + b"hgweb-paths", b".*", default=list, generic=True, ) coreconfigitem( - "hgweb-paths", ".*", default=list, generic=True, + b"hostfingerprints", b".*", default=list, generic=True, ) coreconfigitem( - "hostfingerprints", ".*", default=list, generic=True, + b"hostsecurity", b"ciphers", default=None, ) coreconfigitem( - "hostsecurity", "ciphers", default=None, + b"hostsecurity", b"disabletls10warning", default=False, ) coreconfigitem( - "hostsecurity", "disabletls10warning", default=False, -) -coreconfigitem( - "hostsecurity", "minimumprotocol", default=dynamicdefault, + b"hostsecurity", b"minimumprotocol", default=dynamicdefault, ) coreconfigitem( - "hostsecurity", ".*:minimumprotocol$", default=dynamicdefault, generic=True, + b"hostsecurity", + b".*:minimumprotocol$", + default=dynamicdefault, + generic=True, ) coreconfigitem( - "hostsecurity", ".*:ciphers$", default=dynamicdefault, generic=True, + b"hostsecurity", b".*:ciphers$", default=dynamicdefault, generic=True, ) coreconfigitem( - "hostsecurity", ".*:fingerprints$", default=list, generic=True, + b"hostsecurity", b".*:fingerprints$", default=list, generic=True, ) coreconfigitem( - "hostsecurity", ".*:verifycertsfile$", default=None, generic=True, + b"hostsecurity", b".*:verifycertsfile$", default=None, generic=True, ) coreconfigitem( - "http_proxy", "always", default=False, + b"http_proxy", b"always", default=False, ) coreconfigitem( - "http_proxy", "host", default=None, + b"http_proxy", b"host", default=None, ) coreconfigitem( - "http_proxy", "no", default=list, + b"http_proxy", b"no", default=list, ) coreconfigitem( - "http_proxy", "passwd", default=None, + b"http_proxy", b"passwd", default=None, ) coreconfigitem( - "http_proxy", "user", default=None, + b"http_proxy", b"user", default=None, ) coreconfigitem( - "http", "timeout", default=None, + b"http", b"timeout", default=None, ) coreconfigitem( - "logtoprocess", "commandexception", default=None, + b"logtoprocess", b"commandexception", default=None, ) coreconfigitem( - "logtoprocess", "commandfinish", default=None, + b"logtoprocess", b"commandfinish", default=None, ) coreconfigitem( - "logtoprocess", "command", default=None, + b"logtoprocess", b"command", default=None, ) coreconfigitem( - "logtoprocess", "develwarn", default=None, + b"logtoprocess", b"develwarn", default=None, ) coreconfigitem( - "logtoprocess", "uiblocked", default=None, + b"logtoprocess", b"uiblocked", default=None, ) coreconfigitem( - "merge", "checkunknown", default="abort", + b"merge", b"checkunknown", default=b"abort", ) coreconfigitem( - "merge", "checkignored", default="abort", + b"merge", b"checkignored", default=b"abort", ) coreconfigitem( - "experimental", "merge.checkpathconflicts", default=False, + b"experimental", b"merge.checkpathconflicts", default=False, ) coreconfigitem( - "merge", "followcopies", default=True, + b"merge", b"followcopies", default=True, ) coreconfigitem( - "merge", "on-failure", default="continue", + b"merge", b"on-failure", default=b"continue", ) coreconfigitem( - "merge", "preferancestor", default=lambda: ["*"], experimental=True, + b"merge", b"preferancestor", default=lambda: [b"*"], experimental=True, ) coreconfigitem( - "merge", "strict-capability-check", default=False, + b"merge", b"strict-capability-check", default=False, ) coreconfigitem( - "merge-tools", ".*", default=None, generic=True, + b"merge-tools", b".*", default=None, generic=True, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.args$", - default="$local $base $other", + default=b"$local $base $other", generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.binary$", default=False, generic=True, priority=-1, + b"merge-tools", br".*\.binary$", default=False, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.check$", default=list, generic=True, priority=-1, + b"merge-tools", br".*\.check$", default=list, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.checkchanged$", default=False, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.executable$", default=dynamicdefault, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.fixeol$", default=False, generic=True, priority=-1, + b"merge-tools", br".*\.fixeol$", default=False, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.gui$", default=False, generic=True, priority=-1, + b"merge-tools", br".*\.gui$", default=False, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.mergemarkers$", - default="basic", + default=b"basic", generic=True, priority=-1, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.mergemarkertemplate$", default=dynamicdefault, # take from ui.mergemarkertemplate generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.priority$", default=0, generic=True, priority=-1, + b"merge-tools", br".*\.priority$", default=0, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", + b"merge-tools", br".*\.premerge$", default=dynamicdefault, generic=True, priority=-1, ) coreconfigitem( - "merge-tools", br".*\.symlink$", default=False, generic=True, priority=-1, + b"merge-tools", br".*\.symlink$", default=False, generic=True, priority=-1, ) coreconfigitem( - "pager", "attend-.*", default=dynamicdefault, generic=True, + b"pager", b"attend-.*", default=dynamicdefault, generic=True, ) coreconfigitem( - "pager", "ignore", default=list, + b"pager", b"ignore", default=list, ) coreconfigitem( - "pager", "pager", default=dynamicdefault, + b"pager", b"pager", default=dynamicdefault, ) coreconfigitem( - "patch", "eol", default="strict", + b"patch", b"eol", default=b"strict", ) coreconfigitem( - "patch", "fuzz", default=2, + b"patch", b"fuzz", default=2, ) coreconfigitem( - "paths", "default", default=None, + b"paths", b"default", default=None, ) coreconfigitem( - "paths", "default-push", default=None, + b"paths", b"default-push", default=None, ) coreconfigitem( - "paths", ".*", default=None, generic=True, + b"paths", b".*", default=None, generic=True, ) coreconfigitem( - "phases", "checksubrepos", default="follow", + b"phases", b"checksubrepos", default=b"follow", ) coreconfigitem( - "phases", "new-commit", default="draft", + b"phases", b"new-commit", default=b"draft", ) coreconfigitem( - "phases", "publish", default=True, + b"phases", b"publish", default=True, ) coreconfigitem( - "profiling", "enabled", default=False, + b"profiling", b"enabled", default=False, ) coreconfigitem( - "profiling", "format", default="text", + b"profiling", b"format", default=b"text", ) coreconfigitem( - "profiling", "freq", default=1000, + b"profiling", b"freq", default=1000, ) coreconfigitem( - "profiling", "limit", default=30, + b"profiling", b"limit", default=30, ) coreconfigitem( - "profiling", "nested", default=0, + b"profiling", b"nested", default=0, ) coreconfigitem( - "profiling", "output", default=None, + b"profiling", b"output", default=None, ) coreconfigitem( - "profiling", "showmax", default=0.999, + b"profiling", b"showmax", default=0.999, ) coreconfigitem( - "profiling", "showmin", default=dynamicdefault, + b"profiling", b"showmin", default=dynamicdefault, ) coreconfigitem( - "profiling", "showtime", default=True, + b"profiling", b"showtime", default=True, ) coreconfigitem( - "profiling", "sort", default="inlinetime", + b"profiling", b"sort", default=b"inlinetime", ) coreconfigitem( - "profiling", "statformat", default="hotpath", + b"profiling", b"statformat", default=b"hotpath", ) coreconfigitem( - "profiling", "time-track", default=dynamicdefault, + b"profiling", b"time-track", default=dynamicdefault, ) coreconfigitem( - "profiling", "type", default="stat", + b"profiling", b"type", default=b"stat", ) coreconfigitem( - "progress", "assume-tty", default=False, + b"progress", b"assume-tty", default=False, ) coreconfigitem( - "progress", "changedelay", default=1, + b"progress", b"changedelay", default=1, ) coreconfigitem( - "progress", "clear-complete", default=True, + b"progress", b"clear-complete", default=True, ) coreconfigitem( - "progress", "debug", default=False, + b"progress", b"debug", default=False, ) coreconfigitem( - "progress", "delay", default=3, + b"progress", b"delay", default=3, ) coreconfigitem( - "progress", "disable", default=False, + b"progress", b"disable", default=False, ) coreconfigitem( - "progress", "estimateinterval", default=60.0, + b"progress", b"estimateinterval", default=60.0, ) coreconfigitem( - "progress", - "format", - default=lambda: ["topic", "bar", "number", "estimate"], + b"progress", + b"format", + default=lambda: [b"topic", b"bar", b"number", b"estimate"], ) coreconfigitem( - "progress", "refresh", default=0.1, + b"progress", b"refresh", default=0.1, ) coreconfigitem( - "progress", "width", default=dynamicdefault, + b"progress", b"width", default=dynamicdefault, ) coreconfigitem( - "push", "pushvars.server", default=False, + b"push", b"pushvars.server", default=False, ) coreconfigitem( - "rewrite", - "backup-bundle", + b"rewrite", + b"backup-bundle", default=True, - alias=[("ui", "history-editing-backup")], + alias=[(b"ui", b"history-editing-backup")], ) coreconfigitem( - "rewrite", "update-timestamp", default=False, + b"rewrite", b"update-timestamp", default=False, ) coreconfigitem( - "storage", "new-repo-backend", default="revlogv1", experimental=True, + b"storage", b"new-repo-backend", default=b"revlogv1", experimental=True, ) coreconfigitem( - "storage", - "revlog.optimize-delta-parent-choice", + b"storage", + b"revlog.optimize-delta-parent-choice", default=True, - alias=[("format", "aggressivemergedeltas")], + alias=[(b"format", b"aggressivemergedeltas")], ) coreconfigitem( - "storage", "revlog.reuse-external-delta", default=True, + b"storage", b"revlog.reuse-external-delta", default=True, ) coreconfigitem( - "storage", "revlog.reuse-external-delta-parent", default=None, + b"storage", b"revlog.reuse-external-delta-parent", default=None, ) coreconfigitem( - "storage", "revlog.zlib.level", default=None, + b"storage", b"revlog.zlib.level", default=None, ) coreconfigitem( - "storage", "revlog.zstd.level", default=None, + b"storage", b"revlog.zstd.level", default=None, ) coreconfigitem( - "server", "bookmarks-pushkey-compat", default=True, + b"server", b"bookmarks-pushkey-compat", default=True, ) coreconfigitem( - "server", "bundle1", default=True, + b"server", b"bundle1", default=True, ) coreconfigitem( - "server", "bundle1gd", default=None, + b"server", b"bundle1gd", default=None, ) coreconfigitem( - "server", "bundle1.pull", default=None, + b"server", b"bundle1.pull", default=None, ) coreconfigitem( - "server", "bundle1gd.pull", default=None, + b"server", b"bundle1gd.pull", default=None, ) coreconfigitem( - "server", "bundle1.push", default=None, + b"server", b"bundle1.push", default=None, ) coreconfigitem( - "server", "bundle1gd.push", default=None, + b"server", b"bundle1gd.push", default=None, ) coreconfigitem( - "server", - "bundle2.stream", + b"server", + b"bundle2.stream", default=True, - alias=[("experimental", "bundle2.stream")], + alias=[(b"experimental", b"bundle2.stream")], ) coreconfigitem( - "server", "compressionengines", default=list, + b"server", b"compressionengines", default=list, ) coreconfigitem( - "server", "concurrent-push-mode", default="strict", + b"server", b"concurrent-push-mode", default=b"strict", ) coreconfigitem( - "server", "disablefullbundle", default=False, + b"server", b"disablefullbundle", default=False, ) coreconfigitem( - "server", "maxhttpheaderlen", default=1024, + b"server", b"maxhttpheaderlen", default=1024, ) coreconfigitem( - "server", "pullbundle", default=False, + b"server", b"pullbundle", default=False, ) coreconfigitem( - "server", "preferuncompressed", default=False, + b"server", b"preferuncompressed", default=False, ) coreconfigitem( - "server", "streamunbundle", default=False, + b"server", b"streamunbundle", default=False, ) coreconfigitem( - "server", "uncompressed", default=True, + b"server", b"uncompressed", default=True, ) coreconfigitem( - "server", "uncompressedallowsecret", default=False, + b"server", b"uncompressedallowsecret", default=False, ) coreconfigitem( - "server", "view", default="served", + b"server", b"view", default=b"served", ) coreconfigitem( - "server", "validate", default=False, + b"server", b"validate", default=False, ) coreconfigitem( - "server", "zliblevel", default=-1, + b"server", b"zliblevel", default=-1, ) coreconfigitem( - "server", "zstdlevel", default=3, + b"server", b"zstdlevel", default=3, ) coreconfigitem( - "share", "pool", default=None, + b"share", b"pool", default=None, ) coreconfigitem( - "share", "poolnaming", default="identity", + b"share", b"poolnaming", default=b"identity", ) coreconfigitem( - "shelve", "maxbackups", default=10, + b"shelve", b"maxbackups", default=10, ) coreconfigitem( - "smtp", "host", default=None, + b"smtp", b"host", default=None, ) coreconfigitem( - "smtp", "local_hostname", default=None, + b"smtp", b"local_hostname", default=None, ) coreconfigitem( - "smtp", "password", default=None, + b"smtp", b"password", default=None, ) coreconfigitem( - "smtp", "port", default=dynamicdefault, + b"smtp", b"port", default=dynamicdefault, ) coreconfigitem( - "smtp", "tls", default="none", + b"smtp", b"tls", default=b"none", ) coreconfigitem( - "smtp", "username", default=None, + b"smtp", b"username", default=None, ) coreconfigitem( - "sparse", "missingwarning", default=True, experimental=True, + b"sparse", b"missingwarning", default=True, experimental=True, ) coreconfigitem( - "subrepos", - "allowed", + b"subrepos", + b"allowed", default=dynamicdefault, # to make backporting simpler ) coreconfigitem( - "subrepos", "hg:allowed", default=dynamicdefault, + b"subrepos", b"hg:allowed", default=dynamicdefault, ) coreconfigitem( - "subrepos", "git:allowed", default=dynamicdefault, + b"subrepos", b"git:allowed", default=dynamicdefault, ) coreconfigitem( - "subrepos", "svn:allowed", default=dynamicdefault, + b"subrepos", b"svn:allowed", default=dynamicdefault, ) coreconfigitem( - "templates", ".*", default=None, generic=True, + b"templates", b".*", default=None, generic=True, ) coreconfigitem( - "templateconfig", ".*", default=dynamicdefault, generic=True, + b"templateconfig", b".*", default=dynamicdefault, generic=True, ) coreconfigitem( - "trusted", "groups", default=list, + b"trusted", b"groups", default=list, ) coreconfigitem( - "trusted", "users", default=list, + b"trusted", b"users", default=list, ) coreconfigitem( - "ui", "_usedassubrepo", default=False, + b"ui", b"_usedassubrepo", default=False, ) coreconfigitem( - "ui", "allowemptycommit", default=False, + b"ui", b"allowemptycommit", default=False, ) coreconfigitem( - "ui", "archivemeta", default=True, + b"ui", b"archivemeta", default=True, ) coreconfigitem( - "ui", "askusername", default=False, + b"ui", b"askusername", default=False, ) coreconfigitem( - "ui", "clonebundlefallback", default=False, + b"ui", b"clonebundlefallback", default=False, ) coreconfigitem( - "ui", "clonebundleprefers", default=list, + b"ui", b"clonebundleprefers", default=list, ) coreconfigitem( - "ui", "clonebundles", default=True, + b"ui", b"clonebundles", default=True, ) coreconfigitem( - "ui", "color", default="auto", + b"ui", b"color", default=b"auto", ) coreconfigitem( - "ui", "commitsubrepos", default=False, + b"ui", b"commitsubrepos", default=False, ) coreconfigitem( - "ui", "debug", default=False, + b"ui", b"debug", default=False, ) coreconfigitem( - "ui", "debugger", default=None, + b"ui", b"debugger", default=None, ) coreconfigitem( - "ui", "editor", default=dynamicdefault, + b"ui", b"editor", default=dynamicdefault, ) coreconfigitem( - "ui", "fallbackencoding", default=None, + b"ui", b"fallbackencoding", default=None, ) coreconfigitem( - "ui", "forcecwd", default=None, + b"ui", b"forcecwd", default=None, ) coreconfigitem( - "ui", "forcemerge", default=None, + b"ui", b"forcemerge", default=None, ) coreconfigitem( - "ui", "formatdebug", default=False, + b"ui", b"formatdebug", default=False, ) coreconfigitem( - "ui", "formatjson", default=False, + b"ui", b"formatjson", default=False, ) coreconfigitem( - "ui", "formatted", default=None, + b"ui", b"formatted", default=None, ) coreconfigitem( - "ui", "graphnodetemplate", default=None, + b"ui", b"graphnodetemplate", default=None, ) coreconfigitem( - "ui", "interactive", default=None, + b"ui", b"interactive", default=None, ) coreconfigitem( - "ui", "interface", default=None, + b"ui", b"interface", default=None, ) coreconfigitem( - "ui", "interface.chunkselector", default=None, + b"ui", b"interface.chunkselector", default=None, ) coreconfigitem( - "ui", "large-file-limit", default=10000000, + b"ui", b"large-file-limit", default=10000000, ) coreconfigitem( - "ui", "logblockedtimes", default=False, + b"ui", b"logblockedtimes", default=False, ) coreconfigitem( - "ui", "logtemplate", default=None, + b"ui", b"logtemplate", default=None, ) coreconfigitem( - "ui", "merge", default=None, + b"ui", b"merge", default=None, ) coreconfigitem( - "ui", "mergemarkers", default="basic", + b"ui", b"mergemarkers", default=b"basic", ) coreconfigitem( - "ui", - "mergemarkertemplate", + b"ui", + b"mergemarkertemplate", default=( - "{node|short} " - '{ifeq(tags, "tip", "", ' - 'ifeq(tags, "", "", "{tags} "))}' - '{if(bookmarks, "{bookmarks} ")}' - '{ifeq(branch, "default", "", "{branch} ")}' - "- {author|user}: {desc|firstline}" + b"{node|short} " + b'{ifeq(tags, "tip", "", ' + b'ifeq(tags, "", "", "{tags} "))}' + b'{if(bookmarks, "{bookmarks} ")}' + b'{ifeq(branch, "default", "", "{branch} ")}' + b"- {author|user}: {desc|firstline}" ), ) coreconfigitem( - "ui", "message-output", default="stdio", + b"ui", b"message-output", default=b"stdio", ) coreconfigitem( - "ui", "nontty", default=False, + b"ui", b"nontty", default=False, ) coreconfigitem( - "ui", "origbackuppath", default=None, + b"ui", b"origbackuppath", default=None, ) coreconfigitem( - "ui", "paginate", default=True, + b"ui", b"paginate", default=True, ) coreconfigitem( - "ui", "patch", default=None, + b"ui", b"patch", default=None, ) coreconfigitem( - "ui", "pre-merge-tool-output-template", default=None, + b"ui", b"pre-merge-tool-output-template", default=None, ) coreconfigitem( - "ui", "portablefilenames", default="warn", + b"ui", b"portablefilenames", default=b"warn", ) coreconfigitem( - "ui", "promptecho", default=False, + b"ui", b"promptecho", default=False, ) coreconfigitem( - "ui", "quiet", default=False, + b"ui", b"quiet", default=False, ) coreconfigitem( - "ui", "quietbookmarkmove", default=False, + b"ui", b"quietbookmarkmove", default=False, ) coreconfigitem( - "ui", "relative-paths", default="legacy", + b"ui", b"relative-paths", default=b"legacy", ) coreconfigitem( - "ui", "remotecmd", default="hg", + b"ui", b"remotecmd", default=b"hg", ) coreconfigitem( - "ui", "report_untrusted", default=True, + b"ui", b"report_untrusted", default=True, ) coreconfigitem( - "ui", "rollback", default=True, + b"ui", b"rollback", default=True, ) coreconfigitem( - "ui", "signal-safe-lock", default=True, + b"ui", b"signal-safe-lock", default=True, ) coreconfigitem( - "ui", "slash", default=False, + b"ui", b"slash", default=False, ) coreconfigitem( - "ui", "ssh", default="ssh", + b"ui", b"ssh", default=b"ssh", ) coreconfigitem( - "ui", "ssherrorhint", default=None, + b"ui", b"ssherrorhint", default=None, ) coreconfigitem( - "ui", "statuscopies", default=False, + b"ui", b"statuscopies", default=False, ) coreconfigitem( - "ui", "strict", default=False, + b"ui", b"strict", default=False, ) coreconfigitem( - "ui", "style", default="", + b"ui", b"style", default=b"", ) coreconfigitem( - "ui", "supportcontact", default=None, + b"ui", b"supportcontact", default=None, ) coreconfigitem( - "ui", "textwidth", default=78, + b"ui", b"textwidth", default=78, ) coreconfigitem( - "ui", "timeout", default="600", + b"ui", b"timeout", default=b"600", ) coreconfigitem( - "ui", "timeout.warn", default=0, + b"ui", b"timeout.warn", default=0, ) coreconfigitem( - "ui", "traceback", default=False, + b"ui", b"traceback", default=False, ) coreconfigitem( - "ui", "tweakdefaults", default=False, + b"ui", b"tweakdefaults", default=False, ) -coreconfigitem("ui", "username", alias=[("ui", "user")]) +coreconfigitem(b"ui", b"username", alias=[(b"ui", b"user")]) coreconfigitem( - "ui", "verbose", default=False, + b"ui", b"verbose", default=False, ) coreconfigitem( - "verify", "skipflags", default=None, + b"verify", b"skipflags", default=None, ) coreconfigitem( - "web", "allowbz2", default=False, + b"web", b"allowbz2", default=False, ) coreconfigitem( - "web", "allowgz", default=False, + b"web", b"allowgz", default=False, ) coreconfigitem( - "web", "allow-pull", alias=[("web", "allowpull")], default=True, + b"web", b"allow-pull", alias=[(b"web", b"allowpull")], default=True, ) coreconfigitem( - "web", "allow-push", alias=[("web", "allow_push")], default=list, + b"web", b"allow-push", alias=[(b"web", b"allow_push")], default=list, ) coreconfigitem( - "web", "allowzip", default=False, + b"web", b"allowzip", default=False, ) coreconfigitem( - "web", "archivesubrepos", default=False, + b"web", b"archivesubrepos", default=False, ) coreconfigitem( - "web", "cache", default=True, + b"web", b"cache", default=True, ) coreconfigitem( - "web", "comparisoncontext", default=5, + b"web", b"comparisoncontext", default=5, ) coreconfigitem( - "web", "contact", default=None, + b"web", b"contact", default=None, ) coreconfigitem( - "web", "deny_push", default=list, + b"web", b"deny_push", default=list, ) coreconfigitem( - "web", "guessmime", default=False, + b"web", b"guessmime", default=False, ) coreconfigitem( - "web", "hidden", default=False, + b"web", b"hidden", default=False, ) coreconfigitem( - "web", "labels", default=list, + b"web", b"labels", default=list, ) coreconfigitem( - "web", "logoimg", default="hglogo.png", + b"web", b"logoimg", default=b"hglogo.png", ) coreconfigitem( - "web", "logourl", default="https://mercurial-scm.org/", + b"web", b"logourl", default=b"https://mercurial-scm.org/", ) coreconfigitem( - "web", "accesslog", default="-", + b"web", b"accesslog", default=b"-", ) coreconfigitem( - "web", "address", default="", + b"web", b"address", default=b"", ) coreconfigitem( - "web", "allow-archive", alias=[("web", "allow_archive")], default=list, + b"web", b"allow-archive", alias=[(b"web", b"allow_archive")], default=list, ) coreconfigitem( - "web", "allow_read", default=list, + b"web", b"allow_read", default=list, ) coreconfigitem( - "web", "baseurl", default=None, + b"web", b"baseurl", default=None, ) coreconfigitem( - "web", "cacerts", default=None, + b"web", b"cacerts", default=None, ) coreconfigitem( - "web", "certificate", default=None, + b"web", b"certificate", default=None, ) coreconfigitem( - "web", "collapse", default=False, + b"web", b"collapse", default=False, ) coreconfigitem( - "web", "csp", default=None, + b"web", b"csp", default=None, ) coreconfigitem( - "web", "deny_read", default=list, + b"web", b"deny_read", default=list, ) coreconfigitem( - "web", "descend", default=True, + b"web", b"descend", default=True, ) coreconfigitem( - "web", "description", default="", + b"web", b"description", default=b"", ) coreconfigitem( - "web", "encoding", default=lambda: encoding.encoding, + b"web", b"encoding", default=lambda: encoding.encoding, ) coreconfigitem( - "web", "errorlog", default="-", + b"web", b"errorlog", default=b"-", ) coreconfigitem( - "web", "ipv6", default=False, + b"web", b"ipv6", default=False, ) coreconfigitem( - "web", "maxchanges", default=10, + b"web", b"maxchanges", default=10, ) coreconfigitem( - "web", "maxfiles", default=10, + b"web", b"maxfiles", default=10, ) coreconfigitem( - "web", "maxshortchanges", default=60, + b"web", b"maxshortchanges", default=60, ) coreconfigitem( - "web", "motd", default="", + b"web", b"motd", default=b"", ) coreconfigitem( - "web", "name", default=dynamicdefault, + b"web", b"name", default=dynamicdefault, ) coreconfigitem( - "web", "port", default=8000, + b"web", b"port", default=8000, ) coreconfigitem( - "web", "prefix", default="", + b"web", b"prefix", default=b"", ) coreconfigitem( - "web", "push_ssl", default=True, + b"web", b"push_ssl", default=True, ) coreconfigitem( - "web", "refreshinterval", default=20, + b"web", b"refreshinterval", default=20, ) coreconfigitem( - "web", "server-header", default=None, + b"web", b"server-header", default=None, ) coreconfigitem( - "web", "static", default=None, + b"web", b"static", default=None, ) coreconfigitem( - "web", "staticurl", default=None, + b"web", b"staticurl", default=None, ) coreconfigitem( - "web", "stripes", default=1, + b"web", b"stripes", default=1, ) coreconfigitem( - "web", "style", default="paper", + b"web", b"style", default=b"paper", ) coreconfigitem( - "web", "templates", default=None, + b"web", b"templates", default=None, ) coreconfigitem( - "web", "view", default="served", experimental=True, + b"web", b"view", default=b"served", experimental=True, ) coreconfigitem( - "worker", "backgroundclose", default=dynamicdefault, + b"worker", b"backgroundclose", default=dynamicdefault, ) # Windows defaults to a limit of 512 open files. A buffer of 128 # should give us enough headway. coreconfigitem( - "worker", "backgroundclosemaxqueue", default=384, + b"worker", b"backgroundclosemaxqueue", default=384, ) coreconfigitem( - "worker", "backgroundcloseminfilecount", default=2048, + b"worker", b"backgroundcloseminfilecount", default=2048, ) coreconfigitem( - "worker", "backgroundclosethreadcount", default=4, + b"worker", b"backgroundclosethreadcount", default=4, ) coreconfigitem( - "worker", "enabled", default=True, + b"worker", b"enabled", default=True, ) coreconfigitem( - "worker", "numcpus", default=None, + b"worker", b"numcpus", default=None, ) # Rebase related configuration moved to core because other extension are doing # strange things. For example, shelve import the extensions to reuse some bit # without formally loading it. coreconfigitem( - "commands", "rebase.requiredest", default=False, + b"commands", b"rebase.requiredest", default=False, ) coreconfigitem( - "experimental", "rebaseskipobsolete", default=True, + b"experimental", b"rebaseskipobsolete", default=True, ) coreconfigitem( - "rebase", "singletransaction", default=False, + b"rebase", b"singletransaction", default=False, ) coreconfigitem( - "rebase", "experimental.inmemory", default=False, + b"rebase", b"experimental.inmemory", default=False, ) diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -201,29 +201,29 @@ def obsolete(self): """True if the changeset is obsolete""" - return self.rev() in obsmod.getrevs(self._repo, "obsolete") + return self.rev() in obsmod.getrevs(self._repo, b"obsolete") def extinct(self): """True if the changeset is extinct""" - return self.rev() in obsmod.getrevs(self._repo, "extinct") + return self.rev() in obsmod.getrevs(self._repo, b"extinct") def orphan(self): """True if the changeset is not obsolete, but its ancestor is""" - return self.rev() in obsmod.getrevs(self._repo, "orphan") + return self.rev() in obsmod.getrevs(self._repo, b"orphan") def phasedivergent(self): """True if the changeset tries to be a successor of a public changeset Only non-public and non-obsolete changesets may be phase-divergent. """ - return self.rev() in obsmod.getrevs(self._repo, "phasedivergent") + return self.rev() in obsmod.getrevs(self._repo, b"phasedivergent") def contentdivergent(self): """Is a successor of a changeset with multiple possible successor sets Only non-public and non-obsolete changesets may be content-divergent. """ - return self.rev() in obsmod.getrevs(self._repo, "contentdivergent") + return self.rev() in obsmod.getrevs(self._repo, b"contentdivergent") def isunstable(self): """True if the changeset is either orphan, phase-divergent or @@ -240,11 +240,11 @@ """ instabilities = [] if self.orphan(): - instabilities.append("orphan") + instabilities.append(b"orphan") if self.phasedivergent(): - instabilities.append("phase-divergent") + instabilities.append(b"phase-divergent") if self.contentdivergent(): - instabilities.append("content-divergent") + instabilities.append(b"content-divergent") return instabilities def parents(self): @@ -266,7 +266,7 @@ return self._manifest[path], self._manifest.flags(path) except KeyError: raise error.ManifestLookupError( - self._node, path, _("not found in manifest") + self._node, path, _(b"not found in manifest") ) if r"_manifestdelta" in self.__dict__ or path in self.files(): if path in self._manifestdelta: @@ -279,7 +279,7 @@ node, flag = mfl[self._changeset.manifest].find(path) except KeyError: raise error.ManifestLookupError( - self._node, path, _("not found in manifest") + self._node, path, _(b"not found in manifest") ) return node, flag @@ -291,7 +291,7 @@ try: return self._fileinfo(path)[1] except error.LookupError: - return "" + return b"" @propertycache def _copies(self): @@ -321,7 +321,7 @@ pats=None, include=None, exclude=None, - default="glob", + default=b"glob", listsubrepos=False, badfn=None, ): @@ -446,7 +446,7 @@ listsubrepos=True, ) for rfiles, sfiles in zip(r, s): - rfiles.extend("%s/%s" % (subpath, f) for f in sfiles) + rfiles.extend(b"%s/%s" % (subpath, f) for f in sfiles) for l in r: l.sort() @@ -529,12 +529,12 @@ return sorted(modified) def filesadded(self): - source = self._repo.ui.config("experimental", "copies.read-from") + source = self._repo.ui.config(b"experimental", b"copies.read-from") filesadded = self._changeset.filesadded - if source == "changeset-only": + if source == b"changeset-only": if filesadded is None: filesadded = [] - elif source == "compatibility": + elif source == b"compatibility": if filesadded is None: filesadded = scmutil.computechangesetfilesadded(self) else: @@ -542,12 +542,12 @@ return filesadded def filesremoved(self): - source = self._repo.ui.config("experimental", "copies.read-from") + source = self._repo.ui.config(b"experimental", b"copies.read-from") filesremoved = self._changeset.filesremoved - if source == "changeset-only": + if source == b"changeset-only": if filesremoved is None: filesremoved = [] - elif source == "compatibility": + elif source == b"compatibility": if filesremoved is None: filesremoved = scmutil.computechangesetfilesremoved(self) else: @@ -556,7 +556,7 @@ @propertycache def _copies(self): - source = self._repo.ui.config("experimental", "copies.read-from") + source = self._repo.ui.config(b"experimental", b"copies.read-from") p1copies = self._changeset.p1copies p2copies = self._changeset.p2copies # If config says to get copy metadata only from changeset, then return @@ -564,12 +564,12 @@ # In compatibility mode, we return copy data from the changeset if # it was recorded there, and otherwise we fall back to getting it from # the filelogs (below). - if source == "changeset-only": + if source == b"changeset-only": if p1copies is None: p1copies = {} if p2copies is None: p2copies = {} - elif source == "compatibility": + elif source == b"compatibility": if p1copies is None: # we are in compatiblity mode and there is not data in the # changeset), we get the copy metadata from the filelogs. @@ -584,10 +584,10 @@ return self._changeset.description def branch(self): - return encoding.tolocal(self._changeset.extra.get("branch")) + return encoding.tolocal(self._changeset.extra.get(b"branch")) def closesbranch(self): - return "close" in self._changeset.extra + return b"close" in self._changeset.extra def extra(self): """Return a dict of extra information.""" @@ -605,7 +605,7 @@ return self._repo._phasecache.phase(self._repo, self._rev) def hidden(self): - return self._rev in repoview.filterrevs(self._repo, "visible") + return self._rev in repoview.filterrevs(self._repo, b"visible") def isinmemory(self): return False @@ -656,7 +656,7 @@ anc = cahs[0] else: # experimental config: merge.preferancestor - for r in self._repo.ui.configlist("merge", "preferancestor"): + for r in self._repo.ui.configlist(b"merge", b"preferancestor"): try: ctx = scmutil.revsymbol(self._repo, r) except error.RepoLookupError: @@ -669,13 +669,13 @@ if warn: self._repo.ui.status( ( - _("note: using %s as ancestor of %s and %s\n") + _(b"note: using %s as ancestor of %s and %s\n") % (short(anc), short(self._node), short(n2)) ) - + "".join( + + b"".join( _( - " alternatively, use --config " - "merge.preferancestor=%s\n" + b" alternatively, use --config " + b"merge.preferancestor=%s\n" ) % short(n) for n in sorted(cahs) @@ -695,9 +695,9 @@ def bad(fn, msg): # The manifest doesn't know about subrepos, so don't complain about # paths into valid subrepos. - if any(fn == s or fn.startswith(s + "/") for s in self.substate): + if any(fn == s or fn.startswith(s + b"/") for s in self.substate): return - match.bad(fn, _("no such file in rev %s") % self) + match.bad(fn, _(b"no such file in rev %s") % self) m = matchmod.badmatch(self._repo.narrowmatch(match), bad) return self._manifest.walk(m) @@ -757,9 +757,9 @@ def __bytes__(self): try: - return "%s@%s" % (self.path(), self._changectx) + return b"%s@%s" % (self.path(), self._changectx) except error.LookupError: - return "%s@???" % self.path() + return b"%s@???" % self.path() __str__ = encoding.strmethod(__bytes__) @@ -871,10 +871,10 @@ return False def isexec(self): - return "x" in self.flags() + return b"x" in self.flags() def islink(self): - return "l" in self.flags() + return b"l" in self.flags() def isabsent(self): """whether this filectx represents a file not in self._changectx @@ -895,7 +895,7 @@ if self._filenode is None: raise error.ProgrammingError( - "filectx.cmp() must be reimplemented if not backed by revlog" + b"filectx.cmp() must be reimplemented if not backed by revlog" ) if fctx._filenode is None: @@ -1162,7 +1162,7 @@ assert ( changeid is not None or fileid is not None or changectx is not None - ), "bad args: changeid=%r, fileid=%r, changectx=%r" % ( + ), b"bad args: changeid=%r, fileid=%r, changectx=%r" % ( changeid, fileid, changectx, @@ -1223,11 +1223,11 @@ try: return self._filelog.read(self._filenode) except error.CensoredNodeError: - if self._repo.ui.config("censor", "policy") == "ignore": - return "" + if self._repo.ui.config(b"censor", b"policy") == b"ignore": + return b"" raise error.Abort( - _("censored node: %s") % short(self._filenode), - hint=_("set censor.policy to ignore errors"), + _(b"censored node: %s") % short(self._filenode), + hint=_(b"set censor.policy to ignore errors"), ) def size(self): @@ -1275,7 +1275,7 @@ def __init__( self, repo, - text="", + text=b"", user=None, date=None, extra=None, @@ -1297,12 +1297,12 @@ if extra: self._extra = extra.copy() if branch is not None: - self._extra["branch"] = encoding.fromlocal(branch) - if not self._extra.get("branch"): - self._extra["branch"] = "default" + self._extra[b"branch"] = encoding.fromlocal(branch) + if not self._extra.get(b"branch"): + self._extra[b"branch"] = b"default" def __bytes__(self): - return bytes(self._parents[0]) + "+" + return bytes(self._parents[0]) + b"+" __str__ = encoding.strmethod(__bytes__) @@ -1322,7 +1322,7 @@ @propertycache def _date(self): ui = self._repo.ui - date = ui.configdate("devel", "default-date") + date = ui.configdate(b"devel", b"default-date") if date is None: date = dateutil.makedate() return date @@ -1364,10 +1364,10 @@ filesremoved = removed def branch(self): - return encoding.tolocal(self._extra["branch"]) + return encoding.tolocal(self._extra[b"branch"]) def closesbranch(self): - return "close" in self._extra + return b"close" in self._extra def extra(self): return self._extra @@ -1433,14 +1433,14 @@ """ def __init__( - self, repo, text="", user=None, date=None, extra=None, changes=None + self, repo, text=b"", user=None, date=None, extra=None, changes=None ): branch = None - if not extra or "branch" not in extra: + if not extra or b"branch" not in extra: try: branch = repo.dirstate.branch() except UnicodeDecodeError: - raise error.Abort(_("branch name not in UTF-8!")) + raise error.Abort(_(b"branch name not in UTF-8!")) super(workingctx, self).__init__( repo, text, user, date, extra, changes, branch=branch ) @@ -1448,11 +1448,11 @@ def __iter__(self): d = self._repo.dirstate for f in d: - if d[f] != "r": + if d[f] != b"r": yield f def __contains__(self, key): - return self._repo.dirstate[key] not in "?r" + return self._repo.dirstate[key] not in b"?r" def hex(self): return wdirhex @@ -1501,7 +1501,7 @@ return fl2 if fl2 == fla: return fl1 - return "" # punt for conflicts + return b"" # punt for conflicts return func @@ -1514,12 +1514,12 @@ try: return self._manifest.flags(path) except KeyError: - return "" + return b"" try: return self._flagfunc(path) except OSError: - return "" + return b"" def filectx(self, path, filelog=None): """get a file context from the working directory""" @@ -1528,7 +1528,7 @@ ) def dirty(self, missing=False, merge=True, branch=True): - "check whether a working directory is modified" + b"check whether a working directory is modified" # check subrepos first for s in sorted(self.substate): if self.sub(s).dirty(missing=missing): @@ -1543,7 +1543,7 @@ or (missing and self.deleted()) ) - def add(self, list, prefix=""): + def add(self, list, prefix=b""): with self._repo.wlock(): ui, ds = self._repo.ui, self._repo.dirstate uipath = lambda f: ds.pathto(pathutil.join(prefix, f)) @@ -1557,47 +1557,47 @@ try: st = lstat(f) except OSError: - ui.warn(_("%s does not exist!\n") % uipath(f)) + ui.warn(_(b"%s does not exist!\n") % uipath(f)) rejected.append(f) continue - limit = ui.configbytes("ui", "large-file-limit") + limit = ui.configbytes(b"ui", b"large-file-limit") if limit != 0 and st.st_size > limit: ui.warn( _( - "%s: up to %d MB of RAM may be required " - "to manage this file\n" - "(use 'hg revert %s' to cancel the " - "pending addition)\n" + b"%s: up to %d MB of RAM may be required " + b"to manage this file\n" + b"(use 'hg revert %s' to cancel the " + b"pending addition)\n" ) % (f, 3 * st.st_size // 1000000, uipath(f)) ) if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): ui.warn( _( - "%s not added: only files and symlinks " - "supported currently\n" + b"%s not added: only files and symlinks " + b"supported currently\n" ) % uipath(f) ) rejected.append(f) - elif ds[f] in "amn": - ui.warn(_("%s already tracked!\n") % uipath(f)) - elif ds[f] == "r": + elif ds[f] in b"amn": + ui.warn(_(b"%s already tracked!\n") % uipath(f)) + elif ds[f] == b"r": ds.normallookup(f) else: ds.add(f) return rejected - def forget(self, files, prefix=""): + def forget(self, files, prefix=b""): with self._repo.wlock(): ds = self._repo.dirstate uipath = lambda f: ds.pathto(pathutil.join(prefix, f)) rejected = [] for f in files: if f not in ds: - self._repo.ui.warn(_("%s not tracked!\n") % uipath(f)) + self._repo.ui.warn(_(b"%s not tracked!\n") % uipath(f)) rejected.append(f) - elif ds[f] != "a": + elif ds[f] != b"a": ds.remove(f) else: ds.drop(f) @@ -1610,20 +1610,20 @@ if err.errno != errno.ENOENT: raise self._repo.ui.warn( - _("%s does not exist!\n") % self._repo.dirstate.pathto(dest) + _(b"%s does not exist!\n") % self._repo.dirstate.pathto(dest) ) return if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): self._repo.ui.warn( - _("copy failed: %s is not a file or a " "symbolic link\n") + _(b"copy failed: %s is not a file or a " b"symbolic link\n") % self._repo.dirstate.pathto(dest) ) else: with self._repo.wlock(): ds = self._repo.dirstate - if ds[dest] in "?": + if ds[dest] in b"?": ds.add(dest) - elif ds[dest] in "r": + elif ds[dest] in b"r": ds.normallookup(dest) ds.copy(source, dest) @@ -1632,7 +1632,7 @@ pats=None, include=None, exclude=None, - default="glob", + default=b"glob", listsubrepos=False, badfn=None, ): @@ -1665,16 +1665,16 @@ # symlink sane = [] for f in files: - if self.flags(f) == "l": + if self.flags(f) == b"l": d = self[f].data() if ( - d == "" + d == b"" or len(d) >= 1024 - or "\n" in d + or b"\n" in d or stringutil.binary(d) ): self._repo.ui.debug( - "ignoring suspect symlink placeholder" ' "%s"\n' % f + b"ignoring suspect symlink placeholder" b' "%s"\n' % f ) continue sane.append(f) @@ -1746,7 +1746,7 @@ # already changed simultaneously after last # caching (see also issue5584 for detail) self._repo.ui.debug( - "skip updating dirstate: " "identity mismatch\n" + b"skip updating dirstate: " b"identity mismatch\n" ) except error.LockError: pass @@ -1757,7 +1757,7 @@ def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False): """Gets the status from the dirstate -- internal use only.""" subrepos = [] - if ".hgsub" in self: + if b".hgsub" in self: subrepos = sorted(self.substate) cmp, s = self._repo.dirstate.status( match, subrepos, ignored=ignored, clean=clean, unknown=unknown @@ -1855,7 +1855,7 @@ # might have accidentally ended up with the entire contents of the file # they are supposed to be linking to. s.modified[:] = self._filtersuspectsymlink(s.modified) - if other != self._repo["."]: + if other != self._repo[b"."]: s = super(workingctx, self)._buildstatus( other, s, match, listignored, listclean, listunknown ) @@ -1871,14 +1871,14 @@ If we aren't comparing against the working directory's parent, then we just use the default match object sent to us. """ - if other != self._repo["."]: + if other != self._repo[b"."]: def bad(f, msg): # 'f' may be a directory pattern from 'match.files()', # so 'f not in ctx1' is not enough if f not in other and not other.hasdir(f): self._repo.ui.warn( - "%s: %s\n" % (self._repo.dirstate.pathto(f), msg) + b"%s: %s\n" % (self._repo.dirstate.pathto(f), msg) ) match.bad = bad @@ -1898,7 +1898,7 @@ def matches(self, match): match = self._repo.narrowmatch(match) ds = self._repo.dirstate - return sorted(f for f in ds.matches(match) if ds[f] != "r") + return sorted(f for f in ds.matches(match) if ds[f] != b"r") def markcommitted(self, node): with self._repo.dirstate.parentchange(): @@ -2027,7 +2027,7 @@ def remove(self, ignoremissing=False): """wraps unlink for a repo's working directory""" - rmdir = self._repo.ui.configbool("experimental", "removeemptydirs") + rmdir = self._repo.ui.configbool(b"experimental", b"removeemptydirs") self._repo.wvfs.unlinkpath( self._path, ignoremissing=ignoremissing, rmdir=rmdir ) @@ -2049,7 +2049,9 @@ wvfs = self._repo.wvfs f = self._path wvfs.audit(f) - if self._repo.ui.configbool("experimental", "merge.checkpathconflicts"): + if self._repo.ui.configbool( + b"experimental", b"merge.checkpathconflicts" + ): # remove files under the directory as they should already be # warned and backed up if wvfs.isdir(f) and not wvfs.islink(f): @@ -2092,19 +2094,19 @@ # Drop old manifest cache as it is now out of date. # This is necessary when, e.g., rebasing several nodes with one # ``overlayworkingctx`` (e.g. with --collapse). - util.clearcachedproperty(self, "_manifest") + util.clearcachedproperty(self, b"_manifest") def data(self, path): if self.isdirty(path): - if self._cache[path]["exists"]: - if self._cache[path]["data"] is not None: - return self._cache[path]["data"] + if self._cache[path][b"exists"]: + if self._cache[path][b"data"] is not None: + return self._cache[path][b"data"] else: # Must fallback here, too, because we only set flags. return self._wrappedctx[path].data() else: raise error.ProgrammingError( - "No such file or directory: %s" % path + b"No such file or directory: %s" % path ) else: return self._wrappedctx[path].data() @@ -2128,7 +2130,7 @@ @propertycache def _flagfunc(self): def f(path): - return self._cache[path]["flags"] + return self._cache[path][b"flags"] return f @@ -2139,21 +2141,21 @@ return [ f for f in self._cache.keys() - if self._cache[f]["exists"] and self._existsinparent(f) + if self._cache[f][b"exists"] and self._existsinparent(f) ] def added(self): return [ f for f in self._cache.keys() - if self._cache[f]["exists"] and not self._existsinparent(f) + if self._cache[f][b"exists"] and not self._existsinparent(f) ] def removed(self): return [ f for f in self._cache.keys() - if not self._cache[f]["exists"] and self._existsinparent(f) + if not self._cache[f][b"exists"] and self._existsinparent(f) ] def p1copies(self): @@ -2163,7 +2165,7 @@ if not narrowmatch(f): continue copies.pop(f, None) # delete if it exists - source = self._cache[f]["copied"] + source = self._cache[f][b"copied"] if source: copies[f] = source return copies @@ -2175,7 +2177,7 @@ if not narrowmatch(f): continue copies.pop(f, None) # delete if it exists - source = self._cache[f]["copied"] + source = self._cache[f][b"copied"] if source: copies[f] = source return copies @@ -2185,7 +2187,7 @@ def filedate(self, path): if self.isdirty(path): - return self._cache[path]["date"] + return self._cache[path][b"date"] else: return self._wrappedctx[path].date() @@ -2200,24 +2202,24 @@ def copydata(self, path): if self.isdirty(path): - return self._cache[path]["copied"] + return self._cache[path][b"copied"] else: return None def flags(self, path): if self.isdirty(path): - if self._cache[path]["exists"]: - return self._cache[path]["flags"] + if self._cache[path][b"exists"]: + return self._cache[path][b"flags"] else: raise error.ProgrammingError( - "No such file or directory: %s" % self._path + b"No such file or directory: %s" % self._path ) else: return self._wrappedctx[path].flags() def __contains__(self, key): if key in self._cache: - return self._cache[key]["exists"] + return self._cache[key][b"exists"] return key in self.p1() def _existsinparent(self, path): @@ -2241,22 +2243,22 @@ def fail(path, component): # p1() is the base and we're receiving "writes" for p2()'s # files. - if "l" in self.p1()[component].flags(): + if b"l" in self.p1()[component].flags(): raise error.Abort( - "error: %s conflicts with symlink %s " - "in %d." % (path, component, self.p1().rev()) + b"error: %s conflicts with symlink %s " + b"in %d." % (path, component, self.p1().rev()) ) else: raise error.Abort( - "error: '%s' conflicts with file '%s' in " - "%d." % (path, component, self.p1().rev()) + b"error: '%s' conflicts with file '%s' in " + b"%d." % (path, component, self.p1().rev()) ) # Test that each new directory to be created to write this path from p2 # is not a file in p1. - components = path.split("/") + components = path.split(b"/") for i in pycompat.xrange(len(components)): - component = "/".join(components[0:i]) + component = b"/".join(components[0:i]) if component in self: fail(path, component) @@ -2273,26 +2275,26 @@ if not mfiles: return raise error.Abort( - "error: file '%s' cannot be written because " - " '%s/' is a directory in %s (containing %d " - "entries: %s)" - % (path, path, self.p1(), len(mfiles), ", ".join(mfiles)) + b"error: file '%s' cannot be written because " + b" '%s/' is a directory in %s (containing %d " + b"entries: %s)" + % (path, path, self.p1(), len(mfiles), b", ".join(mfiles)) ) - def write(self, path, data, flags="", **kwargs): + def write(self, path, data, flags=b"", **kwargs): if data is None: - raise error.ProgrammingError("data must be non-None") + raise error.ProgrammingError(b"data must be non-None") self._auditconflicts(path) self._markdirty( path, exists=True, data=data, date=dateutil.makedate(), flags=flags ) def setflags(self, path, l, x): - flag = "" + flag = b"" if l: - flag = "l" + flag = b"l" elif x: - flag = "x" + flag = b"x" self._markdirty(path, exists=True, date=dateutil.makedate(), flags=flag) def remove(self, path): @@ -2306,29 +2308,29 @@ # If this path exists and is a symlink, "follow" it by calling # exists on the destination path. if ( - self._cache[path]["exists"] - and "l" in self._cache[path]["flags"] + self._cache[path][b"exists"] + and b"l" in self._cache[path][b"flags"] ): - return self.exists(self._cache[path]["data"].strip()) + return self.exists(self._cache[path][b"data"].strip()) else: - return self._cache[path]["exists"] + return self._cache[path][b"exists"] return self._existsinparent(path) def lexists(self, path): """lexists returns True if the path exists""" if self.isdirty(path): - return self._cache[path]["exists"] + return self._cache[path][b"exists"] return self._existsinparent(path) def size(self, path): if self.isdirty(path): - if self._cache[path]["exists"]: - return len(self._cache[path]["data"]) + if self._cache[path][b"exists"]: + return len(self._cache[path][b"data"]) else: raise error.ProgrammingError( - "No such file or directory: %s" % self._path + b"No such file or directory: %s" % self._path ) return self._wrappedctx[path].size() @@ -2363,15 +2365,15 @@ files = self.files() def getfile(repo, memctx, path): - if self._cache[path]["exists"]: + if self._cache[path][b"exists"]: return memfilectx( repo, memctx, path, - self._cache[path]["data"], - "l" in self._cache[path]["flags"], - "x" in self._cache[path]["flags"], - self._cache[path]["copied"], + self._cache[path][b"data"], + b"l" in self._cache[path][b"flags"], + b"x" in self._cache[path][b"flags"], + self._cache[path][b"copied"], ) else: # Returning None, but including the path in `files`, is @@ -2424,8 +2426,8 @@ try: underlying = self._wrappedctx[path] if ( - underlying.data() == cache["data"] - and underlying.flags() == cache["flags"] + underlying.data() == cache[b"data"] + and underlying.flags() == cache[b"flags"] ): keys.append(path) except error.ManifestLookupError: @@ -2437,23 +2439,23 @@ return keys def _markdirty( - self, path, exists, data=None, date=None, flags="", copied=None + self, path, exists, data=None, date=None, flags=b"", copied=None ): # data not provided, let's see if we already have some; if not, let's # grab it from our underlying context, so that we always have data if # the file is marked as existing. if exists and data is None: oldentry = self._cache.get(path) or {} - data = oldentry.get("data") + data = oldentry.get(b"data") if data is None: data = self._wrappedctx[path].data() self._cache[path] = { - "exists": exists, - "data": data, - "date": date, - "flags": flags, - "copied": copied, + b"exists": exists, + b"data": data, + b"date": date, + b"flags": flags, + b"copied": copied, } def filectx(self, path, filelog=None): @@ -2527,7 +2529,7 @@ """ def __init__( - self, repo, changes, text="", user=None, date=None, extra=None + self, repo, changes, text=b"", user=None, date=None, extra=None ): super(workingcommitctx, self).__init__( repo, text, user, date, extra, changes @@ -2781,11 +2783,11 @@ super(memfilectx, self).__init__(repo, path, None, changectx) self._data = data if islink: - self._flags = "l" + self._flags = b"l" elif isexec: - self._flags = "x" + self._flags = b"x" else: - self._flags = "" + self._flags = b"" self._copysource = copysource def copysource(self): @@ -2930,7 +2932,7 @@ def cmp(self, fctx): # filecmp follows symlinks whereas `cmp` should not, so skip the fast # path if either side is a symlink. - symlinks = "l" in self.flags() or "l" in fctx.flags() + symlinks = b"l" in self.flags() or b"l" in fctx.flags() if not symlinks and isinstance(fctx, workingfilectx) and self._repo: # Add a fast-path for merge if both sides are disk-backed. # Note that filecmp uses the opposite return values (True if same) @@ -2942,13 +2944,13 @@ return self._path def flags(self): - return "" + return b"" def data(self): return util.readfile(self._path) def decodeddata(self): - with open(self._path, "rb") as f: + with open(self._path, b"rb") as f: return f.read() def remove(self): @@ -2956,5 +2958,5 @@ def write(self, data, flags, **kwargs): assert not flags - with open(self._path, "wb") as f: + with open(self._path, b"wb") as f: f.write(data) diff --git a/mercurial/copies.py b/mercurial/copies.py --- a/mercurial/copies.py +++ b/mercurial/copies.py @@ -170,7 +170,7 @@ ds = repo.dirstate c = ds.copies().copy() for k in list(c): - if ds[k] not in "anm" or (match and not match(k)): + if ds[k] not in b"anm" or (match and not match(k)): del c[k] return c @@ -187,8 +187,8 @@ def usechangesetcentricalgo(repo): """Checks if we should use changeset-centric copy algorithms""" - readfrom = repo.ui.config("experimental", "copies.read-from") - changesetsource = ("changeset-only", "compatibility") + readfrom = repo.ui.config(b"experimental", b"copies.read-from") + changesetsource = (b"changeset-only", b"compatibility") return readfrom in changesetsource @@ -201,13 +201,13 @@ if usechangesetcentricalgo(repo): return _changesetforwardcopies(a, b, match) - debug = repo.ui.debugflag and repo.ui.configbool("devel", "debug.copies") + debug = repo.ui.debugflag and repo.ui.configbool(b"devel", b"debug.copies") dbg = repo.ui.debug if debug: - dbg("debug.copies: looking into rename from %s to %s\n" % (a, b)) + dbg(b"debug.copies: looking into rename from %s to %s\n" % (a, b)) limit = _findlimit(repo, a, b) if debug: - dbg("debug.copies: search limit: %d\n" % limit) + dbg(b"debug.copies: search limit: %d\n" % limit) am = a.manifest() basemf = None if base is None else base.manifest() @@ -231,11 +231,11 @@ ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True) if debug: - dbg("debug.copies: missing files to search: %d\n" % len(missing)) + dbg(b"debug.copies: missing files to search: %d\n" % len(missing)) for f in sorted(missing): if debug: - dbg("debug.copies: tracing file: %s\n" % f) + dbg(b"debug.copies: tracing file: %s\n" % f) fctx = b[f] fctx._ancestrycontext = ancestrycontext @@ -244,11 +244,11 @@ opath = _tracefile(fctx, am, basemf, limit) if opath: if debug: - dbg("debug.copies: rename of: %s\n" % opath) + dbg(b"debug.copies: rename of: %s\n" % opath) cm[f] = opath if debug: dbg( - "debug.copies: time: %f seconds\n" + b"debug.copies: time: %f seconds\n" % (util.timer() - start) ) return cm @@ -342,7 +342,7 @@ def _backwardrenames(a, b, match): - if a._repo.ui.config("experimental", "copytrace") == "off": + if a._repo.ui.config(b"experimental", b"copytrace") == b"off": return {} # Even though we're not taking copies into account, 1:n rename situations @@ -366,26 +366,28 @@ def pathcopies(x, y, match=None): """find {dst@y: src@x} copy mapping for directed compare""" repo = x._repo - debug = repo.ui.debugflag and repo.ui.configbool("devel", "debug.copies") + debug = repo.ui.debugflag and repo.ui.configbool(b"devel", b"debug.copies") if debug: - repo.ui.debug("debug.copies: searching copies from %s to %s\n" % (x, y)) + repo.ui.debug( + b"debug.copies: searching copies from %s to %s\n" % (x, y) + ) if x == y or not x or not y: return {} a = y.ancestor(x) if a == x: if debug: - repo.ui.debug("debug.copies: search mode: forward\n") + repo.ui.debug(b"debug.copies: search mode: forward\n") if y.rev() is None and x == y.p1(): # short-circuit to avoid issues with merge states return _dirstatecopies(repo, match) copies = _forwardcopies(x, y, match=match) elif a == y: if debug: - repo.ui.debug("debug.copies: search mode: backward\n") + repo.ui.debug(b"debug.copies: search mode: backward\n") copies = _backwardrenames(x, y, match=match) else: if debug: - repo.ui.debug("debug.copies: search mode: combined\n") + repo.ui.debug(b"debug.copies: search mode: combined\n") base = None if a.rev() != node.nullrev: base = x @@ -453,7 +455,7 @@ if c2.node() is None and c1.node() == repo.dirstate.p1(): return _dirstatecopies(repo, narrowmatch), {}, {}, {}, {} - copytracing = repo.ui.config("experimental", "copytrace") + copytracing = repo.ui.config(b"experimental", b"copytrace") if stringutil.parsebool(copytracing) is False: # stringutil.parsebool() returns None when it is unable to parse the # value, so we should rely on making sure copytracing is on such cases @@ -466,7 +468,7 @@ # Copy trace disabling is explicitly below the node == p1 logic above # because the logic above is required for a simple copy to be kept across a # rebase. - if copytracing == "heuristics": + if copytracing == b"heuristics": # Do full copytracing if only non-public revisions are involved as # that will be fast enough and will also cover the copies which could # be missed by heuristics @@ -490,9 +492,9 @@ c1 = c1.p1() if c1.mutable() and base.mutable(): sourcecommitlimit = repo.ui.configint( - "experimental", "copytrace.sourcecommitlimit" + b"experimental", b"copytrace.sourcecommitlimit" ) - commits = len(repo.revs("%d::%d", base.rev(), c1.rev())) + commits = len(repo.revs(b"%d::%d", base.rev(), c1.rev())) return commits < sourcecommitlimit return False @@ -592,11 +594,11 @@ u1 = sorted(addedinm1 - addedinm2) u2 = sorted(addedinm2 - addedinm1) - header = " unmatched files in %s" + header = b" unmatched files in %s" if u1: - repo.ui.debug("%s:\n %s\n" % (header % "local", "\n ".join(u1))) + repo.ui.debug(b"%s:\n %s\n" % (header % b"local", b"\n ".join(u1))) if u2: - repo.ui.debug("%s:\n %s\n" % (header % "other", "\n ".join(u2))) + repo.ui.debug(b"%s:\n %s\n" % (header % b"other", b"\n ".join(u2))) fullcopy = copies1.copy() fullcopy.update(copies2) @@ -605,23 +607,23 @@ if repo.ui.debugflag: repo.ui.debug( - " all copies found (* = to merge, ! = divergent, " - "% = renamed and deleted):\n" + b" all copies found (* = to merge, ! = divergent, " + b"% = renamed and deleted):\n" ) for f in sorted(fullcopy): - note = "" + note = b"" if f in copy: - note += "*" + note += b"*" if f in divergeset: - note += "!" + note += b"!" if f in renamedeleteset: - note += "%" + note += b"%" repo.ui.debug( - " src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f, note) + b" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f, note) ) del divergeset - repo.ui.debug(" checking for directory renames\n") + repo.ui.debug(b" checking for directory renames\n") # generate a directory move map d1, d2 = c1.dirs(), c2.dirs() @@ -656,11 +658,11 @@ if not dirmove: return copy, {}, diverge, renamedelete, {} - dirmove = {k + "/": v + "/" for k, v in dirmove.iteritems()} + dirmove = {k + b"/": v + b"/" for k, v in dirmove.iteritems()} for d in dirmove: repo.ui.debug( - " discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d]) + b" discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d]) ) movewithdir = {} @@ -674,7 +676,7 @@ if df not in copy: movewithdir[f] = df repo.ui.debug( - (" pending file src: '%s' -> " "dst: '%s'\n") + (b" pending file src: '%s' -> " b"dst: '%s'\n") % (f, df) ) break @@ -716,11 +718,11 @@ changedfiles = set() m1 = c1.manifest() - if not repo.revs("%d::%d", base.rev(), c2.rev()): + if not repo.revs(b"%d::%d", base.rev(), c2.rev()): # If base is not in c2 branch, we switch to fullcopytracing repo.ui.debug( - "switching to full copytracing as base is not " - "an ancestor of c2\n" + b"switching to full copytracing as base is not " + b"an ancestor of c2\n" ) return _fullcopytracing(repo, c1, c2, base) @@ -728,7 +730,7 @@ while ctx != base: if len(ctx.parents()) == 2: # To keep things simple let's not handle merges - repo.ui.debug("switching to full copytracing because of merges\n") + repo.ui.debug(b"switching to full copytracing because of merges\n") return _fullcopytracing(repo, c1, c2, base) changedfiles.update(ctx.files()) ctx = ctx.p1() @@ -767,14 +769,14 @@ # we can have a lot of candidates which can slow down the heuristics # config value to limit the number of candidates moves to check maxcandidates = repo.ui.configint( - "experimental", "copytrace.movecandidateslimit" + b"experimental", b"copytrace.movecandidateslimit" ) if len(movecandidates) > maxcandidates: repo.ui.status( _( - "skipping copytracing for '%s', more " - "candidates than the limit: %d\n" + b"skipping copytracing for '%s', more " + b"candidates than the limit: %d\n" ) % (f, len(movecandidates)) ) @@ -833,10 +835,10 @@ copies between fromrev and rev. """ exclude = {} - ctraceconfig = repo.ui.config("experimental", "copytrace") + ctraceconfig = repo.ui.config(b"experimental", b"copytrace") bctrace = stringutil.parsebool(ctraceconfig) if skiprev is not None and ( - ctraceconfig == "heuristics" or bctrace or bctrace is None + ctraceconfig == b"heuristics" or bctrace or bctrace is None ): # copytrace='off' skips this line, but not the entire function because # the line below is O(size of the repo) during a rebase, while the rest diff --git a/mercurial/crecord.py b/mercurial/crecord.py --- a/mercurial/crecord.py +++ b/mercurial/crecord.py @@ -83,7 +83,7 @@ This method returns True if curses is found (and that python is built with it) and that the user has the correct flag for the ui. """ - return curses and ui.interface("chunkselector") == "curses" + return curses and ui.interface(b"chunkselector") == b"curses" class patchnode(object): @@ -92,14 +92,14 @@ """ def firstchild(self): - raise NotImplementedError("method must be implemented by subclass") + raise NotImplementedError(b"method must be implemented by subclass") def lastchild(self): - raise NotImplementedError("method must be implemented by subclass") + raise NotImplementedError(b"method must be implemented by subclass") def allchildren(self): - "Return a list of all of the direct children of this node" - raise NotImplementedError("method must be implemented by subclass") + b"Return a list of all of the direct children of this node" + raise NotImplementedError(b"method must be implemented by subclass") def nextsibling(self): """ @@ -107,7 +107,7 @@ of different types between the current item and this closest item. If no such item exists, return None. """ - raise NotImplementedError("method must be implemented by subclass") + raise NotImplementedError(b"method must be implemented by subclass") def prevsibling(self): """ @@ -115,10 +115,10 @@ items of different types between the current item and this closest item. If no such item exists, return None. """ - raise NotImplementedError("method must be implemented by subclass") + raise NotImplementedError(b"method must be implemented by subclass") def parentitem(self): - raise NotImplementedError("method must be implemented by subclass") + raise NotImplementedError(b"method must be implemented by subclass") def nextitem(self, skipfolded=True): """ @@ -260,21 +260,21 @@ return None def firstchild(self): - "return the first child of this item, if one exists. otherwise None." + b"return the first child of this item, if one exists. otherwise None." if len(self.hunks) > 0: return self.hunks[0] else: return None def lastchild(self): - "return the last child of this item, if one exists. otherwise None." + b"return the last child of this item, if one exists. otherwise None." if len(self.hunks) > 0: return self.hunks[-1] else: return None def allchildren(self): - "return a list of all of the direct children of this node" + b"return a list of all of the direct children of this node" return self.hunks def __getattr__(self, name): @@ -282,7 +282,7 @@ class uihunkline(patchnode): - "represents a changed line in a hunk" + b"represents a changed line in a hunk" def __init__(self, linetext, hunk): self.linetext = linetext @@ -315,16 +315,16 @@ return None def parentitem(self): - "return the parent to the current item" + b"return the parent to the current item" return self.hunk def firstchild(self): - "return the first child of this item, if one exists. otherwise None." + b"return the first child of this item, if one exists. otherwise None." # hunk-lines don't have children return None def lastchild(self): - "return the last child of this item, if one exists. otherwise None." + b"return the last child of this item, if one exists. otherwise None." # hunk-lines don't have children return None @@ -368,25 +368,25 @@ return None def parentitem(self): - "return the parent to the current item" + b"return the parent to the current item" return self.header def firstchild(self): - "return the first child of this item, if one exists. otherwise None." + b"return the first child of this item, if one exists. otherwise None." if len(self.changedlines) > 0: return self.changedlines[0] else: return None def lastchild(self): - "return the last child of this item, if one exists. otherwise None." + b"return the last child of this item, if one exists. otherwise None." if len(self.changedlines) > 0: return self.changedlines[-1] else: return None def allchildren(self): - "return a list of all of the direct children of this node" + b"return a list of all of the direct children of this node" return self.changedlines def countchanges(self): @@ -395,14 +395,14 @@ [ l for l in self.changedlines - if l.applied and l.prettystr().startswith("+") + if l.applied and l.prettystr().startswith(b"+") ] ) rem = len( [ l for l in self.changedlines - if l.applied and l.prettystr().startswith("-") + if l.applied and l.prettystr().startswith(b"-") ] ) return add, rem @@ -414,7 +414,7 @@ contextlen = ( len(self.before) + len(self.after) + removedconvertedtocontext ) - if self.after and self.after[-1] == "\\ No newline at end of file\n": + if self.after and self.after[-1] == b"\\ No newline at end of file\n": contextlen -= 1 fromlen = contextlen + self.removed tolen = contextlen + self.added @@ -432,12 +432,12 @@ if tolen == 0 and toline > 0: toline -= 1 - fromtoline = "@@ -%d,%d +%d,%d @@%s\n" % ( + fromtoline = b"@@ -%d,%d +%d,%d @@%s\n" % ( fromline, fromlen, toline, tolen, - self.proc and (" " + self.proc), + self.proc and (b" " + self.proc), ) return fromtoline @@ -453,10 +453,10 @@ changedlinestr = changedline.prettystr() if changedline.applied: hunklinelist.append(changedlinestr) - elif changedlinestr.startswith("-"): - hunklinelist.append(" " + changedlinestr[1:]) + elif changedlinestr.startswith(b"-"): + hunklinelist.append(b" " + changedlinestr[1:]) - fp.write("".join(self.before + hunklinelist + self.after)) + fp.write(b"".join(self.before + hunklinelist + self.after)) pretty = write @@ -501,14 +501,14 @@ for line in self.changedlines: text = line.linetext if line.applied: - if text.startswith("+"): + if text.startswith(b"+"): dels.append(text[1:]) - elif text.startswith("-"): + elif text.startswith(b"-"): adds.append(text[1:]) - elif text.startswith("+"): + elif text.startswith(b"+"): dels.append(text[1:]) adds.append(text[1:]) - hunk = ["-%s" % l for l in dels] + ["+%s" % l for l in adds] + hunk = [b"-%s" % l for l in dels] + [b"+%s" % l for l in adds] h = self._hunk return patchmod.recordhunk( h.header, h.toline, h.fromline, h.proc, h.before, hunk, h.after @@ -561,13 +561,13 @@ curses interface to get selection of chunks, and mark the applied flags of the chosen chunks. """ - ui.write(_("starting interactive selection\n")) + ui.write(_(b"starting interactive selection\n")) chunkselector = curseschunkselector(headerlist, ui, operation) # This is required for ncurses to display non-ASCII characters in # default user locale encoding correctly. --immerrr locale.setlocale(locale.LC_ALL, r"") origsigtstp = sentinel = object() - if util.safehasattr(signal, "SIGTSTP"): + if util.safehasattr(signal, b"SIGTSTP"): origsigtstp = signal.getsignal(signal.SIGTSTP) try: curses.wrapper(chunkselector.main) @@ -603,8 +603,8 @@ chunkselector.stdscr = dummystdscr() if testfn and os.path.exists(testfn): - testf = open(testfn, "rb") - testcommands = [x.rstrip("\n") for x in testf.readlines()] + testf = open(testfn, b"rb") + testcommands = [x.rstrip(b"\n") for x in testf.readlines()] testf.close() while True: if chunkselector.handlekeypressed(testcommands.pop(0), test=True): @@ -613,10 +613,10 @@ _headermessages = { # {operation: text} - "apply": _("Select hunks to apply"), - "discard": _("Select hunks to discard"), - "keep": _("Select hunks to keep"), - None: _("Select hunks to record"), + b"apply": _(b"Select hunks to apply"), + b"discard": _(b"Select hunks to discard"), + b"keep": _(b"Select hunks to keep"), + None: _(b"Select hunks to record"), } @@ -645,7 +645,7 @@ # long as not explicitly set to a falsy value - especially, # when not set at all. This is to stay most compatible with # previous (color only) behaviour. - uicolor = stringutil.parsebool(self.ui.config("ui", "color")) + uicolor = stringutil.parsebool(self.ui.config(b"ui", b"color")) self.usecolor = uicolor is not False # the currently selected header, hunk, or hunk-line @@ -678,14 +678,16 @@ self.firstlineofpadtoprint = 0 # stores optional text for a commit comment provided by the user - self.commenttext = "" + self.commenttext = b"" # if the last 'toggle all' command caused all changes to be applied self.waslasttoggleallapplied = True # affects some ui text if operation not in _headermessages: - raise error.ProgrammingError("unexpected operation: %s" % operation) + raise error.ProgrammingError( + b"unexpected operation: %s" % operation + ) self.operation = operation def uparrowevent(self): @@ -850,7 +852,7 @@ self.currentselecteditem = currentitem def updatescroll(self): - "scroll the screen to fully show the currently-selected" + b"scroll the screen to fully show the currently-selected" selstart = self.selecteditemstartline selend = self.selecteditemendline @@ -868,7 +870,7 @@ self.scrolllines(selstart - padstartbuffered) def scrolllines(self, numlines): - "scroll the screen up (down) by numlines when numlines >0 (<0)." + b"scroll the screen up (down) by numlines when numlines >0 (<0)." self.firstlineofpadtoprint += numlines if self.firstlineofpadtoprint < 0: self.firstlineofpadtoprint = 0 @@ -970,7 +972,7 @@ ) def toggleall(self): - "toggle the applied flag of all items." + b"toggle the applied flag of all items." if self.waslasttoggleallapplied: # then unapply them this time for item in self.headerlist: if item.applied: @@ -982,7 +984,7 @@ self.waslasttoggleallapplied = not self.waslasttoggleallapplied def toggleallbetween(self): - "toggle applied on or off for all items in range [lastapplied,current]." + b"toggle applied on or off for all items in range [lastapplied,current]." if ( not self.lastapplieditem or self.currentselecteditem == self.lastapplieditem @@ -994,7 +996,7 @@ startitem = self.lastapplieditem enditem = self.currentselecteditem # Verify that enditem is "after" startitem, otherwise swap them. - for direction in ["forward", "reverse"]: + for direction in [b"forward", b"reverse"]: nextitem = startitem.nextitem() while nextitem and nextitem != enditem: nextitem = nextitem.nextitem() @@ -1023,7 +1025,7 @@ nextitem = nextitem.nextitem() def togglefolded(self, item=None, foldparent=False): - "toggle folded flag of specified item (defaults to currently selected)" + b"toggle folded flag of specified item (defaults to currently selected)" if item is None: item = self.currentselecteditem if foldparent or (isinstance(item, uiheader) and item.neverunfolded): @@ -1054,7 +1056,7 @@ instr = instr.expandtabs(4) strwidth = encoding.colwidth(instr) numspaces = width - ((strwidth + xstart) % width) - return instr + " " * numspaces + return instr + b" " * numspaces def printstring( self, @@ -1092,8 +1094,8 @@ # strip \n, and convert control characters to ^[char] representation text = re.sub( br"[\x00-\x08\x0a-\x1f]", - lambda m: "^" + chr(ord(m.group()) + 64), - text.strip("\n"), + lambda m: b"^" + chr(ord(m.group()) + 64), + text.strip(b"\n"), ) if pair is not None: @@ -1123,11 +1125,11 @@ colorpair |= textattr y, xstart = self.chunkpad.getyx() - t = "" # variable for counting lines printed + t = b"" # variable for counting lines printed # if requested, show trailing whitespace if showwhtspc: origlen = len(text) - text = text.rstrip(" \n") # tabs have already been expanded + text = text.rstrip(b" \n") # tabs have already been expanded strippedlen = len(text) numtrailingspaces = origlen - strippedlen @@ -1140,11 +1142,11 @@ if towin: for i in range(numtrailingspaces): window.addch(curses.ACS_CKBOARD, wscolorpair) - t += " " * numtrailingspaces + t += b" " * numtrailingspaces if align: if towin: - extrawhitespace = self.alignstring("", window) + extrawhitespace = self.alignstring(b"", window) window.addstr(extrawhitespace, colorpair) else: # need to use t, since the x position hasn't incremented @@ -1160,31 +1162,31 @@ def _getstatuslinesegments(self): """-> [str]. return segments""" selected = self.currentselecteditem.applied - spaceselect = _("space/enter: select") - spacedeselect = _("space/enter: deselect") + spaceselect = _(b"space/enter: select") + spacedeselect = _(b"space/enter: deselect") # Format the selected label into a place as long as the longer of the # two possible labels. This may vary by language. spacelen = max(len(spaceselect), len(spacedeselect)) - selectedlabel = "%-*s" % ( + selectedlabel = b"%-*s" % ( spacelen, spacedeselect if selected else spaceselect, ) segments = [ _headermessages[self.operation], - "-", - _("[x]=selected **=collapsed"), - _("c: confirm"), - _("q: abort"), - _("arrow keys: move/expand/collapse"), + b"-", + _(b"[x]=selected **=collapsed"), + _(b"c: confirm"), + _(b"q: abort"), + _(b"arrow keys: move/expand/collapse"), selectedlabel, - _("?: help"), + _(b"?: help"), ] return segments def _getstatuslines(self): """() -> [str]. return short help used in the top status window""" if self.errorstr is not None: - lines = [self.errorstr, _("Press any key to continue")] + lines = [self.errorstr, _(b"Press any key to continue")] else: # wrap segments to lines segments = self._getstatuslinesegments() @@ -1193,7 +1195,7 @@ lastwidth = width for s in segments: w = encoding.colwidth(s) - sep = " " * (1 + (s and s[0] not in "-[")) + sep = b" " * (1 + (s and s[0] not in b"-[")) if lastwidth + w + len(sep) >= width: lines.append(s) lastwidth = w @@ -1214,7 +1216,7 @@ # print out the status lines at the top try: for line in self._getstatuslines(): - printstring(self.statuswin, line, pairname="legend") + printstring(self.statuswin, line, pairname=b"legend") self.statuswin.refresh() except curses.error: pass @@ -1245,27 +1247,27 @@ # create checkbox string if item.applied: if not isinstance(item, uihunkline) and item.partial: - checkbox = "[~]" + checkbox = b"[~]" else: - checkbox = "[x]" + checkbox = b"[x]" else: - checkbox = "[ ]" + checkbox = b"[ ]" try: if item.folded: - checkbox += "**" + checkbox += b"**" if isinstance(item, uiheader): # one of "m", "a", or "d" (modified, added, deleted) filestatus = item.changetype - checkbox += filestatus + " " + checkbox += filestatus + b" " else: - checkbox += " " + checkbox += b" " if isinstance(item, uiheader): # add two more spaces for headers - checkbox += " " + checkbox += b" " except AttributeError: # not foldable - checkbox += " " + checkbox += b" " return checkbox @@ -1277,18 +1279,18 @@ anything, but just count the number of lines which would be printed. """ - outstr = "" + outstr = b"" text = header.prettystr() chunkindex = self.chunklist.index(header) if chunkindex != 0 and not header.folded: # add separating line before headers outstr += self.printstring( - self.chunkpad, "_" * self.xscreensize, towin=towin, align=False + self.chunkpad, b"_" * self.xscreensize, towin=towin, align=False ) # select color-pair based on if the header is selected colorpair = self.getcolorpair( - name=selected and "selected" or "normal", attrlist=[curses.A_BOLD] + name=selected and b"selected" or b"normal", attrlist=[curses.A_BOLD] ) # print out each line of the chunk, expanding it to screen width @@ -1297,7 +1299,7 @@ indentnumchars = 0 checkbox = self.getstatusprefixstring(header) if not header.folded or ignorefolding: - textlist = text.split("\n") + textlist = text.split(b"\n") linestr = checkbox + textlist[0] else: linestr = checkbox + header.filename() @@ -1307,7 +1309,7 @@ if not header.folded or ignorefolding: if len(textlist) > 1: for line in textlist[1:]: - linestr = " " * (indentnumchars + len(checkbox)) + line + linestr = b" " * (indentnumchars + len(checkbox)) + line outstr += self.printstring( self.chunkpad, linestr, pair=colorpair, towin=towin ) @@ -1317,26 +1319,26 @@ def printhunklinesbefore( self, hunk, selected=False, towin=True, ignorefolding=False ): - "includes start/end line indicator" - outstr = "" + b"includes start/end line indicator" + outstr = b"" # where hunk is in list of siblings hunkindex = hunk.header.hunks.index(hunk) if hunkindex != 0: # add separating line before headers outstr += self.printstring( - self.chunkpad, " " * self.xscreensize, towin=towin, align=False + self.chunkpad, b" " * self.xscreensize, towin=towin, align=False ) colorpair = self.getcolorpair( - name=selected and "selected" or "normal", attrlist=[curses.A_BOLD] + name=selected and b"selected" or b"normal", attrlist=[curses.A_BOLD] ) # print out from-to line with checkbox checkbox = self.getstatusprefixstring(hunk) - lineprefix = " " * self.hunkindentnumchars + checkbox - frtoline = " " + hunk.getfromtoline().strip("\n") + lineprefix = b" " * self.hunkindentnumchars + checkbox + frtoline = b" " + hunk.getfromtoline().strip(b"\n") outstr += self.printstring( self.chunkpad, lineprefix, towin=towin, align=False @@ -1351,41 +1353,45 @@ # print out lines of the chunk preceeding changed-lines for line in hunk.before: - linestr = " " * (self.hunklineindentnumchars + len(checkbox)) + line + linestr = ( + b" " * (self.hunklineindentnumchars + len(checkbox)) + line + ) outstr += self.printstring(self.chunkpad, linestr, towin=towin) return outstr def printhunklinesafter(self, hunk, towin=True, ignorefolding=False): - outstr = "" + outstr = b"" if hunk.folded and not ignorefolding: return outstr # a bit superfluous, but to avoid hard-coding indent amount checkbox = self.getstatusprefixstring(hunk) for line in hunk.after: - linestr = " " * (self.hunklineindentnumchars + len(checkbox)) + line + linestr = ( + b" " * (self.hunklineindentnumchars + len(checkbox)) + line + ) outstr += self.printstring(self.chunkpad, linestr, towin=towin) return outstr def printhunkchangedline(self, hunkline, selected=False, towin=True): - outstr = "" + outstr = b"" checkbox = self.getstatusprefixstring(hunkline) - linestr = hunkline.prettystr().strip("\n") + linestr = hunkline.prettystr().strip(b"\n") # select color-pair based on whether line is an addition/removal if selected: - colorpair = self.getcolorpair(name="selected") - elif linestr.startswith("+"): - colorpair = self.getcolorpair(name="addition") - elif linestr.startswith("-"): - colorpair = self.getcolorpair(name="deletion") - elif linestr.startswith("\\"): - colorpair = self.getcolorpair(name="normal") + colorpair = self.getcolorpair(name=b"selected") + elif linestr.startswith(b"+"): + colorpair = self.getcolorpair(name=b"addition") + elif linestr.startswith(b"-"): + colorpair = self.getcolorpair(name=b"deletion") + elif linestr.startswith(b"\\"): + colorpair = self.getcolorpair(name=b"normal") - lineprefix = " " * self.hunklineindentnumchars + checkbox + lineprefix = b" " * self.hunklineindentnumchars + checkbox outstr += self.printstring( self.chunkpad, lineprefix, towin=towin, align=False ) # add uncolored checkbox/indent @@ -1412,7 +1418,7 @@ self.__printitem( item, ignorefolding, recursechildren, outstr, towin=towin ) - return "".join(outstr) + return b"".join(outstr) def outofdisplayedarea(self): y, _ = self.chunkpad.getyx() # cursor location @@ -1522,7 +1528,7 @@ return numlines def sigwinchhandler(self, n, frame): - "handle window resizing" + b"handle window resizing" try: curses.endwin() self.xscreensize, self.yscreensize = scmutil.termsize(self.ui) @@ -1572,7 +1578,7 @@ else: cval = 0 if name is not None: - if name == "selected": + if name == b"selected": cval = curses.A_REVERSE self.colorpairnames[name] = cval colorpair = self.colorpairs[(fgcolor, bgcolor)] = cval @@ -1592,11 +1598,11 @@ return colorpair def initcolorpair(self, *args, **kwargs): - "same as getcolorpair." + b"same as getcolorpair." self.getcolorpair(*args, **kwargs) def helpwindow(self): - "print a help window to the screen. exit after any keypress." + b"print a help window to the screen. exit after any keypress." helptext = _( """ [press any key to return to the patch-display] @@ -1630,24 +1636,24 @@ ) helpwin = curses.newwin(self.yscreensize, 0, 0, 0) - helplines = helptext.split("\n") - helplines = helplines + [" "] * ( + helplines = helptext.split(b"\n") + helplines = helplines + [b" "] * ( self.yscreensize - self.numstatuslines - len(helplines) - 1 ) try: for line in helplines: - self.printstring(helpwin, line, pairname="legend") + self.printstring(helpwin, line, pairname=b"legend") except curses.error: pass helpwin.refresh() try: - with self.ui.timeblockedsection("crecord"): + with self.ui.timeblockedsection(b"crecord"): helpwin.getkey() except curses.error: pass def commitMessageWindow(self): - "Create a temporary commit message editing window on the screen." + b"Create a temporary commit message editing window on the screen." curses.raw() curses.def_prog_mode() @@ -1697,19 +1703,19 @@ self.recenterdisplayedarea() def confirmationwindow(self, windowtext): - "display an informational window, then wait for and return a keypress." + b"display an informational window, then wait for and return a keypress." confirmwin = curses.newwin(self.yscreensize, 0, 0, 0) try: - lines = windowtext.split("\n") + lines = windowtext.split(b"\n") for line in lines: - self.printstring(confirmwin, line, pairname="selected") + self.printstring(confirmwin, line, pairname=b"selected") except curses.error: pass self.stdscr.refresh() confirmwin.refresh() try: - with self.ui.timeblockedsection("crecord"): + with self.ui.timeblockedsection(b"crecord"): response = chr(self.stdscr.getch()) except ValueError: response = None @@ -1731,11 +1737,11 @@ are you sure you want to review/edit and confirm the selected changes [yn]? """ ) - with self.ui.timeblockedsection("crecord"): + with self.ui.timeblockedsection(b"crecord"): response = self.confirmationwindow(confirmtext) if response is None: - response = "n" - if response.lower().startswith("y"): + response = b"n" + if response.lower().startswith(b"y"): return True else: return False @@ -1748,20 +1754,20 @@ new changeset will be created (the normal commit behavior). """ - if opts.get("amend") is None: - opts["amend"] = True + if opts.get(b"amend") is None: + opts[b"amend"] = True msg = _( - "Amend option is turned on -- committing the currently " - "selected changes will not create a new changeset, but " - "instead update the most recently committed changeset.\n\n" - "Press any key to continue." + b"Amend option is turned on -- committing the currently " + b"selected changes will not create a new changeset, but " + b"instead update the most recently committed changeset.\n\n" + b"Press any key to continue." ) - elif opts.get("amend") is True: - opts["amend"] = None + elif opts.get(b"amend") is True: + opts[b"amend"] = None msg = _( - "Amend option is turned off -- committing the currently " - "selected changes will create a new changeset.\n\n" - "Press any key to continue." + b"Amend option is turned off -- committing the currently " + b"selected changes will create a new changeset.\n\n" + b"Press any key to continue." ) if not test: self.confirmationwindow(msg) @@ -1791,12 +1797,12 @@ def editpatchwitheditor(self, chunk): if chunk is None: - self.ui.write(_("cannot edit patch for whole file")) - self.ui.write("\n") + self.ui.write(_(b"cannot edit patch for whole file")) + self.ui.write(b"\n") return None if chunk.header.binary(): - self.ui.write(_("cannot edit patch for binary file")) - self.ui.write("\n") + self.ui.write(_(b"cannot edit patch for binary file")) + self.ui.write(b"\n") return None # write the initial patch @@ -1807,7 +1813,7 @@ # start the editor and wait for it to complete try: - patch = self.ui.edit(patch.getvalue(), "", action="diff") + patch = self.ui.edit(patch.getvalue(), b"", action=b"diff") except error.Abort as exc: self.errorstr = str(exc) return None @@ -1817,9 +1823,9 @@ # remove comment lines patch = [ - line + "\n" + line + b"\n" for line in patch.splitlines() - if not line.startswith("#") + if not line.startswith(b"#") ] return patchmod.parsepatch(patch) @@ -1881,59 +1887,59 @@ Return true to exit the main loop. """ keypressed = pycompat.bytestr(keypressed) - if keypressed in ["k", "KEY_UP"]: + if keypressed in [b"k", b"KEY_UP"]: self.uparrowevent() - elif keypressed in ["K", "KEY_PPAGE"]: + elif keypressed in [b"K", b"KEY_PPAGE"]: self.uparrowshiftevent() - elif keypressed in ["j", "KEY_DOWN"]: + elif keypressed in [b"j", b"KEY_DOWN"]: self.downarrowevent() - elif keypressed in ["J", "KEY_NPAGE"]: + elif keypressed in [b"J", b"KEY_NPAGE"]: self.downarrowshiftevent() - elif keypressed in ["l", "KEY_RIGHT"]: + elif keypressed in [b"l", b"KEY_RIGHT"]: self.rightarrowevent() - elif keypressed in ["h", "KEY_LEFT"]: + elif keypressed in [b"h", b"KEY_LEFT"]: self.leftarrowevent() - elif keypressed in ["H", "KEY_SLEFT"]: + elif keypressed in [b"H", b"KEY_SLEFT"]: self.leftarrowshiftevent() - elif keypressed in ["q"]: - raise error.Abort(_("user quit")) - elif keypressed in ["a"]: + elif keypressed in [b"q"]: + raise error.Abort(_(b"user quit")) + elif keypressed in [b"a"]: self.toggleamend(self.opts, test) - elif keypressed in ["c"]: + elif keypressed in [b"c"]: return True - elif keypressed in ["r"]: + elif keypressed in [b"r"]: if self.reviewcommit(): - self.opts["review"] = True + self.opts[b"review"] = True return True - elif test and keypressed in ["R"]: - self.opts["review"] = True + elif test and keypressed in [b"R"]: + self.opts[b"review"] = True return True - elif keypressed in [" ", "x"]: + elif keypressed in [b" ", b"x"]: self.toggleapply() - elif keypressed in ["\n", "KEY_ENTER"]: + elif keypressed in [b"\n", b"KEY_ENTER"]: self.toggleapply() self.nextsametype(test=test) - elif keypressed in ["X"]: + elif keypressed in [b"X"]: self.toggleallbetween() - elif keypressed in ["A"]: + elif keypressed in [b"A"]: self.toggleall() - elif keypressed in ["e"]: + elif keypressed in [b"e"]: self.toggleedit(test=test) - elif keypressed in ["f"]: + elif keypressed in [b"f"]: self.togglefolded() - elif keypressed in ["F"]: + elif keypressed in [b"F"]: self.togglefolded(foldparent=True) - elif keypressed in ["m"]: + elif keypressed in [b"m"]: self.commitMessageWindow() - elif keypressed in ["g", "KEY_HOME"]: + elif keypressed in [b"g", b"KEY_HOME"]: self.handlefirstlineevent() - elif keypressed in ["G", "KEY_END"]: + elif keypressed in [b"G", b"KEY_END"]: self.handlelastlineevent() - elif keypressed in ["?"]: + elif keypressed in [b"?"]: self.helpwindow() self.stdscr.clear() self.stdscr.refresh() - elif curses.unctrl(keypressed) in ["^L"]: + elif curses.unctrl(keypressed) in [b"^L"]: # scroll the current line to the top of the screen, and redraw # everything self.scrolllines(self.selecteditemstartline) @@ -1946,7 +1952,7 @@ """ origsigwinch = sentinel = object() - if util.safehasattr(signal, "SIGWINCH"): + if util.safehasattr(signal, b"SIGWINCH"): origsigwinch = signal.signal(signal.SIGWINCH, self.sigwinchhandler) try: return self._main(stdscr) @@ -1981,13 +1987,15 @@ # available colors: black, blue, cyan, green, magenta, white, yellow # init_pair(color_id, foreground_color, background_color) - self.initcolorpair(None, None, name="normal") + self.initcolorpair(None, None, name=b"normal") self.initcolorpair( - curses.COLOR_WHITE, curses.COLOR_MAGENTA, name="selected" + curses.COLOR_WHITE, curses.COLOR_MAGENTA, name=b"selected" ) - self.initcolorpair(curses.COLOR_RED, None, name="deletion") - self.initcolorpair(curses.COLOR_GREEN, None, name="addition") - self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_BLUE, name="legend") + self.initcolorpair(curses.COLOR_RED, None, name=b"deletion") + self.initcolorpair(curses.COLOR_GREEN, None, name=b"addition") + self.initcolorpair( + curses.COLOR_WHITE, curses.COLOR_BLUE, name=b"legend" + ) # newwin([height, width,] begin_y, begin_x) self.statuswin = curses.newwin(self.numstatuslines, 0, 0, 0) self.statuswin.keypad(1) # interpret arrow-key, etc. esc sequences @@ -2005,7 +2013,7 @@ self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize) except curses.error: self.initexc = fallbackerror( - _("this diff is too large to be displayed") + _(b"this diff is too large to be displayed") ) return # initialize selecteditemendline (initial start-line is 0) @@ -2016,19 +2024,19 @@ while True: self.updatescreen() try: - with self.ui.timeblockedsection("crecord"): + with self.ui.timeblockedsection(b"crecord"): keypressed = self.statuswin.getkey() if self.errorstr is not None: self.errorstr = None continue except curses.error: - keypressed = "foobar" + keypressed = b"foobar" if self.handlekeypressed(keypressed): break - if self.commenttext != "": + if self.commenttext != b"": whitespaceremoved = re.sub( br"(?m)^\s.*(\n|$)", b"", self.commenttext ) - if whitespaceremoved != "": - self.opts["message"] = self.commenttext + if whitespaceremoved != b"": + self.opts[b"message"] = self.commenttext diff --git a/mercurial/dagop.py b/mercurial/dagop.py --- a/mercurial/dagop.py +++ b/mercurial/dagop.py @@ -43,7 +43,7 @@ if stopdepth == 0: return if stopdepth < 0: - raise error.ProgrammingError("negative stopdepth") + raise error.ProgrammingError(b"negative stopdepth") if reverse: heapsign = -1 # max heap else: @@ -330,7 +330,7 @@ """ blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts) filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2) - diffinrange = any(stype == "!" for _, stype in filteredblocks) + diffinrange = any(stype == b"!" for _, stype in filteredblocks) return diffinrange, linerange1 @@ -428,9 +428,9 @@ def _countlines(text): - if text.endswith("\n"): - return text.count("\n") - return text.count("\n") + int(bool(text)) + if text.endswith(b"\n"): + return text.count(b"\n") + return text.count(b"\n") + int(bool(text)) def _decoratelines(text, fctx): @@ -464,7 +464,7 @@ for (a1, a2, b1, b2), t in blocks: # Changed blocks ('!') or blocks made only of blank lines ('~') # belong to the child. - if t == "=": + if t == b"=": child.fctxs[b1:b2] = parent.fctxs[a1:a2] child.linenos[b1:b2] = parent.linenos[a1:a2] child.skips[b1:b2] = parent.skips[a1:a2] diff --git a/mercurial/dagparser.py b/mercurial/dagparser.py --- a/mercurial/dagparser.py +++ b/mercurial/dagparser.py @@ -185,17 +185,17 @@ chiter = pycompat.iterbytestr(desc) def nextch(): - return next(chiter, "\0") + return next(chiter, b"\0") def nextrun(c, allow): - s = "" + s = b"" while c in allow: s += c c = nextch() return c, s def nextdelimited(c, limit, escape): - s = "" + s = b"" while c != limit: if c == escape: c = nextch() @@ -204,78 +204,78 @@ return nextch(), s def nextstring(c): - if c == '"': - return nextdelimited(nextch(), '"', "\\") + if c == b'"': + return nextdelimited(nextch(), b'"', b"\\") else: return nextrun(c, wordchars) c = nextch() - while c != "\0": + while c != b"\0": while c in pycompat.bytestr(string.whitespace): c = nextch() - if c == ".": - yield "n", (r, [p1]) + if c == b".": + yield b"n", (r, [p1]) p1 = r r += 1 c = nextch() - elif c == "+": + elif c == b"+": c, digs = nextrun(nextch(), pycompat.bytestr(string.digits)) n = int(digs) for i in pycompat.xrange(0, n): - yield "n", (r, [p1]) + yield b"n", (r, [p1]) p1 = r r += 1 - elif c in "*/": - if c == "*": + elif c in b"*/": + if c == b"*": c = nextch() c, pref = nextstring(c) prefs = [pref] - while c == "/": + while c == b"/": c, pref = nextstring(nextch()) prefs.append(pref) ps = [resolve(ref) for ref in prefs] - yield "n", (r, ps) + yield b"n", (r, ps) p1 = r r += 1 - elif c == "<": + elif c == b"<": c, ref = nextstring(nextch()) p1 = resolve(ref) - elif c == ":": + elif c == b":": c, name = nextstring(nextch()) labels[name] = p1 - yield "l", (p1, name) - elif c == "@": + yield b"l", (p1, name) + elif c == b"@": c, text = nextstring(nextch()) - yield "a", text - elif c == "!": + yield b"a", text + elif c == b"!": c = nextch() - if c == "!": - cmd = "" + if c == b"!": + cmd = b"" c = nextch() - while c not in "\n\r\0": + while c not in b"\n\r\0": cmd += c c = nextch() - yield "C", cmd + yield b"C", cmd else: c, cmd = nextstring(c) - yield "c", cmd - elif c == "#": - while c not in "\n\r\0": + yield b"c", cmd + elif c == b"#": + while c not in b"\n\r\0": c = nextch() - elif c == "$": + elif c == b"$": p1 = -1 c = nextch() - elif c == "\0": + elif c == b"\0": return # in case it was preceded by whitespace else: - s = "" + s = b"" i = 0 - while c != "\0" and i < 10: + while c != b"\0" and i < 10: s += c i += 1 c = nextch() raise error.Abort( - _("invalid character in dag description: " "%s...") % s + _(b"invalid character in dag description: " b"%s...") % s ) @@ -292,9 +292,9 @@ """generates single lines for dagtext()""" def wrapstring(text): - if re.match("^[0-9a-z]*$", text): + if re.match(b"^[0-9a-z]*$", text): return text - return '"' + text.replace("\\", "\\\\").replace('"', '"') + '"' + return b'"' + text.replace(b"\\", b"\\\\").replace(b'"', b'"') + b'"' def gen(): labels = {} @@ -302,12 +302,12 @@ wantr = 0 needroot = False for kind, data in events: - if kind == "n": + if kind == b"n": r, ps = data # sanity check if r != wantr: - raise error.Abort(_("expected id %i, got %i") % (wantr, r)) + raise error.Abort(_(b"expected id %i, got %i") % (wantr, r)) if not ps: ps = [-1] else: @@ -315,8 +315,8 @@ if p >= r: raise error.Abort( _( - "parent id %i is larger than " - "current id %i" + b"parent id %i is larger than " + b"current id %i" ) % (p, r) ) @@ -327,81 +327,81 @@ if len(ps) == 1 and ps[0] == -1: if needroot: if run: - yield "+%d" % run + yield b"+%d" % run run = 0 if wrapnonlinear: - yield "\n" - yield "$" + yield b"\n" + yield b"$" p1 = -1 else: needroot = True if len(ps) == 1 and ps[0] == p1: if usedots: - yield "." + yield b"." else: run += 1 else: if run: - yield "+%d" % run + yield b"+%d" % run run = 0 if wrapnonlinear: - yield "\n" + yield b"\n" prefs = [] for p in ps: if p == p1: - prefs.append("") + prefs.append(b"") elif p in labels: prefs.append(labels[p]) else: - prefs.append("%d" % (r - p)) - yield "*" + "/".join(prefs) + prefs.append(b"%d" % (r - p)) + yield b"*" + b"/".join(prefs) else: if run: - yield "+%d" % run + yield b"+%d" % run run = 0 - if kind == "l": + if kind == b"l": rid, name = data labels[rid] = name - yield ":" + name + yield b":" + name if wraplabels: - yield "\n" - elif kind == "c": - yield "!" + wrapstring(data) + yield b"\n" + elif kind == b"c": + yield b"!" + wrapstring(data) if wrapcommands: - yield "\n" - elif kind == "C": - yield "!!" + data - yield "\n" - elif kind == "a": + yield b"\n" + elif kind == b"C": + yield b"!!" + data + yield b"\n" + elif kind == b"a": if wrapannotations: - yield "\n" - yield "@" + wrapstring(data) - elif kind == "#": - yield "#" + data - yield "\n" + yield b"\n" + yield b"@" + wrapstring(data) + elif kind == b"#": + yield b"#" + data + yield b"\n" else: raise error.Abort( - _("invalid event type in dag: " "('%s', '%s')") + _(b"invalid event type in dag: " b"('%s', '%s')") % ( stringutil.escapestr(kind), stringutil.escapestr(data), ) ) if run: - yield "+%d" % run + yield b"+%d" % run - line = "" + line = b"" for part in gen(): - if part == "\n": + if part == b"\n": if line: yield line - line = "" + line = b"" else: if len(line) + len(part) >= maxlinewidth: yield line - line = "" - elif addspaces and line and part != ".": - line += " " + line = b"" + elif addspaces and line and part != b".": + line += b" " line += part if line: yield line @@ -494,7 +494,7 @@ '+1 :f +1 :p2 *f */p2' """ - return "\n".join( + return b"\n".join( dagtextlines( dag, addspaces, diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -95,7 +95,7 @@ command = registrar.command() -@command("debugancestor", [], _("[INDEX] REV1 REV2"), optionalrepo=True) +@command(b"debugancestor", [], _(b"[INDEX] REV1 REV2"), optionalrepo=True) def debugancestor(ui, repo, *args): """find the ancestor revision of two revisions in a given index""" if len(args) == 3: @@ -105,18 +105,18 @@ elif len(args) == 2: if not repo: raise error.Abort( - _("there is no Mercurial repository here " "(.hg not found)") + _(b"there is no Mercurial repository here " b"(.hg not found)") ) rev1, rev2 = args r = repo.changelog lookup = repo.lookup else: - raise error.Abort(_("either two or three arguments required")) + raise error.Abort(_(b"either two or three arguments required")) a = r.ancestor(lookup(rev1), lookup(rev2)) - ui.write("%d:%s\n" % (r.rev(a), hex(a))) - - -@command("debugapplystreamclonebundle", [], "FILE") + ui.write(b"%d:%s\n" % (r.rev(a), hex(a))) + + +@command(b"debugapplystreamclonebundle", [], b"FILE") def debugapplystreamclonebundle(ui, repo, fname): """apply a stream clone bundle file""" f = hg.openpath(ui, fname) @@ -125,18 +125,23 @@ @command( - "debugbuilddag", + b"debugbuilddag", [ - ("m", "mergeable-file", None, _("add single file mergeable changes")), + ( + b"m", + b"mergeable-file", + None, + _(b"add single file mergeable changes"), + ), ( - "o", - "overwritten-file", + b"o", + b"overwritten-file", None, - _("add single file all revs overwrite"), + _(b"add single file all revs overwrite"), ), - ("n", "new-file", None, _("add new file at each rev")), + (b"n", b"new-file", None, _(b"add new file at each rev")), ], - _("[OPTION]... [TEXT]"), + _(b"[OPTION]... [TEXT]"), ) def debugbuilddag( ui, @@ -179,38 +184,40 @@ """ if text is None: - ui.status(_("reading DAG from stdin\n")) + ui.status(_(b"reading DAG from stdin\n")) text = ui.fin.read() cl = repo.changelog if len(cl) > 0: - raise error.Abort(_("repository is not empty")) + raise error.Abort(_(b"repository is not empty")) # determine number of revs in DAG total = 0 for type, data in dagparser.parsedag(text): - if type == "n": + if type == b"n": total += 1 if mergeable_file: linesperrev = 2 # make a file with k lines per rev initialmergedlines = [ - "%d" % i for i in pycompat.xrange(0, total * linesperrev) + b"%d" % i for i in pycompat.xrange(0, total * linesperrev) ] - initialmergedlines.append("") + initialmergedlines.append(b"") tags = [] - progress = ui.makeprogress(_("building"), unit=_("revisions"), total=total) - with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"): + progress = ui.makeprogress( + _(b"building"), unit=_(b"revisions"), total=total + ) + with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"): at = -1 - atbranch = "default" + atbranch = b"default" nodeids = [] id = 0 progress.update(id) for type, data in dagparser.parsedag(text): - if type == "n": - ui.note(("node %s\n" % pycompat.bytestr(data))) + if type == b"n": + ui.note((b"node %s\n" % pycompat.bytestr(data))) id, ps = data files = [] @@ -218,7 +225,7 @@ p2 = None if mergeable_file: - fn = "mf" + fn = b"mf" p1 = repo[ps[0]] if len(ps) > 1: p2 = repo[ps[1]] @@ -228,30 +235,30 @@ ] m3 = simplemerge.Merge3Text(base, local, other) ml = [l.strip() for l in m3.merge_lines()] - ml.append("") + ml.append(b"") elif at > 0: - ml = p1[fn].data().split("\n") + ml = p1[fn].data().split(b"\n") else: ml = initialmergedlines - ml[id * linesperrev] += " r%i" % id - mergedtext = "\n".join(ml) + ml[id * linesperrev] += b" r%i" % id + mergedtext = b"\n".join(ml) files.append(fn) filecontent[fn] = mergedtext if overwritten_file: - fn = "of" + fn = b"of" files.append(fn) - filecontent[fn] = "r%i\n" % id + filecontent[fn] = b"r%i\n" % id if new_file: - fn = "nf%i" % id + fn = b"nf%i" % id files.append(fn) - filecontent[fn] = "r%i\n" % id + filecontent[fn] = b"r%i\n" % id if len(ps) > 1: if not p2: p2 = repo[ps[1]] for fn in p2: - if fn.startswith("nf"): + if fn.startswith(b"nf"): files.append(fn) filecontent[fn] = p2[fn].data() @@ -271,43 +278,43 @@ cx = context.memctx( repo, pars, - "r%i" % id, + b"r%i" % id, files, fctxfn, date=(id, 0), - user="debugbuilddag", - extra={"branch": atbranch}, + user=b"debugbuilddag", + extra={b"branch": atbranch}, ) nodeid = repo.commitctx(cx) nodeids.append(nodeid) at = id - elif type == "l": + elif type == b"l": id, name = data - ui.note(("tag %s\n" % name)) - tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name)) - elif type == "a": - ui.note(("branch %s\n" % data)) + ui.note((b"tag %s\n" % name)) + tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name)) + elif type == b"a": + ui.note((b"branch %s\n" % data)) atbranch = data progress.update(id) if tags: - repo.vfs.write("localtags", "".join(tags)) + repo.vfs.write(b"localtags", b"".join(tags)) def _debugchangegroup(ui, gen, all=None, indent=0, **opts): - indent_string = " " * indent + indent_string = b" " * indent if all: ui.write( - "%sformat: id, p1, p2, cset, delta base, len(delta)\n" + b"%sformat: id, p1, p2, cset, delta base, len(delta)\n" % indent_string ) def showchunks(named): - ui.write("\n%s%s\n" % (indent_string, named)) + ui.write(b"\n%s%s\n" % (indent_string, named)) for deltadata in gen.deltaiter(): node, p1, p2, cs, deltabase, delta, flags = deltadata ui.write( - "%s%s %s %s %s %s %d\n" + b"%s%s %s %s %s %s %d\n" % ( indent_string, hex(node), @@ -320,37 +327,37 @@ ) chunkdata = gen.changelogheader() - showchunks("changelog") + showchunks(b"changelog") chunkdata = gen.manifestheader() - showchunks("manifest") + showchunks(b"manifest") for chunkdata in iter(gen.filelogheader, {}): - fname = chunkdata["filename"] + fname = chunkdata[b"filename"] showchunks(fname) else: if isinstance(gen, bundle2.unbundle20): - raise error.Abort(_("use debugbundle2 for this file")) + raise error.Abort(_(b"use debugbundle2 for this file")) chunkdata = gen.changelogheader() for deltadata in gen.deltaiter(): node, p1, p2, cs, deltabase, delta, flags = deltadata - ui.write("%s%s\n" % (indent_string, hex(node))) + ui.write(b"%s%s\n" % (indent_string, hex(node))) def _debugobsmarkers(ui, part, indent=0, **opts): """display version and markers contained in 'data'""" opts = pycompat.byteskwargs(opts) data = part.read() - indent_string = " " * indent + indent_string = b" " * indent try: version, markers = obsolete._readmarkers(data) except error.UnknownVersion as exc: - msg = "%sunsupported version: %s (%d bytes)\n" + msg = b"%sunsupported version: %s (%d bytes)\n" msg %= indent_string, exc.version, len(data) ui.write(msg) else: - msg = "%sversion: %d (%d bytes)\n" + msg = b"%sversion: %d (%d bytes)\n" msg %= indent_string, version, len(data) ui.write(msg) - fm = ui.formatter("debugobsolete", opts) + fm = ui.formatter(b"debugobsolete", opts) for rawmarker in sorted(markers): m = obsutil.marker(None, rawmarker) fm.startitem() @@ -361,17 +368,17 @@ def _debugphaseheads(ui, data, indent=0): """display version and markers contained in 'data'""" - indent_string = " " * indent + indent_string = b" " * indent headsbyphase = phases.binarydecode(data) for phase in phases.allphases: for head in headsbyphase[phase]: ui.write(indent_string) - ui.write("%s %s\n" % (hex(head), phases.phasenames[phase])) + ui.write(b"%s %s\n" % (hex(head), phases.phasenames[phase])) def _quasirepr(thing): if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)): - return "{%s}" % ( + return b"{%s}" % ( b", ".join(b"%s: %s" % (k, thing[k]) for k in sorted(thing)) ) return pycompat.bytestr(repr(thing)) @@ -380,35 +387,35 @@ def _debugbundle2(ui, gen, all=None, **opts): """lists the contents of a bundle2""" if not isinstance(gen, bundle2.unbundle20): - raise error.Abort(_("not a bundle2 file")) - ui.write(("Stream params: %s\n" % _quasirepr(gen.params))) + raise error.Abort(_(b"not a bundle2 file")) + ui.write((b"Stream params: %s\n" % _quasirepr(gen.params))) parttypes = opts.get(r"part_type", []) for part in gen.iterparts(): if parttypes and part.type not in parttypes: continue - msg = "%s -- %s (mandatory: %r)\n" + msg = b"%s -- %s (mandatory: %r)\n" ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory))) - if part.type == "changegroup": - version = part.params.get("version", "01") - cg = changegroup.getunbundler(version, part, "UN") + if part.type == b"changegroup": + version = part.params.get(b"version", b"01") + cg = changegroup.getunbundler(version, part, b"UN") if not ui.quiet: _debugchangegroup(ui, cg, all=all, indent=4, **opts) - if part.type == "obsmarkers": + if part.type == b"obsmarkers": if not ui.quiet: _debugobsmarkers(ui, part, indent=4, **opts) - if part.type == "phase-heads": + if part.type == b"phase-heads": if not ui.quiet: _debugphaseheads(ui, part, indent=4) @command( - "debugbundle", + b"debugbundle", [ - ("a", "all", None, _("show all details")), - ("", "part-type", [], _("show only the named part type")), - ("", "spec", None, _("print the bundlespec of the bundle")), + (b"a", b"all", None, _(b"show all details")), + (b"", b"part-type", [], _(b"show only the named part type")), + (b"", b"spec", None, _(b"print the bundlespec of the bundle")), ], - _("FILE"), + _(b"FILE"), norepo=True, ) def debugbundle(ui, bundlepath, all=None, spec=None, **opts): @@ -416,7 +423,7 @@ with hg.openpath(ui, bundlepath) as f: if spec: spec = exchange.getbundlespec(ui, f) - ui.write("%s\n" % spec) + ui.write(b"%s\n" % spec) return gen = exchange.readbundle(ui, f, bundlepath) @@ -425,25 +432,25 @@ _debugchangegroup(ui, gen, all=all, **opts) -@command("debugcapabilities", [], _("PATH"), norepo=True) +@command(b"debugcapabilities", [], _(b"PATH"), norepo=True) def debugcapabilities(ui, path, **opts): """lists the capabilities of a remote peer""" opts = pycompat.byteskwargs(opts) peer = hg.peer(ui, opts, path) caps = peer.capabilities() - ui.write("Main capabilities:\n") + ui.write(b"Main capabilities:\n") for c in sorted(caps): - ui.write(" %s\n" % c) + ui.write(b" %s\n" % c) b2caps = bundle2.bundle2caps(peer) if b2caps: - ui.write("Bundle2 capabilities:\n") + ui.write(b"Bundle2 capabilities:\n") for key, values in sorted(b2caps.iteritems()): - ui.write(" %s\n" % key) + ui.write(b" %s\n" % key) for v in values: - ui.write(" %s\n" % v) - - -@command("debugcheckstate", [], "") + ui.write(b" %s\n" % v) + + +@command(b"debugcheckstate", [], b"") def debugcheckstate(ui, repo): """validate the correctness of the current dirstate""" parent1, parent2 = repo.dirstate.parents() @@ -452,35 +459,35 @@ errors = 0 for f in repo.dirstate: state = repo.dirstate[f] - if state in "nr" and f not in m1: - ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state)) + if state in b"nr" and f not in m1: + ui.warn(_(b"%s in state %s, but not in manifest1\n") % (f, state)) errors += 1 - if state in "a" and f in m1: - ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state)) + if state in b"a" and f in m1: + ui.warn(_(b"%s in state %s, but also in manifest1\n") % (f, state)) errors += 1 - if state in "m" and f not in m1 and f not in m2: + if state in b"m" and f not in m1 and f not in m2: ui.warn( - _("%s in state %s, but not in either manifest\n") % (f, state) + _(b"%s in state %s, but not in either manifest\n") % (f, state) ) errors += 1 for f in m1: state = repo.dirstate[f] - if state not in "nrm": - ui.warn(_("%s in manifest1, but listed as state %s") % (f, state)) + if state not in b"nrm": + ui.warn(_(b"%s in manifest1, but listed as state %s") % (f, state)) errors += 1 if errors: - error = _(".hg/dirstate inconsistent with current parent's manifest") + error = _(b".hg/dirstate inconsistent with current parent's manifest") raise error.Abort(error) @command( - "debugcolor", - [("", "style", None, _("show all configured styles"))], - "hg debugcolor", + b"debugcolor", + [(b"", b"style", None, _(b"show all configured styles"))], + b"hg debugcolor", ) def debugcolor(ui, repo, **opts): """show available color, effects or style""" - ui.write("color mode: %s\n" % stringutil.pprint(ui._colormode)) + ui.write(b"color mode: %s\n" % stringutil.pprint(ui._colormode)) if opts.get(r"style"): return _debugdisplaystyle(ui) else: @@ -493,34 +500,34 @@ for effect in color._activeeffects(ui).keys(): ui._styles[effect] = effect if ui._terminfoparams: - for k, v in ui.configitems("color"): - if k.startswith("color."): + for k, v in ui.configitems(b"color"): + if k.startswith(b"color."): ui._styles[k] = k[6:] - elif k.startswith("terminfo."): + elif k.startswith(b"terminfo."): ui._styles[k] = k[9:] - ui.write(_("available colors:\n")) + ui.write(_(b"available colors:\n")) # sort label with a '_' after the other to group '_background' entry. - items = sorted(ui._styles.items(), key=lambda i: ("_" in i[0], i[0], i[1])) + items = sorted(ui._styles.items(), key=lambda i: (b"_" in i[0], i[0], i[1])) for colorname, label in items: - ui.write("%s\n" % colorname, label=label) + ui.write(b"%s\n" % colorname, label=label) def _debugdisplaystyle(ui): - ui.write(_("available style:\n")) + ui.write(_(b"available style:\n")) if not ui._styles: return width = max(len(s) for s in ui._styles) for label, effects in sorted(ui._styles.items()): - ui.write("%s" % label, label=label) + ui.write(b"%s" % label, label=label) if effects: # 50 - ui.write(": ") - ui.write(" " * (max(0, width - len(label)))) - ui.write(", ".join(ui.label(e, e) for e in effects.split())) - ui.write("\n") - - -@command("debugcreatestreamclonebundle", [], "FILE") + ui.write(b": ") + ui.write(b" " * (max(0, width - len(label)))) + ui.write(b", ".join(ui.label(e, e) for e in effects.split())) + ui.write(b"\n") + + +@command(b"debugcreatestreamclonebundle", [], b"FILE") def debugcreatestreamclonebundle(ui, repo, fname): """create a stream clone bundle file @@ -532,26 +539,26 @@ if phases.hassecret(repo): ui.warn( _( - "(warning: stream clone bundle will contain secret " - "revisions)\n" + b"(warning: stream clone bundle will contain secret " + b"revisions)\n" ) ) requirements, gen = streamclone.generatebundlev1(repo) changegroup.writechunks(ui, gen, fname) - ui.write(_("bundle requirements: %s\n") % ", ".join(sorted(requirements))) + ui.write(_(b"bundle requirements: %s\n") % b", ".join(sorted(requirements))) @command( - "debugdag", + b"debugdag", [ - ("t", "tags", None, _("use tags as labels")), - ("b", "branches", None, _("annotate with branch names")), - ("", "dots", None, _("use dots for runs")), - ("s", "spaces", None, _("separate elements by spaces")), + (b"t", b"tags", None, _(b"use tags as labels")), + (b"b", b"branches", None, _(b"annotate with branch names")), + (b"", b"dots", None, _(b"use dots for runs")), + (b"s", b"spaces", None, _(b"separate elements by spaces")), ], - _("[OPTION]... [FILE [REV]...]"), + _(b"[OPTION]... [FILE [REV]...]"), optionalrepo=True, ) def debugdag(ui, repo, file_=None, *revs, **opts): @@ -570,9 +577,9 @@ def events(): for r in rlog: - yield "n", (r, list(p for p in rlog.parentrevs(r) if p != -1)) + yield b"n", (r, list(p for p in rlog.parentrevs(r) if p != -1)) if r in revs: - yield "l", (r, "r%i" % r) + yield b"l", (r, b"r%i" % r) elif repo: cl = repo.changelog @@ -584,22 +591,22 @@ labels.setdefault(cl.rev(n), []).append(l) def events(): - b = "default" + b = b"default" for r in cl: if branches: - newb = cl.read(cl.node(r))[5]["branch"] + newb = cl.read(cl.node(r))[5][b"branch"] if newb != b: - yield "a", newb + yield b"a", newb b = newb - yield "n", (r, list(p for p in cl.parentrevs(r) if p != -1)) + yield b"n", (r, list(p for p in cl.parentrevs(r) if p != -1)) if tags: ls = labels.get(r) if ls: for l in ls: - yield "l", (r, l) + yield b"l", (r, l) else: - raise error.Abort(_("need repo for changelog dag")) + raise error.Abort(_(b"need repo for changelog dag")) for line in dagparser.dagtextlines( events(), @@ -611,30 +618,30 @@ maxlinewidth=70, ): ui.write(line) - ui.write("\n") - - -@command("debugdata", cmdutil.debugrevlogopts, _("-c|-m|FILE REV")) + ui.write(b"\n") + + +@command(b"debugdata", cmdutil.debugrevlogopts, _(b"-c|-m|FILE REV")) def debugdata(ui, repo, file_, rev=None, **opts): """dump the contents of a data file revision""" opts = pycompat.byteskwargs(opts) - if opts.get("changelog") or opts.get("manifest") or opts.get("dir"): + if opts.get(b"changelog") or opts.get(b"manifest") or opts.get(b"dir"): if rev is not None: - raise error.CommandError("debugdata", _("invalid arguments")) + raise error.CommandError(b"debugdata", _(b"invalid arguments")) file_, rev = None, file_ elif rev is None: - raise error.CommandError("debugdata", _("invalid arguments")) - r = cmdutil.openstorage(repo, "debugdata", file_, opts) + raise error.CommandError(b"debugdata", _(b"invalid arguments")) + r = cmdutil.openstorage(repo, b"debugdata", file_, opts) try: ui.write(r.rawdata(r.lookup(rev))) except KeyError: - raise error.Abort(_("invalid revision identifier %s") % rev) + raise error.Abort(_(b"invalid revision identifier %s") % rev) @command( - "debugdate", - [("e", "extended", None, _("try extended date formats"))], - _("[-e] DATE [RANGE]"), + b"debugdate", + [(b"e", b"extended", None, _(b"try extended date formats"))], + _(b"[-e] DATE [RANGE]"), norepo=True, optionalrepo=True, ) @@ -644,17 +651,17 @@ d = dateutil.parsedate(date, util.extendeddateformats) else: d = dateutil.parsedate(date) - ui.write("internal: %d %d\n" % d) - ui.write("standard: %s\n" % dateutil.datestr(d)) + ui.write(b"internal: %d %d\n" % d) + ui.write(b"standard: %s\n" % dateutil.datestr(d)) if range: m = dateutil.matchdate(range) - ui.write("match: %s\n" % m(d[0])) + ui.write(b"match: %s\n" % m(d[0])) @command( - "debugdeltachain", + b"debugdeltachain", cmdutil.debugrevlogopts + cmdutil.formatteropts, - _("-c|-m|FILE"), + _(b"-c|-m|FILE"), optionalrepo=True, ) def debugdeltachain(ui, repo, file_=None, **opts): @@ -693,7 +700,7 @@ The sparse read can be enabled with experimental.sparse-read = True """ opts = pycompat.byteskwargs(opts) - r = cmdutil.openrevlog(repo, "debugdeltachain", file_, opts) + r = cmdutil.openrevlog(repo, b"debugdeltachain", file_, opts) index = r.index start = r.start length = r.length @@ -708,20 +715,20 @@ if generaldelta: if e[3] == e[5]: - deltatype = "p1" + deltatype = b"p1" elif e[3] == e[6]: - deltatype = "p2" + deltatype = b"p2" elif e[3] == rev - 1: - deltatype = "prev" + deltatype = b"prev" elif e[3] == rev: - deltatype = "base" + deltatype = b"base" else: - deltatype = "other" + deltatype = b"other" else: if e[3] == rev: - deltatype = "base" + deltatype = b"base" else: - deltatype = "prev" + deltatype = b"prev" chain = r._deltachain(rev)[0] for iterrev in chain: @@ -730,16 +737,16 @@ return compsize, uncompsize, deltatype, chain, chainsize - fm = ui.formatter("debugdeltachain", opts) + fm = ui.formatter(b"debugdeltachain", opts) fm.plain( - " rev chain# chainlen prev delta " - "size rawsize chainsize ratio lindist extradist " - "extraratio" + b" rev chain# chainlen prev delta " + b"size rawsize chainsize ratio lindist extradist " + b"extraratio" ) if withsparseread: - fm.plain(" readsize largestblk rddensity srchunks") - fm.plain("\n") + fm.plain(b" readsize largestblk rddensity srchunks") + fm.plain(b"\n") chainbases = {} for rev in r: @@ -767,10 +774,10 @@ fm.startitem() fm.write( - "rev chainid chainlen prevrev deltatype compsize " - "uncompsize chainsize chainratio lindist extradist " - "extraratio", - "%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f", + b"rev chainid chainlen prevrev deltatype compsize " + b"uncompsize chainsize chainratio lindist extradist " + b"extraratio", + b"%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f", rev, chainid, len(chain), @@ -816,8 +823,8 @@ readdensity = 1 fm.write( - "readsize largestblock readdensity srchunks", - " %10d %10d %9.5f %8d", + b"readsize largestblock readdensity srchunks", + b" %10d %10d %9.5f %8d", readsize, largestblock, readdensity, @@ -828,19 +835,24 @@ srchunks=srchunks, ) - fm.plain("\n") + fm.plain(b"\n") fm.end() @command( - "debugdirstate|debugstate", + b"debugdirstate|debugstate", [ - ("", "nodates", None, _("do not display the saved mtime (DEPRECATED)")), - ("", "dates", True, _("display the saved mtime")), - ("", "datesort", None, _("sort by saved mtime")), + ( + b"", + b"nodates", + None, + _(b"do not display the saved mtime (DEPRECATED)"), + ), + (b"", b"dates", True, _(b"display the saved mtime")), + (b"", b"datesort", None, _(b"sort by saved mtime")), ], - _("[OPTION]..."), + _(b"[OPTION]..."), ) def debugstate(ui, repo, **opts): """show the contents of the current dirstate""" @@ -856,67 +868,67 @@ keyfunc = None # sort by filename for file_, ent in sorted(repo.dirstate.iteritems(), key=keyfunc): if ent[3] == -1: - timestr = "unset " + timestr = b"unset " elif nodates: - timestr = "set " + timestr = b"set " else: timestr = time.strftime( r"%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]) ) timestr = encoding.strtolocal(timestr) if ent[1] & 0o20000: - mode = "lnk" + mode = b"lnk" else: - mode = "%3o" % (ent[1] & 0o777 & ~util.umask) - ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_)) + mode = b"%3o" % (ent[1] & 0o777 & ~util.umask) + ui.write(b"%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_)) for f in repo.dirstate.copies(): - ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f)) + ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f)) @command( - "debugdiscovery", + b"debugdiscovery", [ - ("", "old", None, _("use old-style discovery")), + (b"", b"old", None, _(b"use old-style discovery")), ( - "", - "nonheads", + b"", + b"nonheads", None, - _("use old-style discovery with non-heads included"), + _(b"use old-style discovery with non-heads included"), ), - ("", "rev", [], "restrict discovery to this set of revs"), - ("", "seed", "12323", "specify the random seed use for discovery"), + (b"", b"rev", [], b"restrict discovery to this set of revs"), + (b"", b"seed", b"12323", b"specify the random seed use for discovery"), ] + cmdutil.remoteopts, - _("[--rev REV] [OTHER]"), + _(b"[--rev REV] [OTHER]"), ) -def debugdiscovery(ui, repo, remoteurl="default", **opts): +def debugdiscovery(ui, repo, remoteurl=b"default", **opts): """runs the changeset discovery protocol in isolation""" opts = pycompat.byteskwargs(opts) remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl)) remote = hg.peer(repo, opts, remoteurl) - ui.status(_("comparing with %s\n") % util.hidepassword(remoteurl)) + ui.status(_(b"comparing with %s\n") % util.hidepassword(remoteurl)) # make sure tests are repeatable - random.seed(int(opts["seed"])) - - if opts.get("old"): + random.seed(int(opts[b"seed"])) + + if opts.get(b"old"): def doit(pushedrevs, remoteheads, remote=remote): - if not util.safehasattr(remote, "branches"): + if not util.safehasattr(remote, b"branches"): # enable in-client legacy support remote = localrepo.locallegacypeer(remote.local()) common, _in, hds = treediscovery.findcommonincoming( repo, remote, force=True ) common = set(common) - if not opts.get("nonheads"): + if not opts.get(b"nonheads"): ui.write( - "unpruned common: %s\n" - % " ".join(sorted(short(n) for n in common)) + b"unpruned common: %s\n" + % b" ".join(sorted(short(n) for n in common)) ) clnode = repo.changelog.node - common = repo.revs("heads(::%ln)", common) + common = repo.revs(b"heads(::%ln)", common) common = {clnode(r) for r in common} return common, hds @@ -933,8 +945,8 @@ return common, hds remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None) - localrevs = opts["rev"] - with util.timedcm("debug-discovery") as t: + localrevs = opts[b"rev"] + with util.timedcm(b"debug-discovery") as t: common, hds = doit(localrevs, remoterevs) # compute all statistics @@ -943,46 +955,48 @@ lheads = set(repo.heads()) data = {} - data["elapsed"] = t.elapsed - data["nb-common"] = len(common) - data["nb-common-local"] = len(common & lheads) - data["nb-common-remote"] = len(common & rheads) - data["nb-common-both"] = len(common & rheads & lheads) - data["nb-local"] = len(lheads) - data["nb-local-missing"] = data["nb-local"] - data["nb-common-local"] - data["nb-remote"] = len(rheads) - data["nb-remote-unknown"] = data["nb-remote"] - data["nb-common-remote"] - data["nb-revs"] = len(repo.revs("all()")) - data["nb-revs-common"] = len(repo.revs("::%ln", common)) - data["nb-revs-missing"] = data["nb-revs"] - data["nb-revs-common"] + data[b"elapsed"] = t.elapsed + data[b"nb-common"] = len(common) + data[b"nb-common-local"] = len(common & lheads) + data[b"nb-common-remote"] = len(common & rheads) + data[b"nb-common-both"] = len(common & rheads & lheads) + data[b"nb-local"] = len(lheads) + data[b"nb-local-missing"] = data[b"nb-local"] - data[b"nb-common-local"] + data[b"nb-remote"] = len(rheads) + data[b"nb-remote-unknown"] = data[b"nb-remote"] - data[b"nb-common-remote"] + data[b"nb-revs"] = len(repo.revs(b"all()")) + data[b"nb-revs-common"] = len(repo.revs(b"::%ln", common)) + data[b"nb-revs-missing"] = data[b"nb-revs"] - data[b"nb-revs-common"] # display discovery summary - ui.write("elapsed time: %(elapsed)f seconds\n" % data) - ui.write("heads summary:\n") - ui.write(" total common heads: %(nb-common)9d\n" % data) - ui.write(" also local heads: %(nb-common-local)9d\n" % data) - ui.write(" also remote heads: %(nb-common-remote)9d\n" % data) - ui.write(" both: %(nb-common-both)9d\n" % data) - ui.write(" local heads: %(nb-local)9d\n" % data) - ui.write(" common: %(nb-common-local)9d\n" % data) - ui.write(" missing: %(nb-local-missing)9d\n" % data) - ui.write(" remote heads: %(nb-remote)9d\n" % data) - ui.write(" common: %(nb-common-remote)9d\n" % data) - ui.write(" unknown: %(nb-remote-unknown)9d\n" % data) - ui.write("local changesets: %(nb-revs)9d\n" % data) - ui.write(" common: %(nb-revs-common)9d\n" % data) - ui.write(" missing: %(nb-revs-missing)9d\n" % data) + ui.write(b"elapsed time: %(elapsed)f seconds\n" % data) + ui.write(b"heads summary:\n") + ui.write(b" total common heads: %(nb-common)9d\n" % data) + ui.write(b" also local heads: %(nb-common-local)9d\n" % data) + ui.write(b" also remote heads: %(nb-common-remote)9d\n" % data) + ui.write(b" both: %(nb-common-both)9d\n" % data) + ui.write(b" local heads: %(nb-local)9d\n" % data) + ui.write(b" common: %(nb-common-local)9d\n" % data) + ui.write(b" missing: %(nb-local-missing)9d\n" % data) + ui.write(b" remote heads: %(nb-remote)9d\n" % data) + ui.write(b" common: %(nb-common-remote)9d\n" % data) + ui.write(b" unknown: %(nb-remote-unknown)9d\n" % data) + ui.write(b"local changesets: %(nb-revs)9d\n" % data) + ui.write(b" common: %(nb-revs-common)9d\n" % data) + ui.write(b" missing: %(nb-revs-missing)9d\n" % data) if ui.verbose: ui.write( - "common heads: %s\n" % " ".join(sorted(short(n) for n in common)) + b"common heads: %s\n" % b" ".join(sorted(short(n) for n in common)) ) _chunksize = 4 << 10 -@command("debugdownload", [("o", "output", "", _("path")),], optionalrepo=True) +@command( + b"debugdownload", [(b"o", b"output", b"", _(b"path")),], optionalrepo=True +) def debugdownload(ui, repo, url, output=None, **opts): """download a resource using Mercurial logic and config """ @@ -990,7 +1004,7 @@ dest = ui if output: - dest = open(output, "wb", _chunksize) + dest = open(output, b"wb", _chunksize) try: data = fh.read(_chunksize) while data: @@ -1001,89 +1015,95 @@ dest.close() -@command("debugextensions", cmdutil.formatteropts, [], optionalrepo=True) +@command(b"debugextensions", cmdutil.formatteropts, [], optionalrepo=True) def debugextensions(ui, repo, **opts): """show information about active extensions""" opts = pycompat.byteskwargs(opts) exts = extensions.extensions(ui) hgver = util.version() - fm = ui.formatter("debugextensions", opts) + fm = ui.formatter(b"debugextensions", opts) for extname, extmod in sorted(exts, key=operator.itemgetter(0)): isinternal = extensions.ismoduleinternal(extmod) extsource = pycompat.fsencode(extmod.__file__) if isinternal: exttestedwith = [] # never expose magic string to users else: - exttestedwith = getattr(extmod, "testedwith", "").split() + exttestedwith = getattr(extmod, "testedwith", b"").split() extbuglink = getattr(extmod, "buglink", None) fm.startitem() if ui.quiet or ui.verbose: - fm.write("name", "%s\n", extname) + fm.write(b"name", b"%s\n", extname) else: - fm.write("name", "%s", extname) + fm.write(b"name", b"%s", extname) if isinternal or hgver in exttestedwith: - fm.plain("\n") + fm.plain(b"\n") elif not exttestedwith: - fm.plain(_(" (untested!)\n")) + fm.plain(_(b" (untested!)\n")) else: lasttestedversion = exttestedwith[-1] - fm.plain(" (%s!)\n" % lasttestedversion) + fm.plain(b" (%s!)\n" % lasttestedversion) fm.condwrite( ui.verbose and extsource, - "source", - _(" location: %s\n"), - extsource or "", + b"source", + _(b" location: %s\n"), + extsource or b"", ) if ui.verbose: - fm.plain(_(" bundled: %s\n") % ["no", "yes"][isinternal]) + fm.plain(_(b" bundled: %s\n") % [b"no", b"yes"][isinternal]) fm.data(bundled=isinternal) fm.condwrite( ui.verbose and exttestedwith, - "testedwith", - _(" tested with: %s\n"), - fm.formatlist(exttestedwith, name="ver"), + b"testedwith", + _(b" tested with: %s\n"), + fm.formatlist(exttestedwith, name=b"ver"), ) fm.condwrite( ui.verbose and extbuglink, - "buglink", - _(" bug reporting: %s\n"), - extbuglink or "", + b"buglink", + _(b" bug reporting: %s\n"), + extbuglink or b"", ) fm.end() @command( - "debugfileset", + b"debugfileset", [ - ("r", "rev", "", _("apply the filespec on this revision"), _("REV")), ( - "", - "all-files", - False, - _("test files from all revisions and working directory"), + b"r", + b"rev", + b"", + _(b"apply the filespec on this revision"), + _(b"REV"), ), ( - "s", - "show-matcher", - None, - _("print internal representation of matcher"), + b"", + b"all-files", + False, + _(b"test files from all revisions and working directory"), ), ( - "p", - "show-stage", + b"s", + b"show-matcher", + None, + _(b"print internal representation of matcher"), + ), + ( + b"p", + b"show-stage", [], - _("print parsed tree at the given stage"), - _("NAME"), + _(b"print parsed tree at the given stage"), + _(b"NAME"), ), ], - _("[-r REV] [--all-files] [OPTION]... FILESPEC"), + _(b"[-r REV] [--all-files] [OPTION]... FILESPEC"), ) def debugfileset(ui, repo, expr, **opts): """parse and apply a fileset specification""" @@ -1091,42 +1111,42 @@ fileset.symbols # force import of fileset so we have predicates to optimize opts = pycompat.byteskwargs(opts) - ctx = scmutil.revsingle(repo, opts.get("rev"), None) + ctx = scmutil.revsingle(repo, opts.get(b"rev"), None) stages = [ - ("parsed", pycompat.identity), - ("analyzed", filesetlang.analyze), - ("optimized", filesetlang.optimize), + (b"parsed", pycompat.identity), + (b"analyzed", filesetlang.analyze), + (b"optimized", filesetlang.optimize), ] stagenames = set(n for n, f in stages) showalways = set() - if ui.verbose and not opts["show_stage"]: + if ui.verbose and not opts[b"show_stage"]: # show parsed tree by --verbose (deprecated) - showalways.add("parsed") - if opts["show_stage"] == ["all"]: + showalways.add(b"parsed") + if opts[b"show_stage"] == [b"all"]: showalways.update(stagenames) else: - for n in opts["show_stage"]: + for n in opts[b"show_stage"]: if n not in stagenames: - raise error.Abort(_("invalid stage name: %s") % n) - showalways.update(opts["show_stage"]) + raise error.Abort(_(b"invalid stage name: %s") % n) + showalways.update(opts[b"show_stage"]) tree = filesetlang.parse(expr) for n, f in stages: tree = f(tree) if n in showalways: - if opts["show_stage"] or n != "parsed": - ui.write("* %s:\n" % n) - ui.write(filesetlang.prettyformat(tree), "\n") + if opts[b"show_stage"] or n != b"parsed": + ui.write(b"* %s:\n" % n) + ui.write(filesetlang.prettyformat(tree), b"\n") files = set() - if opts["all_files"]: + if opts[b"all_files"]: for r in repo: c = repo[r] files.update(c.files()) files.update(c.substate) - if opts["all_files"] or ctx.rev() is None: + if opts[b"all_files"] or ctx.rev() is None: wctx = repo[None] files.update( repo.dirstate.walk( @@ -1142,15 +1162,15 @@ files.update(ctx.substate) m = ctx.matchfileset(expr) - if opts["show_matcher"] or (opts["show_matcher"] is None and ui.verbose): - ui.write("* matcher:\n", stringutil.prettyrepr(m), "\n") + if opts[b"show_matcher"] or (opts[b"show_matcher"] is None and ui.verbose): + ui.write(b"* matcher:\n", stringutil.prettyrepr(m), b"\n") for f in sorted(files): if not m(f): continue - ui.write("%s\n" % f) - - -@command("debugformat", [] + cmdutil.formatteropts) + ui.write(b"%s\n" % f) + + +@command(b"debugformat", [] + cmdutil.formatteropts) def debugformat(ui, repo, **opts): """display format information about the current repository @@ -1158,96 +1178,102 @@ Mercurial default.""" opts = pycompat.byteskwargs(opts) maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant) - maxvariantlength = max(len("format-variant"), maxvariantlength) + maxvariantlength = max(len(b"format-variant"), maxvariantlength) def makeformatname(name): - return "%s:" + (" " * (maxvariantlength - len(name))) - - fm = ui.formatter("debugformat", opts) + return b"%s:" + (b" " * (maxvariantlength - len(name))) + + fm = ui.formatter(b"debugformat", opts) if fm.isplain(): def formatvalue(value): - if util.safehasattr(value, "startswith"): + if util.safehasattr(value, b"startswith"): return value if value: - return "yes" + return b"yes" else: - return "no" + return b"no" else: formatvalue = pycompat.identity - fm.plain("format-variant") - fm.plain(" " * (maxvariantlength - len("format-variant"))) - fm.plain(" repo") + fm.plain(b"format-variant") + fm.plain(b" " * (maxvariantlength - len(b"format-variant"))) + fm.plain(b" repo") if ui.verbose: - fm.plain(" config default") - fm.plain("\n") + fm.plain(b" config default") + fm.plain(b"\n") for fv in upgrade.allformatvariant: fm.startitem() repovalue = fv.fromrepo(repo) configvalue = fv.fromconfig(repo) if repovalue != configvalue: - namelabel = "formatvariant.name.mismatchconfig" - repolabel = "formatvariant.repo.mismatchconfig" + namelabel = b"formatvariant.name.mismatchconfig" + repolabel = b"formatvariant.repo.mismatchconfig" elif repovalue != fv.default: - namelabel = "formatvariant.name.mismatchdefault" - repolabel = "formatvariant.repo.mismatchdefault" + namelabel = b"formatvariant.name.mismatchdefault" + repolabel = b"formatvariant.repo.mismatchdefault" else: - namelabel = "formatvariant.name.uptodate" - repolabel = "formatvariant.repo.uptodate" - - fm.write("name", makeformatname(fv.name), fv.name, label=namelabel) - fm.write("repo", " %3s", formatvalue(repovalue), label=repolabel) + namelabel = b"formatvariant.name.uptodate" + repolabel = b"formatvariant.repo.uptodate" + + fm.write(b"name", makeformatname(fv.name), fv.name, label=namelabel) + fm.write(b"repo", b" %3s", formatvalue(repovalue), label=repolabel) if fv.default != configvalue: - configlabel = "formatvariant.config.special" + configlabel = b"formatvariant.config.special" else: - configlabel = "formatvariant.config.default" + configlabel = b"formatvariant.config.default" fm.condwrite( ui.verbose, - "config", - " %6s", + b"config", + b" %6s", formatvalue(configvalue), label=configlabel, ) fm.condwrite( ui.verbose, - "default", - " %7s", + b"default", + b" %7s", formatvalue(fv.default), - label="formatvariant.default", + label=b"formatvariant.default", ) - fm.plain("\n") + fm.plain(b"\n") fm.end() -@command("debugfsinfo", [], _("[PATH]"), norepo=True) -def debugfsinfo(ui, path="."): +@command(b"debugfsinfo", [], _(b"[PATH]"), norepo=True) +def debugfsinfo(ui, path=b"."): """show information detected about current filesystem""" - ui.write("path: %s\n" % path) - ui.write("mounted on: %s\n" % (util.getfsmountpoint(path) or "(unknown)")) - ui.write("exec: %s\n" % (util.checkexec(path) and "yes" or "no")) - ui.write("fstype: %s\n" % (util.getfstype(path) or "(unknown)")) - ui.write("symlink: %s\n" % (util.checklink(path) and "yes" or "no")) - ui.write("hardlink: %s\n" % (util.checknlink(path) and "yes" or "no")) - casesensitive = "(unknown)" + ui.write(b"path: %s\n" % path) + ui.write(b"mounted on: %s\n" % (util.getfsmountpoint(path) or b"(unknown)")) + ui.write(b"exec: %s\n" % (util.checkexec(path) and b"yes" or b"no")) + ui.write(b"fstype: %s\n" % (util.getfstype(path) or b"(unknown)")) + ui.write(b"symlink: %s\n" % (util.checklink(path) and b"yes" or b"no")) + ui.write(b"hardlink: %s\n" % (util.checknlink(path) and b"yes" or b"no")) + casesensitive = b"(unknown)" try: - with pycompat.namedtempfile(prefix=".debugfsinfo", dir=path) as f: - casesensitive = util.fscasesensitive(f.name) and "yes" or "no" + with pycompat.namedtempfile(prefix=b".debugfsinfo", dir=path) as f: + casesensitive = util.fscasesensitive(f.name) and b"yes" or b"no" except OSError: pass - ui.write("case-sensitive: %s\n" % casesensitive) + ui.write(b"case-sensitive: %s\n" % casesensitive) @command( - "debuggetbundle", + b"debuggetbundle", [ - ("H", "head", [], _("id of head node"), _("ID")), - ("C", "common", [], _("id of common node"), _("ID")), - ("t", "type", "bzip2", _("bundle compression type to use"), _("TYPE")), + (b"H", b"head", [], _(b"id of head node"), _(b"ID")), + (b"C", b"common", [], _(b"id of common node"), _(b"ID")), + ( + b"t", + b"type", + b"bzip2", + _(b"bundle compression type to use"), + _(b"TYPE"), + ), ], - _("REPO FILE [-H|-C ID]..."), + _(b"REPO FILE [-H|-C ID]..."), norepo=True, ) def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts): @@ -1258,8 +1284,8 @@ """ opts = pycompat.byteskwargs(opts) repo = hg.peer(ui, opts, repopath) - if not repo.capable("getbundle"): - raise error.Abort("getbundle() not supported by target repository") + if not repo.capable(b"getbundle"): + raise error.Abort(b"getbundle() not supported by target repository") args = {} if common: args[r"common"] = [bin(s) for s in common] @@ -1267,22 +1293,22 @@ args[r"heads"] = [bin(s) for s in head] # TODO: get desired bundlecaps from command line. args[r"bundlecaps"] = None - bundle = repo.getbundle("debug", **args) - - bundletype = opts.get("type", "bzip2").lower() + bundle = repo.getbundle(b"debug", **args) + + bundletype = opts.get(b"type", b"bzip2").lower() btypes = { - "none": "HG10UN", - "bzip2": "HG10BZ", - "gzip": "HG10GZ", - "bundle2": "HG20", + b"none": b"HG10UN", + b"bzip2": b"HG10BZ", + b"gzip": b"HG10GZ", + b"bundle2": b"HG20", } bundletype = btypes.get(bundletype) if bundletype not in bundle2.bundletypes: - raise error.Abort(_("unknown bundle type specified with --type")) + raise error.Abort(_(b"unknown bundle type specified with --type")) bundle2.writebundle(ui, bundle, bundlepath, bundletype) -@command("debugignore", [], "[FILE]") +@command(b"debugignore", [], b"[FILE]") def debugignore(ui, repo, *files, **opts): """display the combined ignore pattern and information about ignored files @@ -1294,7 +1320,7 @@ ignore = repo.dirstate._ignore if not files: # Show all the patterns - ui.write("%s\n" % pycompat.byterepr(ignore)) + ui.write(b"%s\n" % pycompat.byterepr(ignore)) else: m = scmutil.match(repo[None], pats=files) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) @@ -1302,7 +1328,7 @@ nf = util.normpath(f) ignored = None ignoredata = None - if nf != ".": + if nf != b".": if ignore(nf): ignored = nf ignoredata = repo.dirstate._ignorefileandline(nf) @@ -1314,33 +1340,33 @@ break if ignored: if ignored == nf: - ui.write(_("%s is ignored\n") % uipathfn(f)) + ui.write(_(b"%s is ignored\n") % uipathfn(f)) else: ui.write( _( - "%s is ignored because of " - "containing directory %s\n" + b"%s is ignored because of " + b"containing directory %s\n" ) % (uipathfn(f), ignored) ) ignorefile, lineno, line = ignoredata ui.write( - _("(ignore rule in %s, line %d: '%s')\n") + _(b"(ignore rule in %s, line %d: '%s')\n") % (ignorefile, lineno, line) ) else: - ui.write(_("%s is not ignored\n") % uipathfn(f)) + ui.write(_(b"%s is not ignored\n") % uipathfn(f)) @command( - "debugindex", + b"debugindex", cmdutil.debugrevlogopts + cmdutil.formatteropts, - _("-c|-m|FILE"), + _(b"-c|-m|FILE"), ) def debugindex(ui, repo, file_=None, **opts): """dump index data for a storage primitive""" opts = pycompat.byteskwargs(opts) - store = cmdutil.openstorage(repo, "debugindex", file_, opts) + store = cmdutil.openstorage(repo, b"debugindex", file_, opts) if ui.debugflag: shortfn = hex @@ -1352,7 +1378,7 @@ idlen = len(shortfn(store.node(i))) break - fm = ui.formatter("debugindex", opts) + fm = ui.formatter(b"debugindex", opts) fm.plain( b" rev linkrev %s %s p2\n" % (b"nodeid".ljust(idlen), b"p1".ljust(idlen)) @@ -1364,44 +1390,47 @@ fm.startitem() fm.write(b"rev", b"%6d ", rev) - fm.write(b"linkrev", "%7d ", store.linkrev(rev)) - fm.write(b"node", "%s ", shortfn(node)) - fm.write(b"p1", "%s ", shortfn(parents[0])) - fm.write(b"p2", "%s", shortfn(parents[1])) + fm.write(b"linkrev", b"%7d ", store.linkrev(rev)) + fm.write(b"node", b"%s ", shortfn(node)) + fm.write(b"p1", b"%s ", shortfn(parents[0])) + fm.write(b"p2", b"%s", shortfn(parents[1])) fm.plain(b"\n") fm.end() @command( - "debugindexdot", cmdutil.debugrevlogopts, _("-c|-m|FILE"), optionalrepo=True + b"debugindexdot", + cmdutil.debugrevlogopts, + _(b"-c|-m|FILE"), + optionalrepo=True, ) def debugindexdot(ui, repo, file_=None, **opts): """dump an index DAG as a graphviz dot file""" opts = pycompat.byteskwargs(opts) - r = cmdutil.openstorage(repo, "debugindexdot", file_, opts) - ui.write("digraph G {\n") + r = cmdutil.openstorage(repo, b"debugindexdot", file_, opts) + ui.write(b"digraph G {\n") for i in r: node = r.node(i) pp = r.parents(node) - ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i)) + ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i)) if pp[1] != nullid: - ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i)) - ui.write("}\n") - - -@command("debugindexstats", []) + ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i)) + ui.write(b"}\n") + + +@command(b"debugindexstats", []) def debugindexstats(ui, repo): """show stats related to the changelog index""" repo.changelog.shortest(nullid, 1) index = repo.changelog.index - if not util.safehasattr(index, "stats"): - raise error.Abort(_("debugindexstats only works with native code")) + if not util.safehasattr(index, b"stats"): + raise error.Abort(_(b"debugindexstats only works with native code")) for k, v in sorted(index.stats().items()): - ui.write("%s: %d\n" % (k, v)) - - -@command("debuginstall", [] + cmdutil.formatteropts, "", norepo=True) + ui.write(b"%s: %d\n" % (k, v)) + + +@command(b"debuginstall", [] + cmdutil.formatteropts, b"", norepo=True) def debuginstall(ui, **opts): """test Mercurial installation @@ -1411,11 +1440,11 @@ problems = 0 - fm = ui.formatter("debuginstall", opts) + fm = ui.formatter(b"debuginstall", opts) fm.startitem() # encoding - fm.write("encoding", _("checking encoding (%s)...\n"), encoding.encoding) + fm.write(b"encoding", _(b"checking encoding (%s)...\n"), encoding.encoding) err = None try: codecs.lookup(pycompat.sysstr(encoding.encoding)) @@ -1424,52 +1453,52 @@ problems += 1 fm.condwrite( err, - "encodingerror", - _(" %s\n" " (check that your locale is properly set)\n"), + b"encodingerror", + _(b" %s\n" b" (check that your locale is properly set)\n"), err, ) # Python fm.write( - "pythonexe", - _("checking Python executable (%s)\n"), - pycompat.sysexecutable or _("unknown"), + b"pythonexe", + _(b"checking Python executable (%s)\n"), + pycompat.sysexecutable or _(b"unknown"), ) fm.write( - "pythonver", - _("checking Python version (%s)\n"), - ("%d.%d.%d" % sys.version_info[:3]), + b"pythonver", + _(b"checking Python version (%s)\n"), + (b"%d.%d.%d" % sys.version_info[:3]), ) fm.write( - "pythonlib", - _("checking Python lib (%s)...\n"), + b"pythonlib", + _(b"checking Python lib (%s)...\n"), os.path.dirname(pycompat.fsencode(os.__file__)), ) security = set(sslutil.supportedprotocols) if sslutil.hassni: - security.add("sni") + security.add(b"sni") fm.write( - "pythonsecurity", - _("checking Python security support (%s)\n"), - fm.formatlist(sorted(security), name="protocol", fmt="%s", sep=","), + b"pythonsecurity", + _(b"checking Python security support (%s)\n"), + fm.formatlist(sorted(security), name=b"protocol", fmt=b"%s", sep=b","), ) # These are warnings, not errors. So don't increment problem count. This # may change in the future. - if "tls1.2" not in security: + if b"tls1.2" not in security: fm.plain( _( - " TLS 1.2 not supported by Python install; " - "network connections lack modern security\n" + b" TLS 1.2 not supported by Python install; " + b"network connections lack modern security\n" ) ) - if "sni" not in security: + if b"sni" not in security: fm.plain( _( - " SNI not supported by Python install; may have " - "connectivity issues with some servers\n" + b" SNI not supported by Python install; may have " + b"connectivity issues with some servers\n" ) ) @@ -1478,27 +1507,27 @@ # hg version hgver = util.version() fm.write( - "hgver", _("checking Mercurial version (%s)\n"), hgver.split("+")[0] + b"hgver", _(b"checking Mercurial version (%s)\n"), hgver.split(b"+")[0] ) fm.write( - "hgverextra", - _("checking Mercurial custom build (%s)\n"), - "+".join(hgver.split("+")[1:]), + b"hgverextra", + _(b"checking Mercurial custom build (%s)\n"), + b"+".join(hgver.split(b"+")[1:]), ) # compiled modules fm.write( - "hgmodulepolicy", _("checking module policy (%s)\n"), policy.policy + b"hgmodulepolicy", _(b"checking module policy (%s)\n"), policy.policy ) fm.write( - "hgmodules", - _("checking installed modules (%s)...\n"), + b"hgmodules", + _(b"checking installed modules (%s)...\n"), os.path.dirname(pycompat.fsencode(__file__)), ) - rustandc = policy.policy in ("rust+c", "rust+c-allow") + rustandc = policy.policy in (b"rust+c", b"rust+c-allow") rustext = rustandc # for now, that's the only case - cext = policy.policy in ("c", "allow") or rustandc + cext = policy.policy in (b"c", b"allow") or rustandc nopure = cext or rustext if nopure: err = None @@ -1523,54 +1552,57 @@ except Exception as inst: err = stringutil.forcebytestr(inst) problems += 1 - fm.condwrite(err, "extensionserror", " %s\n", err) + fm.condwrite(err, b"extensionserror", b" %s\n", err) compengines = util.compengines._engines.values() fm.write( - "compengines", - _("checking registered compression engines (%s)\n"), + b"compengines", + _(b"checking registered compression engines (%s)\n"), fm.formatlist( sorted(e.name() for e in compengines), - name="compengine", - fmt="%s", - sep=", ", + name=b"compengine", + fmt=b"%s", + sep=b", ", ), ) fm.write( - "compenginesavail", - _("checking available compression engines " "(%s)\n"), + b"compenginesavail", + _(b"checking available compression engines " b"(%s)\n"), fm.formatlist( sorted(e.name() for e in compengines if e.available()), - name="compengine", - fmt="%s", - sep=", ", + name=b"compengine", + fmt=b"%s", + sep=b", ", ), ) wirecompengines = compression.compengines.supportedwireengines( compression.SERVERROLE ) fm.write( - "compenginesserver", - _("checking available compression engines " "for wire protocol (%s)\n"), + b"compenginesserver", + _( + b"checking available compression engines " + b"for wire protocol (%s)\n" + ), fm.formatlist( [e.name() for e in wirecompengines if e.wireprotosupport()], - name="compengine", - fmt="%s", - sep=", ", + name=b"compengine", + fmt=b"%s", + sep=b", ", ), ) - re2 = "missing" + re2 = b"missing" if util._re2: - re2 = "available" - fm.plain(_('checking "re2" regexp engine (%s)\n') % re2) + re2 = b"available" + fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2) fm.data(re2=bool(util._re2)) # templates p = templater.templatepaths() - fm.write("templatedirs", "checking templates (%s)...\n", " ".join(p)) - fm.condwrite(not p, "", _(" no template directories found\n")) + fm.write(b"templatedirs", b"checking templates (%s)...\n", b" ".join(p)) + fm.condwrite(not p, b"", _(b" no template directories found\n")) if p: - m = templater.templatepath("map-cmdline.default") + m = templater.templatepath(b"map-cmdline.default") if m: # template found, check if it is working err = None @@ -1579,51 +1611,51 @@ except Exception as inst: err = stringutil.forcebytestr(inst) p = None - fm.condwrite(err, "defaulttemplateerror", " %s\n", err) + fm.condwrite(err, b"defaulttemplateerror", b" %s\n", err) else: p = None fm.condwrite( - p, "defaulttemplate", _("checking default template (%s)\n"), m + p, b"defaulttemplate", _(b"checking default template (%s)\n"), m ) fm.condwrite( not m, - "defaulttemplatenotfound", - _(" template '%s' not found\n"), - "default", + b"defaulttemplatenotfound", + _(b" template '%s' not found\n"), + b"default", ) if not p: problems += 1 fm.condwrite( - not p, "", _(" (templates seem to have been installed incorrectly)\n") + not p, b"", _(b" (templates seem to have been installed incorrectly)\n") ) # editor editor = ui.geteditor() editor = util.expandpath(editor) editorbin = procutil.shellsplit(editor)[0] - fm.write("editor", _("checking commit editor... (%s)\n"), editorbin) + fm.write(b"editor", _(b"checking commit editor... (%s)\n"), editorbin) cmdpath = procutil.findexe(editorbin) fm.condwrite( - not cmdpath and editor == "vi", - "vinotfound", + not cmdpath and editor == b"vi", + b"vinotfound", _( - " No commit editor set and can't find %s in PATH\n" - " (specify a commit editor in your configuration" - " file)\n" + b" No commit editor set and can't find %s in PATH\n" + b" (specify a commit editor in your configuration" + b" file)\n" ), - not cmdpath and editor == "vi" and editorbin, + not cmdpath and editor == b"vi" and editorbin, ) fm.condwrite( - not cmdpath and editor != "vi", - "editornotfound", + not cmdpath and editor != b"vi", + b"editornotfound", _( - " Can't find editor '%s' in PATH\n" - " (specify a commit editor in your configuration" - " file)\n" + b" Can't find editor '%s' in PATH\n" + b" (specify a commit editor in your configuration" + b" file)\n" ), not cmdpath and editorbin, ) - if not cmdpath and editor != "vi": + if not cmdpath and editor != b"vi": problems += 1 # check username @@ -1635,13 +1667,15 @@ err = stringutil.forcebytestr(e) problems += 1 - fm.condwrite(username, "username", _("checking username (%s)\n"), username) + fm.condwrite( + username, b"username", _(b"checking username (%s)\n"), username + ) fm.condwrite( err, - "usernameerror", + b"usernameerror", _( - "checking username...\n %s\n" - " (specify a username in your configuration file)\n" + b"checking username...\n %s\n" + b" (specify a username in your configuration file)\n" ), err, ) @@ -1651,13 +1685,13 @@ if handler is not None: problems += handler(ui, fm) - fm.condwrite(not problems, "", _("no problems detected\n")) + fm.condwrite(not problems, b"", _(b"no problems detected\n")) if not problems: fm.data(problems=problems) fm.condwrite( problems, - "problems", - _("%d problems detected," " please check your install!\n"), + b"problems", + _(b"%d problems detected," b" please check your install!\n"), problems, ) fm.end() @@ -1665,7 +1699,7 @@ return problems -@command("debugknown", [], _("REPO ID..."), norepo=True) +@command(b"debugknown", [], _(b"REPO ID..."), norepo=True) def debugknown(ui, repopath, *ids, **opts): """test whether node ids are known to a repo @@ -1674,32 +1708,37 @@ """ opts = pycompat.byteskwargs(opts) repo = hg.peer(ui, opts, repopath) - if not repo.capable("known"): - raise error.Abort("known() not supported by target repository") + if not repo.capable(b"known"): + raise error.Abort(b"known() not supported by target repository") flags = repo.known([bin(s) for s in ids]) - ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags]))) - - -@command("debuglabelcomplete", [], _("LABEL...")) + ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags]))) + + +@command(b"debuglabelcomplete", [], _(b"LABEL...")) def debuglabelcomplete(ui, repo, *args): """backwards compatibility with old bash completion scripts (DEPRECATED)""" debugnamecomplete(ui, repo, *args) @command( - "debuglocks", + b"debuglocks", [ - ("L", "force-lock", None, _("free the store lock (DANGEROUS)")), + (b"L", b"force-lock", None, _(b"free the store lock (DANGEROUS)")), ( - "W", - "force-wlock", + b"W", + b"force-wlock", None, - _("free the working state lock (DANGEROUS)"), + _(b"free the working state lock (DANGEROUS)"), ), - ("s", "set-lock", None, _("set the store lock until stopped")), - ("S", "set-wlock", None, _("set the working state lock until stopped")), + (b"s", b"set-lock", None, _(b"set the store lock until stopped")), + ( + b"S", + b"set-wlock", + None, + _(b"set the working state lock until stopped"), + ), ], - _("[OPTION]..."), + _(b"[OPTION]..."), ) def debuglocks(ui, repo, **opts): """show or modify state of locks @@ -1727,9 +1766,9 @@ """ if opts.get(r"force_lock"): - repo.svfs.unlink("lock") + repo.svfs.unlink(b"lock") if opts.get(r"force_wlock"): - repo.vfs.unlink("wlock") + repo.vfs.unlink(b"wlock") if opts.get(r"force_lock") or opts.get(r"force_wlock"): return 0 @@ -1739,14 +1778,14 @@ try: locks.append(repo.wlock(False)) except error.LockHeld: - raise error.Abort(_("wlock is already held")) + raise error.Abort(_(b"wlock is already held")) if opts.get(r"set_lock"): try: locks.append(repo.lock(False)) except error.LockHeld: - raise error.Abort(_("lock is already held")) + raise error.Abort(_(b"lock is already held")) if len(locks): - ui.promptchoice(_("ready to release the lock (y)? $$ &Yes")) + ui.promptchoice(_(b"ready to release the lock (y)? $$ &Yes")) return 0 finally: release(*locks) @@ -1769,44 +1808,44 @@ age = now - st[stat.ST_MTIME] user = util.username(st.st_uid) locker = vfs.readlock(name) - if ":" in locker: - host, pid = locker.split(":") + if b":" in locker: + host, pid = locker.split(b":") if host == socket.gethostname(): - locker = "user %s, process %s" % (user or b"None", pid) + locker = b"user %s, process %s" % (user or b"None", pid) else: - locker = "user %s, process %s, host %s" % ( + locker = b"user %s, process %s, host %s" % ( user or b"None", pid, host, ) - ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age)) + ui.write(b"%-6s %s (%ds)\n" % (name + b":", locker, age)) return 1 except OSError as e: if e.errno != errno.ENOENT: raise - ui.write("%-6s free\n" % (name + ":")) + ui.write(b"%-6s free\n" % (name + b":")) return 0 - held += report(repo.svfs, "lock", repo.lock) - held += report(repo.vfs, "wlock", repo.wlock) + held += report(repo.svfs, b"lock", repo.lock) + held += report(repo.vfs, b"wlock", repo.wlock) return held @command( - "debugmanifestfulltextcache", + b"debugmanifestfulltextcache", [ - ("", "clear", False, _("clear the cache")), + (b"", b"clear", False, _(b"clear the cache")), ( - "a", - "add", + b"a", + b"add", [], - _("add the given manifest nodes to the cache"), - _("NODE"), + _(b"add the given manifest nodes to the cache"), + _(b"NODE"), ), ], - "", + b"", ) def debugmanifestfulltextcache(ui, repo, add=(), **opts): """show, clear or amend the contents of the manifest fulltext cache""" @@ -1817,8 +1856,8 @@ return r._fulltextcache except AttributeError: msg = _( - "Current revlog implementation doesn't appear to have a " - "manifest fulltext cache\n" + b"Current revlog implementation doesn't appear to have a " + b"manifest fulltext cache\n" ) raise error.Abort(msg) @@ -1836,18 +1875,18 @@ try: manifest = m[store.lookup(n)] except error.LookupError as e: - raise error.Abort(e, hint="Check your manifest node id") + raise error.Abort(e, hint=b"Check your manifest node id") manifest.read() # stores revisision in cache too return cache = getcache() if not len(cache): - ui.write(_("cache empty\n")) + ui.write(_(b"cache empty\n")) else: ui.write( _( - "cache contains %d manifest entries, in order of most to " - "least recent:\n" + b"cache contains %d manifest entries, in order of most to " + b"least recent:\n" ) % (len(cache),) ) @@ -1858,16 +1897,16 @@ size = len(data) totalsize += size + 24 # 20 bytes nodeid, 4 bytes size ui.write( - _("id: %s, size %s\n") % (hex(nodeid), util.bytecount(size)) + _(b"id: %s, size %s\n") % (hex(nodeid), util.bytecount(size)) ) - ondisk = cache._opener.stat("manifestfulltextcache").st_size + ondisk = cache._opener.stat(b"manifestfulltextcache").st_size ui.write( - _("total cache data size %s, on-disk %s\n") + _(b"total cache data size %s, on-disk %s\n") % (util.bytecount(totalsize), util.bytecount(ondisk)) ) -@command("debugmergestate", [], "") +@command(b"debugmergestate", [], b"") def debugmergestate(ui, repo, *args): """print merge state @@ -1876,12 +1915,12 @@ def _hashornull(h): if h == nullhex: - return "null" + return b"null" else: return h def printrecords(version): - ui.write("* version %d records\n" % version) + ui.write(b"* version %d records\n" % version) if version == 1: records = v1records else: @@ -1889,58 +1928,59 @@ for rtype, record in records: # pretty print some record types - if rtype == "L": - ui.write("local: %s\n" % record) - elif rtype == "O": - ui.write("other: %s\n" % record) - elif rtype == "m": - driver, mdstate = record.split("\0", 1) - ui.write('merge driver: %s (state "%s")\n' % (driver, mdstate)) - elif rtype in "FDC": - r = record.split("\0") + if rtype == b"L": + ui.write(b"local: %s\n" % record) + elif rtype == b"O": + ui.write(b"other: %s\n" % record) + elif rtype == b"m": + driver, mdstate = record.split(b"\0", 1) + ui.write(b'merge driver: %s (state "%s")\n' % (driver, mdstate)) + elif rtype in b"FDC": + r = record.split(b"\0") f, state, hash, lfile, afile, anode, ofile = r[0:7] if version == 1: - onode = "not stored in v1 format" + onode = b"not stored in v1 format" flags = r[7] else: onode, flags = r[7:9] ui.write( - 'file: %s (record type "%s", state "%s", hash %s)\n' + b'file: %s (record type "%s", state "%s", hash %s)\n' % (f, rtype, state, _hashornull(hash)) ) - ui.write(' local path: %s (flags "%s")\n' % (lfile, flags)) + ui.write(b' local path: %s (flags "%s")\n' % (lfile, flags)) ui.write( - " ancestor path: %s (node %s)\n" + b" ancestor path: %s (node %s)\n" % (afile, _hashornull(anode)) ) ui.write( - " other path: %s (node %s)\n" % (ofile, _hashornull(onode)) + b" other path: %s (node %s)\n" + % (ofile, _hashornull(onode)) ) - elif rtype == "f": - filename, rawextras = record.split("\0", 1) - extras = rawextras.split("\0") + elif rtype == b"f": + filename, rawextras = record.split(b"\0", 1) + extras = rawextras.split(b"\0") i = 0 extrastrings = [] while i < len(extras): - extrastrings.append("%s = %s" % (extras[i], extras[i + 1])) + extrastrings.append(b"%s = %s" % (extras[i], extras[i + 1])) i += 2 ui.write( - "file extras: %s (%s)\n" - % (filename, ", ".join(extrastrings)) + b"file extras: %s (%s)\n" + % (filename, b", ".join(extrastrings)) ) - elif rtype == "l": - labels = record.split("\0", 2) + elif rtype == b"l": + labels = record.split(b"\0", 2) labels = [l for l in labels if len(l) > 0] - ui.write("labels:\n") - ui.write((" local: %s\n" % labels[0])) - ui.write((" other: %s\n" % labels[1])) + ui.write(b"labels:\n") + ui.write((b" local: %s\n" % labels[0])) + ui.write((b" other: %s\n" % labels[1])) if len(labels) > 2: - ui.write((" base: %s\n" % labels[2])) + ui.write((b" base: %s\n" % labels[2])) else: ui.write( - "unrecognized entry: %s\t%s\n" - % (rtype, record.replace("\0", "\t")) + b"unrecognized entry: %s\t%s\n" + % (rtype, record.replace(b"\0", b"\t")) ) # Avoid mergestate.read() since it may raise an exception for unsupported @@ -1951,7 +1991,7 @@ # sort so that reasonable information is on top v1records = ms._readrecordsv1() v2records = ms._readrecordsv2() - order = "LOml" + order = b"LOml" def key(r): idx = order.find(r[0]) @@ -1964,21 +2004,21 @@ v2records.sort(key=key) if not v1records and not v2records: - ui.write("no merge state found\n") + ui.write(b"no merge state found\n") elif not v2records: - ui.note("no version 2 merge state\n") + ui.note(b"no version 2 merge state\n") printrecords(1) elif ms._v1v2match(v1records, v2records): - ui.note("v1 and v2 states match: using v2\n") + ui.note(b"v1 and v2 states match: using v2\n") printrecords(2) else: - ui.note("v1 and v2 states mismatch: using v1\n") + ui.note(b"v1 and v2 states mismatch: using v1\n") printrecords(1) if ui.verbose: printrecords(2) -@command("debugnamecomplete", [], _("NAME...")) +@command(b"debugnamecomplete", [], _(b"NAME...")) def debugnamecomplete(ui, repo, *args): """complete "names" - tags, open branch names, bookmark names""" @@ -1986,7 +2026,7 @@ # since we previously only listed open branches, we will handle that # specially (after this for loop) for name, ns in repo.names.iteritems(): - if name != "branches": + if name != b"branches": names.update(ns.listnames(repo)) names.update( tag @@ -1995,36 +2035,36 @@ ) completions = set() if not args: - args = [""] + args = [b""] for a in args: completions.update(n for n in names if n.startswith(a)) - ui.write("\n".join(sorted(completions))) - ui.write("\n") + ui.write(b"\n".join(sorted(completions))) + ui.write(b"\n") @command( - "debugobsolete", + b"debugobsolete", [ - ("", "flags", 0, _("markers flag")), + (b"", b"flags", 0, _(b"markers flag")), ( - "", - "record-parents", + b"", + b"record-parents", False, - _("record parent information for the precursor"), + _(b"record parent information for the precursor"), ), - ("r", "rev", [], _("display markers relevant to REV")), + (b"r", b"rev", [], _(b"display markers relevant to REV")), ( - "", - "exclusive", + b"", + b"exclusive", False, - _("restrict display to markers only " "relevant to REV"), + _(b"restrict display to markers only " b"relevant to REV"), ), - ("", "index", False, _("display index of the marker")), - ("", "delete", [], _("delete markers specified by indices")), + (b"", b"index", False, _(b"display index of the marker")), + (b"", b"delete", [], _(b"delete markers specified by indices")), ] + cmdutil.commitopts2 + cmdutil.formatteropts, - _("[OBSOLETED [REPLACEMENT ...]]"), + _(b"[OBSOLETED [REPLACEMENT ...]]"), ) def debugobsolete(ui, repo, precursor=None, *successors, **opts): """create arbitrary obsolete marker @@ -2044,54 +2084,54 @@ return n except TypeError: raise error.Abort( - "changeset references must be full hexadecimal " - "node identifiers" + b"changeset references must be full hexadecimal " + b"node identifiers" ) - if opts.get("delete"): + if opts.get(b"delete"): indices = [] - for v in opts.get("delete"): + for v in opts.get(b"delete"): try: indices.append(int(v)) except ValueError: raise error.Abort( - _("invalid index value: %r") % v, - hint=_("use integers for indices"), + _(b"invalid index value: %r") % v, + hint=_(b"use integers for indices"), ) if repo.currenttransaction(): raise error.Abort( - _("cannot delete obsmarkers in the middle " "of transaction.") + _(b"cannot delete obsmarkers in the middle " b"of transaction.") ) with repo.lock(): n = repair.deleteobsmarkers(repo.obsstore, indices) - ui.write(_("deleted %i obsolescence markers\n") % n) + ui.write(_(b"deleted %i obsolescence markers\n") % n) return if precursor is not None: - if opts["rev"]: - raise error.Abort("cannot select revision when creating marker") + if opts[b"rev"]: + raise error.Abort(b"cannot select revision when creating marker") metadata = {} - metadata["user"] = encoding.fromlocal(opts["user"] or ui.username()) + metadata[b"user"] = encoding.fromlocal(opts[b"user"] or ui.username()) succs = tuple(parsenodeid(succ) for succ in successors) l = repo.lock() try: - tr = repo.transaction("debugobsolete") + tr = repo.transaction(b"debugobsolete") try: - date = opts.get("date") + date = opts.get(b"date") if date: date = dateutil.parsedate(date) else: date = None prec = parsenodeid(precursor) parents = None - if opts["record_parents"]: + if opts[b"record_parents"]: if prec not in repo.unfiltered(): raise error.Abort( - "cannot used --record-parents on " - "unknown changesets" + b"cannot used --record-parents on " + b"unknown changesets" ) parents = repo.unfiltered()[prec].parents() parents = tuple(p.node() for p in parents) @@ -2099,7 +2139,7 @@ tr, prec, succs, - opts["flags"], + opts[b"flags"], parents=parents, date=date, metadata=metadata, @@ -2108,19 +2148,19 @@ tr.close() except ValueError as exc: raise error.Abort( - _("bad obsmarker input: %s") % pycompat.bytestr(exc) + _(b"bad obsmarker input: %s") % pycompat.bytestr(exc) ) finally: tr.release() finally: l.release() else: - if opts["rev"]: - revs = scmutil.revrange(repo, opts["rev"]) + if opts[b"rev"]: + revs = scmutil.revrange(repo, opts[b"rev"]) nodes = [repo[r].node() for r in revs] markers = list( obsutil.getmarkers( - repo, nodes=nodes, exclusive=opts["exclusive"] + repo, nodes=nodes, exclusive=opts[b"exclusive"] ) ) markers.sort(key=lambda x: x._data) @@ -2129,12 +2169,12 @@ markerstoiter = markers isrelevant = lambda m: True - if opts.get("rev") and opts.get("index"): + if opts.get(b"rev") and opts.get(b"index"): markerstoiter = obsutil.getmarkers(repo) markerset = set(markers) isrelevant = lambda m: m in markerset - fm = ui.formatter("debugobsolete", opts) + fm = ui.formatter(b"debugobsolete", opts) for i, m in enumerate(markerstoiter): if not isrelevant(m): # marker can be irrelevant when we're iterating over a set @@ -2146,48 +2186,48 @@ # are relevant to --rev value continue fm.startitem() - ind = i if opts.get("index") else None + ind = i if opts.get(b"index") else None cmdutil.showmarker(fm, m, index=ind) fm.end() @command( - "debugp1copies", - [("r", "rev", "", _("revision to debug"), _("REV"))], - _("[-r REV]"), + b"debugp1copies", + [(b"r", b"rev", b"", _(b"revision to debug"), _(b"REV"))], + _(b"[-r REV]"), ) def debugp1copies(ui, repo, **opts): """dump copy information compared to p1""" opts = pycompat.byteskwargs(opts) - ctx = scmutil.revsingle(repo, opts.get("rev"), default=None) + ctx = scmutil.revsingle(repo, opts.get(b"rev"), default=None) for dst, src in ctx.p1copies().items(): - ui.write("%s -> %s\n" % (src, dst)) + ui.write(b"%s -> %s\n" % (src, dst)) @command( - "debugp2copies", - [("r", "rev", "", _("revision to debug"), _("REV"))], - _("[-r REV]"), + b"debugp2copies", + [(b"r", b"rev", b"", _(b"revision to debug"), _(b"REV"))], + _(b"[-r REV]"), ) def debugp1copies(ui, repo, **opts): """dump copy information compared to p2""" opts = pycompat.byteskwargs(opts) - ctx = scmutil.revsingle(repo, opts.get("rev"), default=None) + ctx = scmutil.revsingle(repo, opts.get(b"rev"), default=None) for dst, src in ctx.p2copies().items(): - ui.write("%s -> %s\n" % (src, dst)) + ui.write(b"%s -> %s\n" % (src, dst)) @command( - "debugpathcomplete", + b"debugpathcomplete", [ - ("f", "full", None, _("complete an entire path")), - ("n", "normal", None, _("show only normal files")), - ("a", "added", None, _("show only added files")), - ("r", "removed", None, _("show only removed files")), + (b"f", b"full", None, _(b"complete an entire path")), + (b"n", b"normal", None, _(b"show only normal files")), + (b"a", b"added", None, _(b"show only added files")), + (b"r", b"removed", None, _(b"show only removed files")), ], - _("FILESPEC..."), + _(b"FILESPEC..."), ) def debugpathcomplete(ui, repo, *specs, **opts): """complete part or all of a tracked path @@ -2205,11 +2245,11 @@ if spec != repo.root and not spec.startswith(rootdir): return [], [] if os.path.isdir(spec): - spec += "/" + spec += b"/" spec = spec[len(rootdir) :] - fixpaths = pycompat.ossep != "/" + fixpaths = pycompat.ossep != b"/" if fixpaths: - spec = spec.replace(pycompat.ossep, "/") + spec = spec.replace(pycompat.ossep, b"/") speclen = len(spec) fullpaths = opts[r"full"] files, dirs = set(), set() @@ -2217,7 +2257,7 @@ for f, st in dirstate.iteritems(): if f.startswith(spec) and st[0] in acceptable: if fixpaths: - f = f.replace("/", pycompat.ossep) + f = f.replace(b"/", pycompat.ossep) if fullpaths: addfile(f) continue @@ -2228,31 +2268,31 @@ addfile(f) return files, dirs - acceptable = "" + acceptable = b"" if opts[r"normal"]: - acceptable += "nm" + acceptable += b"nm" if opts[r"added"]: - acceptable += "a" + acceptable += b"a" if opts[r"removed"]: - acceptable += "r" + acceptable += b"r" cwd = repo.getcwd() if not specs: - specs = ["."] + specs = [b"."] files, dirs = set(), set() for spec in specs: - f, d = complete(spec, acceptable or "nmar") + f, d = complete(spec, acceptable or b"nmar") files.update(f) dirs.update(d) files.update(dirs) - ui.write("\n".join(repo.pathto(p, cwd) for p in sorted(files))) - ui.write("\n") + ui.write(b"\n".join(repo.pathto(p, cwd) for p in sorted(files))) + ui.write(b"\n") @command( - "debugpathcopies", + b"debugpathcopies", cmdutil.walkopts, - "hg debugpathcopies REV1 REV2 [FILE]", + b"hg debugpathcopies REV1 REV2 [FILE]", inferrepo=True, ) def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts): @@ -2261,16 +2301,16 @@ ctx2 = scmutil.revsingle(repo, rev2) m = scmutil.match(ctx1, pats, opts) for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()): - ui.write("%s -> %s\n" % (src, dst)) - - -@command("debugpeer", [], _("PATH"), norepo=True) + ui.write(b"%s -> %s\n" % (src, dst)) + + +@command(b"debugpeer", [], _(b"PATH"), norepo=True) def debugpeer(ui, path): """establish a connection to a peer repository""" # Always enable peer request logging. Requires --debug to display # though. overrides = { - ("devel", "debug.peer-request"): True, + (b"devel", b"debug.peer-request"): True, } with ui.configoverride(overrides): @@ -2279,20 +2319,20 @@ local = peer.local() is not None canpush = peer.canpush() - ui.write(_("url: %s\n") % peer.url()) - ui.write(_("local: %s\n") % (_("yes") if local else _("no"))) - ui.write(_("pushable: %s\n") % (_("yes") if canpush else _("no"))) + ui.write(_(b"url: %s\n") % peer.url()) + ui.write(_(b"local: %s\n") % (_(b"yes") if local else _(b"no"))) + ui.write(_(b"pushable: %s\n") % (_(b"yes") if canpush else _(b"no"))) @command( - "debugpickmergetool", + b"debugpickmergetool", [ - ("r", "rev", "", _("check for files in this revision"), _("REV")), - ("", "changedelete", None, _("emulate merging change and delete")), + (b"r", b"rev", b"", _(b"check for files in this revision"), _(b"REV")), + (b"", b"changedelete", None, _(b"emulate merging change and delete")), ] + cmdutil.walkopts + cmdutil.mergetoolopts, - _("[PATTERN]..."), + _(b"[PATTERN]..."), inferrepo=True, ) def debugpickmergetool(ui, repo, *pats, **opts): @@ -2339,21 +2379,21 @@ """ opts = pycompat.byteskwargs(opts) overrides = {} - if opts["tool"]: - overrides[("ui", "forcemerge")] = opts["tool"] - ui.note("with --tool %r\n" % (pycompat.bytestr(opts["tool"]))) - - with ui.configoverride(overrides, "debugmergepatterns"): - hgmerge = encoding.environ.get("HGMERGE") + if opts[b"tool"]: + overrides[(b"ui", b"forcemerge")] = opts[b"tool"] + ui.note(b"with --tool %r\n" % (pycompat.bytestr(opts[b"tool"]))) + + with ui.configoverride(overrides, b"debugmergepatterns"): + hgmerge = encoding.environ.get(b"HGMERGE") if hgmerge is not None: - ui.note("with HGMERGE=%r\n" % (pycompat.bytestr(hgmerge))) - uimerge = ui.config("ui", "merge") + ui.note(b"with HGMERGE=%r\n" % (pycompat.bytestr(hgmerge))) + uimerge = ui.config(b"ui", b"merge") if uimerge: - ui.note("with ui.merge=%r\n" % (pycompat.bytestr(uimerge))) - - ctx = scmutil.revsingle(repo, opts.get("rev")) + ui.note(b"with ui.merge=%r\n" % (pycompat.bytestr(uimerge))) + + ctx = scmutil.revsingle(repo, opts.get(b"rev")) m = scmutil.match(ctx, pats, opts) - changedelete = opts["changedelete"] + changedelete = opts[b"changedelete"] for path in ctx.walk(m): fctx = ctx[path] try: @@ -2364,16 +2404,16 @@ ui, path, fctx.isbinary(), - "l" in fctx.flags(), + b"l" in fctx.flags(), changedelete, ) finally: if not ui.debugflag: ui.popbuffer() - ui.write("%s = %s\n" % (path, tool)) - - -@command("debugpushkey", [], _("REPO NAMESPACE [KEY OLD NEW]"), norepo=True) + ui.write(b"%s = %s\n" % (path, tool)) + + +@command(b"debugpushkey", [], _(b"REPO NAMESPACE [KEY OLD NEW]"), norepo=True) def debugpushkey(ui, repopath, namespace, *keyinfo, **opts): """access the pushkey key/value protocol @@ -2388,38 +2428,43 @@ key, old, new = keyinfo with target.commandexecutor() as e: r = e.callcommand( - "pushkey", - {"namespace": namespace, "key": key, "old": old, "new": new,}, + b"pushkey", + { + b"namespace": namespace, + b"key": key, + b"old": old, + b"new": new, + }, ).result() - ui.status(pycompat.bytestr(r) + "\n") + ui.status(pycompat.bytestr(r) + b"\n") return not r else: for k, v in sorted(target.listkeys(namespace).iteritems()): ui.write( - "%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v)) + b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v)) ) -@command("debugpvec", [], _("A B")) +@command(b"debugpvec", [], _(b"A B")) def debugpvec(ui, repo, a, b=None): ca = scmutil.revsingle(repo, a) cb = scmutil.revsingle(repo, b) pa = pvec.ctxpvec(ca) pb = pvec.ctxpvec(cb) if pa == pb: - rel = "=" + rel = b"=" elif pa > pb: - rel = ">" + rel = b">" elif pa < pb: - rel = "<" + rel = b"<" elif pa | pb: - rel = "|" - ui.write(_("a: %s\n") % pa) - ui.write(_("b: %s\n") % pb) - ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth)) + rel = b"|" + ui.write(_(b"a: %s\n") % pa) + ui.write(_(b"b: %s\n") % pb) + ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth)) ui.write( - _("delta: %d hdist: %d distance: %d relation: %s\n") + _(b"delta: %d hdist: %d distance: %d relation: %s\n") % ( abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec), @@ -2430,20 +2475,20 @@ @command( - "debugrebuilddirstate|debugrebuildstate", + b"debugrebuilddirstate|debugrebuildstate", [ - ("r", "rev", "", _("revision to rebuild to"), _("REV")), + (b"r", b"rev", b"", _(b"revision to rebuild to"), _(b"REV")), ( - "", - "minimal", + b"", + b"minimal", None, _( - "only rebuild files that are inconsistent with " - "the working copy parent" + b"only rebuild files that are inconsistent with " + b"the working copy parent" ), ), ], - _("[-r REV]"), + _(b"[-r REV]"), ) def debugrebuilddirstate(ui, repo, rev, **opts): """rebuild the dirstate as it would look like for the given revision @@ -2472,56 +2517,56 @@ dirstatefiles = set(dirstate) manifestonly = manifestfiles - dirstatefiles dsonly = dirstatefiles - manifestfiles - dsnotadded = set(f for f in dsonly if dirstate[f] != "a") + dsnotadded = set(f for f in dsonly if dirstate[f] != b"a") changedfiles = manifestonly | dsnotadded dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles) -@command("debugrebuildfncache", [], "") +@command(b"debugrebuildfncache", [], b"") def debugrebuildfncache(ui, repo): """rebuild the fncache file""" repair.rebuildfncache(ui, repo) @command( - "debugrename", - [("r", "rev", "", _("revision to debug"), _("REV"))], - _("[-r REV] [FILE]..."), + b"debugrename", + [(b"r", b"rev", b"", _(b"revision to debug"), _(b"REV"))], + _(b"[-r REV] [FILE]..."), ) def debugrename(ui, repo, *pats, **opts): """dump rename information""" opts = pycompat.byteskwargs(opts) - ctx = scmutil.revsingle(repo, opts.get("rev")) + ctx = scmutil.revsingle(repo, opts.get(b"rev")) m = scmutil.match(ctx, pats, opts) for abs in ctx.walk(m): fctx = ctx[abs] o = fctx.filelog().renamed(fctx.filenode()) rel = repo.pathto(abs) if o: - ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1]))) + ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1]))) else: - ui.write(_("%s not renamed\n") % rel) + ui.write(_(b"%s not renamed\n") % rel) @command( - "debugrevlog", - cmdutil.debugrevlogopts + [("d", "dump", False, _("dump index data"))], - _("-c|-m|FILE"), + b"debugrevlog", + cmdutil.debugrevlogopts + [(b"d", b"dump", False, _(b"dump index data"))], + _(b"-c|-m|FILE"), optionalrepo=True, ) def debugrevlog(ui, repo, file_=None, **opts): """show data and statistics about a revlog""" opts = pycompat.byteskwargs(opts) - r = cmdutil.openrevlog(repo, "debugrevlog", file_, opts) - - if opts.get("dump"): + r = cmdutil.openrevlog(repo, b"debugrevlog", file_, opts) + + if opts.get(b"dump"): numrevs = len(r) ui.write( ( - "# rev p1rev p2rev start end deltastart base p1 p2" - " rawsize totalsize compression heads chainlen\n" + b"# rev p1rev p2rev start end deltastart base p1 p2" + b" rawsize totalsize compression heads chainlen\n" ) ) ts = 0 @@ -2543,8 +2588,8 @@ except ZeroDivisionError: compression = 0 ui.write( - "%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d " - "%11d %5d %8d\n" + b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d " + b"%11d %5d %8d\n" % ( rev, p1, @@ -2569,12 +2614,12 @@ flags = [] gdelta = False if v & revlog.FLAG_INLINE_DATA: - flags.append("inline") + flags.append(b"inline") if v & revlog.FLAG_GENERALDELTA: gdelta = True - flags.append("generaldelta") + flags.append(b"generaldelta") if not flags: - flags = ["(none)"] + flags = [b"(none)"] ### tracks merge vs single parent nummerges = 0 @@ -2676,14 +2721,14 @@ numother += 1 # Obtain data on the raw chunks in the revlog. - if util.safehasattr(r, "_getsegmentforrevs"): + if util.safehasattr(r, b"_getsegmentforrevs"): segment = r._getsegmentforrevs(rev, rev)[1] else: segment = r._revlog._getsegmentforrevs(rev, rev)[1] if segment: chunktype = bytes(segment[0:1]) else: - chunktype = "empty" + chunktype = b"empty" if chunktype not in chunktypecounts: chunktypecounts[chunktype] = 0 @@ -2725,14 +2770,14 @@ if totalsize: compratio = totalrawsize / totalsize - basedfmtstr = "%%%dd\n" - basepcfmtstr = "%%%dd %s(%%5.2f%%%%)\n" + basedfmtstr = b"%%%dd\n" + basepcfmtstr = b"%%%dd %s(%%5.2f%%%%)\n" def dfmtstr(max): return basedfmtstr % len(str(max)) def pcfmtstr(max, padding=0): - return basepcfmtstr % (len(str(max)), " " * padding) + return basepcfmtstr % (len(str(max)), b" " * padding) def pcfmt(value, total): if total: @@ -2740,129 +2785,131 @@ else: return value, 100.0 - ui.write("format : %d\n" % format) - ui.write("flags : %s\n" % ", ".join(flags)) - - ui.write("\n") + ui.write(b"format : %d\n" % format) + ui.write(b"flags : %s\n" % b", ".join(flags)) + + ui.write(b"\n") fmt = pcfmtstr(totalsize) fmt2 = dfmtstr(totalsize) - ui.write("revisions : " + fmt2 % numrevs) - ui.write(" merges : " + fmt % pcfmt(nummerges, numrevs)) - ui.write(" normal : " + fmt % pcfmt(numrevs - nummerges, numrevs)) - ui.write("revisions : " + fmt2 % numrevs) - ui.write(" empty : " + fmt % pcfmt(numempty, numrevs)) + ui.write(b"revisions : " + fmt2 % numrevs) + ui.write(b" merges : " + fmt % pcfmt(nummerges, numrevs)) + ui.write(b" normal : " + fmt % pcfmt(numrevs - nummerges, numrevs)) + ui.write(b"revisions : " + fmt2 % numrevs) + ui.write(b" empty : " + fmt % pcfmt(numempty, numrevs)) ui.write( - " text : " + b" text : " + fmt % pcfmt(numemptytext, numemptytext + numemptydelta) ) ui.write( - " delta : " + b" delta : " + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta) ) - ui.write(" snapshot : " + fmt % pcfmt(numfull + numsemi, numrevs)) + ui.write(b" snapshot : " + fmt % pcfmt(numfull + numsemi, numrevs)) for depth in sorted(numsnapdepth): ui.write( - (" lvl-%-3d : " % depth) + (b" lvl-%-3d : " % depth) + fmt % pcfmt(numsnapdepth[depth], numrevs) ) - ui.write(" deltas : " + fmt % pcfmt(numdeltas, numrevs)) - ui.write("revision size : " + fmt2 % totalsize) - ui.write(" snapshot : " + fmt % pcfmt(fulltotal + semitotal, totalsize)) + ui.write(b" deltas : " + fmt % pcfmt(numdeltas, numrevs)) + ui.write(b"revision size : " + fmt2 % totalsize) + ui.write( + b" snapshot : " + fmt % pcfmt(fulltotal + semitotal, totalsize) + ) for depth in sorted(numsnapdepth): ui.write( - (" lvl-%-3d : " % depth) + (b" lvl-%-3d : " % depth) + fmt % pcfmt(snaptotal[depth], totalsize) ) - ui.write(" deltas : " + fmt % pcfmt(deltatotal, totalsize)) + ui.write(b" deltas : " + fmt % pcfmt(deltatotal, totalsize)) def fmtchunktype(chunktype): - if chunktype == "empty": - return " %s : " % chunktype + if chunktype == b"empty": + return b" %s : " % chunktype elif chunktype in pycompat.bytestr(string.ascii_letters): - return " 0x%s (%s) : " % (hex(chunktype), chunktype) + return b" 0x%s (%s) : " % (hex(chunktype), chunktype) else: - return " 0x%s : " % hex(chunktype) - - ui.write("\n") - ui.write("chunks : " + fmt2 % numrevs) + return b" 0x%s : " % hex(chunktype) + + ui.write(b"\n") + ui.write(b"chunks : " + fmt2 % numrevs) for chunktype in sorted(chunktypecounts): ui.write(fmtchunktype(chunktype)) ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs)) - ui.write("chunks size : " + fmt2 % totalsize) + ui.write(b"chunks size : " + fmt2 % totalsize) for chunktype in sorted(chunktypecounts): ui.write(fmtchunktype(chunktype)) ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize)) - ui.write("\n") + ui.write(b"\n") fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio)) - ui.write("avg chain length : " + fmt % avgchainlen) - ui.write("max chain length : " + fmt % maxchainlen) - ui.write("max chain reach : " + fmt % maxchainspan) - ui.write("compression ratio : " + fmt % compratio) + ui.write(b"avg chain length : " + fmt % avgchainlen) + ui.write(b"max chain length : " + fmt % maxchainlen) + ui.write(b"max chain reach : " + fmt % maxchainspan) + ui.write(b"compression ratio : " + fmt % compratio) if format > 0: - ui.write("\n") + ui.write(b"\n") ui.write( - "uncompressed data size (min/max/avg) : %d / %d / %d\n" + b"uncompressed data size (min/max/avg) : %d / %d / %d\n" % tuple(datasize) ) ui.write( - "full revision size (min/max/avg) : %d / %d / %d\n" + b"full revision size (min/max/avg) : %d / %d / %d\n" % tuple(fullsize) ) ui.write( - "inter-snapshot size (min/max/avg) : %d / %d / %d\n" + b"inter-snapshot size (min/max/avg) : %d / %d / %d\n" % tuple(semisize) ) for depth in sorted(snapsizedepth): if depth == 0: continue ui.write( - " level-%-3d (min/max/avg) : %d / %d / %d\n" + b" level-%-3d (min/max/avg) : %d / %d / %d\n" % ((depth,) + tuple(snapsizedepth[depth])) ) ui.write( - "delta size (min/max/avg) : %d / %d / %d\n" + b"delta size (min/max/avg) : %d / %d / %d\n" % tuple(deltasize) ) if numdeltas > 0: - ui.write("\n") + ui.write(b"\n") fmt = pcfmtstr(numdeltas) fmt2 = pcfmtstr(numdeltas, 4) - ui.write("deltas against prev : " + fmt % pcfmt(numprev, numdeltas)) + ui.write(b"deltas against prev : " + fmt % pcfmt(numprev, numdeltas)) if numprev > 0: ui.write( - " where prev = p1 : " + fmt2 % pcfmt(nump1prev, numprev) + b" where prev = p1 : " + fmt2 % pcfmt(nump1prev, numprev) ) ui.write( - " where prev = p2 : " + fmt2 % pcfmt(nump2prev, numprev) + b" where prev = p2 : " + fmt2 % pcfmt(nump2prev, numprev) ) ui.write( - " other : " + fmt2 % pcfmt(numoprev, numprev) + b" other : " + fmt2 % pcfmt(numoprev, numprev) ) if gdelta: - ui.write("deltas against p1 : " + fmt % pcfmt(nump1, numdeltas)) - ui.write("deltas against p2 : " + fmt % pcfmt(nump2, numdeltas)) + ui.write(b"deltas against p1 : " + fmt % pcfmt(nump1, numdeltas)) + ui.write(b"deltas against p2 : " + fmt % pcfmt(nump2, numdeltas)) ui.write( - "deltas against other : " + fmt % pcfmt(numother, numdeltas) + b"deltas against other : " + fmt % pcfmt(numother, numdeltas) ) @command( - "debugrevlogindex", + b"debugrevlogindex", cmdutil.debugrevlogopts - + [("f", "format", 0, _("revlog format"), _("FORMAT"))], - _("[-f FORMAT] -c|-m|FILE"), + + [(b"f", b"format", 0, _(b"revlog format"), _(b"FORMAT"))], + _(b"[-f FORMAT] -c|-m|FILE"), optionalrepo=True, ) def debugrevlogindex(ui, repo, file_=None, **opts): """dump the contents of a revlog index""" opts = pycompat.byteskwargs(opts) - r = cmdutil.openrevlog(repo, "debugrevlogindex", file_, opts) - format = opts.get("format", 0) + r = cmdutil.openrevlog(repo, b"debugrevlogindex", file_, opts) + format = opts.get(b"format", 0) if format not in (0, 1): - raise error.Abort(_("unknown format %d") % format) + raise error.Abort(_(b"unknown format %d") % format) if ui.debugflag: shortfn = hex @@ -2878,27 +2925,27 @@ if format == 0: if ui.verbose: ui.write( - (" rev offset length linkrev" " %s %s p2\n") - % ("nodeid".ljust(idlen), "p1".ljust(idlen)) + (b" rev offset length linkrev" b" %s %s p2\n") + % (b"nodeid".ljust(idlen), b"p1".ljust(idlen)) ) else: ui.write( - " rev linkrev %s %s p2\n" - % ("nodeid".ljust(idlen), "p1".ljust(idlen)) + b" rev linkrev %s %s p2\n" + % (b"nodeid".ljust(idlen), b"p1".ljust(idlen)) ) elif format == 1: if ui.verbose: ui.write( ( - " rev flag offset length size link p1" - " p2 %s\n" + b" rev flag offset length size link p1" + b" p2 %s\n" ) - % "nodeid".rjust(idlen) + % b"nodeid".rjust(idlen) ) else: ui.write( - " rev flag size link p1 p2 %s\n" - % "nodeid".rjust(idlen) + b" rev flag size link p1 p2 %s\n" + % b"nodeid".rjust(idlen) ) for i in r: @@ -2910,7 +2957,7 @@ pp = [nullid, nullid] if ui.verbose: ui.write( - "% 6d % 9d % 7d % 7d %s %s %s\n" + b"% 6d % 9d % 7d % 7d %s %s %s\n" % ( i, r.start(i), @@ -2923,7 +2970,7 @@ ) else: ui.write( - "% 6d % 7d %s %s %s\n" + b"% 6d % 7d %s %s %s\n" % ( i, r.linkrev(i), @@ -2936,7 +2983,7 @@ pr = r.parentrevs(i) if ui.verbose: ui.write( - "% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" + b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % ( i, r.flags(i), @@ -2951,7 +2998,7 @@ ) else: ui.write( - "% 6d %04x % 8d % 6d % 6d % 6d %s\n" + b"% 6d %04x % 8d % 6d % 6d % 6d %s\n" % ( i, r.flags(i), @@ -2965,32 +3012,37 @@ @command( - "debugrevspec", + b"debugrevspec", [ ( - "", - "optimize", + b"", + b"optimize", None, - _("print parsed tree after optimizing (DEPRECATED)"), + _(b"print parsed tree after optimizing (DEPRECATED)"), ), - ("", "show-revs", True, _("print list of result revisions (default)")), ( - "s", - "show-set", - None, - _("print internal representation of result set"), + b"", + b"show-revs", + True, + _(b"print list of result revisions (default)"), ), ( - "p", - "show-stage", + b"s", + b"show-set", + None, + _(b"print internal representation of result set"), + ), + ( + b"p", + b"show-stage", [], - _("print parsed tree at the given stage"), - _("NAME"), + _(b"print parsed tree at the given stage"), + _(b"NAME"), ), - ("", "no-optimized", False, _("evaluate tree without optimization")), - ("", "verify-optimized", False, _("verify optimized result")), + (b"", b"no-optimized", False, _(b"evaluate tree without optimization")), + (b"", b"verify-optimized", False, _(b"verify optimized result")), ], - "REVSPEC", + b"REVSPEC", ) def debugrevspec(ui, repo, expr, **opts): """parse and apply a revision specification @@ -3005,42 +3057,42 @@ one. Returns 1 if the optimized result differs. """ opts = pycompat.byteskwargs(opts) - aliases = ui.configitems("revsetalias") + aliases = ui.configitems(b"revsetalias") stages = [ - ("parsed", lambda tree: tree), + (b"parsed", lambda tree: tree), ( - "expanded", + b"expanded", lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn), ), - ("concatenated", revsetlang.foldconcat), - ("analyzed", revsetlang.analyze), - ("optimized", revsetlang.optimize), + (b"concatenated", revsetlang.foldconcat), + (b"analyzed", revsetlang.analyze), + (b"optimized", revsetlang.optimize), ] - if opts["no_optimized"]: + if opts[b"no_optimized"]: stages = stages[:-1] - if opts["verify_optimized"] and opts["no_optimized"]: + if opts[b"verify_optimized"] and opts[b"no_optimized"]: raise error.Abort( - _("cannot use --verify-optimized with " "--no-optimized") + _(b"cannot use --verify-optimized with " b"--no-optimized") ) stagenames = set(n for n, f in stages) showalways = set() showchanged = set() - if ui.verbose and not opts["show_stage"]: + if ui.verbose and not opts[b"show_stage"]: # show parsed tree by --verbose (deprecated) - showalways.add("parsed") - showchanged.update(["expanded", "concatenated"]) - if opts["optimize"]: - showalways.add("optimized") - if opts["show_stage"] and opts["optimize"]: - raise error.Abort(_("cannot use --optimize with --show-stage")) - if opts["show_stage"] == ["all"]: + showalways.add(b"parsed") + showchanged.update([b"expanded", b"concatenated"]) + if opts[b"optimize"]: + showalways.add(b"optimized") + if opts[b"show_stage"] and opts[b"optimize"]: + raise error.Abort(_(b"cannot use --optimize with --show-stage")) + if opts[b"show_stage"] == [b"all"]: showalways.update(stagenames) else: - for n in opts["show_stage"]: + for n in opts[b"show_stage"]: if n not in stagenames: - raise error.Abort(_("invalid stage name: %s") % n) - showalways.update(opts["show_stage"]) + raise error.Abort(_(b"invalid stage name: %s") % n) + showalways.update(opts[b"show_stage"]) treebystage = {} printedtree = None @@ -3048,59 +3100,59 @@ for n, f in stages: treebystage[n] = tree = f(tree) if n in showalways or (n in showchanged and tree != printedtree): - if opts["show_stage"] or n != "parsed": - ui.write("* %s:\n" % n) - ui.write(revsetlang.prettyformat(tree), "\n") + if opts[b"show_stage"] or n != b"parsed": + ui.write(b"* %s:\n" % n) + ui.write(revsetlang.prettyformat(tree), b"\n") printedtree = tree - if opts["verify_optimized"]: - arevs = revset.makematcher(treebystage["analyzed"])(repo) - brevs = revset.makematcher(treebystage["optimized"])(repo) - if opts["show_set"] or (opts["show_set"] is None and ui.verbose): - ui.write("* analyzed set:\n", stringutil.prettyrepr(arevs), "\n") - ui.write("* optimized set:\n", stringutil.prettyrepr(brevs), "\n") + if opts[b"verify_optimized"]: + arevs = revset.makematcher(treebystage[b"analyzed"])(repo) + brevs = revset.makematcher(treebystage[b"optimized"])(repo) + if opts[b"show_set"] or (opts[b"show_set"] is None and ui.verbose): + ui.write(b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n") + ui.write(b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n") arevs = list(arevs) brevs = list(brevs) if arevs == brevs: return 0 - ui.write("--- analyzed\n", label="diff.file_a") - ui.write("+++ optimized\n", label="diff.file_b") + ui.write(b"--- analyzed\n", label=b"diff.file_a") + ui.write(b"+++ optimized\n", label=b"diff.file_b") sm = difflib.SequenceMatcher(None, arevs, brevs) for tag, alo, ahi, blo, bhi in sm.get_opcodes(): if tag in (r"delete", r"replace"): for c in arevs[alo:ahi]: - ui.write("-%d\n" % c, label="diff.deleted") + ui.write(b"-%d\n" % c, label=b"diff.deleted") if tag in (r"insert", r"replace"): for c in brevs[blo:bhi]: - ui.write("+%d\n" % c, label="diff.inserted") + ui.write(b"+%d\n" % c, label=b"diff.inserted") if tag == r"equal": for c in arevs[alo:ahi]: - ui.write(" %d\n" % c) + ui.write(b" %d\n" % c) return 1 func = revset.makematcher(tree) revs = func(repo) - if opts["show_set"] or (opts["show_set"] is None and ui.verbose): - ui.write("* set:\n", stringutil.prettyrepr(revs), "\n") - if not opts["show_revs"]: + if opts[b"show_set"] or (opts[b"show_set"] is None and ui.verbose): + ui.write(b"* set:\n", stringutil.prettyrepr(revs), b"\n") + if not opts[b"show_revs"]: return for c in revs: - ui.write("%d\n" % c) + ui.write(b"%d\n" % c) @command( - "debugserve", + b"debugserve", [ ( - "", - "sshstdio", + b"", + b"sshstdio", False, - _("run an SSH server bound to process handles"), + _(b"run an SSH server bound to process handles"), ), - ("", "logiofd", "", _("file descriptor to log server I/O to")), - ("", "logiofile", "", _("file to log server I/O to")), + (b"", b"logiofd", b"", _(b"file descriptor to log server I/O to")), + (b"", b"logiofile", b"", _(b"file to log server I/O to")), ], - "", + b"", ) def debugserve(ui, repo, **opts): """run a server with advanced settings @@ -3111,31 +3163,31 @@ """ opts = pycompat.byteskwargs(opts) - if not opts["sshstdio"]: - raise error.Abort(_("only --sshstdio is currently supported")) + if not opts[b"sshstdio"]: + raise error.Abort(_(b"only --sshstdio is currently supported")) logfh = None - if opts["logiofd"] and opts["logiofile"]: - raise error.Abort(_("cannot use both --logiofd and --logiofile")) - - if opts["logiofd"]: + if opts[b"logiofd"] and opts[b"logiofile"]: + raise error.Abort(_(b"cannot use both --logiofd and --logiofile")) + + if opts[b"logiofd"]: # Line buffered because output is line based. try: - logfh = os.fdopen(int(opts["logiofd"]), r"ab", 1) + logfh = os.fdopen(int(opts[b"logiofd"]), r"ab", 1) except OSError as e: if e.errno != errno.ESPIPE: raise # can't seek a pipe, so `ab` mode fails on py3 - logfh = os.fdopen(int(opts["logiofd"]), r"wb", 1) - elif opts["logiofile"]: - logfh = open(opts["logiofile"], "ab", 1) + logfh = os.fdopen(int(opts[b"logiofd"]), r"wb", 1) + elif opts[b"logiofile"]: + logfh = open(opts[b"logiofile"], b"ab", 1) s = wireprotoserver.sshserver(ui, repo, logfh=logfh) s.serve_forever() -@command("debugsetparents", [], _("REV1 [REV2]")) +@command(b"debugsetparents", [], _(b"REV1 [REV2]")) def debugsetparents(ui, repo, rev1, rev2=None): """manually set the parents of the current working directory @@ -3148,39 +3200,39 @@ """ node1 = scmutil.revsingle(repo, rev1).node() - node2 = scmutil.revsingle(repo, rev2, "null").node() + node2 = scmutil.revsingle(repo, rev2, b"null").node() with repo.wlock(): repo.setparents(node1, node2) -@command("debugsidedata", cmdutil.debugrevlogopts, _("-c|-m|FILE REV")) +@command(b"debugsidedata", cmdutil.debugrevlogopts, _(b"-c|-m|FILE REV")) def debugsidedata(ui, repo, file_, rev=None, **opts): """dump the side data for a cl/manifest/file revision""" opts = pycompat.byteskwargs(opts) - if opts.get("changelog") or opts.get("manifest") or opts.get("dir"): + if opts.get(b"changelog") or opts.get(b"manifest") or opts.get(b"dir"): if rev is not None: - raise error.CommandError("debugdata", _("invalid arguments")) + raise error.CommandError(b"debugdata", _(b"invalid arguments")) file_, rev = None, file_ elif rev is None: - raise error.CommandError("debugdata", _("invalid arguments")) - r = cmdutil.openstorage(repo, "debugdata", file_, opts) + raise error.CommandError(b"debugdata", _(b"invalid arguments")) + r = cmdutil.openstorage(repo, b"debugdata", file_, opts) r = getattr(r, "_revlog", r) try: sidedata = r.sidedata(r.lookup(rev)) except KeyError: - raise error.Abort(_("invalid revision identifier %s") % rev) + raise error.Abort(_(b"invalid revision identifier %s") % rev) if sidedata: sidedata = list(sidedata.items()) sidedata.sort() - ui.write(("%d sidedata entries\n" % len(sidedata))) + ui.write((b"%d sidedata entries\n" % len(sidedata))) for key, value in sidedata: - ui.write((" entry-%04o size %d\n" % (key, len(value)))) + ui.write((b" entry-%04o size %d\n" % (key, len(value)))) if ui.verbose: - ui.write((" %s\n" % repr(value))) - - -@command("debugssl", [], "[SOURCE]", optionalrepo=True) + ui.write((b" %s\n" % repr(value))) + + +@command(b"debugssl", [], b"[SOURCE]", optionalrepo=True) def debugssl(ui, repo, source=None, **opts): """test a secure connection to a server @@ -3196,30 +3248,30 @@ """ if not pycompat.iswindows: raise error.Abort( - _("certificate chain building is only possible on " "Windows") + _(b"certificate chain building is only possible on " b"Windows") ) if not source: if not repo: raise error.Abort( _( - "there is no Mercurial repository here, and no " - "server specified" + b"there is no Mercurial repository here, and no " + b"server specified" ) ) - source = "default" + source = b"default" source, branches = hg.parseurl(ui.expandpath(source)) url = util.url(source) - defaultport = {"https": 443, "ssh": 22} + defaultport = {b"https": 443, b"ssh": 22} if url.scheme in defaultport: try: addr = (url.host, int(url.port or defaultport[url.scheme])) except ValueError: - raise error.Abort(_("malformed port number in URL")) + raise error.Abort(_(b"malformed port number in URL")) else: - raise error.Abort(_("only https and ssh connections are supported")) + raise error.Abort(_(b"only https and ssh connections are supported")) from . import win32 @@ -3234,40 +3286,40 @@ s.connect(addr) cert = s.getpeercert(True) - ui.status(_("checking the certificate chain for %s\n") % url.host) + ui.status(_(b"checking the certificate chain for %s\n") % url.host) complete = win32.checkcertificatechain(cert, build=False) if not complete: - ui.status(_("certificate chain is incomplete, updating... ")) + ui.status(_(b"certificate chain is incomplete, updating... ")) if not win32.checkcertificatechain(cert): - ui.status(_("failed.\n")) + ui.status(_(b"failed.\n")) else: - ui.status(_("done.\n")) + ui.status(_(b"done.\n")) else: - ui.status(_("full certificate chain is available\n")) + ui.status(_(b"full certificate chain is available\n")) finally: s.close() @command( - "debugsub", - [("r", "rev", "", _("revision to check"), _("REV"))], - _("[-r REV] [REV]"), + b"debugsub", + [(b"r", b"rev", b"", _(b"revision to check"), _(b"REV"))], + _(b"[-r REV] [REV]"), ) def debugsub(ui, repo, rev=None): ctx = scmutil.revsingle(repo, rev, None) for k, v in sorted(ctx.substate.items()): - ui.write("path %s\n" % k) - ui.write(" source %s\n" % v[0]) - ui.write(" revision %s\n" % v[1]) + ui.write(b"path %s\n" % k) + ui.write(b" source %s\n" % v[0]) + ui.write(b" revision %s\n" % v[1]) @command( - "debugsuccessorssets", - [("", "closest", False, _("return closest successors sets only"))], - _("[REV]"), + b"debugsuccessorssets", + [(b"", b"closest", False, _(b"return closest successors sets only"))], + _(b"[REV]"), ) def debugsuccessorssets(ui, repo, *revs, **opts): """show set of successors for revision @@ -3307,26 +3359,26 @@ node2str = short for rev in scmutil.revrange(repo, revs): ctx = repo[rev] - ui.write("%s\n" % ctx2str(ctx)) + ui.write(b"%s\n" % ctx2str(ctx)) for succsset in obsutil.successorssets( repo, ctx.node(), closest=opts[r"closest"], cache=cache ): if succsset: - ui.write(" ") + ui.write(b" ") ui.write(node2str(succsset[0])) for node in succsset[1:]: - ui.write(" ") + ui.write(b" ") ui.write(node2str(node)) - ui.write("\n") + ui.write(b"\n") @command( - "debugtemplate", + b"debugtemplate", [ - ("r", "rev", [], _("apply template on changesets"), _("REV")), - ("D", "define", [], _("define template keyword"), _("KEY=VALUE")), + (b"r", b"rev", [], _(b"apply template on changesets"), _(b"REV")), + (b"D", b"define", [], _(b"define template keyword"), _(b"KEY=VALUE")), ], - _("[-r REV]... [-D KEY=VALUE]... TEMPLATE"), + _(b"[-r REV]... [-D KEY=VALUE]... TEMPLATE"), optionalrepo=True, ) def debugtemplate(ui, repo, tmpl, **opts): @@ -3342,72 +3394,72 @@ if opts[r"rev"]: if repo is None: raise error.RepoError( - _("there is no Mercurial repository here " "(.hg not found)") + _(b"there is no Mercurial repository here " b"(.hg not found)") ) revs = scmutil.revrange(repo, opts[r"rev"]) props = {} for d in opts[r"define"]: try: - k, v = (e.strip() for e in d.split("=", 1)) - if not k or k == "ui": + k, v = (e.strip() for e in d.split(b"=", 1)) + if not k or k == b"ui": raise ValueError props[k] = v except ValueError: - raise error.Abort(_("malformed keyword definition: %s") % d) + raise error.Abort(_(b"malformed keyword definition: %s") % d) if ui.verbose: - aliases = ui.configitems("templatealias") + aliases = ui.configitems(b"templatealias") tree = templater.parse(tmpl) - ui.note(templater.prettyformat(tree), "\n") + ui.note(templater.prettyformat(tree), b"\n") newtree = templater.expandaliases(tree, aliases) if newtree != tree: - ui.note("* expanded:\n", templater.prettyformat(newtree), "\n") + ui.note(b"* expanded:\n", templater.prettyformat(newtree), b"\n") if revs is None: tres = formatter.templateresources(ui, repo) t = formatter.maketemplater(ui, tmpl, resources=tres) if ui.verbose: kwds, funcs = t.symbolsuseddefault() - ui.write("* keywords: %s\n" % ", ".join(sorted(kwds))) - ui.write("* functions: %s\n" % ", ".join(sorted(funcs))) + ui.write(b"* keywords: %s\n" % b", ".join(sorted(kwds))) + ui.write(b"* functions: %s\n" % b", ".join(sorted(funcs))) ui.write(t.renderdefault(props)) else: displayer = logcmdutil.maketemplater(ui, repo, tmpl) if ui.verbose: kwds, funcs = displayer.t.symbolsuseddefault() - ui.write("* keywords: %s\n" % ", ".join(sorted(kwds))) - ui.write("* functions: %s\n" % ", ".join(sorted(funcs))) + ui.write(b"* keywords: %s\n" % b", ".join(sorted(kwds))) + ui.write(b"* functions: %s\n" % b", ".join(sorted(funcs))) for r in revs: displayer.show(repo[r], **pycompat.strkwargs(props)) displayer.close() @command( - "debuguigetpass", - [("p", "prompt", "", _("prompt text"), _("TEXT")),], - _("[-p TEXT]"), + b"debuguigetpass", + [(b"p", b"prompt", b"", _(b"prompt text"), _(b"TEXT")),], + _(b"[-p TEXT]"), norepo=True, ) -def debuguigetpass(ui, prompt=""): +def debuguigetpass(ui, prompt=b""): """show prompt to type password""" r = ui.getpass(prompt) - ui.write("respose: %s\n" % r) + ui.write(b"respose: %s\n" % r) @command( - "debuguiprompt", - [("p", "prompt", "", _("prompt text"), _("TEXT")),], - _("[-p TEXT]"), + b"debuguiprompt", + [(b"p", b"prompt", b"", _(b"prompt text"), _(b"TEXT")),], + _(b"[-p TEXT]"), norepo=True, ) -def debuguiprompt(ui, prompt=""): +def debuguiprompt(ui, prompt=b""): """show plain prompt""" r = ui.prompt(prompt) - ui.write("response: %s\n" % r) - - -@command("debugupdatecaches", []) + ui.write(b"response: %s\n" % r) + + +@command(b"debugupdatecaches", []) def debugupdatecaches(ui, repo, *pats, **opts): """warm all known caches in the repository""" with repo.wlock(), repo.lock(): @@ -3415,13 +3467,19 @@ @command( - "debugupgraderepo", + b"debugupgraderepo", [ - ("o", "optimize", [], _("extra optimization to perform"), _("NAME")), - ("", "run", False, _("performs an upgrade")), - ("", "backup", True, _("keep the old repository content around")), - ("", "changelog", None, _("select the changelog for upgrade")), - ("", "manifest", None, _("select the manifest for upgrade")), + ( + b"o", + b"optimize", + [], + _(b"extra optimization to perform"), + _(b"NAME"), + ), + (b"", b"run", False, _(b"performs an upgrade")), + (b"", b"backup", True, _(b"keep the old repository content around")), + (b"", b"changelog", None, _(b"select the changelog for upgrade")), + (b"", b"manifest", None, _(b"select the manifest for upgrade")), ], ) def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts): @@ -3457,57 +3515,61 @@ @command( - "debugwalk", cmdutil.walkopts, _("[OPTION]... [FILE]..."), inferrepo=True + b"debugwalk", cmdutil.walkopts, _(b"[OPTION]... [FILE]..."), inferrepo=True ) def debugwalk(ui, repo, *pats, **opts): """show how files match on given patterns""" opts = pycompat.byteskwargs(opts) m = scmutil.match(repo[None], pats, opts) if ui.verbose: - ui.write("* matcher:\n", stringutil.prettyrepr(m), "\n") + ui.write(b"* matcher:\n", stringutil.prettyrepr(m), b"\n") items = list(repo[None].walk(m)) if not items: return f = lambda fn: fn - if ui.configbool("ui", "slash") and pycompat.ossep != "/": + if ui.configbool(b"ui", b"slash") and pycompat.ossep != b"/": f = lambda fn: util.normpath(fn) - fmt = "f %%-%ds %%-%ds %%s" % ( + fmt = b"f %%-%ds %%-%ds %%s" % ( max([len(abs) for abs in items]), max([len(repo.pathto(abs)) for abs in items]), ) for abs in items: - line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and "exact" or "") - ui.write("%s\n" % line.rstrip()) - - -@command("debugwhyunstable", [], _("REV")) + line = fmt % ( + abs, + f(repo.pathto(abs)), + m.exact(abs) and b"exact" or b"", + ) + ui.write(b"%s\n" % line.rstrip()) + + +@command(b"debugwhyunstable", [], _(b"REV")) def debugwhyunstable(ui, repo, rev): """explain instabilities of a changeset""" for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)): - dnodes = "" - if entry.get("divergentnodes"): + dnodes = b"" + if entry.get(b"divergentnodes"): dnodes = ( - " ".join( - "%s (%s)" % (ctx.hex(), ctx.phasestr()) - for ctx in entry["divergentnodes"] + b" ".join( + b"%s (%s)" % (ctx.hex(), ctx.phasestr()) + for ctx in entry[b"divergentnodes"] ) - + " " + + b" " ) ui.write( - "%s: %s%s %s\n" - % (entry["instability"], dnodes, entry["reason"], entry["node"]) + b"%s: %s%s %s\n" + % (entry[b"instability"], dnodes, entry[b"reason"], entry[b"node"]) ) @command( - "debugwireargs", + b"debugwireargs", [ - ("", "three", "", "three"), - ("", "four", "", "four"), - ("", "five", "", "five"), + (b"", b"three", b"", b"three"), + (b"", b"four", b"", b"four"), + (b"", b"five", b"", b"five"), ] + cmdutil.remoteopts, - _("REPO [OPTIONS]... [ONE [TWO]]"), + _(b"REPO [OPTIONS]... [ONE [TWO]]"), norepo=True, ) def debugwireargs(ui, repopath, *vals, **opts): @@ -3523,9 +3585,9 @@ # run twice to check that we don't mess up the stream for the next command res1 = repo.debugwireargs(*vals, **args) res2 = repo.debugwireargs(*vals, **args) - ui.write("%s\n" % res1) + ui.write(b"%s\n" % res1) if res1 != res2: - ui.warn("%s\n" % res2) + ui.warn(b"%s\n" % res2) def _parsewirelangblocks(fh): @@ -3554,7 +3616,7 @@ # Else we start with an indent. if not activeaction: - raise error.Abort(_("indented line outside of block")) + raise error.Abort(_(b"indented line outside of block")) indent = len(line) - len(line.lstrip()) @@ -3571,20 +3633,25 @@ @command( - "debugwireproto", + b"debugwireproto", [ - ("", "localssh", False, _("start an SSH server for this repo")), - ("", "peer", "", _("construct a specific version of the peer")), - ("", "noreadstderr", False, _("do not read from stderr of the remote")), + (b"", b"localssh", False, _(b"start an SSH server for this repo")), + (b"", b"peer", b"", _(b"construct a specific version of the peer")), ( - "", - "nologhandshake", + b"", + b"noreadstderr", False, - _("do not log I/O related to the peer handshake"), + _(b"do not read from stderr of the remote"), + ), + ( + b"", + b"nologhandshake", + False, + _(b"do not log I/O related to the peer handshake"), ), ] + cmdutil.remoteopts, - _("[PATH]"), + _(b"[PATH]"), optionalrepo=True, ) def debugwireproto(ui, repo, path=None, **opts): @@ -3770,22 +3837,27 @@ """ opts = pycompat.byteskwargs(opts) - if opts["localssh"] and not repo: - raise error.Abort(_("--localssh requires a repository")) - - if opts["peer"] and opts["peer"] not in ("raw", "http2", "ssh1", "ssh2"): + if opts[b"localssh"] and not repo: + raise error.Abort(_(b"--localssh requires a repository")) + + if opts[b"peer"] and opts[b"peer"] not in ( + b"raw", + b"http2", + b"ssh1", + b"ssh2", + ): raise error.Abort( - _("invalid value for --peer"), - hint=_('valid values are "raw", "ssh1", and "ssh2"'), + _(b"invalid value for --peer"), + hint=_(b'valid values are "raw", "ssh1", and "ssh2"'), ) - if path and opts["localssh"]: + if path and opts[b"localssh"]: raise error.Abort( - _("cannot specify --localssh with an explicit " "path") + _(b"cannot specify --localssh with an explicit " b"path") ) if ui.interactive(): - ui.write(_("(waiting for commands on stdin)\n")) + ui.write(_(b"(waiting for commands on stdin)\n")) blocks = list(_parsewirelangblocks(ui.fin)) @@ -3795,15 +3867,15 @@ stderr = None opener = None - if opts["localssh"]: + if opts[b"localssh"]: # We start the SSH server in its own process so there is process # separation. This prevents a whole class of potential bugs around # shared state from interfering with server operation. args = procutil.hgcmd() + [ - "-R", + b"-R", repo.root, - "debugserve", - "--sshstdio", + b"debugserve", + b"--sshstdio", ] proc = subprocess.Popen( pycompat.rapply(procutil.tonativestr, args), @@ -3818,7 +3890,7 @@ stderr = proc.stderr # We turn the pipes into observers so we can log I/O. - if ui.verbose or opts["peer"] == "raw": + if ui.verbose or opts[b"peer"] == b"raw": stdin = util.makeloggingfileobject( ui, proc.stdin, b"i", logdata=True ) @@ -3831,11 +3903,11 @@ # --localssh also implies the peer connection settings. - url = "ssh://localserver" - autoreadstderr = not opts["noreadstderr"] - - if opts["peer"] == "ssh1": - ui.write(_("creating ssh peer for wire protocol version 1\n")) + url = b"ssh://localserver" + autoreadstderr = not opts[b"noreadstderr"] + + if opts[b"peer"] == b"ssh1": + ui.write(_(b"creating ssh peer for wire protocol version 1\n")) peer = sshpeer.sshv1peer( ui, url, @@ -3846,8 +3918,8 @@ None, autoreadstderr=autoreadstderr, ) - elif opts["peer"] == "ssh2": - ui.write(_("creating ssh peer for wire protocol version 2\n")) + elif opts[b"peer"] == b"ssh2": + ui.write(_(b"creating ssh peer for wire protocol version 2\n")) peer = sshpeer.sshv2peer( ui, url, @@ -3858,11 +3930,11 @@ None, autoreadstderr=autoreadstderr, ) - elif opts["peer"] == "raw": - ui.write(_("using raw connection to peer\n")) + elif opts[b"peer"] == b"raw": + ui.write(_(b"using raw connection to peer\n")) peer = None else: - ui.write(_("creating ssh peer from handshake results\n")) + ui.write(_(b"creating ssh peer from handshake results\n")) peer = sshpeer.makepeer( ui, url, @@ -3878,8 +3950,8 @@ # TODO consider not doing this because we skip # ``hg.wirepeersetupfuncs`` and potentially other useful functionality. u = util.url(path) - if u.scheme != "http": - raise error.Abort(_("only http:// paths are currently supported")) + if u.scheme != b"http": + raise error.Abort(_(b"only http:// paths are currently supported")) url, authinfo = u.authinfo() openerargs = { @@ -3902,94 +3974,94 @@ # Don't send default headers when in raw mode. This allows us to # bypass most of the behavior of our URL handling code so we can # have near complete control over what's sent on the wire. - if opts["peer"] == "raw": + if opts[b"peer"] == b"raw": openerargs[r"sendaccept"] = False opener = urlmod.opener(ui, authinfo, **openerargs) - if opts["peer"] == "http2": - ui.write(_("creating http peer for wire protocol version 2\n")) + if opts[b"peer"] == b"http2": + ui.write(_(b"creating http peer for wire protocol version 2\n")) # We go through makepeer() because we need an API descriptor for # the peer instance to be useful. with ui.configoverride( - {("experimental", "httppeer.advertise-v2"): True} + {(b"experimental", b"httppeer.advertise-v2"): True} ): - if opts["nologhandshake"]: + if opts[b"nologhandshake"]: ui.pushbuffer() peer = httppeer.makepeer(ui, path, opener=opener) - if opts["nologhandshake"]: + if opts[b"nologhandshake"]: ui.popbuffer() if not isinstance(peer, httppeer.httpv2peer): raise error.Abort( _( - "could not instantiate HTTP peer for " - "wire protocol version 2" + b"could not instantiate HTTP peer for " + b"wire protocol version 2" ), hint=_( - "the server may not have the feature " - "enabled or is not allowing this " - "client version" + b"the server may not have the feature " + b"enabled or is not allowing this " + b"client version" ), ) - elif opts["peer"] == "raw": - ui.write(_("using raw connection to peer\n")) + elif opts[b"peer"] == b"raw": + ui.write(_(b"using raw connection to peer\n")) peer = None - elif opts["peer"]: + elif opts[b"peer"]: raise error.Abort( - _("--peer %s not supported with HTTP peers") % opts["peer"] + _(b"--peer %s not supported with HTTP peers") % opts[b"peer"] ) else: peer = httppeer.makepeer(ui, path, opener=opener) # We /could/ populate stdin/stdout with sock.makefile()... else: - raise error.Abort(_("unsupported connection configuration")) + raise error.Abort(_(b"unsupported connection configuration")) batchedcommands = None # Now perform actions based on the parsed wire language instructions. for action, lines in blocks: - if action in ("raw", "raw+"): + if action in (b"raw", b"raw+"): if not stdin: - raise error.Abort(_("cannot call raw/raw+ on this peer")) + raise error.Abort(_(b"cannot call raw/raw+ on this peer")) # Concatenate the data together. - data = "".join(l.lstrip() for l in lines) + data = b"".join(l.lstrip() for l in lines) data = stringutil.unescapestr(data) stdin.write(data) - if action == "raw+": + if action == b"raw+": stdin.flush() - elif action == "flush": + elif action == b"flush": if not stdin: - raise error.Abort(_("cannot call flush on this peer")) + raise error.Abort(_(b"cannot call flush on this peer")) stdin.flush() - elif action.startswith("command"): + elif action.startswith(b"command"): if not peer: raise error.Abort( _( - "cannot send commands unless peer instance " - "is available" + b"cannot send commands unless peer instance " + b"is available" ) ) - command = action.split(" ", 1)[1] + command = action.split(b" ", 1)[1] args = {} for line in lines: # We need to allow empty values. - fields = line.lstrip().split(" ", 1) + fields = line.lstrip().split(b" ", 1) if len(fields) == 1: key = fields[0] - value = "" + value = b"" else: key, value = fields - if value.startswith("eval:"): + if value.startswith(b"eval:"): value = stringutil.evalpythonliteral(value[5:]) else: value = stringutil.unescapestr(value) @@ -4000,17 +4072,17 @@ batchedcommands.append((command, args)) continue - ui.status(_("sending %s command\n") % command) - - if "PUSHFILE" in args: - with open(args["PUSHFILE"], r"rb") as fh: - del args["PUSHFILE"] + ui.status(_(b"sending %s command\n") % command) + + if b"PUSHFILE" in args: + with open(args[b"PUSHFILE"], r"rb") as fh: + del args[b"PUSHFILE"] res, output = peer._callpush( command, fh, **pycompat.strkwargs(args) ) - ui.status(_("result: %s\n") % stringutil.escapestr(res)) + ui.status(_(b"result: %s\n") % stringutil.escapestr(res)) ui.status( - _("remote output: %s\n") % stringutil.escapestr(output) + _(b"remote output: %s\n") % stringutil.escapestr(output) ) else: with peer.commandexecutor() as e: @@ -4019,46 +4091,47 @@ if isinstance(res, wireprotov2peer.commandresponse): val = res.objects() ui.status( - _("response: %s\n") + _(b"response: %s\n") % stringutil.pprint(val, bprefix=True, indent=2) ) else: ui.status( - _("response: %s\n") + _(b"response: %s\n") % stringutil.pprint(res, bprefix=True, indent=2) ) - elif action == "batchbegin": + elif action == b"batchbegin": if batchedcommands is not None: - raise error.Abort(_("nested batchbegin not allowed")) + raise error.Abort(_(b"nested batchbegin not allowed")) batchedcommands = [] - elif action == "batchsubmit": + elif action == b"batchsubmit": # There is a batching API we could go through. But it would be # difficult to normalize requests into function calls. It is easier # to bypass this layer and normalize to commands + args. ui.status( - _("sending batch with %d sub-commands\n") % len(batchedcommands) + _(b"sending batch with %d sub-commands\n") + % len(batchedcommands) ) for i, chunk in enumerate(peer._submitbatch(batchedcommands)): ui.status( - _("response #%d: %s\n") % (i, stringutil.escapestr(chunk)) + _(b"response #%d: %s\n") % (i, stringutil.escapestr(chunk)) ) batchedcommands = None - elif action.startswith("httprequest "): + elif action.startswith(b"httprequest "): if not opener: raise error.Abort( - _("cannot use httprequest without an HTTP " "peer") + _(b"cannot use httprequest without an HTTP " b"peer") ) - request = action.split(" ", 2) + request = action.split(b" ", 2) if len(request) != 3: raise error.Abort( _( - "invalid httprequest: expected format is " - '"httprequest ' + b"invalid httprequest: expected format is " + b'"httprequest ' ) ) @@ -4077,7 +4150,7 @@ continue if line.startswith(b"BODYFILE "): - with open(line.split(b" ", 1), "rb") as fh: + with open(line.split(b" ", 1), b"rb") as fh: body = fh.read() elif line.startswith(b"frame "): frame = wireprotoframing.makeframefromhumanstring( @@ -4087,7 +4160,7 @@ frames.append(frame) else: raise error.Abort( - _("unknown argument to httprequest: %s") % line + _(b"unknown argument to httprequest: %s") % line ) url = path + httppath @@ -4113,45 +4186,47 @@ ct = res.headers.get(r"Content-Type") if ct == r"application/mercurial-cbor": ui.write( - _("cbor> %s\n") + _(b"cbor> %s\n") % stringutil.pprint( cborutil.decodeall(body), bprefix=True, indent=2 ) ) - elif action == "close": + elif action == b"close": peer.close() - elif action == "readavailable": + elif action == b"readavailable": if not stdout or not stderr: - raise error.Abort(_("readavailable not available on this peer")) + raise error.Abort( + _(b"readavailable not available on this peer") + ) stdin.close() stdout.read() stderr.read() - elif action == "readline": + elif action == b"readline": if not stdout: - raise error.Abort(_("readline not available on this peer")) + raise error.Abort(_(b"readline not available on this peer")) stdout.readline() - elif action == "ereadline": + elif action == b"ereadline": if not stderr: - raise error.Abort(_("ereadline not available on this peer")) + raise error.Abort(_(b"ereadline not available on this peer")) stderr.readline() - elif action.startswith("read "): - count = int(action.split(" ", 1)[1]) + elif action.startswith(b"read "): + count = int(action.split(b" ", 1)[1]) if not stdout: - raise error.Abort(_("read not available on this peer")) + raise error.Abort(_(b"read not available on this peer")) stdout.read(count) - elif action.startswith("eread "): - count = int(action.split(" ", 1)[1]) + elif action.startswith(b"eread "): + count = int(action.split(b" ", 1)[1]) if not stderr: - raise error.Abort(_("eread not available on this peer")) + raise error.Abort(_(b"eread not available on this peer")) stderr.read(count) else: - raise error.Abort(_("unknown action: %s") % action) + raise error.Abort(_(b"unknown action: %s") % action) if batchedcommands is not None: - raise error.Abort(_('unclosed "batchbegin" request')) + raise error.Abort(_(b'unclosed "batchbegin" request')) if peer: peer.close() diff --git a/mercurial/destutil.py b/mercurial/destutil.py --- a/mercurial/destutil.py +++ b/mercurial/destutil.py @@ -76,9 +76,9 @@ # get the max revision for the given successors set, # i.e. the 'tip' of a set - node = repo.revs("max(%ln)", successors).first() + node = repo.revs(b"max(%ln)", successors).first() if bookmarks.isactivewdirparent(repo): - movemark = repo["."].node() + movemark = repo[b"."].node() return node, movemark, None @@ -102,20 +102,20 @@ currentbranch = wc.branch() if clean: - currentbranch = repo["."].branch() + currentbranch = repo[b"."].branch() if currentbranch in repo.branchmap(): heads = repo.branchheads(currentbranch) if heads: - node = repo.revs("max(.::(%ln))", heads).first() + node = repo.revs(b"max(.::(%ln))", heads).first() if bookmarks.isactivewdirparent(repo): - movemark = repo["."].node() - elif currentbranch == "default" and not wc.p1(): + movemark = repo[b"."].node() + elif currentbranch == b"default" and not wc.p1(): # "null" parent belongs to "default" branch, but it doesn't exist, so # update to the tipmost non-closed branch head - node = repo.revs("max(head() and not closed())").first() + node = repo.revs(b"max(head() and not closed())").first() else: - node = repo["."].node() + node = repo[b"."].node() return node, movemark, None @@ -127,29 +127,29 @@ if currentbranch in repo.branchmap(): # here, all descendant branch heads are closed heads = repo.branchheads(currentbranch, closed=True) - assert heads, "any branch has at least one head" - node = repo.revs("max(.::(%ln))", heads).first() + assert heads, b"any branch has at least one head" + node = repo.revs(b"max(.::(%ln))", heads).first() assert node is not None, ( - "any revision has at least " "one descendant branch head" + b"any revision has at least " b"one descendant branch head" ) if bookmarks.isactivewdirparent(repo): - movemark = repo["."].node() + movemark = repo[b"."].node() else: # here, no "default" branch, and all branches are closed - node = repo.lookup("tip") - assert node is not None, "'tip' exists even in empty repository" + node = repo.lookup(b"tip") + assert node is not None, b"'tip' exists even in empty repository" return node, movemark, None # order in which each step should be evaluated # steps are run until one finds a destination -destupdatesteps = ["evolution", "bookmark", "branch", "branchfallback"] +destupdatesteps = [b"evolution", b"bookmark", b"branch", b"branchfallback"] # mapping to ease extension overriding steps. destupdatestepmap = { - "evolution": _destupdateobs, - "bookmark": _destupdatebook, - "branch": _destupdatebranch, - "branchfallback": _destupdatebranchfallback, + b"evolution": _destupdateobs, + b"bookmark": _destupdatebook, + b"branch": _destupdatebranch, + b"branchfallback": _destupdatebranchfallback, } @@ -176,108 +176,108 @@ msgdestmerge = { # too many matching divergent bookmark - "toomanybookmarks": { - "merge": ( + b"toomanybookmarks": { + b"merge": ( _( - "multiple matching bookmarks to merge -" - " please merge with an explicit rev or bookmark" + b"multiple matching bookmarks to merge -" + b" please merge with an explicit rev or bookmark" ), - _("run 'hg heads' to see all heads"), + _(b"run 'hg heads' to see all heads"), ), - "rebase": ( + b"rebase": ( _( - "multiple matching bookmarks to rebase -" - " please rebase to an explicit rev or bookmark" + b"multiple matching bookmarks to rebase -" + b" please rebase to an explicit rev or bookmark" ), - _("run 'hg heads' to see all heads"), + _(b"run 'hg heads' to see all heads"), ), }, # no other matching divergent bookmark - "nootherbookmarks": { - "merge": ( + b"nootherbookmarks": { + b"merge": ( _( - "no matching bookmark to merge - " - "please merge with an explicit rev or bookmark" + b"no matching bookmark to merge - " + b"please merge with an explicit rev or bookmark" ), - _("run 'hg heads' to see all heads"), + _(b"run 'hg heads' to see all heads"), ), - "rebase": ( + b"rebase": ( _( - "no matching bookmark to rebase - " - "please rebase to an explicit rev or bookmark" + b"no matching bookmark to rebase - " + b"please rebase to an explicit rev or bookmark" ), - _("run 'hg heads' to see all heads"), + _(b"run 'hg heads' to see all heads"), ), }, # branch have too many unbookmarked heads, no obvious destination - "toomanyheads": { - "merge": ( - _("branch '%s' has %d heads - please merge with an explicit rev"), - _("run 'hg heads .' to see heads"), + b"toomanyheads": { + b"merge": ( + _(b"branch '%s' has %d heads - please merge with an explicit rev"), + _(b"run 'hg heads .' to see heads"), ), - "rebase": ( - _("branch '%s' has %d heads - please rebase to an explicit rev"), - _("run 'hg heads .' to see heads"), + b"rebase": ( + _(b"branch '%s' has %d heads - please rebase to an explicit rev"), + _(b"run 'hg heads .' to see heads"), ), }, # branch have no other unbookmarked heads - "bookmarkedheads": { - "merge": ( - _("heads are bookmarked - please merge with an explicit rev"), - _("run 'hg heads' to see all heads"), + b"bookmarkedheads": { + b"merge": ( + _(b"heads are bookmarked - please merge with an explicit rev"), + _(b"run 'hg heads' to see all heads"), ), - "rebase": ( - _("heads are bookmarked - please rebase to an explicit rev"), - _("run 'hg heads' to see all heads"), + b"rebase": ( + _(b"heads are bookmarked - please rebase to an explicit rev"), + _(b"run 'hg heads' to see all heads"), ), }, # branch have just a single heads, but there is other branches - "nootherbranchheads": { - "merge": ( - _("branch '%s' has one head - please merge with an explicit rev"), - _("run 'hg heads' to see all heads"), + b"nootherbranchheads": { + b"merge": ( + _(b"branch '%s' has one head - please merge with an explicit rev"), + _(b"run 'hg heads' to see all heads"), ), - "rebase": ( - _("branch '%s' has one head - please rebase to an explicit rev"), - _("run 'hg heads' to see all heads"), + b"rebase": ( + _(b"branch '%s' has one head - please rebase to an explicit rev"), + _(b"run 'hg heads' to see all heads"), ), }, # repository have a single head - "nootherheads": { - "merge": (_("nothing to merge"), None), - "rebase": (_("nothing to rebase"), None), + b"nootherheads": { + b"merge": (_(b"nothing to merge"), None), + b"rebase": (_(b"nothing to rebase"), None), }, # repository have a single head and we are not on it - "nootherheadsbehind": { - "merge": (_("nothing to merge"), _("use 'hg update' instead")), - "rebase": (_("nothing to rebase"), _("use 'hg update' instead")), + b"nootherheadsbehind": { + b"merge": (_(b"nothing to merge"), _(b"use 'hg update' instead")), + b"rebase": (_(b"nothing to rebase"), _(b"use 'hg update' instead")), }, # We are not on a head - "notatheads": { - "merge": ( - _("working directory not at a head revision"), - _("use 'hg update' or merge with an explicit revision"), + b"notatheads": { + b"merge": ( + _(b"working directory not at a head revision"), + _(b"use 'hg update' or merge with an explicit revision"), ), - "rebase": ( - _("working directory not at a head revision"), - _("use 'hg update' or rebase to an explicit revision"), + b"rebase": ( + _(b"working directory not at a head revision"), + _(b"use 'hg update' or rebase to an explicit revision"), ), }, - "emptysourceset": { - "merge": (_("source set is empty"), None), - "rebase": (_("source set is empty"), None), + b"emptysourceset": { + b"merge": (_(b"source set is empty"), None), + b"rebase": (_(b"source set is empty"), None), }, - "multiplebranchessourceset": { - "merge": (_("source set is rooted in multiple branches"), None), - "rebase": ( - _("rebaseset is rooted in multiple named branches"), - _("specify an explicit destination with --dest"), + b"multiplebranchessourceset": { + b"merge": (_(b"source set is rooted in multiple branches"), None), + b"rebase": ( + _(b"rebaseset is rooted in multiple named branches"), + _(b"specify an explicit destination with --dest"), ), }, } -def _destmergebook(repo, action="merge", sourceset=None, destspace=None): +def _destmergebook(repo, action=b"merge", sourceset=None, destspace=None): """find merge destination in the active bookmark case""" node = None bmheads = bookmarks.headsforactive(repo) @@ -288,17 +288,17 @@ else: node = bmheads[0] elif len(bmheads) > 2: - msg, hint = msgdestmerge["toomanybookmarks"][action] + msg, hint = msgdestmerge[b"toomanybookmarks"][action] raise error.ManyMergeDestAbort(msg, hint=hint) elif len(bmheads) <= 1: - msg, hint = msgdestmerge["nootherbookmarks"][action] + msg, hint = msgdestmerge[b"nootherbookmarks"][action] raise error.NoMergeDestAbort(msg, hint=hint) assert node is not None return node def _destmergebranch( - repo, action="merge", sourceset=None, onheadcheck=True, destspace=None + repo, action=b"merge", sourceset=None, onheadcheck=True, destspace=None ): """find merge destination based on branch heads""" node = None @@ -307,36 +307,36 @@ sourceset = [repo[repo.dirstate.p1()].rev()] branch = repo.dirstate.branch() elif not sourceset: - msg, hint = msgdestmerge["emptysourceset"][action] + msg, hint = msgdestmerge[b"emptysourceset"][action] raise error.NoMergeDestAbort(msg, hint=hint) else: branch = None - for ctx in repo.set("roots(%ld::%ld)", sourceset, sourceset): + for ctx in repo.set(b"roots(%ld::%ld)", sourceset, sourceset): if branch is not None and ctx.branch() != branch: - msg, hint = msgdestmerge["multiplebranchessourceset"][action] + msg, hint = msgdestmerge[b"multiplebranchessourceset"][action] raise error.ManyMergeDestAbort(msg, hint=hint) branch = ctx.branch() bheads = repo.branchheads(branch) - onhead = repo.revs("%ld and %ln", sourceset, bheads) + onhead = repo.revs(b"%ld and %ln", sourceset, bheads) if onheadcheck and not onhead: # Case A: working copy if not on a head. (merge only) # # This is probably a user mistake We bailout pointing at 'hg update' if len(repo.heads()) <= 1: - msg, hint = msgdestmerge["nootherheadsbehind"][action] + msg, hint = msgdestmerge[b"nootherheadsbehind"][action] else: - msg, hint = msgdestmerge["notatheads"][action] + msg, hint = msgdestmerge[b"notatheads"][action] raise error.Abort(msg, hint=hint) # remove heads descendants of source from the set - bheads = list(repo.revs("%ln - (%ld::)", bheads, sourceset)) + bheads = list(repo.revs(b"%ln - (%ld::)", bheads, sourceset)) # filters out bookmarked heads - nbhs = list(repo.revs("%ld - bookmark()", bheads)) + nbhs = list(repo.revs(b"%ld - bookmark()", bheads)) if destspace is not None: # restrict search space # used in the 'hg pull --rebase' case, see issue 5214. - nbhs = list(repo.revs("%ld and %ld", destspace, nbhs)) + nbhs = list(repo.revs(b"%ld and %ld", destspace, nbhs)) if len(nbhs) > 1: # Case B: There is more than 1 other anonymous heads @@ -344,7 +344,7 @@ # This means that there will be more than 1 candidate. This is # ambiguous. We abort asking the user to pick as explicit destination # instead. - msg, hint = msgdestmerge["toomanyheads"][action] + msg, hint = msgdestmerge[b"toomanyheads"][action] msg %= (branch, len(bheads) + 1) raise error.ManyMergeDestAbort(msg, hint=hint) elif not nbhs: @@ -353,16 +353,16 @@ # This means that there is no natural candidate to merge with. # We abort, with various messages for various cases. if bheads: - msg, hint = msgdestmerge["bookmarkedheads"][action] + msg, hint = msgdestmerge[b"bookmarkedheads"][action] elif len(repo.heads()) > 1: - msg, hint = msgdestmerge["nootherbranchheads"][action] + msg, hint = msgdestmerge[b"nootherbranchheads"][action] msg %= branch elif not onhead: # if 'onheadcheck == False' (rebase case), # this was not caught in Case A. - msg, hint = msgdestmerge["nootherheadsbehind"][action] + msg, hint = msgdestmerge[b"nootherheadsbehind"][action] else: - msg, hint = msgdestmerge["nootherheads"][action] + msg, hint = msgdestmerge[b"nootherheads"][action] raise error.NoMergeDestAbort(msg, hint=hint) else: node = nbhs[0] @@ -371,7 +371,7 @@ def destmerge( - repo, action="merge", sourceset=None, onheadcheck=True, destspace=None + repo, action=b"merge", sourceset=None, onheadcheck=True, destspace=None ): """return the default destination for a merge @@ -398,14 +398,16 @@ def desthistedit(ui, repo): """Default base revision to edit for `hg histedit`.""" - default = ui.config("histedit", "defaultrev") + default = ui.config(b"histedit", b"defaultrev") if default is None: revs = stack.getstack(repo) elif default: revs = scmutil.revrange(repo, [default]) else: - raise error.Abort(_("config option histedit.defaultrev can't be empty")) + raise error.Abort( + _(b"config option histedit.defaultrev can't be empty") + ) if revs: # Take the first revision of the revset as the root @@ -422,11 +424,11 @@ def _statusotherbook(ui, repo): bmheads = bookmarks.headsforactive(repo) curhead = repo._bookmarks[repo._activebookmark] - if repo.revs("%n and parents()", curhead): + if repo.revs(b"%n and parents()", curhead): # we are on the active bookmark bmheads = [b for b in bmheads if curhead != b] if bmheads: - msg = _('%i other divergent bookmarks for "%s"\n') + msg = _(b'%i other divergent bookmarks for "%s"\n') ui.status(msg % (len(bmheads), repo._activebookmark)) @@ -434,7 +436,7 @@ currentbranch = repo.dirstate.branch() allheads = repo.branchheads(currentbranch, closed=True) heads = repo.branchheads(currentbranch) - if repo.revs("%ln and parents()", allheads): + if repo.revs(b"%ln and parents()", allheads): # we are on a head, even though it might be closed # # on closed otherheads @@ -444,35 +446,35 @@ # x 0 there is only one non-closed branch head # N there are some non-closed branch heads # ========= ========== - otherheads = repo.revs("%ln - parents()", heads) - if repo["."].closesbranch(): + otherheads = repo.revs(b"%ln - parents()", heads) + if repo[b"."].closesbranch(): ui.warn( _( - 'no open descendant heads on branch "%s", ' - "updating to a closed head\n" + b'no open descendant heads on branch "%s", ' + b"updating to a closed head\n" ) % currentbranch ) if otherheads: ui.warn( _( - "(committing will reopen the head, " - "use 'hg heads .' to see %i other heads)\n" + b"(committing will reopen the head, " + b"use 'hg heads .' to see %i other heads)\n" ) % (len(otherheads)) ) else: ui.warn( - _('(committing will reopen branch "%s")\n') % currentbranch + _(b'(committing will reopen branch "%s")\n') % currentbranch ) elif otherheads: - curhead = repo["."] + curhead = repo[b"."] ui.status( - _('updated to "%s: %s"\n') - % (curhead, curhead.description().split("\n")[0]) + _(b'updated to "%s: %s"\n') + % (curhead, curhead.description().split(b"\n")[0]) ) ui.status( - _('%i other heads for branch "%s"\n') + _(b'%i other heads for branch "%s"\n') % (len(otherheads), currentbranch) ) diff --git a/mercurial/diffhelper.py b/mercurial/diffhelper.py --- a/mercurial/diffhelper.py +++ b/mercurial/diffhelper.py @@ -31,18 +31,18 @@ for i in pycompat.xrange(num): s = fp.readline() if not s: - raise error.ParseError(_("incomplete hunk")) - if s == "\\ No newline at end of file\n": + raise error.ParseError(_(b"incomplete hunk")) + if s == b"\\ No newline at end of file\n": fixnewline(hunk, a, b) continue - if s == "\n" or s == "\r\n": + if s == b"\n" or s == b"\r\n": # Some patches may be missing the control char # on empty lines. Supply a leading space. - s = " " + s + s = b" " + s hunk.append(s) - if s.startswith("+"): + if s.startswith(b"+"): b.append(s[1:]) - elif s.startswith("-"): + elif s.startswith(b"-"): a.append(s) else: b.append(s[1:]) @@ -53,14 +53,14 @@ """Fix up the last lines of a and b when the patch has no newline at EOF""" l = hunk[-1] # tolerate CRLF in last line - if l.endswith("\r\n"): + if l.endswith(b"\r\n"): hline = l[:-2] else: hline = l[:-1] - if hline.startswith((" ", "+")): + if hline.startswith((b" ", b"+")): b[-1] = hline[1:] - if hline.startswith((" ", "-")): + if hline.startswith((b" ", b"-")): a[-1] = hline hunk[-1] = hline diff --git a/mercurial/diffutil.py b/mercurial/diffutil.py --- a/mercurial/diffutil.py +++ b/mercurial/diffutil.py @@ -18,7 +18,7 @@ def diffallopts( - ui, opts=None, untrusted=False, section="diff", configprefix="" + ui, opts=None, untrusted=False, section=b"diff", configprefix=b"" ): """return diffopts with all features supported and parsed""" return difffeatureopts( @@ -37,11 +37,11 @@ ui, opts=None, untrusted=False, - section="diff", + section=b"diff", git=False, whitespace=False, formatchanging=False, - configprefix="", + configprefix=b"", ): """return diffopts with only opted-in features parsed @@ -72,24 +72,24 @@ # core options, expected to be understood by every diff parser buildopts = { - "nodates": get("nodates"), - "showfunc": get("show_function", "showfunc"), - "context": get("unified", getter=ui.config), + b"nodates": get(b"nodates"), + b"showfunc": get(b"show_function", b"showfunc"), + b"context": get(b"unified", getter=ui.config), } - buildopts["xdiff"] = ui.configbool("experimental", "xdiff") + buildopts[b"xdiff"] = ui.configbool(b"experimental", b"xdiff") if git: - buildopts["git"] = get("git") + buildopts[b"git"] = get(b"git") # since this is in the experimental section, we need to call # ui.configbool directory - buildopts["showsimilarity"] = ui.configbool( - "experimental", "extendedheader.similarity" + buildopts[b"showsimilarity"] = ui.configbool( + b"experimental", b"extendedheader.similarity" ) # need to inspect the ui object instead of using get() since we want to # test for an int - hconf = ui.config("experimental", "extendedheader.index") + hconf = ui.config(b"experimental", b"extendedheader.index") if hconf is not None: hlen = None try: @@ -97,38 +97,40 @@ # word (e.g. short, full, none) hlen = int(hconf) if hlen < 0 or hlen > 40: - msg = _("invalid length for extendedheader.index: '%d'\n") + msg = _(b"invalid length for extendedheader.index: '%d'\n") ui.warn(msg % hlen) except ValueError: # default value - if hconf == "short" or hconf == "": + if hconf == b"short" or hconf == b"": hlen = 12 - elif hconf == "full": + elif hconf == b"full": hlen = 40 - elif hconf != "none": - msg = _("invalid value for extendedheader.index: '%s'\n") + elif hconf != b"none": + msg = _(b"invalid value for extendedheader.index: '%s'\n") ui.warn(msg % hconf) finally: - buildopts["index"] = hlen + buildopts[b"index"] = hlen if whitespace: - buildopts["ignorews"] = get("ignore_all_space", "ignorews") - buildopts["ignorewsamount"] = get( - "ignore_space_change", "ignorewsamount" + buildopts[b"ignorews"] = get(b"ignore_all_space", b"ignorews") + buildopts[b"ignorewsamount"] = get( + b"ignore_space_change", b"ignorewsamount" ) - buildopts["ignoreblanklines"] = get( - "ignore_blank_lines", "ignoreblanklines" + buildopts[b"ignoreblanklines"] = get( + b"ignore_blank_lines", b"ignoreblanklines" ) - buildopts["ignorewseol"] = get("ignore_space_at_eol", "ignorewseol") + buildopts[b"ignorewseol"] = get(b"ignore_space_at_eol", b"ignorewseol") if formatchanging: - buildopts["text"] = opts and opts.get("text") - binary = None if opts is None else opts.get("binary") - buildopts["nobinary"] = ( + buildopts[b"text"] = opts and opts.get(b"text") + binary = None if opts is None else opts.get(b"binary") + buildopts[b"nobinary"] = ( not binary if binary is not None - else get("nobinary", forceplain=False) + else get(b"nobinary", forceplain=False) ) - buildopts["noprefix"] = get("noprefix", forceplain=False) - buildopts["worddiff"] = get("word_diff", "word-diff", forceplain=False) + buildopts[b"noprefix"] = get(b"noprefix", forceplain=False) + buildopts[b"worddiff"] = get( + b"word_diff", b"word-diff", forceplain=False + ) return mdiff.diffopts(**pycompat.strkwargs(buildopts)) diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -87,8 +87,8 @@ self._ui = ui self._filecache = {} self._parentwriters = 0 - self._filename = "dirstate" - self._pendingfilename = "%s.pending" % self._filename + self._filename = b"dirstate" + self._pendingfilename = b"%s.pending" % self._filename self._plchangecallbacks = {} self._origpl = None self._updatedfiles = set() @@ -140,14 +140,14 @@ # cache to keep the lookup fast.) return self._sparsematchfn() - @repocache("branch") + @repocache(b"branch") def _branch(self): try: - return self._opener.read("branch").strip() or "default" + return self._opener.read(b"branch").strip() or b"default" except IOError as inst: if inst.errno != errno.ENOENT: raise - return "default" + return b"default" @property def _pl(self): @@ -156,18 +156,18 @@ def hasdir(self, d): return self._map.hastrackeddir(d) - @rootcache(".hgignore") + @rootcache(b".hgignore") def _ignore(self): files = self._ignorefiles() if not files: return matchmod.never() - pats = ["include:%s" % f for f in files] - return matchmod.match(self._root, "", [], pats, warn=self._ui.warn) + pats = [b"include:%s" % f for f in files] + return matchmod.match(self._root, b"", [], pats, warn=self._ui.warn) @propertycache def _slash(self): - return self._ui.configbool("ui", "slash") and pycompat.ossep != "/" + return self._ui.configbool(b"ui", b"slash") and pycompat.ossep != b"/" @propertycache def _checklink(self): @@ -179,7 +179,7 @@ @propertycache def _checkcase(self): - return not util.fscasesensitive(self._join(".hg")) + return not util.fscasesensitive(self._join(b".hg")) def _join(self, f): # much faster than os.path.join() @@ -193,12 +193,12 @@ try: st = os.lstat(self._join(x)) if util.statislink(st): - return "l" + return b"l" if util.statisexec(st): - return "x" + return b"x" except OSError: pass - return "" + return b"" return f @@ -207,20 +207,20 @@ def f(x): if os.path.islink(self._join(x)): - return "l" - if "x" in fallback(x): - return "x" - return "" + return b"l" + if b"x" in fallback(x): + return b"x" + return b"" return f if self._checkexec: def f(x): - if "l" in fallback(x): - return "l" + if b"l" in fallback(x): + return b"l" if util.isexec(self._join(x)): - return "x" - return "" + return b"x" + return b"" return f else: @@ -229,7 +229,7 @@ @propertycache def _cwd(self): # internal config: ui.forcecwd - forcecwd = self._ui.config("ui", "forcecwd") + forcecwd = self._ui.config(b"ui", b"forcecwd") if forcecwd: return forcecwd return encoding.getcwd() @@ -243,7 +243,7 @@ """ cwd = self._cwd if cwd == self._root: - return "" + return b"" # self._root ends with a path separator if self._root is '/' or 'C:\' rootsep = self._root if not util.endswithsep(rootsep): @@ -272,7 +272,7 @@ a marked for addition ? not tracked """ - return self._map.get(key, ("?",))[0] + return self._map.get(key, (b"?",))[0] def __contains__(self, key): return key in self._map @@ -308,8 +308,8 @@ """ if self._parentwriters == 0: raise ValueError( - "cannot set dirstate parent outside of " - "dirstate.parentchange context manager" + b"cannot set dirstate parent outside of " + b"dirstate.parentchange context manager" ) self._dirty = True @@ -328,13 +328,13 @@ continue # Discard 'm' markers when moving away from a merge state - if s[0] == "m": + if s[0] == b"m": source = self._map.copymap.get(f) if source: copies[f] = source self.normallookup(f) # Also fix up otherparent markers - elif s[0] == "n" and s[2] == -2: + elif s[0] == b"n" and s[2] == -2: source = self._map.copymap.get(f) if source: copies[f] = source @@ -343,14 +343,14 @@ def setbranch(self, branch): self.__class__._branch.set(self, encoding.fromlocal(branch)) - f = self._opener("branch", "w", atomictemp=True, checkambig=True) + f = self._opener(b"branch", b"w", atomictemp=True, checkambig=True) try: - f.write(self._branch + "\n") + f.write(self._branch + b"\n") f.close() # make sure filecache has the correct stat info for _branch after # replacing the underlying file - ce = self._filecache["_branch"] + ce = self._filecache[b"_branch"] if ce: ce.refresh() except: # re-raises @@ -393,20 +393,20 @@ def _addpath(self, f, state, mode, size, mtime): oldstate = self[f] - if state == "a" or oldstate == "r": + if state == b"a" or oldstate == b"r": scmutil.checkfilename(f) if self._map.hastrackeddir(f): raise error.Abort( - _("directory %r already in dirstate") % pycompat.bytestr(f) + _(b"directory %r already in dirstate") % pycompat.bytestr(f) ) # shadows for d in util.finddirs(f): if self._map.hastrackeddir(d): break entry = self._map.get(d) - if entry is not None and entry[0] != "r": + if entry is not None and entry[0] != b"r": raise error.Abort( - _("file %r in dirstate clashes with %r") + _(b"file %r in dirstate clashes with %r") % (pycompat.bytestr(d), pycompat.bytestr(f)) ) self._dirty = True @@ -430,7 +430,7 @@ mode = s.st_mode size = s.st_size mtime = s[stat.ST_MTIME] - self._addpath(f, "n", mode, size & _rangemask, mtime & _rangemask) + self._addpath(f, b"n", mode, size & _rangemask, mtime & _rangemask) self._map.copymap.pop(f, None) if f in self._map.nonnormalset: self._map.nonnormalset.remove(f) @@ -448,7 +448,7 @@ # being removed, restore that state. entry = self._map.get(f) if entry is not None: - if entry[0] == "r" and entry[2] in (-1, -2): + if entry[0] == b"r" and entry[2] in (-1, -2): source = self._map.copymap.get(f) if entry[2] == -1: self.merge(f) @@ -457,28 +457,28 @@ if source: self.copy(source, f) return - if entry[0] == "m" or entry[0] == "n" and entry[2] == -2: + if entry[0] == b"m" or entry[0] == b"n" and entry[2] == -2: return - self._addpath(f, "n", 0, -1, -1) + self._addpath(f, b"n", 0, -1, -1) self._map.copymap.pop(f, None) def otherparent(self, f): """Mark as coming from the other parent, always dirty.""" if self._pl[1] == nullid: raise error.Abort( - _("setting %r to other parent " "only allowed in merges") % f + _(b"setting %r to other parent " b"only allowed in merges") % f ) - if f in self and self[f] == "n": + if f in self and self[f] == b"n": # merge-like - self._addpath(f, "m", 0, -2, -1) + self._addpath(f, b"m", 0, -2, -1) else: # add-like - self._addpath(f, "n", 0, -2, -1) + self._addpath(f, b"n", 0, -2, -1) self._map.copymap.pop(f, None) def add(self, f): """Mark a file added.""" - self._addpath(f, "a", 0, -1, -1) + self._addpath(f, b"a", 0, -1, -1) self._map.copymap.pop(f, None) def remove(self, f): @@ -490,9 +490,9 @@ entry = self._map.get(f) if entry is not None: # backup the previous state - if entry[0] == "m": # merge + if entry[0] == b"m": # merge size = -1 - elif entry[0] == "n" and entry[2] == -2: # other parent + elif entry[0] == b"n" and entry[2] == -2: # other parent size = -2 self._map.otherparentset.add(f) self._updatedfiles.add(f) @@ -519,21 +519,21 @@ exists = os.path.lexists(os.path.join(self._root, path)) if not exists: # Maybe a path component exists - if not ignoremissing and "/" in path: - d, f = path.rsplit("/", 1) + if not ignoremissing and b"/" in path: + d, f = path.rsplit(b"/", 1) d = self._normalize(d, False, ignoremissing, None) - folded = d + "/" + f + folded = d + b"/" + f else: # No path components, preserve original case folded = path else: # recursively normalize leading directory components # against dirstate - if "/" in normed: - d, f = normed.rsplit("/", 1) + if b"/" in normed: + d, f = normed.rsplit(b"/", 1) d = self._normalize(d, False, ignoremissing, True) - r = self._root + "/" + d - folded = d + "/" + util.fspath(f, r) + r = self._root + b"/" + d + folded = d + b"/" + util.fspath(f, r) else: folded = util.fspath(normed, self._root) storemap[normed] = folded @@ -645,14 +645,14 @@ # delay writing in-memory changes out tr.addfilegenerator( - "dirstate", + b"dirstate", (self._filename,), self._writedirstate, - location="plain", + location=b"plain", ) return - st = self._opener(filename, "w", atomictemp=True, checkambig=True) + st = self._opener(filename, b"w", atomictemp=True, checkambig=True) self._writedirstate(st) def addparentchangecallback(self, category, callback): @@ -678,12 +678,12 @@ # enough 'delaywrite' prevents 'pack_dirstate' from dropping # timestamp of each entries in dirstate, because of 'now > mtime' - delaywrite = self._ui.configint("debug", "dirstate.delaywrite") + delaywrite = self._ui.configint(b"debug", b"dirstate.delaywrite") if delaywrite > 0: # do we have any files to delay for? items = self._map.iteritems() for f, e in items: - if e[0] == "n" and e[3] == now: + if e[0] == b"n" and e[3] == now: import time # to avoid useless import # rather than sleep n seconds, sleep until the next @@ -715,10 +715,10 @@ def _ignorefiles(self): files = [] - if os.path.exists(self._join(".hgignore")): - files.append(self._join(".hgignore")) - for name, path in self._ui.configitems("ui"): - if name == "ignore" or name.startswith("ignore."): + if os.path.exists(self._join(b".hgignore")): + files.append(self._join(b".hgignore")) + for name, path in self._ui.configitems(b"ui"): + if name == b"ignore" or name.startswith(b"ignore."): # we need to use os.path.join here rather than self._join # because path is arbitrary and user-specified files.append(os.path.join(self._rootdir, util.expandpath(path))) @@ -733,18 +733,18 @@ i, self._ui.warn, sourceinfo=True ) for pattern, lineno, line in patterns: - kind, p = matchmod._patsplit(pattern, "glob") - if kind == "subinclude": + kind, p = matchmod._patsplit(pattern, b"glob") + if kind == b"subinclude": if p not in visited: files.append(p) continue m = matchmod.match( - self._root, "", [], [pattern], warn=self._ui.warn + self._root, b"", [], [pattern], warn=self._ui.warn ) if m(f): return (i, lineno, line) visited.add(i) - return (None, -1, "") + return (None, -1, b"") def _walkexplicit(self, match, subrepos): """Get stat data about the files explicitly specified by match. @@ -757,18 +757,18 @@ directories and that were not found.""" def badtype(mode): - kind = _("unknown") + kind = _(b"unknown") if stat.S_ISCHR(mode): - kind = _("character device") + kind = _(b"character device") elif stat.S_ISBLK(mode): - kind = _("block device") + kind = _(b"block device") elif stat.S_ISFIFO(mode): - kind = _("fifo") + kind = _(b"fifo") elif stat.S_ISSOCK(mode): - kind = _("socket") + kind = _(b"socket") elif stat.S_ISDIR(mode): - kind = _("directory") - return _("unsupported file type (type is %s)") % kind + kind = _(b"directory") + return _(b"unsupported file type (type is %s)") % kind matchedir = match.explicitdir badfn = match.bad @@ -793,7 +793,7 @@ subrepos.sort() i, j = 0, 0 while i < len(files) and j < len(subrepos): - subpath = subrepos[j] + "/" + subpath = subrepos[j] + b"/" if files[i] < subpath: i += 1 continue @@ -801,13 +801,13 @@ del files[i] j += 1 - if not files or "" in files: - files = [""] + if not files or b"" in files: + files = [b""] # constructing the foldmap is expensive, so don't do it for the # common case where files is [''] normalize = None results = dict.fromkeys(subrepos) - results[".hg"] = None + results[b".hg"] = None for ff in files: if normalize: @@ -849,7 +849,7 @@ # aren't filtered here because they will be tested later. if match.anypats(): for f in list(results): - if f == ".hg" or f in subrepos: + if f == b".hg" or f in subrepos: # keep sentinel to disable further out-of-repo walks continue if not match(f): @@ -952,11 +952,11 @@ visitentries = match.visitchildrenset(nd) if not visitentries: continue - if visitentries == "this" or visitentries == "all": + if visitentries == b"this" or visitentries == b"all": visitentries = None skip = None - if nd != "": - skip = ".hg" + if nd != b"": + skip = b".hg" try: entries = listdir(join(nd), stat=True, skip=skip) except OSError as inst: @@ -982,10 +982,10 @@ # interested in comparing it to files currently in the # dmap -- therefore normalizefile is enough nf = normalizefile( - nd and (nd + "/" + f) or f, True, True + nd and (nd + b"/" + f) or f, True, True ) else: - nf = nd and (nd + "/" + f) or f + nf = nd and (nd + b"/" + f) or f if nf not in results: if kind == dirkind: if not ignore(nf): @@ -1016,7 +1016,7 @@ for s in subrepos: del results[s] - del results[".hg"] + del results[b".hg"] # step 3: visit remaining files from dmap if not skipstep3 and not exact: @@ -1134,9 +1134,9 @@ size = t[2] time = t[3] - if not st and state in "nma": + if not st and state in b"nma": dadd(fn) - elif state == "n": + elif state == b"n": if ( size >= 0 and ( @@ -1160,11 +1160,11 @@ ladd(fn) elif listclean: cadd(fn) - elif state == "m": + elif state == b"m": madd(fn) - elif state == "a": + elif state == b"a": aadd(fn) - elif state == "r": + elif state == b"r": radd(fn) return ( @@ -1208,7 +1208,7 @@ # output file will be used to create backup of dirstate at this point. if self._dirty or not self._opener.exists(filename): self._writedirstate( - self._opener(filename, "w", atomictemp=True, checkambig=True) + self._opener(filename, b"w", atomictemp=True, checkambig=True) ) if tr: @@ -1216,16 +1216,16 @@ # changes written out above, even if dirstate is never # changed after this tr.addfilegenerator( - "dirstate", + b"dirstate", (self._filename,), self._writedirstate, - location="plain", + location=b"plain", ) # ensure that pending file written above is unlinked at # failure, even if tr.writepending isn't invoked until the # end of this transaction - tr.registertmp(filename, location="plain") + tr.registertmp(filename, location=b"plain") self._opener.tryunlink(backupname) # hardlink backup is okay because _writedirstate is always called @@ -1291,7 +1291,7 @@ self._ui = ui self._opener = opener self._root = root - self._filename = "dirstate" + self._filename = b"dirstate" self._parents = None self._dirtyparents = False @@ -1315,12 +1315,12 @@ self._map.clear() self.copymap.clear() self.setparents(nullid, nullid) - util.clearcachedproperty(self, "_dirs") - util.clearcachedproperty(self, "_alldirs") - util.clearcachedproperty(self, "filefoldmap") - util.clearcachedproperty(self, "dirfoldmap") - util.clearcachedproperty(self, "nonnormalset") - util.clearcachedproperty(self, "otherparentset") + util.clearcachedproperty(self, b"_dirs") + util.clearcachedproperty(self, b"_alldirs") + util.clearcachedproperty(self, b"filefoldmap") + util.clearcachedproperty(self, b"dirfoldmap") + util.clearcachedproperty(self, b"nonnormalset") + util.clearcachedproperty(self, b"otherparentset") def items(self): return self._map.iteritems() @@ -1352,12 +1352,12 @@ def addfile(self, f, oldstate, state, mode, size, mtime): """Add a tracked file to the dirstate.""" - if oldstate in "?r" and r"_dirs" in self.__dict__: + if oldstate in b"?r" and r"_dirs" in self.__dict__: self._dirs.addpath(f) - if oldstate == "?" and r"_alldirs" in self.__dict__: + if oldstate == b"?" and r"_alldirs" in self.__dict__: self._alldirs.addpath(f) self._map[f] = dirstatetuple(state, mode, size, mtime) - if state != "n" or mtime == -1: + if state != b"n" or mtime == -1: self.nonnormalset.add(f) if size == -2: self.otherparentset.add(f) @@ -1370,14 +1370,14 @@ the file's previous state. In the future, we should refactor this to be more explicit about what that state is. """ - if oldstate not in "?r" and r"_dirs" in self.__dict__: + if oldstate not in b"?r" and r"_dirs" in self.__dict__: self._dirs.delpath(f) - if oldstate == "?" and r"_alldirs" in self.__dict__: + if oldstate == b"?" and r"_alldirs" in self.__dict__: self._alldirs.addpath(f) if r"filefoldmap" in self.__dict__: normed = util.normcase(f) self.filefoldmap.pop(normed, None) - self._map[f] = dirstatetuple("r", 0, size, 0) + self._map[f] = dirstatetuple(b"r", 0, size, 0) self.nonnormalset.add(f) def dropfile(self, f, oldstate): @@ -1387,7 +1387,7 @@ """ exists = self._map.pop(f, None) is not None if exists: - if oldstate != "r" and r"_dirs" in self.__dict__: + if oldstate != b"r" and r"_dirs" in self.__dict__: self._dirs.delpath(f) if r"_alldirs" in self.__dict__: self._alldirs.delpath(f) @@ -1400,7 +1400,7 @@ def clearambiguoustimes(self, files, now): for f in files: e = self.get(f) - if e is not None and e[0] == "n" and e[3] == now: + if e is not None and e[0] == b"n" and e[3] == now: self._map[f] = dirstatetuple(e[0], e[1], e[2], -1) self.nonnormalset.add(f) @@ -1412,9 +1412,9 @@ nonnorm = set() otherparent = set() for fname, e in self._map.iteritems(): - if e[0] != "n" or e[3] == -1: + if e[0] != b"n" or e[3] == -1: nonnorm.add(fname) - if e[0] == "n" and e[2] == -2: + if e[0] == b"n" and e[2] == -2: otherparent.add(fname) return nonnorm, otherparent @@ -1435,9 +1435,9 @@ f = {} normcase = util.normcase for name, s in self._map.iteritems(): - if s[0] != "r": + if s[0] != b"r": f[normcase(name)] = name - f["."] = "." # prevents useless util.fspath() invocation + f[b"."] = b"." # prevents useless util.fspath() invocation return f def hastrackeddir(self, d): @@ -1456,7 +1456,7 @@ @propertycache def _dirs(self): - return util.dirs(self._map, "r") + return util.dirs(self._map, b"r") @propertycache def _alldirs(self): @@ -1467,7 +1467,7 @@ if self._pendingmode is not None and self._pendingmode != mode: fp.close() raise error.Abort( - _("working directory state may be " "changed parallelly") + _(b"working directory state may be " b"changed parallelly") ) self._pendingmode = mode return fp @@ -1482,7 +1482,7 @@ if err.errno != errno.ENOENT: raise # File doesn't exist, so the current state is empty - st = "" + st = b"" l = len(st) if l == 40: @@ -1491,7 +1491,7 @@ self._parents = (nullid, nullid) else: raise error.Abort( - _("working directory state appears " "damaged!") + _(b"working directory state appears " b"damaged!") ) return self._parents @@ -1519,7 +1519,7 @@ if not st: return - if util.safehasattr(parsers, "dict_new_presized"): + if util.safehasattr(parsers, b"dict_new_presized"): # Make an estimate of the number of files in the dirstate based on # its size. From a linear regression on a set of real-world repos, # all over 10,000 files, the size of a dirstate entry is 85 @@ -1595,7 +1595,7 @@ self._ui = ui self._opener = opener self._root = root - self._filename = "dirstate" + self._filename = b"dirstate" self._parents = None self._dirtyparents = False @@ -1636,9 +1636,9 @@ def clear(self): self._rustmap.clear() self.setparents(nullid, nullid) - util.clearcachedproperty(self, "_dirs") - util.clearcachedproperty(self, "_alldirs") - util.clearcachedproperty(self, "dirfoldmap") + util.clearcachedproperty(self, b"_dirs") + util.clearcachedproperty(self, b"_alldirs") + util.clearcachedproperty(self, b"dirfoldmap") def items(self): return self._rustmap.items() @@ -1668,7 +1668,7 @@ if self._pendingmode is not None and self._pendingmode != mode: fp.close() raise error.Abort( - _("working directory state may be " "changed parallelly") + _(b"working directory state may be " b"changed parallelly") ) self._pendingmode = mode return fp @@ -1688,13 +1688,13 @@ if err.errno != errno.ENOENT: raise # File doesn't exist, so the current state is empty - st = "" + st = b"" try: self._parents = self._rustmap.parents(st) except ValueError: raise error.Abort( - _("working directory state appears " "damaged!") + _(b"working directory state appears " b"damaged!") ) return self._parents diff --git a/mercurial/dirstateguard.py b/mercurial/dirstateguard.py --- a/mercurial/dirstateguard.py +++ b/mercurial/dirstateguard.py @@ -34,8 +34,8 @@ self._repo = repo self._active = False self._closed = False - self._backupname = "dirstate.backup.%s.%d" % (name, id(self)) - self._narrowspecbackupname = "narrowspec.backup.%s.%d" % ( + self._backupname = b"dirstate.backup.%s.%d" % (name, id(self)) + self._narrowspecbackupname = b"narrowspec.backup.%s.%d" % ( name, id(self), ) @@ -54,7 +54,7 @@ def close(self): if not self._active: # already inactivated msg = ( - _("can't close already inactivated backup: %s") + _(b"can't close already inactivated backup: %s") % self._backupname ) raise error.Abort(msg) @@ -77,7 +77,7 @@ if not self._closed: if not self._active: # already inactivated msg = ( - _("can't release already inactivated backup: %s") + _(b"can't release already inactivated backup: %s") % self._backupname ) raise error.Abort(msg) diff --git a/mercurial/discovery.py b/mercurial/discovery.py --- a/mercurial/discovery.py +++ b/mercurial/discovery.py @@ -50,7 +50,7 @@ extensions a good hook into outgoing. """ - if not remote.capable("getbundle"): + if not remote.capable(b"getbundle"): return treediscovery.findcommonincoming(repo, remote, heads, force) if heads: @@ -162,8 +162,8 @@ og.missingheads = onlyheads or repo.heads() elif onlyheads is None: # use visible heads as it should be cached - og.missingheads = repo.filtered("served").heads() - og.excluded = [ctx.node() for ctx in repo.set("secret() or extinct()")] + og.missingheads = repo.filtered(b"served").heads() + og.excluded = [ctx.node() for ctx in repo.set(b"secret() or extinct()")] else: # compute common, missing and exclude secret stuff sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads) @@ -222,7 +222,7 @@ branches.add(ctx.branch()) with remote.commandexecutor() as e: - remotemap = e.callcommand("branchmap", {}).result() + remotemap = e.callcommand(b"branchmap", {}).result() knownnode = cl.hasnode # do not use nodemap until it is filtered # A. register remote heads of branches which are in outgoing set @@ -291,7 +291,7 @@ # - another element of outgoing.missing # - nullrev # This explains why the new head are very simple to compute. - r = repo.set("heads(%ln + %ln)", oldheads, outgoing.missing) + r = repo.set(b"heads(%ln + %ln)", oldheads, outgoing.missing) newheads = sorted(c.node() for c in r) # set some unsynced head to issue the "unsynced changes" warning if inc: @@ -309,7 +309,7 @@ with remote.commandexecutor() as e: remotebookmarks = e.callcommand( - "listkeys", {"namespace": "bookmarks",} + b"listkeys", {b"namespace": b"bookmarks",} ).result() bookmarkedheads = set() @@ -317,7 +317,7 @@ # internal config: bookmarks.pushing newbookmarks = [ localbookmarks.expandname(b) - for b in pushop.ui.configlist("bookmarks", "pushing") + for b in pushop.ui.configlist(b"bookmarks", b"pushing") ] for bm in localbookmarks: @@ -356,7 +356,7 @@ # remote is empty, nothing to check. return - if remote.capable("branchmap"): + if remote.capable(b"branchmap"): headssum = _headssummary(pushop) else: headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) @@ -366,7 +366,7 @@ ] # 1. Check for new branches on the remote. if newbranches and not newbranch: # new branch requires --new-branch - branchnames = ", ".join(sorted(newbranches)) + branchnames = b", ".join(sorted(newbranches)) # Calculate how many of the new branches are closed branches closedbranches = set() for tag, heads, tip, isclosed in repo.branchmap().iterbranches(): @@ -374,13 +374,13 @@ closedbranches.add(tag) closedbranches = closedbranches & set(newbranches) if closedbranches: - errmsg = _("push creates new remote branches: %s (%d closed)!") % ( + errmsg = _(b"push creates new remote branches: %s (%d closed)!") % ( branchnames, len(closedbranches), ) else: - errmsg = _("push creates new remote branches: %s!") % branchnames - hint = _("use 'hg push --new-branch' to create new remote branches") + errmsg = _(b"push creates new remote branches: %s!") % branchnames + hint = _(b"use 'hg push --new-branch' to create new remote branches") raise error.Abort(errmsg, hint=hint) # 2. Find heads that we need not warn about @@ -409,18 +409,18 @@ heads = scmutil.nodesummaries(repo, unsyncedheads) if heads is None: repo.ui.status( - _("remote has heads that are " "not known locally\n") + _(b"remote has heads that are " b"not known locally\n") ) elif branch is None: repo.ui.status( - _("remote has heads that are " "not known locally: %s\n") + _(b"remote has heads that are " b"not known locally: %s\n") % heads ) else: repo.ui.status( _( - "remote has heads on branch '%s' that are " - "not known locally: %s\n" + b"remote has heads on branch '%s' that are " + b"not known locally: %s\n" ) % (branch, heads) ) @@ -429,49 +429,50 @@ dhs = list(newhs) if errormsg is None: errormsg = ( - _("push creates new branch '%s' with multiple heads") + _(b"push creates new branch '%s' with multiple heads") % branch ) hint = _( - "merge or" - " see 'hg help push' for details about" - " pushing new heads" + b"merge or" + b" see 'hg help push' for details about" + b" pushing new heads" ) elif len(newhs) > len(oldhs): # remove bookmarked or existing remote heads from the new heads list dhs = sorted(newhs - nowarnheads - oldhs) if dhs: if errormsg is None: - if branch not in ("default", None): + if branch not in (b"default", None): errormsg = _( - "push creates new remote head %s " "on branch '%s'!" + b"push creates new remote head %s " b"on branch '%s'!" ) % (short(dhs[0]), branch) elif repo[dhs[0]].bookmarks(): errormsg = _( - "push creates new remote head %s " "with bookmark '%s'!" + b"push creates new remote head %s " + b"with bookmark '%s'!" ) % (short(dhs[0]), repo[dhs[0]].bookmarks()[0]) else: - errormsg = _("push creates new remote head %s!") % short( + errormsg = _(b"push creates new remote head %s!") % short( dhs[0] ) if unsyncedheads: hint = _( - "pull and merge or" - " see 'hg help push' for details about" - " pushing new heads" + b"pull and merge or" + b" see 'hg help push' for details about" + b" pushing new heads" ) else: hint = _( - "merge or" - " see 'hg help push' for details about" - " pushing new heads" + b"merge or" + b" see 'hg help push' for details about" + b" pushing new heads" ) if branch is None: - repo.ui.note(_("new remote heads:\n")) + repo.ui.note(_(b"new remote heads:\n")) else: - repo.ui.note(_("new remote heads on branch '%s':\n") % branch) + repo.ui.note(_(b"new remote heads on branch '%s':\n") % branch) for h in dhs: - repo.ui.note(" %s\n" % short(h)) + repo.ui.note(b" %s\n" % short(h)) if errormsg: raise error.Abort(errormsg, hint=hint) @@ -513,8 +514,8 @@ else: if successorsmarkers.get(h) is not None: msg = ( - "checkheads: remote head unknown locally has" - " local marker: %s\n" + b"checkheads: remote head unknown locally has" + b" local marker: %s\n" ) repo.ui.debug(msg % hex(h)) unknownheads.add(h) @@ -533,7 +534,9 @@ # Get all revs/nodes on the branch exclusive to this head # (already filtered heads are "ignored")) - branchrevs = unfi.revs("only(%n, (%ln+%ln))", nh, localcandidate, newhs) + branchrevs = unfi.revs( + b"only(%n, (%ln+%ln))", nh, localcandidate, newhs + ) branchnodes = [tonode(r) for r in branchrevs] # The branch won't be hidden on the remote if diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -93,7 +93,7 @@ except: # re-raises below if exc is None: exc = sys.exc_info()[1] - self.ui.warn("error in exit handlers:\n") + self.ui.warn(b"error in exit handlers:\n") self.ui.traceback(force=True) finally: if exc is not None: @@ -101,9 +101,9 @@ def run(): - "run the command in sys.argv" + b"run the command in sys.argv" initstdio() - with tracing.log("parse args into request"): + with tracing.log(b"parse args into request"): req = request(pycompat.sysargv[1:]) err = None try: @@ -113,18 +113,18 @@ status = -1 # In all cases we try to flush stdio streams. - if util.safehasattr(req.ui, "fout"): + if util.safehasattr(req.ui, b"fout"): try: req.ui.fout.flush() except IOError as e: err = e status = -1 - if util.safehasattr(req.ui, "ferr"): + if util.safehasattr(req.ui, b"ferr"): try: if err is not None and err.errno != errno.EPIPE: req.ui.ferr.write( - "abort: %s\n" % encoding.strtolocal(err.strerror) + b"abort: %s\n" % encoding.strtolocal(err.strerror) ) req.ui.ferr.flush() # There's not much we can do about an I/O error here. So (possibly) @@ -178,10 +178,10 @@ def _reportsimilar(write, similar): if len(similar) == 1: - write(_("(did you mean %s?)\n") % similar[0]) + write(_(b"(did you mean %s?)\n") % similar[0]) elif similar: - ss = ", ".join(sorted(similar)) - write(_("(did you mean one of %s?)\n") % ss) + ss = b", ".join(sorted(similar)) + write(_(b"(did you mean one of %s?)\n") % ss) def _formatparse(write, inst): @@ -191,25 +191,25 @@ similar = _getsimilar(inst.symbols, inst.function) if len(inst.args) > 1: write( - _("hg: parse error at %s: %s\n") + _(b"hg: parse error at %s: %s\n") % (pycompat.bytestr(inst.args[1]), inst.args[0]) ) - if inst.args[0].startswith(" "): - write(_("unexpected leading whitespace\n")) + if inst.args[0].startswith(b" "): + write(_(b"unexpected leading whitespace\n")) else: - write(_("hg: parse error: %s\n") % inst.args[0]) + write(_(b"hg: parse error: %s\n") % inst.args[0]) _reportsimilar(write, similar) if inst.hint: - write(_("(%s)\n") % inst.hint) + write(_(b"(%s)\n") % inst.hint) def _formatargs(args): - return " ".join(procutil.shellquote(a) for a in args) + return b" ".join(procutil.shellquote(a) for a in args) def dispatch(req): """run the command specified in req.args; returns an integer status code""" - with tracing.log("dispatch.dispatch"): + with tracing.log(b"dispatch.dispatch"): if req.ferr: ferr = req.ferr elif req.ui: @@ -221,8 +221,8 @@ if not req.ui: req.ui = uimod.ui.load() req.earlyoptions.update(_earlyparseopts(req.ui, req.args)) - if req.earlyoptions["traceback"]: - req.ui.setconfig("ui", "traceback", "on", "--traceback") + if req.earlyoptions[b"traceback"]: + req.ui.setconfig(b"ui", b"traceback", b"on", b"--traceback") # set ui streams from the request if req.fin: @@ -234,9 +234,9 @@ if req.fmsg: req.ui.fmsg = req.fmsg except error.Abort as inst: - ferr.write(_("abort: %s\n") % inst) + ferr.write(_(b"abort: %s\n") % inst) if inst.hint: - ferr.write(_("(%s)\n") % inst.hint) + ferr.write(_(b"(%s)\n") % inst.hint) return -1 except error.ParseError as inst: _formatparse(ferr.write, inst) @@ -248,16 +248,16 @@ try: ret = _runcatch(req) or 0 except error.ProgrammingError as inst: - req.ui.error(_("** ProgrammingError: %s\n") % inst) + req.ui.error(_(b"** ProgrammingError: %s\n") % inst) if inst.hint: - req.ui.error(_("** (%s)\n") % inst.hint) + req.ui.error(_(b"** (%s)\n") % inst.hint) raise except KeyboardInterrupt as inst: try: if isinstance(inst, error.SignalInterrupt): - msg = _("killed!\n") + msg = _(b"killed!\n") else: - msg = _("interrupted!\n") + msg = _(b"interrupted!\n") req.ui.error(msg) except error.SignalInterrupt: # maybe pager would quit without consuming all the output, and @@ -271,16 +271,16 @@ duration = util.timer() - starttime req.ui.flush() if req.ui.logblockedtimes: - req.ui._blockedtimes["command_duration"] = duration * 1000 + req.ui._blockedtimes[b"command_duration"] = duration * 1000 req.ui.log( - "uiblocked", - "ui blocked ms\n", + b"uiblocked", + b"ui blocked ms\n", **pycompat.strkwargs(req.ui._blockedtimes) ) return_code = ret & 255 req.ui.log( - "commandfinish", - "%s exited %d after %0.2f seconds\n", + b"commandfinish", + b"%s exited %d after %0.2f seconds\n", msg, return_code, duration, @@ -296,14 +296,14 @@ def _runcatch(req): - with tracing.log("dispatch._runcatch"): + with tracing.log(b"dispatch._runcatch"): def catchterm(*args): raise error.SignalInterrupt ui = req.ui try: - for name in "SIGBREAK", "SIGHUP", "SIGTERM": + for name in b"SIGBREAK", b"SIGHUP", b"SIGTERM": num = getattr(signal, name, None) if num: signal.signal(num, catchterm) @@ -330,7 +330,7 @@ # it's not a command that server operators expect to # be safe to offer to users in a sandbox. pass - if realcmd == "serve" and "--stdio" in cmdargs: + if realcmd == b"serve" and b"--stdio" in cmdargs: # We want to constrain 'hg serve --stdio' instances pretty # closely, as many shared-ssh access tools want to grant # access to run *only* 'hg -R $repo serve --stdio'. We @@ -341,38 +341,40 @@ # name. This used to actually run the debugger. if ( len(req.args) != 4 - or req.args[0] != "-R" - or req.args[1].startswith("--") - or req.args[2] != "serve" - or req.args[3] != "--stdio" + or req.args[0] != b"-R" + or req.args[1].startswith(b"--") + or req.args[2] != b"serve" + or req.args[3] != b"--stdio" ): raise error.Abort( - _("potentially unsafe serve --stdio invocation: %s") + _(b"potentially unsafe serve --stdio invocation: %s") % (stringutil.pprint(req.args),) ) try: - debugger = "pdb" - debugtrace = {"pdb": pdb.set_trace} - debugmortem = {"pdb": pdb.post_mortem} + debugger = b"pdb" + debugtrace = {b"pdb": pdb.set_trace} + debugmortem = {b"pdb": pdb.post_mortem} # read --config before doing anything else # (e.g. to change trust settings for reading .hg/hgrc) - cfgs = _parseconfig(req.ui, req.earlyoptions["config"]) + cfgs = _parseconfig(req.ui, req.earlyoptions[b"config"]) if req.repo: # copy configs that were passed on the cmdline (--config) to # the repo ui for sec, name, val in cfgs: - req.repo.ui.setconfig(sec, name, val, source="--config") + req.repo.ui.setconfig( + sec, name, val, source=b"--config" + ) # developer config: ui.debugger - debugger = ui.config("ui", "debugger") + debugger = ui.config(b"ui", b"debugger") debugmod = pdb if not debugger or ui.plain(): # if we are in HGPLAIN mode, then disable custom debugging - debugger = "pdb" - elif req.earlyoptions["debugger"]: + debugger = b"pdb" + elif req.earlyoptions[b"debugger"]: # This import can be slow for fancy debuggers, so only # do it when absolutely necessary, i.e. when actual # debugging has been requested @@ -386,22 +388,22 @@ debugmortem[debugger] = debugmod.post_mortem # enter the debugger before command execution - if req.earlyoptions["debugger"]: + if req.earlyoptions[b"debugger"]: ui.warn( _( - "entering debugger - " - "type c to continue starting hg or h for help\n" + b"entering debugger - " + b"type c to continue starting hg or h for help\n" ) ) if ( - debugger != "pdb" - and debugtrace[debugger] == debugtrace["pdb"] + debugger != b"pdb" + and debugtrace[debugger] == debugtrace[b"pdb"] ): ui.warn( _( - "%s debugger specified " - "but its module was not found\n" + b"%s debugger specified " + b"but its module was not found\n" ) % debugger ) @@ -413,7 +415,7 @@ ui.flush() except: # re-raises # enter the debugger when we hit an exception - if req.earlyoptions["debugger"]: + if req.earlyoptions[b"debugger"]: traceback.print_exc() debugmortem[debugger](sys.exc_info()[2]) raise @@ -430,23 +432,23 @@ return scmutil.callcatch(ui, func) except error.AmbiguousCommand as inst: ui.warn( - _("hg: command '%s' is ambiguous:\n %s\n") - % (inst.args[0], " ".join(inst.args[1])) + _(b"hg: command '%s' is ambiguous:\n %s\n") + % (inst.args[0], b" ".join(inst.args[1])) ) except error.CommandError as inst: if inst.args[0]: - ui.pager("help") + ui.pager(b"help") msgbytes = pycompat.bytestr(inst.args[1]) - ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes)) + ui.warn(_(b"hg %s: %s\n") % (inst.args[0], msgbytes)) commands.help_(ui, inst.args[0], full=False, command=True) else: - ui.warn(_("hg: %s\n") % inst.args[1]) - ui.warn(_("(use 'hg help -v' for a list of global options)\n")) + ui.warn(_(b"hg: %s\n") % inst.args[1]) + ui.warn(_(b"(use 'hg help -v' for a list of global options)\n")) except error.ParseError as inst: _formatparse(ui.warn, inst) return -1 except error.UnknownCommand as inst: - nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0] + nocmdmsg = _(b"hg: unknown command '%s'\n") % inst.args[0] try: # check if the command is in a disabled extension # (but don't check for extensions themselves) @@ -465,7 +467,7 @@ suggested = True if not suggested: ui.warn(nocmdmsg) - ui.warn(_("(use 'hg help' for a list of commands)\n")) + ui.warn(_(b"(use 'hg help' for a list of commands)\n")) except IOError: raise except KeyboardInterrupt: @@ -480,10 +482,10 @@ def aliasargs(fn, givenargs): args = [] # only care about alias 'args', ignore 'args' set by extensions.wrapfunction - if not util.safehasattr(fn, "_origfunc"): + if not util.safehasattr(fn, b"_origfunc"): args = getattr(fn, "args", args) if args: - cmd = " ".join(map(procutil.shellquote, args)) + cmd = b" ".join(map(procutil.shellquote, args)) nums = [] @@ -492,7 +494,7 @@ nums.append(num) if num < len(givenargs): return givenargs[num] - raise error.Abort(_("too few arguments for command alias")) + raise error.Abort(_(b"too few arguments for command alias")) cmd = re.sub(br"\$(\d+|\$)", replacer, cmd) givenargs = [x for i, x in enumerate(givenargs) if i not in nums] @@ -507,17 +509,17 @@ """ # util.interpolate can't deal with "$@" (with quotes) because it's only # built to match prefix + patterns. - replacemap = dict(("$%d" % (i + 1), arg) for i, arg in enumerate(args)) - replacemap["$0"] = name - replacemap["$$"] = "$" - replacemap["$@"] = " ".join(args) + replacemap = dict((b"$%d" % (i + 1), arg) for i, arg in enumerate(args)) + replacemap[b"$0"] = name + replacemap[b"$$"] = b"$" + replacemap[b"$@"] = b" ".join(args) # Typical Unix shells interpolate "$@" (with quotes) as all the positional # parameters, separated out into words. Emulate the same behavior here by # quoting the arguments individually. POSIX shells will then typically # tokenize each argument into exactly one word. - replacemap['"$@"'] = " ".join(procutil.shellquote(arg) for arg in args) + replacemap[b'"$@"'] = b" ".join(procutil.shellquote(arg) for arg in args) # escape '\$' for regex - regex = "|".join(replacemap.keys()).replace("$", br"\$") + regex = b"|".join(replacemap.keys()).replace(b"$", br"\$") r = re.compile(regex) return r.sub(lambda x: replacemap[x.group()], cmd) @@ -525,12 +527,12 @@ class cmdalias(object): def __init__(self, ui, name, definition, cmdtable, source): self.name = self.cmd = name - self.cmdname = "" + self.cmdname = b"" self.definition = definition self.fn = None self.givenargs = [] self.opts = [] - self.help = "" + self.help = b"" self.badalias = None self.unknowncmd = False self.source = source @@ -546,33 +548,33 @@ self.shadows = False if not self.definition: - self.badalias = _("no definition for alias '%s'") % self.name + self.badalias = _(b"no definition for alias '%s'") % self.name return - if self.definition.startswith("!"): + if self.definition.startswith(b"!"): shdef = self.definition[1:] self.shell = True def fn(ui, *args): - env = {"HG_ARGS": " ".join((self.name,) + args)} + env = {b"HG_ARGS": b" ".join((self.name,) + args)} def _checkvar(m): - if m.groups()[0] == "$": + if m.groups()[0] == b"$": return m.group() elif int(m.groups()[0]) <= len(args): return m.group() else: ui.debug( - "No argument found for substitution " - "of %i variable in alias '%s' definition.\n" + b"No argument found for substitution " + b"of %i variable in alias '%s' definition.\n" % (int(m.groups()[0]), self.name) ) - return "" + return b"" cmd = re.sub(br"\$(\d+|\$)", _checkvar, shdef) cmd = aliasinterpolate(self.name, args, cmd) return ui.system( - cmd, environ=env, blockedtag="alias_%s" % self.name + cmd, environ=env, blockedtag=b"alias_%s" % self.name ) self.fn = fn @@ -583,7 +585,7 @@ try: args = pycompat.shlexsplit(self.definition) except ValueError as inst: - self.badalias = _("error in definition for alias '%s': %s") % ( + self.badalias = _(b"error in definition for alias '%s': %s") % ( self.name, stringutil.forcebytestr(inst), ) @@ -591,9 +593,9 @@ earlyopts, args = _earlysplitopts(args) if earlyopts: self.badalias = _( - "error in definition for alias '%s': %s may " - "only be given on the command line" - ) % (self.name, "/".join(pycompat.ziplist(*earlyopts)[0])) + b"error in definition for alias '%s': %s may " + b"only be given on the command line" + ) % (self.name, b"/".join(pycompat.ziplist(*earlyopts)[0])) return self.cmdname = cmd = args.pop(0) self.givenargs = args @@ -610,42 +612,43 @@ self._populatehelp(ui, name, cmd, self.fn, cmdhelp) except error.UnknownCommand: - self.badalias = _("alias '%s' resolves to unknown command '%s'") % ( - self.name, - cmd, - ) + self.badalias = _( + b"alias '%s' resolves to unknown command '%s'" + ) % (self.name, cmd,) self.unknowncmd = True except error.AmbiguousCommand: self.badalias = _( - "alias '%s' resolves to ambiguous command '%s'" + b"alias '%s' resolves to ambiguous command '%s'" ) % (self.name, cmd) def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None): # confine strings to be passed to i18n.gettext() cfg = {} - for k in ("doc", "help", "category"): - v = ui.config("alias", "%s:%s" % (name, k), None) + for k in (b"doc", b"help", b"category"): + v = ui.config(b"alias", b"%s:%s" % (name, k), None) if v is None: continue if not encoding.isasciistr(v): self.badalias = _( - "non-ASCII character in alias definition " "'%s:%s'" + b"non-ASCII character in alias definition " b"'%s:%s'" ) % (name, k) return cfg[k] = v - self.help = cfg.get("help", defaulthelp or "") - if self.help and self.help.startswith("hg " + cmd): + self.help = cfg.get(b"help", defaulthelp or b"") + if self.help and self.help.startswith(b"hg " + cmd): # drop prefix in old-style help lines so hg shows the alias self.help = self.help[4 + len(cmd) :] - self.owndoc = "doc" in cfg - doc = cfg.get("doc", pycompat.getdoc(fn)) + self.owndoc = b"doc" in cfg + doc = cfg.get(b"doc", pycompat.getdoc(fn)) if doc is not None: doc = pycompat.sysstr(doc) self.__doc__ = doc - self.helpcategory = cfg.get("category", registrar.command.CATEGORY_NONE) + self.helpcategory = cfg.get( + b"category", registrar.command.CATEGORY_NONE + ) @property def args(self): @@ -661,7 +664,7 @@ } if name not in adefaults: raise AttributeError(name) - if self.badalias or util.safehasattr(self, "shell"): + if self.badalias or util.safehasattr(self, b"shell"): return adefaults[name] return getattr(self.fn, name) @@ -672,29 +675,29 @@ try: # check if the command is in a disabled extension cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2] - hint = _("'%s' is provided by '%s' extension") % (cmd, ext) + hint = _(b"'%s' is provided by '%s' extension") % (cmd, ext) except error.UnknownCommand: pass raise error.Abort(self.badalias, hint=hint) if self.shadows: ui.debug( - "alias '%s' shadows command '%s'\n" % (self.name, self.cmdname) + b"alias '%s' shadows command '%s'\n" % (self.name, self.cmdname) ) ui.log( - "commandalias", - "alias '%s' expands to '%s'\n", + b"commandalias", + b"alias '%s' expands to '%s'\n", self.name, self.definition, ) - if util.safehasattr(self, "shell"): + if util.safehasattr(self, b"shell"): return self.fn(ui, *args, **opts) else: try: return util.checksignature(self.fn)(ui, *args, **opts) except error.SignatureError: - args = " ".join([self.cmdname] + self.args) - ui.debug("alias '%s' expands to '%s'\n" % (self.name, args)) + args = b" ".join([self.cmdname] + self.args) + ui.debug(b"alias '%s' expands to '%s'\n" % (self.name, args)) raise @@ -738,7 +741,7 @@ # aliases are processed after extensions have been loaded, so they # may use extension commands. Aliases can also use other alias definitions, # but only if they have been defined prior to the current definition. - for alias, definition in ui.configitems("alias", ignoresub=True): + for alias, definition in ui.configitems(b"alias", ignoresub=True): try: if cmdtable[alias].definition == definition: continue @@ -746,7 +749,7 @@ # definition might not exist or it might not be a cmdalias pass - source = ui.configsource("alias", alias) + source = ui.configsource(b"alias", alias) entry = lazyaliasentry(ui, alias, definition, cmdtable, source) cmdtable[alias] = entry @@ -763,11 +766,11 @@ if args: cmd, args = args[0], args[1:] aliases, entry = cmdutil.findcmd( - cmd, commands.table, ui.configbool("ui", "strict") + cmd, commands.table, ui.configbool(b"ui", b"strict") ) cmd = aliases[0] args = aliasargs(entry[0], args) - defaults = ui.config("defaults", cmd) + defaults = ui.config(b"defaults", cmd) if defaults: args = ( pycompat.maplist(util.expandpath, pycompat.shlexsplit(defaults)) @@ -802,17 +805,17 @@ for cfg in config: try: - name, value = [cfgelem.strip() for cfgelem in cfg.split("=", 1)] - section, name = name.split(".", 1) + name, value = [cfgelem.strip() for cfgelem in cfg.split(b"=", 1)] + section, name = name.split(b".", 1) if not section or not name: raise IndexError - ui.setconfig(section, name, value, "--config") + ui.setconfig(section, name, value, b"--config") configs.append((section, name, value)) except (IndexError, ValueError): raise error.Abort( _( - "malformed --config option: %r " - "(use --config section.name=value)" + b"malformed --config option: %r " + b"(use --config section.name=value)" ) % pycompat.bytestr(cfg) ) @@ -826,18 +829,18 @@ args, commands.globalopts, options, - gnu=not ui.plain("strictflags"), + gnu=not ui.plain(b"strictflags"), early=True, - optaliases={"repository": ["repo"]}, + optaliases={b"repository": [b"repo"]}, ) return options def _earlysplitopts(args): """Split args into a list of possible early options and remainder args""" - shortoptions = "R:" + shortoptions = b"R:" # TODO: perhaps 'debugger' should be included - longoptions = ["cwd=", "repository=", "repo=", "config="] + longoptions = [b"cwd=", b"repository=", b"repo=", b"config="] return fancyopts.earlygetopt( args, shortoptions, longoptions, gnu=True, keepsep=True ) @@ -848,9 +851,9 @@ hook.hook( lui, repo, - "pre-%s" % cmd, + b"pre-%s" % cmd, True, - args=" ".join(fullargs), + args=b" ".join(fullargs), pats=cmdpats, opts=cmdoptions, ) @@ -860,9 +863,9 @@ hook.hook( lui, repo, - "post-%s" % cmd, + b"post-%s" % cmd, False, - args=" ".join(fullargs), + args=b" ".join(fullargs), result=ret, pats=cmdpats, opts=cmdoptions, @@ -872,9 +875,9 @@ hook.hook( lui, repo, - "fail-%s" % cmd, + b"fail-%s" % cmd, False, - args=" ".join(fullargs), + args=b" ".join(fullargs), pats=cmdpats, opts=cmdoptions, ) @@ -892,20 +895,20 @@ wd = encoding.getcwd() except OSError as e: raise error.Abort( - _("error getting current working directory: %s") + _(b"error getting current working directory: %s") % encoding.strtolocal(e.strerror) ) - path = cmdutil.findrepo(wd) or "" + path = cmdutil.findrepo(wd) or b"" if not path: lui = ui else: lui = ui.copy() - lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) + lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) if rpath: path = lui.expandpath(rpath) lui = ui.copy() - lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) + lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) return path, lui @@ -926,7 +929,7 @@ cmd = args[0] try: - strict = ui.configbool("ui", "strict") + strict = ui.configbool(b"ui", b"strict") aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict) except (error.AmbiguousCommand, error.UnknownCommand): return @@ -934,7 +937,7 @@ cmd = aliases[0] fn = entry[0] - if cmd and util.safehasattr(fn, "shell"): + if cmd and util.safehasattr(fn, b"shell"): # shell alias shouldn't receive early options which are consumed by hg _earlyopts, args = _earlysplitopts(args) d = lambda: fn(ui, *args[1:]) @@ -948,11 +951,11 @@ ui = req.ui # check for cwd - cwd = req.earlyoptions["cwd"] + cwd = req.earlyoptions[b"cwd"] if cwd: os.chdir(cwd) - rpath = req.earlyoptions["repository"] + rpath = req.earlyoptions[b"repository"] path, lui = _getlocal(ui, rpath) uis = {ui, lui} @@ -961,20 +964,20 @@ uis.add(req.repo.ui) if ( - req.earlyoptions["verbose"] - or req.earlyoptions["debug"] - or req.earlyoptions["quiet"] + req.earlyoptions[b"verbose"] + or req.earlyoptions[b"debug"] + or req.earlyoptions[b"quiet"] ): - for opt in ("verbose", "debug", "quiet"): + for opt in (b"verbose", b"debug", b"quiet"): val = pycompat.bytestr(bool(req.earlyoptions[opt])) for ui_ in uis: - ui_.setconfig("ui", opt, val, "--" + opt) + ui_.setconfig(b"ui", opt, val, b"--" + opt) - if req.earlyoptions["profile"]: + if req.earlyoptions[b"profile"]: for ui_ in uis: - ui_.setconfig("profiling", "enabled", "true", "--profile") + ui_.setconfig(b"profiling", b"enabled", b"true", b"--profile") - profile = lui.configbool("profiling", "enabled") + profile = lui.configbool(b"profiling", b"enabled") with profiling.profile(lui, enabled=profile) as profiler: # Configure extensions in phases: uisetup, extsetup, cmdtable, and # reposetup @@ -998,7 +1001,7 @@ return shellaliasfn() # check for fallback encoding - fallback = lui.config("ui", "fallbackencoding") + fallback = lui.config(b"ui", b"fallbackencoding") if fallback: encoding.fallbackencoding = fallback @@ -1008,26 +1011,26 @@ # store the canonical command name in request object for later access req.canonical_command = cmd - if options["config"] != req.earlyoptions["config"]: - raise error.Abort(_("option --config may not be abbreviated!")) - if options["cwd"] != req.earlyoptions["cwd"]: - raise error.Abort(_("option --cwd may not be abbreviated!")) - if options["repository"] != req.earlyoptions["repository"]: + if options[b"config"] != req.earlyoptions[b"config"]: + raise error.Abort(_(b"option --config may not be abbreviated!")) + if options[b"cwd"] != req.earlyoptions[b"cwd"]: + raise error.Abort(_(b"option --cwd may not be abbreviated!")) + if options[b"repository"] != req.earlyoptions[b"repository"]: raise error.Abort( _( - "option -R has to be separated from other options (e.g. not " - "-qR) and --repository may only be abbreviated as --repo!" + b"option -R has to be separated from other options (e.g. not " + b"-qR) and --repository may only be abbreviated as --repo!" ) ) - if options["debugger"] != req.earlyoptions["debugger"]: - raise error.Abort(_("option --debugger may not be abbreviated!")) + if options[b"debugger"] != req.earlyoptions[b"debugger"]: + raise error.Abort(_(b"option --debugger may not be abbreviated!")) # don't validate --profile/--traceback, which can be enabled from now - if options["encoding"]: - encoding.encoding = options["encoding"] - if options["encodingmode"]: - encoding.encodingmode = options["encodingmode"] - if options["time"]: + if options[b"encoding"]: + encoding.encoding = options[b"encoding"] + if options[b"encodingmode"]: + encoding.encodingmode = options[b"encodingmode"] + if options[b"time"]: def get_times(): t = os.times() @@ -1041,7 +1044,7 @@ def print_time(): t = get_times() ui.warn( - _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") + _(b"time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") % ( t[4] - s[4], t[0] - s[0], @@ -1052,42 +1055,42 @@ ) ui.atexit(print_time) - if options["profile"]: + if options[b"profile"]: profiler.start() # if abbreviated version of this were used, take them in account, now - if options["verbose"] or options["debug"] or options["quiet"]: - for opt in ("verbose", "debug", "quiet"): + if options[b"verbose"] or options[b"debug"] or options[b"quiet"]: + for opt in (b"verbose", b"debug", b"quiet"): if options[opt] == req.earlyoptions[opt]: continue val = pycompat.bytestr(bool(options[opt])) for ui_ in uis: - ui_.setconfig("ui", opt, val, "--" + opt) + ui_.setconfig(b"ui", opt, val, b"--" + opt) - if options["traceback"]: + if options[b"traceback"]: for ui_ in uis: - ui_.setconfig("ui", "traceback", "on", "--traceback") + ui_.setconfig(b"ui", b"traceback", b"on", b"--traceback") - if options["noninteractive"]: + if options[b"noninteractive"]: for ui_ in uis: - ui_.setconfig("ui", "interactive", "off", "-y") + ui_.setconfig(b"ui", b"interactive", b"off", b"-y") - if cmdoptions.get("insecure", False): + if cmdoptions.get(b"insecure", False): for ui_ in uis: ui_.insecureconnections = True # setup color handling before pager, because setting up pager # might cause incorrect console information - coloropt = options["color"] + coloropt = options[b"color"] for ui_ in uis: if coloropt: - ui_.setconfig("ui", "color", coloropt, "--color") + ui_.setconfig(b"ui", b"color", coloropt, b"--color") color.setup(ui_) - if stringutil.parsebool(options["pager"]): + if stringutil.parsebool(options[b"pager"]): # ui.pager() expects 'internal-always-' prefix in this case - ui.pager("internal-always-" + cmd) - elif options["pager"] != "auto": + ui.pager(b"internal-always-" + cmd) + elif options[b"pager"] != b"auto": for ui_ in uis: ui_.disablepager() @@ -1095,12 +1098,12 @@ for ui_ in uis: extensions.populateui(ui_) - if options["version"]: + if options[b"version"]: return commands.version_(ui) - if options["help"]: + if options[b"help"]: return commands.help_(ui, cmd, command=cmd is not None) elif not cmd: - return commands.help_(ui, "shortlist") + return commands.help_(ui, b"shortlist") repo = None cmdpats = args[:] @@ -1125,10 +1128,10 @@ ) if not repo.local(): raise error.Abort( - _("repository '%s' is not local") % path + _(b"repository '%s' is not local") % path ) repo.ui.setconfig( - "bundle", "mainreporoot", repo.root, "repo" + b"bundle", b"mainreporoot", repo.root, b"repo" ) except error.RequirementError: raise @@ -1141,28 +1144,28 @@ repos = pycompat.maplist(cmdutil.findrepo, args) guess = repos[0] if guess and repos.count(guess) == len(repos): - req.args = ["--repository", guess] + fullargs - req.earlyoptions["repository"] = guess + req.args = [b"--repository", guess] + fullargs + req.earlyoptions[b"repository"] = guess return _dispatch(req) if not path: raise error.RepoError( _( - "no repository found in" - " '%s' (.hg not found)" + b"no repository found in" + b" '%s' (.hg not found)" ) % encoding.getcwd() ) raise if repo: ui = repo.ui - if options["hidden"]: + if options[b"hidden"]: repo = repo.unfiltered() args.insert(0, repo) elif rpath: - ui.warn(_("warning: --repository ignored\n")) + ui.warn(_(b"warning: --repository ignored\n")) msg = _formatargs(fullargs) - ui.log("command", "%s\n", msg) + ui.log(b"command", b"%s\n", msg) strcmdopt = pycompat.strkwargs(cmdoptions) d = lambda: util.checksignature(func)(ui, *args, **strcmdopt) try: @@ -1177,10 +1180,10 @@ def _runcommand(ui, options, cmd, cmdfunc): """Run a command function, possibly with profiling enabled.""" try: - with tracing.log("Running %s command" % cmd): + with tracing.log(b"Running %s command" % cmd): return cmdfunc() except error.SignatureError: - raise error.CommandError(cmd, _("invalid arguments")) + raise error.CommandError(cmd, _(b"invalid arguments")) def _exceptionwarning(ui): @@ -1194,16 +1197,18 @@ # of date) will be clueful enough to notice the implausible # version number and try updating. ct = util.versiontuple(n=2) - worst = None, ct, "" - if ui.config("ui", "supportcontact") is None: + worst = None, ct, b"" + if ui.config(b"ui", b"supportcontact") is None: for name, mod in extensions.extensions(): # 'testedwith' should be bytes, but not all extensions are ported # to py3 and we don't want UnicodeException because of that. - testedwith = stringutil.forcebytestr(getattr(mod, "testedwith", "")) - report = getattr(mod, "buglink", _("the extension author.")) + testedwith = stringutil.forcebytestr( + getattr(mod, "testedwith", b"") + ) + report = getattr(mod, "buglink", _(b"the extension author.")) if not testedwith.strip(): # We found an untested extension. It's likely the culprit. - worst = name, "unknown", report + worst = name, b"unknown", report break # Never blame on extensions bundled with Mercurial. @@ -1221,35 +1226,35 @@ if worst[0] is not None: name, testedwith, report = worst if not isinstance(testedwith, (bytes, str)): - testedwith = ".".join( + testedwith = b".".join( [stringutil.forcebytestr(c) for c in testedwith] ) warning = _( - "** Unknown exception encountered with " - "possibly-broken third-party extension %s\n" - "** which supports versions %s of Mercurial.\n" - "** Please disable %s and try your action again.\n" - "** If that fixes the bug please report it to %s\n" + b"** Unknown exception encountered with " + b"possibly-broken third-party extension %s\n" + b"** which supports versions %s of Mercurial.\n" + b"** Please disable %s and try your action again.\n" + b"** If that fixes the bug please report it to %s\n" ) % (name, testedwith, name, stringutil.forcebytestr(report)) else: - bugtracker = ui.config("ui", "supportcontact") + bugtracker = ui.config(b"ui", b"supportcontact") if bugtracker is None: - bugtracker = _("https://mercurial-scm.org/wiki/BugTracker") + bugtracker = _(b"https://mercurial-scm.org/wiki/BugTracker") warning = ( _( - "** unknown exception encountered, " - "please report by visiting\n** " + b"** unknown exception encountered, " + b"please report by visiting\n** " ) + bugtracker - + "\n" + + b"\n" ) - sysversion = pycompat.sysbytes(sys.version).replace("\n", "") + sysversion = pycompat.sysbytes(sys.version).replace(b"\n", b"") warning += ( - (_("** Python %s\n") % sysversion) - + (_("** Mercurial Distributed SCM (version %s)\n") % util.version()) + (_(b"** Python %s\n") % sysversion) + + (_(b"** Mercurial Distributed SCM (version %s)\n") % util.version()) + ( - _("** Extensions loaded: %s\n") - % ", ".join([x[0] for x in extensions.extensions()]) + _(b"** Extensions loaded: %s\n") + % b", ".join([x[0] for x in extensions.extensions()]) ) ) return warning @@ -1263,8 +1268,8 @@ """ warning = _exceptionwarning(ui) ui.log( - "commandexception", - "%s\n%s\n", + b"commandexception", + b"%s\n%s\n", warning, pycompat.sysbytes(traceback.format_exc()), ) diff --git a/mercurial/encoding.py b/mercurial/encoding.py --- a/mercurial/encoding.py +++ b/mercurial/encoding.py @@ -36,11 +36,11 @@ # sanity. _ignore = [ unichr(int(x, 16)).encode("utf-8") - for x in "200c 200d 200e 200f 202a 202b 202c 202d 202e " - "206a 206b 206c 206d 206e 206f feff".split() + for x in b"200c 200d 200e 200f 202a 202b 202c 202d 202e " + b"206a 206b 206c 206d 206e 206f feff".split() ] # verify the next function will work -assert all(i.startswith(("\xe2", "\xef")) for i in _ignore) +assert all(i.startswith((b"\xe2", b"\xef")) for i in _ignore) def hfsignoreclean(s): @@ -51,9 +51,9 @@ >>> hfsignoreclean(u'.h\ufeffg'.encode('utf-8')) '.hg' """ - if "\xe2" in s or "\xef" in s: + if b"\xe2" in s or b"\xef" in s: for c in _ignore: - s = s.replace(c, "") + s = s.replace(c, b"") return s @@ -72,24 +72,24 @@ ) # re-exports _encodingrewrites = { - "646": "ascii", - "ANSI_X3.4-1968": "ascii", + b"646": b"ascii", + b"ANSI_X3.4-1968": b"ascii", } # cp65001 is a Windows variant of utf-8, which isn't supported on Python 2. # No idea if it should be rewritten to the canonical name 'utf-8' on Python 3. # https://bugs.python.org/issue13216 if pycompat.iswindows and not pycompat.ispy3: - _encodingrewrites["cp65001"] = "utf-8" + _encodingrewrites[b"cp65001"] = b"utf-8" try: - encoding = environ.get("HGENCODING") + encoding = environ.get(b"HGENCODING") if not encoding: - encoding = locale.getpreferredencoding().encode("ascii") or "ascii" + encoding = locale.getpreferredencoding().encode("ascii") or b"ascii" encoding = _encodingrewrites.get(encoding, encoding) except locale.Error: - encoding = "ascii" -encodingmode = environ.get("HGENCODINGMODE", "strict") -fallbackencoding = "ISO-8859-1" + encoding = b"ascii" +encodingmode = environ.get(b"HGENCODINGMODE", b"strict") +fallbackencoding = b"ISO-8859-1" class localstr(bytes): @@ -157,7 +157,7 @@ try: # make sure string is actually stored in UTF-8 u = s.decode("UTF-8") - if encoding == "UTF-8": + if encoding == b"UTF-8": # fast path return s r = u.encode(_sysstr(encoding), r"replace") @@ -179,7 +179,7 @@ # can't round-trip return u.encode(_sysstr(encoding), r"replace") except LookupError as k: - raise error.Abort(k, hint="please check your locale settings") + raise error.Abort(k, hint=b"please check your locale settings") def fromlocal(s): @@ -205,10 +205,10 @@ except UnicodeDecodeError as inst: sub = s[max(0, inst.start - 10) : inst.start + 10] raise error.Abort( - "decoding near '%s': %s!" % (sub, pycompat.bytestr(inst)) + b"decoding near '%s': %s!" % (sub, pycompat.bytestr(inst)) ) except LookupError as k: - raise error.Abort(k, hint="please check your locale settings") + raise error.Abort(k, hint=b"please check your locale settings") def unitolocal(u): @@ -265,17 +265,19 @@ # How to treat ambiguous-width characters. Set to 'wide' to treat as wide. _wide = _sysstr( - environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide" and "WFA" or "WF" + environ.get(b"HGENCODINGAMBIGUOUS", b"narrow") == b"wide" + and b"WFA" + or b"WF" ) def colwidth(s): - "Find the column width of a string for display in the local encoding" + b"Find the column width of a string for display in the local encoding" return ucolwidth(s.decode(_sysstr(encoding), r"replace")) def ucolwidth(d): - "Find the column width of a Unicode string for display" + b"Find the column width of a Unicode string for display" eaw = getattr(unicodedata, "east_asian_width", None) if eaw is not None: return sum([eaw(c) in _wide and 2 or 1 for c in d]) @@ -291,7 +293,7 @@ return t -def trim(s, width, ellipsis="", leftside=False): +def trim(s, width, ellipsis=b"", leftside=False): """Trim string 's' to at most 'width' columns (including 'ellipsis'). If 'leftside' is True, left side of string 's' is trimmed. @@ -389,7 +391,7 @@ def lower(s): - "best-effort encoding-aware case-folding of local string s" + b"best-effort encoding-aware case-folding of local string s" try: return asciilower(s) except UnicodeDecodeError: @@ -407,11 +409,11 @@ except UnicodeError: return s.lower() # we don't know how to fold this except in ASCII except LookupError as k: - raise error.Abort(k, hint="please check your locale settings") + raise error.Abort(k, hint=b"please check your locale settings") def upper(s): - "best-effort encoding-aware case-folding of local string s" + b"best-effort encoding-aware case-folding of local string s" try: return asciiupper(s) except UnicodeDecodeError: @@ -432,7 +434,7 @@ except UnicodeError: return s.upper() # we don't know how to fold this except in ASCII except LookupError as k: - raise error.Abort(k, hint="please check your locale settings") + raise error.Abort(k, hint=b"please check your locale settings") class normcasespecs(object): @@ -574,7 +576,7 @@ return fromlocal(s) elif isasciistr(s): return s - if "\xed" not in s: + if b"\xed" not in s: try: s.decode("utf-8", _utf8strict) return s @@ -582,13 +584,13 @@ pass s = pycompat.bytestr(s) - r = "" + r = b"" pos = 0 l = len(s) while pos < l: try: c = getutf8char(s, pos) - if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf": + if b"\xed\xb0\x80" <= c <= b"\xed\xb3\xbf": # have to re-escape existing U+DCxx characters c = unichr(0xDC00 + ord(s[pos])).encode("utf-8", _utf8strict) pos += 1 @@ -627,7 +629,7 @@ if isasciistr(s): return s # fast path - look for uDxxx prefixes in s - if "\xed" not in s: + if b"\xed" not in s: return s # We could do this with the unicode type but some Python builds @@ -636,14 +638,14 @@ # helper again to walk the string without "decoding" it. s = pycompat.bytestr(s) - r = "" + r = b"" pos = 0 l = len(s) while pos < l: c = getutf8char(s, pos) pos += len(c) # unescape U+DCxx characters - if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf": + if b"\xed\xb0\x80" <= c <= b"\xed\xb3\xbf": c = pycompat.bytechr(ord(c.decode("utf-8", _utf8strict)) & 0xFF) r += c return r diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -73,7 +73,7 @@ from .node import short name = short(name) - RevlogError.__init__(self, "%s@%s: %s" % (index, name, message)) + RevlogError.__init__(self, b"%s@%s: %s" % (index, name, message)) def __bytes__(self): return RevlogError.__bytes__(self) @@ -150,7 +150,7 @@ def __init__(self): from .i18n import _ - Abort.__init__(self, _("response expected")) + Abort.__init__(self, _(b"response expected")) class OutOfBandError(Hint, Exception): @@ -175,7 +175,7 @@ def __init__(self, function, symbols): from .i18n import _ - ParseError.__init__(self, _("unknown identifier: %s") % function) + ParseError.__init__(self, _(b"unknown identifier: %s") % function) self.function = function self.symbols = symbols @@ -214,13 +214,13 @@ from .i18n import _ self.recordtypes = sorted(recordtypes) - s = " ".join(self.recordtypes) + s = b" ".join(self.recordtypes) Abort.__init__( self, - _("unsupported merge state records: %s") % s, + _(b"unsupported merge state records: %s") % s, hint=_( - "see https://mercurial-scm.org/wiki/MergeStateRecords for " - "more information" + b"see https://mercurial-scm.org/wiki/MergeStateRecords for " + b"more information" ), ) @@ -244,7 +244,7 @@ class LockHeld(LockError): def __init__(self, errno, filename, desc, locker): - LockError.__init__(self, errno, "Lock held", filename, desc) + LockError.__init__(self, errno, b"Lock held", filename, desc) self.locker = locker @@ -322,7 +322,7 @@ self.params = params self.values = values if self.parttype is None: - msg = "Stream Parameter" + msg = b"Stream Parameter" else: msg = parttype entries = self.params @@ -334,9 +334,9 @@ if val is None: entries.append(val) else: - entries.append("%s=%r" % (par, pycompat.maybebytestr(val))) + entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val))) if entries: - msg = "%s - %s" % (msg, ", ".join(entries)) + msg = b"%s - %s" % (msg, b", ".join(entries)) ValueError.__init__(self, msg) @@ -360,7 +360,7 @@ self.ret = ret # no i18n expected to be processed into a better message Abort.__init__( - self, 'failed to update value for "%s/%s"' % (namespace, key) + self, b'failed to update value for "%s/%s"' % (namespace, key) ) @@ -373,7 +373,7 @@ def __init__(self, filename, node, tombstone): from .node import short - StorageError.__init__(self, "%s:%s" % (filename, short(node))) + StorageError.__init__(self, b"%s:%s" % (filename, short(node))) self.tombstone = tombstone diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -44,49 +44,49 @@ urlerr = util.urlerr urlreq = util.urlreq -_NARROWACL_SECTION = "narrowacl" +_NARROWACL_SECTION = b"narrowacl" # Maps bundle version human names to changegroup versions. _bundlespeccgversions = { - "v1": "01", - "v2": "02", - "packed1": "s1", - "bundle2": "02", # legacy + b"v1": b"01", + b"v2": b"02", + b"packed1": b"s1", + b"bundle2": b"02", # legacy } # Maps bundle version with content opts to choose which part to bundle _bundlespeccontentopts = { - "v1": { - "changegroup": True, - "cg.version": "01", - "obsolescence": False, - "phases": False, - "tagsfnodescache": False, - "revbranchcache": False, + b"v1": { + b"changegroup": True, + b"cg.version": b"01", + b"obsolescence": False, + b"phases": False, + b"tagsfnodescache": False, + b"revbranchcache": False, }, - "v2": { - "changegroup": True, - "cg.version": "02", - "obsolescence": False, - "phases": False, - "tagsfnodescache": True, - "revbranchcache": True, + b"v2": { + b"changegroup": True, + b"cg.version": b"02", + b"obsolescence": False, + b"phases": False, + b"tagsfnodescache": True, + b"revbranchcache": True, }, - "packed1": {"cg.version": "s1"}, + b"packed1": {b"cg.version": b"s1"}, } -_bundlespeccontentopts["bundle2"] = _bundlespeccontentopts["v2"] +_bundlespeccontentopts[b"bundle2"] = _bundlespeccontentopts[b"v2"] _bundlespecvariants = { - "streamv2": { - "changegroup": False, - "streamv2": True, - "tagsfnodescache": False, - "revbranchcache": False, + b"streamv2": { + b"changegroup": False, + b"streamv2": True, + b"tagsfnodescache": False, + b"revbranchcache": False, } } # Compression engines allowed in version 1. THIS SHOULD NEVER CHANGE. -_bundlespecv1compengines = {"gzip", "bzip2", "none"} +_bundlespecv1compengines = {b"gzip", b"bzip2", b"none"} @attr.s @@ -134,51 +134,51 @@ """ def parseparams(s): - if ";" not in s: + if b";" not in s: return s, {} params = {} - version, paramstr = s.split(";", 1) - - for p in paramstr.split(";"): - if "=" not in p: + version, paramstr = s.split(b";", 1) + + for p in paramstr.split(b";"): + if b"=" not in p: raise error.InvalidBundleSpecification( _( - "invalid bundle specification: " - 'missing "=" in parameter: %s' + b"invalid bundle specification: " + b'missing "=" in parameter: %s' ) % p ) - key, value = p.split("=", 1) + key, value = p.split(b"=", 1) key = urlreq.unquote(key) value = urlreq.unquote(value) params[key] = value return version, params - if strict and "-" not in spec: + if strict and b"-" not in spec: raise error.InvalidBundleSpecification( _( - "invalid bundle specification; " - "must be prefixed with compression: %s" + b"invalid bundle specification; " + b"must be prefixed with compression: %s" ) % spec ) - if "-" in spec: - compression, version = spec.split("-", 1) + if b"-" in spec: + compression, version = spec.split(b"-", 1) if compression not in util.compengines.supportedbundlenames: raise error.UnsupportedBundleSpecification( - _("%s compression is not supported") % compression + _(b"%s compression is not supported") % compression ) version, params = parseparams(version) if version not in _bundlespeccgversions: raise error.UnsupportedBundleSpecification( - _("%s is not a recognized bundle version") % version + _(b"%s is not a recognized bundle version") % version ) else: # Value could be just the compression or just the version, in which @@ -189,49 +189,49 @@ if spec in util.compengines.supportedbundlenames: compression = spec - version = "v1" + version = b"v1" # Generaldelta repos require v2. - if "generaldelta" in repo.requirements: - version = "v2" + if b"generaldelta" in repo.requirements: + version = b"v2" # Modern compression engines require v2. if compression not in _bundlespecv1compengines: - version = "v2" + version = b"v2" elif spec in _bundlespeccgversions: - if spec == "packed1": - compression = "none" + if spec == b"packed1": + compression = b"none" else: - compression = "bzip2" + compression = b"bzip2" version = spec else: raise error.UnsupportedBundleSpecification( - _("%s is not a recognized bundle specification") % spec + _(b"%s is not a recognized bundle specification") % spec ) # Bundle version 1 only supports a known set of compression engines. - if version == "v1" and compression not in _bundlespecv1compengines: + if version == b"v1" and compression not in _bundlespecv1compengines: raise error.UnsupportedBundleSpecification( - _("compression engine %s is not supported on v1 bundles") + _(b"compression engine %s is not supported on v1 bundles") % compression ) # The specification for packed1 can optionally declare the data formats # required to apply it. If we see this metadata, compare against what the # repo supports and error if the bundle isn't compatible. - if version == "packed1" and "requirements" in params: - requirements = set(params["requirements"].split(",")) + if version == b"packed1" and b"requirements" in params: + requirements = set(params[b"requirements"].split(b",")) missingreqs = requirements - repo.supportedformats if missingreqs: raise error.UnsupportedBundleSpecification( - _("missing support for repository features: %s") - % ", ".join(sorted(missingreqs)) + _(b"missing support for repository features: %s") + % b", ".join(sorted(missingreqs)) ) # Compute contentopts based on the version contentopts = _bundlespeccontentopts.get(version, {}).copy() # Process the variants - if "stream" in params and params["stream"] == "v2": - variant = _bundlespecvariants["streamv2"] + if b"stream" in params and params[b"stream"] == b"v2": + variant = _bundlespecvariants[b"streamv2"] contentopts.update(variant) engine = util.compengines.forbundlename(compression) @@ -248,28 +248,30 @@ alg = None if not fname: - fname = "stream" - if not header.startswith("HG") and header.startswith("\0"): + fname = b"stream" + if not header.startswith(b"HG") and header.startswith(b"\0"): fh = changegroup.headerlessfixup(fh, header) - header = "HG10" - alg = "UN" + header = b"HG10" + alg = b"UN" elif vfs: fname = vfs.join(fname) magic, version = header[0:2], header[2:4] - if magic != "HG": - raise error.Abort(_("%s: not a Mercurial bundle") % fname) - if version == "10": + if magic != b"HG": + raise error.Abort(_(b"%s: not a Mercurial bundle") % fname) + if version == b"10": if alg is None: alg = changegroup.readexactly(fh, 2) return changegroup.cg1unpacker(fh, alg) - elif version.startswith("2"): + elif version.startswith(b"2"): return bundle2.getunbundler(ui, fh, magicstring=magic + version) - elif version == "S1": + elif version == b"S1": return streamclone.streamcloneapplier(fh) else: - raise error.Abort(_("%s: unknown bundle version %s") % (fname, version)) + raise error.Abort( + _(b"%s: unknown bundle version %s") % (fname, version) + ) def getbundlespec(ui, fh): @@ -288,54 +290,56 @@ b = readbundle(ui, fh, None) if isinstance(b, changegroup.cg1unpacker): alg = b._type - if alg == "_truncatedBZ": - alg = "BZ" + if alg == b"_truncatedBZ": + alg = b"BZ" comp = speccompression(alg) if not comp: - raise error.Abort(_("unknown compression algorithm: %s") % alg) - return "%s-v1" % comp + raise error.Abort(_(b"unknown compression algorithm: %s") % alg) + return b"%s-v1" % comp elif isinstance(b, bundle2.unbundle20): - if "Compression" in b.params: - comp = speccompression(b.params["Compression"]) + if b"Compression" in b.params: + comp = speccompression(b.params[b"Compression"]) if not comp: - raise error.Abort(_("unknown compression algorithm: %s") % comp) + raise error.Abort( + _(b"unknown compression algorithm: %s") % comp + ) else: - comp = "none" + comp = b"none" version = None for part in b.iterparts(): - if part.type == "changegroup": - version = part.params["version"] - if version in ("01", "02"): - version = "v2" + if part.type == b"changegroup": + version = part.params[b"version"] + if version in (b"01", b"02"): + version = b"v2" else: raise error.Abort( _( - "changegroup version %s does not have " - "a known bundlespec" + b"changegroup version %s does not have " + b"a known bundlespec" ) % version, - hint=_("try upgrading your Mercurial " "client"), + hint=_(b"try upgrading your Mercurial " b"client"), ) - elif part.type == "stream2" and version is None: + elif part.type == b"stream2" and version is None: # A stream2 part requires to be part of a v2 bundle - requirements = urlreq.unquote(part.params["requirements"]) + requirements = urlreq.unquote(part.params[b"requirements"]) splitted = requirements.split() params = bundle2._formatrequirementsparams(splitted) - return "none-v2;stream=v2;%s" % params + return b"none-v2;stream=v2;%s" % params if not version: raise error.Abort( - _("could not identify changegroup version in " "bundle") + _(b"could not identify changegroup version in " b"bundle") ) - return "%s-%s" % (comp, version) + return b"%s-%s" % (comp, version) elif isinstance(b, streamclone.streamcloneapplier): requirements = streamclone.readbundle1header(fh)[2] formatted = bundle2._formatrequirementsparams(requirements) - return "none-packed1;%s" % formatted + return b"none-packed1;%s" % formatted else: - raise error.Abort(_("unknown bundle type: %s") % b) + raise error.Abort(_(b"unknown bundle type: %s") % b) def _computeoutgoing(repo, heads, common): @@ -361,30 +365,33 @@ def _checkpublish(pushop): repo = pushop.repo ui = repo.ui - behavior = ui.config("experimental", "auto-publish") - if pushop.publish or behavior not in ("warn", "confirm", "abort"): + behavior = ui.config(b"experimental", b"auto-publish") + if pushop.publish or behavior not in (b"warn", b"confirm", b"abort"): return - remotephases = listkeys(pushop.remote, "phases") - if not remotephases.get("publishing", False): + remotephases = listkeys(pushop.remote, b"phases") + if not remotephases.get(b"publishing", False): return if pushop.revs is None: - published = repo.filtered("served").revs("not public()") + published = repo.filtered(b"served").revs(b"not public()") else: - published = repo.revs("::%ln - public()", pushop.revs) + published = repo.revs(b"::%ln - public()", pushop.revs) if published: - if behavior == "warn": - ui.warn(_("%i changesets about to be published\n") % len(published)) - elif behavior == "confirm": + if behavior == b"warn": + ui.warn( + _(b"%i changesets about to be published\n") % len(published) + ) + elif behavior == b"confirm": if ui.promptchoice( - _("push and publish %i changesets (yn)?" "$$ &Yes $$ &No") + _(b"push and publish %i changesets (yn)?" b"$$ &Yes $$ &No") % len(published) ): - raise error.Abort(_("user quit")) - elif behavior == "abort": - msg = _("push would publish %i changesets") % len(published) + raise error.Abort(_(b"user quit")) + elif behavior == b"abort": + msg = _(b"push would publish %i changesets") % len(published) hint = _( - "use --publish or adjust 'experimental.auto-publish'" " config" + b"use --publish or adjust 'experimental.auto-publish'" + b" config" ) raise error.Abort(msg, hint=hint) @@ -400,9 +407,9 @@ # should be used. # # developer config: devel.legacy.exchange - exchange = ui.configlist("devel", "legacy.exchange") - forcebundle1 = "bundle2" not in exchange and "bundle1" in exchange - return forcebundle1 or not op.remote.capable("bundle2") + exchange = ui.configlist(b"devel", b"legacy.exchange") + forcebundle1 = b"bundle2" not in exchange and b"bundle1" in exchange + return forcebundle1 or not op.remote.capable(b"bundle2") class pushoperation(object): @@ -521,7 +528,7 @@ # and # * commonheads parents on missing revset = unfi.set( - "%ln and parents(roots(%ln))", + b"%ln and parents(roots(%ln))", self.outgoing.commonheads, self.outgoing.missing, ) @@ -539,17 +546,17 @@ # mapping of message used when pushing bookmark bookmsgmap = { - "update": ( - _("updating bookmark %s\n"), - _("updating bookmark %s failed!\n"), + b"update": ( + _(b"updating bookmark %s\n"), + _(b"updating bookmark %s failed!\n"), ), - "export": ( - _("exporting bookmark %s\n"), - _("exporting bookmark %s failed!\n"), + b"export": ( + _(b"exporting bookmark %s\n"), + _(b"exporting bookmark %s failed!\n"), ), - "delete": ( - _("deleting remote bookmark %s\n"), - _("deleting remote bookmark %s failed!\n"), + b"delete": ( + _(b"deleting remote bookmark %s\n"), + _(b"deleting remote bookmark %s failed!\n"), ), } @@ -590,20 +597,20 @@ ) if missing: msg = _( - "required features are not" - " supported in the destination:" - " %s" - ) % (", ".join(sorted(missing))) + b"required features are not" + b" supported in the destination:" + b" %s" + ) % (b", ".join(sorted(missing))) raise error.Abort(msg) if not pushop.remote.canpush(): - raise error.Abort(_("destination does not support push")) - - if not pushop.remote.capable("unbundle"): + raise error.Abort(_(b"destination does not support push")) + + if not pushop.remote.capable(b"unbundle"): raise error.Abort( _( - "cannot push: destination does not support the " - "unbundle wire protocol command" + b"cannot push: destination does not support the " + b"unbundle wire protocol command" ) ) @@ -612,7 +619,7 @@ try: # bundle2 push may receive a reply bundle touching bookmarks # requiring the wlock. Take it now to ensure proper ordering. - maypushback = pushop.ui.configbool("experimental", "bundle2.pushback") + maypushback = pushop.ui.configbool(b"experimental", b"bundle2.pushback") if ( (not _forcebundle1(pushop)) and maypushback @@ -621,13 +628,13 @@ wlock = pushop.repo.wlock() lock = pushop.repo.lock() pushop.trmanager = transactionmanager( - pushop.repo, "push-response", pushop.remote.url() + pushop.repo, b"push-response", pushop.remote.url() ) except error.LockUnavailable as err: # source repo cannot be locked. # We do not abort the push, but just disable the local phase # synchronisation. - msg = "cannot lock source repository: %s\n" % stringutil.forcebytestr( + msg = b"cannot lock source repository: %s\n" % stringutil.forcebytestr( err ) pushop.ui.debug(msg) @@ -645,7 +652,7 @@ _pushobsolete(pushop) _pushbookmark(pushop) - if repo.ui.configbool("experimental", "remotenames"): + if repo.ui.configbool(b"experimental", b"remotenames"): logexchange.pullremotenames(repo, remote) return pushop @@ -686,7 +693,7 @@ step(pushop) -@pushdiscovery("changeset") +@pushdiscovery(b"changeset") def _pushdiscoverychangeset(pushop): """discover the changeset that need to be pushed""" fci = discovery.findcommonincoming @@ -713,20 +720,20 @@ pushop.incoming = inc -@pushdiscovery("phase") +@pushdiscovery(b"phase") def _pushdiscoveryphase(pushop): """discover the phase that needs to be pushed (computed for both success and failure case for changesets push)""" outgoing = pushop.outgoing unfi = pushop.repo.unfiltered() - remotephases = listkeys(pushop.remote, "phases") + remotephases = listkeys(pushop.remote, b"phases") if ( - pushop.ui.configbool("ui", "_usedassubrepo") + pushop.ui.configbool(b"ui", b"_usedassubrepo") and remotephases # server supports phases and not pushop.outgoing.missing # no changesets to be pushed - and remotephases.get("publishing", False) + and remotephases.get(b"publishing", False) ): # When: # - this is a subrepo push @@ -746,10 +753,10 @@ ) droots = pushop.remotephases.draftroots - extracond = "" + extracond = b"" if not pushop.remotephases.publishing: - extracond = " and public()" - revset = "heads((%%ln::%%ln) %s)" % extracond + extracond = b" and public()" + revset = b"heads((%%ln::%%ln) %s)" % extracond # Get the list of all revs draft on remote by public here. # XXX Beware that revset break if droots is not strictly # XXX root we may want to ensure it is but it is costly @@ -757,7 +764,7 @@ if not pushop.remotephases.publishing and pushop.publish: future = list( unfi.set( - "%ln and (not public() or %ln::)", pushop.futureheads, droots + b"%ln and (not public() or %ln::)", pushop.futureheads, droots ) ) elif not outgoing.missing: @@ -768,7 +775,7 @@ # should not be necessary for publishing server, but because of an # issue fixed in xxxxx we have to do it anyway. fdroots = list( - unfi.set("roots(%ln + %ln::)", outgoing.missing, droots) + unfi.set(b"roots(%ln + %ln::)", outgoing.missing, droots) ) fdroots = [f.node() for f in fdroots] future = list(unfi.set(revset, fdroots, pushop.futureheads)) @@ -776,7 +783,7 @@ pushop.fallbackoutdatedphases = fallback -@pushdiscovery("obsmarker") +@pushdiscovery(b"obsmarker") def _pushdiscoveryobsmarkers(pushop): if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt): return @@ -784,28 +791,28 @@ if not pushop.repo.obsstore: return - if "obsolete" not in listkeys(pushop.remote, "namespaces"): + if b"obsolete" not in listkeys(pushop.remote, b"namespaces"): return repo = pushop.repo # very naive computation, that can be quite expensive on big repo. # However: evolution is currently slow on them anyway. - nodes = (c.node() for c in repo.set("::%ln", pushop.futureheads)) + nodes = (c.node() for c in repo.set(b"::%ln", pushop.futureheads)) pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes) -@pushdiscovery("bookmarks") +@pushdiscovery(b"bookmarks") def _pushdiscoverybookmarks(pushop): ui = pushop.ui repo = pushop.repo.unfiltered() remote = pushop.remote - ui.debug("checking for updated bookmarks\n") + ui.debug(b"checking for updated bookmarks\n") ancestors = () if pushop.revs: revnums = pycompat.maplist(repo.changelog.rev, pushop.revs) ancestors = repo.changelog.ancestors(revnums, inclusive=True) - remotebookmark = bookmod.unhexlifybookmarks(listkeys(remote, "bookmarks")) + remotebookmark = bookmod.unhexlifybookmarks(listkeys(remote, b"bookmarks")) explicit = { repo._bookmarks.expandname(bookmark) for bookmark in pushop.bookmarks @@ -833,7 +840,7 @@ for b, scid, dcid in addsrc: if b in explicit: explicit.remove(b) - pushop.outbookmarks.append((b, "", scid)) + pushop.outbookmarks.append((b, b"", scid)) # search for overwritten bookmark for b, scid, dcid in list(advdst) + list(diverge) + list(differ): if b in explicit: @@ -844,7 +851,7 @@ if b in explicit: explicit.remove(b) # treat as "deleted locally" - pushop.outbookmarks.append((b, dcid, "")) + pushop.outbookmarks.append((b, dcid, b"")) # identical bookmarks shouldn't get reported for b, scid, dcid in same: if b in explicit: @@ -855,8 +862,8 @@ # we should probably list all of them pushop.ui.warn( _( - "bookmark %s does not exist on the local " - "or remote repository!\n" + b"bookmark %s does not exist on the local " + b"or remote repository!\n" ) % explicit[0] ) @@ -878,13 +885,13 @@ # then, save the iteration if unfi.obsstore: # this message are here for 80 char limit reason - mso = _("push includes obsolete changeset: %s!") - mspd = _("push includes phase-divergent changeset: %s!") - mscd = _("push includes content-divergent changeset: %s!") + mso = _(b"push includes obsolete changeset: %s!") + mspd = _(b"push includes phase-divergent changeset: %s!") + mscd = _(b"push includes content-divergent changeset: %s!") mst = { - "orphan": _("push includes orphan changeset: %s!"), - "phase-divergent": mspd, - "content-divergent": mscd, + b"orphan": _(b"push includes orphan changeset: %s!"), + b"phase-divergent": mspd, + b"content-divergent": mscd, } # If we are to push if there is at least one # obsolete or unstable changeset in missing, at @@ -942,10 +949,12 @@ # * 'force' do not check for push race, # * if we don't push anything, there are nothing to check. if not pushop.force and pushop.outgoing.missingheads: - allowunrelated = "related" in bundler.capabilities.get("checkheads", ()) + allowunrelated = b"related" in bundler.capabilities.get( + b"checkheads", () + ) emptyremote = pushop.pushbranchmap is None if not allowunrelated or emptyremote: - bundler.newpart("check:heads", data=iter(pushop.remoteheads)) + bundler.newpart(b"check:heads", data=iter(pushop.remoteheads)) else: affected = set() for branch, heads in pushop.pushbranchmap.iteritems(): @@ -956,7 +965,7 @@ affected |= remote - set(newheads) if affected: data = iter(sorted(affected)) - bundler.newpart("check:updated-heads", data=data) + bundler.newpart(b"check:updated-heads", data=data) def _pushing(pushop): @@ -969,29 +978,29 @@ ) -@b2partsgenerator("check-bookmarks") +@b2partsgenerator(b"check-bookmarks") def _pushb2checkbookmarks(pushop, bundler): """insert bookmark move checking""" if not _pushing(pushop) or pushop.force: return b2caps = bundle2.bundle2caps(pushop.remote) - hasbookmarkcheck = "bookmarks" in b2caps + hasbookmarkcheck = b"bookmarks" in b2caps if not (pushop.outbookmarks and hasbookmarkcheck): return data = [] for book, old, new in pushop.outbookmarks: data.append((book, old)) checkdata = bookmod.binaryencode(data) - bundler.newpart("check:bookmarks", data=checkdata) - - -@b2partsgenerator("check-phases") + bundler.newpart(b"check:bookmarks", data=checkdata) + + +@b2partsgenerator(b"check-phases") def _pushb2checkphases(pushop, bundler): """insert phase move checking""" if not _pushing(pushop) or pushop.force: return b2caps = bundle2.bundle2caps(pushop.remote) - hasphaseheads = "heads" in b2caps.get("phases", ()) + hasphaseheads = b"heads" in b2caps.get(b"phases", ()) if pushop.remotephases is not None and hasphaseheads: # check that the remote phase has not changed checks = [[] for p in phases.allphases] @@ -1001,18 +1010,18 @@ for nodes in checks: nodes.sort() checkdata = phases.binaryencode(checks) - bundler.newpart("check:phases", data=checkdata) - - -@b2partsgenerator("changeset") + bundler.newpart(b"check:phases", data=checkdata) + + +@b2partsgenerator(b"changeset") def _pushb2ctx(pushop, bundler): """handle changegroup push through bundle2 addchangegroup result is stored in the ``pushop.cgresult`` attribute. """ - if "changesets" in pushop.stepsdone: + if b"changesets" in pushop.stepsdone: return - pushop.stepsdone.add("changesets") + pushop.stepsdone.add(b"changesets") # Send known heads to the server for race detection. if not _pushcheckoutgoing(pushop): return @@ -1021,8 +1030,8 @@ _pushb2ctxcheckheads(pushop, bundler) b2caps = bundle2.bundle2caps(pushop.remote) - version = "01" - cgversions = b2caps.get("changegroup") + version = b"01" + cgversions = b2caps.get(b"changegroup") if cgversions: # 3.1 and 3.2 ship with an empty value cgversions = [ v @@ -1030,37 +1039,37 @@ if v in changegroup.supportedoutgoingversions(pushop.repo) ] if not cgversions: - raise error.Abort(_("no common changegroup version")) + raise error.Abort(_(b"no common changegroup version")) version = max(cgversions) cgstream = changegroup.makestream( - pushop.repo, pushop.outgoing, version, "push" + pushop.repo, pushop.outgoing, version, b"push" ) - cgpart = bundler.newpart("changegroup", data=cgstream) + cgpart = bundler.newpart(b"changegroup", data=cgstream) if cgversions: - cgpart.addparam("version", version) - if "treemanifest" in pushop.repo.requirements: - cgpart.addparam("treemanifest", "1") + cgpart.addparam(b"version", version) + if b"treemanifest" in pushop.repo.requirements: + cgpart.addparam(b"treemanifest", b"1") def handlereply(op): """extract addchangegroup returns from server reply""" cgreplies = op.records.getreplies(cgpart.id) - assert len(cgreplies["changegroup"]) == 1 - pushop.cgresult = cgreplies["changegroup"][0]["return"] + assert len(cgreplies[b"changegroup"]) == 1 + pushop.cgresult = cgreplies[b"changegroup"][0][b"return"] return handlereply -@b2partsgenerator("phase") +@b2partsgenerator(b"phase") def _pushb2phases(pushop, bundler): """handle phase push through bundle2""" - if "phases" in pushop.stepsdone: + if b"phases" in pushop.stepsdone: return b2caps = bundle2.bundle2caps(pushop.remote) ui = pushop.repo.ui - legacyphase = "phases" in ui.configlist("devel", "legacy.exchange") - haspushkey = "pushkey" in b2caps - hasphaseheads = "heads" in b2caps.get("phases", ()) + legacyphase = b"phases" in ui.configlist(b"devel", b"legacy.exchange") + haspushkey = b"pushkey" in b2caps + hasphaseheads = b"heads" in b2caps.get(b"phases", ()) if hasphaseheads and not legacyphase: return _pushb2phaseheads(pushop, bundler) @@ -1070,100 +1079,100 @@ def _pushb2phaseheads(pushop, bundler): """push phase information through a bundle2 - binary part""" - pushop.stepsdone.add("phases") + pushop.stepsdone.add(b"phases") if pushop.outdatedphases: updates = [[] for p in phases.allphases] updates[0].extend(h.node() for h in pushop.outdatedphases) phasedata = phases.binaryencode(updates) - bundler.newpart("phase-heads", data=phasedata) + bundler.newpart(b"phase-heads", data=phasedata) def _pushb2phasespushkey(pushop, bundler): """push phase information through a bundle2 - pushkey part""" - pushop.stepsdone.add("phases") + pushop.stepsdone.add(b"phases") part2node = [] def handlefailure(pushop, exc): targetid = int(exc.partid) for partid, node in part2node: if partid == targetid: - raise error.Abort(_("updating %s to public failed") % node) + raise error.Abort(_(b"updating %s to public failed") % node) enc = pushkey.encode for newremotehead in pushop.outdatedphases: - part = bundler.newpart("pushkey") - part.addparam("namespace", enc("phases")) - part.addparam("key", enc(newremotehead.hex())) - part.addparam("old", enc("%d" % phases.draft)) - part.addparam("new", enc("%d" % phases.public)) + part = bundler.newpart(b"pushkey") + part.addparam(b"namespace", enc(b"phases")) + part.addparam(b"key", enc(newremotehead.hex())) + part.addparam(b"old", enc(b"%d" % phases.draft)) + part.addparam(b"new", enc(b"%d" % phases.public)) part2node.append((part.id, newremotehead)) pushop.pkfailcb[part.id] = handlefailure def handlereply(op): for partid, node in part2node: partrep = op.records.getreplies(partid) - results = partrep["pushkey"] + results = partrep[b"pushkey"] assert len(results) <= 1 msg = None if not results: - msg = _("server ignored update of %s to public!\n") % node - elif not int(results[0]["return"]): - msg = _("updating %s to public failed!\n") % node + msg = _(b"server ignored update of %s to public!\n") % node + elif not int(results[0][b"return"]): + msg = _(b"updating %s to public failed!\n") % node if msg is not None: pushop.ui.warn(msg) return handlereply -@b2partsgenerator("obsmarkers") +@b2partsgenerator(b"obsmarkers") def _pushb2obsmarkers(pushop, bundler): - if "obsmarkers" in pushop.stepsdone: + if b"obsmarkers" in pushop.stepsdone: return remoteversions = bundle2.obsmarkersversion(bundler.capabilities) if obsolete.commonversion(remoteversions) is None: return - pushop.stepsdone.add("obsmarkers") + pushop.stepsdone.add(b"obsmarkers") if pushop.outobsmarkers: markers = sorted(pushop.outobsmarkers) bundle2.buildobsmarkerspart(bundler, markers) -@b2partsgenerator("bookmarks") +@b2partsgenerator(b"bookmarks") def _pushb2bookmarks(pushop, bundler): """handle bookmark push through bundle2""" - if "bookmarks" in pushop.stepsdone: + if b"bookmarks" in pushop.stepsdone: return b2caps = bundle2.bundle2caps(pushop.remote) - legacy = pushop.repo.ui.configlist("devel", "legacy.exchange") - legacybooks = "bookmarks" in legacy - - if not legacybooks and "bookmarks" in b2caps: + legacy = pushop.repo.ui.configlist(b"devel", b"legacy.exchange") + legacybooks = b"bookmarks" in legacy + + if not legacybooks and b"bookmarks" in b2caps: return _pushb2bookmarkspart(pushop, bundler) - elif "pushkey" in b2caps: + elif b"pushkey" in b2caps: return _pushb2bookmarkspushkey(pushop, bundler) def _bmaction(old, new): """small utility for bookmark pushing""" if not old: - return "export" + return b"export" elif not new: - return "delete" - return "update" + return b"delete" + return b"update" def _abortonsecretctx(pushop, node, b): """abort if a given bookmark points to a secret changeset""" if node and pushop.repo[node].phase() == phases.secret: raise error.Abort( - _("cannot push bookmark %s as it points to a secret" " changeset") + _(b"cannot push bookmark %s as it points to a secret" b" changeset") % b ) def _pushb2bookmarkspart(pushop, bundler): - pushop.stepsdone.add("bookmarks") + pushop.stepsdone.add(b"bookmarks") if not pushop.outbookmarks: return @@ -1174,7 +1183,7 @@ data.append((book, new)) allactions.append((book, _bmaction(old, new))) checkdata = bookmod.binaryencode(data) - bundler.newpart("bookmarks", data=checkdata) + bundler.newpart(b"bookmarks", data=checkdata) def handlereply(op): ui = pushop.ui @@ -1186,7 +1195,7 @@ def _pushb2bookmarkspushkey(pushop, bundler): - pushop.stepsdone.add("bookmarks") + pushop.stepsdone.add(b"bookmarks") part2book = [] enc = pushkey.encode @@ -1200,16 +1209,16 @@ for book, old, new in pushop.outbookmarks: _abortonsecretctx(pushop, new, book) - part = bundler.newpart("pushkey") - part.addparam("namespace", enc("bookmarks")) - part.addparam("key", enc(book)) - part.addparam("old", enc(hex(old))) - part.addparam("new", enc(hex(new))) - action = "update" + part = bundler.newpart(b"pushkey") + part.addparam(b"namespace", enc(b"bookmarks")) + part.addparam(b"key", enc(book)) + part.addparam(b"old", enc(hex(old))) + part.addparam(b"new", enc(hex(new))) + action = b"update" if not old: - action = "export" + action = b"export" elif not new: - action = "delete" + action = b"delete" part2book.append((part.id, book, action)) pushop.pkfailcb[part.id] = handlefailure @@ -1217,12 +1226,12 @@ ui = pushop.ui for partid, book, action in part2book: partrep = op.records.getreplies(partid) - results = partrep["pushkey"] + results = partrep[b"pushkey"] assert len(results) <= 1 if not results: - pushop.ui.warn(_("server ignored bookmark %s update\n") % book) + pushop.ui.warn(_(b"server ignored bookmark %s update\n") % book) else: - ret = int(results[0]["return"]) + ret = int(results[0][b"return"]) if ret: ui.status(bookmsgmap[action][0] % book) else: @@ -1233,23 +1242,23 @@ return handlereply -@b2partsgenerator("pushvars", idx=0) +@b2partsgenerator(b"pushvars", idx=0) def _getbundlesendvars(pushop, bundler): """send shellvars via bundle2""" pushvars = pushop.pushvars if pushvars: shellvars = {} for raw in pushvars: - if "=" not in raw: + if b"=" not in raw: msg = ( - "unable to parse variable '%s', should follow " - "'KEY=VALUE' or 'KEY=' format" + b"unable to parse variable '%s', should follow " + b"'KEY=VALUE' or 'KEY=' format" ) raise error.Abort(msg % raw) - k, v = raw.split("=", 1) + k, v = raw.split(b"=", 1) shellvars[k] = v - part = bundler.newpart("pushvars") + part = bundler.newpart(b"pushvars") for key, value in shellvars.iteritems(): part.addparam(key, value, mandatory=False) @@ -1262,14 +1271,14 @@ evolve in the future.""" bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote)) pushback = pushop.trmanager and pushop.ui.configbool( - "experimental", "bundle2.pushback" + b"experimental", b"bundle2.pushback" ) # create reply capability capsblob = bundle2.encodecaps( - bundle2.getrepocaps(pushop.repo, allowpushback=pushback, role="client") + bundle2.getrepocaps(pushop.repo, allowpushback=pushback, role=b"client") ) - bundler.newpart("replycaps", data=capsblob) + bundler.newpart(b"replycaps", data=capsblob) replyhandlers = [] for partgenname in b2partsgenorder: partgen = b2partsgenmapping[partgenname] @@ -1284,27 +1293,27 @@ try: with pushop.remote.commandexecutor() as e: reply = e.callcommand( - "unbundle", + b"unbundle", { - "bundle": stream, - "heads": ["force"], - "url": pushop.remote.url(), + b"bundle": stream, + b"heads": [b"force"], + b"url": pushop.remote.url(), }, ).result() except error.BundleValueError as exc: - raise error.Abort(_("missing support for %s") % exc) + raise error.Abort(_(b"missing support for %s") % exc) try: trgetter = None if pushback: trgetter = pushop.trmanager.transaction op = bundle2.processbundle(pushop.repo, reply, trgetter) except error.BundleValueError as exc: - raise error.Abort(_("missing support for %s") % exc) + raise error.Abort(_(b"missing support for %s") % exc) except bundle2.AbortFromPart as exc: - pushop.ui.status(_("remote: %s\n") % exc) + pushop.ui.status(_(b"remote: %s\n") % exc) if exc.hint is not None: - pushop.ui.status(_("remote: %s\n") % ("(%s)" % exc.hint)) - raise error.Abort(_("push failed on remote")) + pushop.ui.status(_(b"remote: %s\n") % (b"(%s)" % exc.hint)) + raise error.Abort(_(b"push failed on remote")) except error.PushkeyFailed as exc: partid = int(exc.partid) if partid not in pushop.pkfailcb: @@ -1316,14 +1325,14 @@ def _pushchangeset(pushop): """Make the actual push of changeset bundle to remote repo""" - if "changesets" in pushop.stepsdone: + if b"changesets" in pushop.stepsdone: return - pushop.stepsdone.add("changesets") + pushop.stepsdone.add(b"changesets") if not _pushcheckoutgoing(pushop): return # Should have verified this in push(). - assert pushop.remote.capable("unbundle") + assert pushop.remote.capable(b"unbundle") pushop.repo.prepushoutgoinghooks(pushop) outgoing = pushop.outgoing @@ -1338,14 +1347,14 @@ cg = changegroup.makechangegroup( pushop.repo, outgoing, - "01", - "push", + b"01", + b"push", fastpath=True, bundlecaps=bundlecaps, ) else: cg = changegroup.makechangegroup( - pushop.repo, outgoing, "01", "push", bundlecaps=bundlecaps + pushop.repo, outgoing, b"01", b"push", bundlecaps=bundlecaps ) # apply changegroup to remote @@ -1354,7 +1363,7 @@ # finds it has different heads (someone else won # commit/push race), server aborts. if pushop.force: - remoteheads = ["force"] + remoteheads = [b"force"] else: remoteheads = pushop.remoteheads # ssh: return remote's addchangegroup() @@ -1366,12 +1375,12 @@ """synchronise phase information locally and remotely""" cheads = pushop.commonheads # even when we don't push, exchanging phase data is useful - remotephases = listkeys(pushop.remote, "phases") + remotephases = listkeys(pushop.remote, b"phases") if ( - pushop.ui.configbool("ui", "_usedassubrepo") + pushop.ui.configbool(b"ui", b"_usedassubrepo") and remotephases # server supports phases and pushop.cgresult is None # nothing was pushed - and remotephases.get("publishing", False) + and remotephases.get(b"publishing", False) ): # When: # - this is a subrepo push @@ -1382,7 +1391,7 @@ # We drop the possible phase synchronisation done by # courtesy to publish changesets possibly locally draft # on the remote. - remotephases = {"publishing": "True"} + remotephases = {b"publishing": b"True"} if not remotephases: # old server or public only reply from non-publishing _localphasemove(pushop, cheads) # don't push any phase data as there is nothing to push @@ -1390,7 +1399,7 @@ ana = phases.analyzeremotephases(pushop.repo, cheads, remotephases) pheads, droots = ana ### Apply remote phase on local - if remotephases.get("publishing", False): + if remotephases.get(b"publishing", False): _localphasemove(pushop, cheads) else: # publish = False _localphasemove(pushop, pheads) @@ -1398,14 +1407,14 @@ ### Apply local phase on remote if pushop.cgresult: - if "phases" in pushop.stepsdone: + if b"phases" in pushop.stepsdone: # phases already pushed though bundle2 return outdated = pushop.outdatedphases else: outdated = pushop.fallbackoutdatedphases - pushop.stepsdone.add("phases") + pushop.stepsdone.add(b"phases") # filter heads already turned public by the push outdated = [c for c in outdated if c.node() not in pheads] @@ -1413,18 +1422,18 @@ for newremotehead in outdated: with pushop.remote.commandexecutor() as e: r = e.callcommand( - "pushkey", + b"pushkey", { - "namespace": "phases", - "key": newremotehead.hex(), - "old": "%d" % phases.draft, - "new": "%d" % phases.public, + b"namespace": b"phases", + b"key": newremotehead.hex(), + b"old": b"%d" % phases.draft, + b"new": b"%d" % phases.public, }, ).result() if not r: pushop.ui.warn( - _("updating %s to public failed!\n") % newremotehead + _(b"updating %s to public failed!\n") % newremotehead ) @@ -1443,8 +1452,8 @@ if actualmoves: pushop.ui.status( _( - "cannot lock source repo, skipping " - "local %s phase update\n" + b"cannot lock source repo, skipping " + b"local %s phase update\n" ) % phasestr ) @@ -1452,47 +1461,47 @@ def _pushobsolete(pushop): """utility function to push obsolete markers to a remote""" - if "obsmarkers" in pushop.stepsdone: + if b"obsmarkers" in pushop.stepsdone: return repo = pushop.repo remote = pushop.remote - pushop.stepsdone.add("obsmarkers") + pushop.stepsdone.add(b"obsmarkers") if pushop.outobsmarkers: - pushop.ui.debug("try to push obsolete markers to remote\n") + pushop.ui.debug(b"try to push obsolete markers to remote\n") rslts = [] remotedata = obsolete._pushkeyescape(sorted(pushop.outobsmarkers)) for key in sorted(remotedata, reverse=True): # reverse sort to ensure we end with dump0 data = remotedata[key] - rslts.append(remote.pushkey("obsolete", key, "", data)) + rslts.append(remote.pushkey(b"obsolete", key, b"", data)) if [r for r in rslts if not r]: - msg = _("failed to push some obsolete markers!\n") + msg = _(b"failed to push some obsolete markers!\n") repo.ui.warn(msg) def _pushbookmark(pushop): """Update bookmark position on remote""" - if pushop.cgresult == 0 or "bookmarks" in pushop.stepsdone: + if pushop.cgresult == 0 or b"bookmarks" in pushop.stepsdone: return - pushop.stepsdone.add("bookmarks") + pushop.stepsdone.add(b"bookmarks") ui = pushop.ui remote = pushop.remote for b, old, new in pushop.outbookmarks: - action = "update" + action = b"update" if not old: - action = "export" + action = b"export" elif not new: - action = "delete" + action = b"delete" with remote.commandexecutor() as e: r = e.callcommand( - "pushkey", + b"pushkey", { - "namespace": "bookmarks", - "key": b, - "old": hex(old), - "new": hex(new), + b"namespace": b"bookmarks", + b"key": b, + b"old": hex(old), + b"new": hex(new), }, ).result() @@ -1610,10 +1619,10 @@ def transaction(self): """Return an open transaction object, constructing if necessary""" if not self._tr: - trname = "%s\n%s" % (self.source, util.hidepassword(self.url)) + trname = b"%s\n%s" % (self.source, util.hidepassword(self.url)) self._tr = self.repo.transaction(trname) - self._tr.hookargs["source"] = self.source - self._tr.hookargs["url"] = self.url + self._tr.hookargs[b"source"] = self.source + self._tr.hookargs[b"url"] = self.url return self._tr def close(self): @@ -1629,7 +1638,7 @@ def listkeys(remote, namespace): with remote.commandexecutor() as e: - return e.callcommand("listkeys", {"namespace": namespace}).result() + return e.callcommand(b"listkeys", {b"namespace": namespace}).result() def _fullpullbundle2(repo, pullop): @@ -1647,12 +1656,12 @@ def headsofdiff(h1, h2): """Returns heads(h1 % h2)""" - res = unfi.set("heads(%ln %% %ln)", h1, h2) + res = unfi.set(b"heads(%ln %% %ln)", h1, h2) return set(ctx.node() for ctx in res) def headsofunion(h1, h2): """Returns heads((h1 + h2) - null)""" - res = unfi.set("heads((%ln + %ln - null))", h1, h2) + res = unfi.set(b"heads((%ln + %ln - null))", h1, h2) return set(ctx.node() for ctx in res) while True: @@ -1744,19 +1753,19 @@ missing = set(peerlocal.requirements) - pullop.repo.supported if missing: msg = _( - "required features are not" - " supported in the destination:" - " %s" - ) % (", ".join(sorted(missing))) + b"required features are not" + b" supported in the destination:" + b" %s" + ) % (b", ".join(sorted(missing))) raise error.Abort(msg) - pullop.trmanager = transactionmanager(repo, "pull", remote.url()) + pullop.trmanager = transactionmanager(repo, b"pull", remote.url()) wlock = util.nullcontextmanager() if not bookmod.bookmarksinstore(repo): wlock = repo.wlock() with wlock, repo.lock(), pullop.trmanager: # Use the modern wire protocol, if available. - if remote.capable("command-changesetdata"): + if remote.capable(b"command-changesetdata"): exchangev2.pull(pullop) else: # This should ideally be in _pullbundle2(). However, it needs to run @@ -1772,7 +1781,7 @@ _pullobsolete(pullop) # storing remotenames - if repo.ui.configbool("experimental", "remotenames"): + if repo.ui.configbool(b"experimental", b"remotenames"): logexchange.pullremotenames(repo, remote) return pullop @@ -1813,7 +1822,7 @@ step(pullop) -@pulldiscovery("b1:bookmarks") +@pulldiscovery(b"b1:bookmarks") def _pullbookmarkbundle1(pullop): """fetch bookmark data in bundle1 case @@ -1821,15 +1830,15 @@ discovery to reduce the chance and impact of race conditions.""" if pullop.remotebookmarks is not None: return - if pullop.canusebundle2 and "listkeys" in pullop.remotebundle2caps: + if pullop.canusebundle2 and b"listkeys" in pullop.remotebundle2caps: # all known bundle2 servers now support listkeys, but lets be nice with # new implementation. return - books = listkeys(pullop.remote, "bookmarks") + books = listkeys(pullop.remote, b"bookmarks") pullop.remotebookmarks = bookmod.unhexlifybookmarks(books) -@pulldiscovery("changegroup") +@pulldiscovery(b"changegroup") def _pulldiscoverychangegroup(pullop): """discovery phase for the pull @@ -1866,7 +1875,7 @@ """pull data using bundle2 For now, the only supported data are changegroup.""" - kwargs = {"bundlecaps": caps20to10(pullop.repo, role="client")} + kwargs = {b"bundlecaps": caps20to10(pullop.repo, role=b"client")} # make ui easier to access ui = pullop.repo.ui @@ -1876,60 +1885,60 @@ streaming = streamclone.canperformstreamclone(pullop, bundle2=True)[0] # declare pull perimeters - kwargs["common"] = pullop.common - kwargs["heads"] = pullop.heads or pullop.rheads + kwargs[b"common"] = pullop.common + kwargs[b"heads"] = pullop.heads or pullop.rheads # check server supports narrow and then adding includepats and excludepats servernarrow = pullop.remote.capable(wireprototypes.NARROWCAP) if servernarrow and pullop.includepats: - kwargs["includepats"] = pullop.includepats + kwargs[b"includepats"] = pullop.includepats if servernarrow and pullop.excludepats: - kwargs["excludepats"] = pullop.excludepats + kwargs[b"excludepats"] = pullop.excludepats if streaming: - kwargs["cg"] = False - kwargs["stream"] = True - pullop.stepsdone.add("changegroup") - pullop.stepsdone.add("phases") + kwargs[b"cg"] = False + kwargs[b"stream"] = True + pullop.stepsdone.add(b"changegroup") + pullop.stepsdone.add(b"phases") else: # pulling changegroup - pullop.stepsdone.add("changegroup") - - kwargs["cg"] = pullop.fetch - - legacyphase = "phases" in ui.configlist("devel", "legacy.exchange") - hasbinaryphase = "heads" in pullop.remotebundle2caps.get("phases", ()) + pullop.stepsdone.add(b"changegroup") + + kwargs[b"cg"] = pullop.fetch + + legacyphase = b"phases" in ui.configlist(b"devel", b"legacy.exchange") + hasbinaryphase = b"heads" in pullop.remotebundle2caps.get(b"phases", ()) if not legacyphase and hasbinaryphase: - kwargs["phases"] = True - pullop.stepsdone.add("phases") - - if "listkeys" in pullop.remotebundle2caps: - if "phases" not in pullop.stepsdone: - kwargs["listkeys"] = ["phases"] + kwargs[b"phases"] = True + pullop.stepsdone.add(b"phases") + + if b"listkeys" in pullop.remotebundle2caps: + if b"phases" not in pullop.stepsdone: + kwargs[b"listkeys"] = [b"phases"] bookmarksrequested = False - legacybookmark = "bookmarks" in ui.configlist("devel", "legacy.exchange") - hasbinarybook = "bookmarks" in pullop.remotebundle2caps + legacybookmark = b"bookmarks" in ui.configlist(b"devel", b"legacy.exchange") + hasbinarybook = b"bookmarks" in pullop.remotebundle2caps if pullop.remotebookmarks is not None: - pullop.stepsdone.add("request-bookmarks") + pullop.stepsdone.add(b"request-bookmarks") if ( - "request-bookmarks" not in pullop.stepsdone + b"request-bookmarks" not in pullop.stepsdone and pullop.remotebookmarks is None and not legacybookmark and hasbinarybook ): - kwargs["bookmarks"] = True + kwargs[b"bookmarks"] = True bookmarksrequested = True - if "listkeys" in pullop.remotebundle2caps: - if "request-bookmarks" not in pullop.stepsdone: + if b"listkeys" in pullop.remotebundle2caps: + if b"request-bookmarks" not in pullop.stepsdone: # make sure to always includes bookmark data when migrating # `hg incoming --bundle` to using this function. - pullop.stepsdone.add("request-bookmarks") - kwargs.setdefault("listkeys", []).append("bookmarks") + pullop.stepsdone.add(b"request-bookmarks") + kwargs.setdefault(b"listkeys", []).append(b"bookmarks") # If this is a full pull / clone and the server supports the clone bundles # feature, tell the server whether we attempted a clone bundle. The @@ -1937,61 +1946,61 @@ # will enable the server to treat clients that support clone bundles # differently from those that don't. if ( - pullop.remote.capable("clonebundles") + pullop.remote.capable(b"clonebundles") and pullop.heads is None and list(pullop.common) == [nullid] ): - kwargs["cbattempted"] = pullop.clonebundleattempted + kwargs[b"cbattempted"] = pullop.clonebundleattempted if streaming: - pullop.repo.ui.status(_("streaming all changes\n")) + pullop.repo.ui.status(_(b"streaming all changes\n")) elif not pullop.fetch: - pullop.repo.ui.status(_("no changes found\n")) + pullop.repo.ui.status(_(b"no changes found\n")) pullop.cgresult = 0 else: if pullop.heads is None and list(pullop.common) == [nullid]: - pullop.repo.ui.status(_("requesting all changes\n")) + pullop.repo.ui.status(_(b"requesting all changes\n")) if obsolete.isenabled(pullop.repo, obsolete.exchangeopt): remoteversions = bundle2.obsmarkersversion(pullop.remotebundle2caps) if obsolete.commonversion(remoteversions) is not None: - kwargs["obsmarkers"] = True - pullop.stepsdone.add("obsmarkers") + kwargs[b"obsmarkers"] = True + pullop.stepsdone.add(b"obsmarkers") _pullbundle2extraprepare(pullop, kwargs) with pullop.remote.commandexecutor() as e: args = dict(kwargs) - args["source"] = "pull" - bundle = e.callcommand("getbundle", args).result() + args[b"source"] = b"pull" + bundle = e.callcommand(b"getbundle", args).result() try: op = bundle2.bundleoperation( - pullop.repo, pullop.gettransaction, source="pull" + pullop.repo, pullop.gettransaction, source=b"pull" ) - op.modes["bookmarks"] = "records" + op.modes[b"bookmarks"] = b"records" bundle2.processbundle(pullop.repo, bundle, op=op) except bundle2.AbortFromPart as exc: - pullop.repo.ui.status(_("remote: abort: %s\n") % exc) - raise error.Abort(_("pull failed on remote"), hint=exc.hint) + pullop.repo.ui.status(_(b"remote: abort: %s\n") % exc) + raise error.Abort(_(b"pull failed on remote"), hint=exc.hint) except error.BundleValueError as exc: - raise error.Abort(_("missing support for %s") % exc) + raise error.Abort(_(b"missing support for %s") % exc) if pullop.fetch: pullop.cgresult = bundle2.combinechangegroupresults(op) # processing phases change - for namespace, value in op.records["listkeys"]: - if namespace == "phases": + for namespace, value in op.records[b"listkeys"]: + if namespace == b"phases": _pullapplyphases(pullop, value) # processing bookmark update if bookmarksrequested: books = {} - for record in op.records["bookmarks"]: - books[record["bookmark"]] = record["node"] + for record in op.records[b"bookmarks"]: + books[record[b"bookmark"]] = record[b"node"] pullop.remotebookmarks = books else: - for namespace, value in op.records["listkeys"]: - if namespace == "bookmarks": + for namespace, value in op.records[b"listkeys"]: + if namespace == b"bookmarks": pullop.remotebookmarks = bookmod.unhexlifybookmarks(value) # bookmark data were either already there or pulled in the bundle @@ -2008,70 +2017,70 @@ # We delay the open of the transaction as late as possible so we # don't open transaction for nothing or you break future useful # rollback call - if "changegroup" in pullop.stepsdone: + if b"changegroup" in pullop.stepsdone: return - pullop.stepsdone.add("changegroup") + pullop.stepsdone.add(b"changegroup") if not pullop.fetch: - pullop.repo.ui.status(_("no changes found\n")) + pullop.repo.ui.status(_(b"no changes found\n")) pullop.cgresult = 0 return tr = pullop.gettransaction() if pullop.heads is None and list(pullop.common) == [nullid]: - pullop.repo.ui.status(_("requesting all changes\n")) - elif pullop.heads is None and pullop.remote.capable("changegroupsubset"): + pullop.repo.ui.status(_(b"requesting all changes\n")) + elif pullop.heads is None and pullop.remote.capable(b"changegroupsubset"): # issue1320, avoid a race if remote changed after discovery pullop.heads = pullop.rheads - if pullop.remote.capable("getbundle"): + if pullop.remote.capable(b"getbundle"): # TODO: get bundlecaps from remote cg = pullop.remote.getbundle( - "pull", common=pullop.common, heads=pullop.heads or pullop.rheads + b"pull", common=pullop.common, heads=pullop.heads or pullop.rheads ) elif pullop.heads is None: with pullop.remote.commandexecutor() as e: cg = e.callcommand( - "changegroup", {"nodes": pullop.fetch, "source": "pull",} + b"changegroup", {b"nodes": pullop.fetch, b"source": b"pull",} ).result() - elif not pullop.remote.capable("changegroupsubset"): + elif not pullop.remote.capable(b"changegroupsubset"): raise error.Abort( _( - "partial pull cannot be done because " - "other repository doesn't support " - "changegroupsubset." + b"partial pull cannot be done because " + b"other repository doesn't support " + b"changegroupsubset." ) ) else: with pullop.remote.commandexecutor() as e: cg = e.callcommand( - "changegroupsubset", + b"changegroupsubset", { - "bases": pullop.fetch, - "heads": pullop.heads, - "source": "pull", + b"bases": pullop.fetch, + b"heads": pullop.heads, + b"source": b"pull", }, ).result() bundleop = bundle2.applybundle( - pullop.repo, cg, tr, "pull", pullop.remote.url() + pullop.repo, cg, tr, b"pull", pullop.remote.url() ) pullop.cgresult = bundle2.combinechangegroupresults(bundleop) def _pullphase(pullop): # Get remote phases data from remote - if "phases" in pullop.stepsdone: + if b"phases" in pullop.stepsdone: return - remotephases = listkeys(pullop.remote, "phases") + remotephases = listkeys(pullop.remote, b"phases") _pullapplyphases(pullop, remotephases) def _pullapplyphases(pullop, remotephases): """apply phase movement from observed remote state""" - if "phases" in pullop.stepsdone: + if b"phases" in pullop.stepsdone: return - pullop.stepsdone.add("phases") - publishing = bool(remotephases.get("publishing", False)) + pullop.stepsdone.add(b"phases") + publishing = bool(remotephases.get(b"publishing", False)) if remotephases and not publishing: # remote is new and non-publishing pheads, _dr = phases.analyzeremotephases( @@ -2104,9 +2113,9 @@ def _pullbookmarks(pullop): """process the remote bookmark information to update the local one""" - if "bookmarks" in pullop.stepsdone: + if b"bookmarks" in pullop.stepsdone: return - pullop.stepsdone.add("bookmarks") + pullop.stepsdone.add(b"bookmarks") repo = pullop.repo remotebookmarks = pullop.remotebookmarks bookmod.updatefromremote( @@ -2127,18 +2136,18 @@ a new transaction have been created (when applicable). Exists mostly to allow overriding for experimentation purpose""" - if "obsmarkers" in pullop.stepsdone: + if b"obsmarkers" in pullop.stepsdone: return - pullop.stepsdone.add("obsmarkers") + pullop.stepsdone.add(b"obsmarkers") tr = None if obsolete.isenabled(pullop.repo, obsolete.exchangeopt): - pullop.repo.ui.debug("fetching remote obsolete markers\n") - remoteobs = listkeys(pullop.remote, "obsolete") - if "dump0" in remoteobs: + pullop.repo.ui.debug(b"fetching remote obsolete markers\n") + remoteobs = listkeys(pullop.remote, b"obsolete") + if b"dump0" in remoteobs: tr = pullop.gettransaction() markers = [] for key in sorted(remoteobs, reverse=True): - if key.startswith("dump"): + if key.startswith(b"dump"): data = util.b85decode(remoteobs[key]) version, newmarks = obsolete._readmarkers(data) markers += newmarks @@ -2156,29 +2165,29 @@ """ ui = repo.ui # TODO this assumes existence of HTTP and is a layering violation. - username = ui.shortuser(ui.environ.get("REMOTE_USER") or ui.username()) + username = ui.shortuser(ui.environ.get(b"REMOTE_USER") or ui.username()) user_includes = ui.configlist( _NARROWACL_SECTION, - username + ".includes", - ui.configlist(_NARROWACL_SECTION, "default.includes"), + username + b".includes", + ui.configlist(_NARROWACL_SECTION, b"default.includes"), ) user_excludes = ui.configlist( _NARROWACL_SECTION, - username + ".excludes", - ui.configlist(_NARROWACL_SECTION, "default.excludes"), + username + b".excludes", + ui.configlist(_NARROWACL_SECTION, b"default.excludes"), ) if not user_includes: raise error.Abort( - _("{} configuration for user {} is empty").format( + _(b"{} configuration for user {} is empty").format( _NARROWACL_SECTION, username ) ) user_includes = [ - "path:." if p == "*" else "path:" + p for p in user_includes + b"path:." if p == b"*" else b"path:" + p for p in user_includes ] user_excludes = [ - "path:." if p == "*" else "path:" + p for p in user_excludes + b"path:." if p == b"*" else b"path:" + p for p in user_excludes ] req_includes = set(kwargs.get(r"includepats", [])) @@ -2190,7 +2199,7 @@ if invalid_includes: raise error.Abort( - _("The following includes are not accessible for {}: {}").format( + _(b"The following includes are not accessible for {}: {}").format( username, invalid_includes ) ) @@ -2265,7 +2274,7 @@ r1, r2, r3 = sorted(ellipsisroots[head]) for nr1, nr2 in ((r2, r3), (r1, r3), (r1, r2)): mid = repo.revs( - "sort(merge() & %d::%d & %d::%d, -rev)", nr1, head, nr2, head + b"sort(merge() & %d::%d & %d::%d, -rev)", nr1, head, nr2, head ) for j in mid: if j == nr2: @@ -2273,7 +2282,10 @@ if j not in ellipsisroots or len(ellipsisroots[j]) < 2: return j, (nr1, nr2) raise error.Abort( - _("Failed to split up ellipsis node! head: %d, " "roots: %d %d %d") + _( + b"Failed to split up ellipsis node! head: %d, " + b"roots: %d %d %d" + ) % (head, r1, r2, r3) ) @@ -2338,9 +2350,9 @@ def caps20to10(repo, role): """return a set with appropriate options to use bundle20 during getbundle""" - caps = {"HG20"} + caps = {b"HG20"} capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role=role)) - caps.add("bundle2=" + urlreq.quote(capsblob)) + caps.add(b"bundle2=" + urlreq.quote(capsblob)) return caps @@ -2377,7 +2389,7 @@ def bundle2requested(bundlecaps): if bundlecaps is not None: - return any(cap.startswith("HG2") for cap in bundlecaps) + return any(cap.startswith(b"HG2") for cap in bundlecaps) return False @@ -2397,34 +2409,36 @@ usebundle2 = bundle2requested(bundlecaps) # bundle10 case if not usebundle2: - if bundlecaps and not kwargs.get("cg", True): - raise ValueError(_("request for bundle10 must include changegroup")) + if bundlecaps and not kwargs.get(b"cg", True): + raise ValueError( + _(b"request for bundle10 must include changegroup") + ) if kwargs: raise ValueError( - _("unsupported getbundle arguments: %s") - % ", ".join(sorted(kwargs.keys())) + _(b"unsupported getbundle arguments: %s") + % b", ".join(sorted(kwargs.keys())) ) outgoing = _computeoutgoing(repo, heads, common) - info["bundleversion"] = 1 + info[b"bundleversion"] = 1 return ( info, changegroup.makestream( - repo, outgoing, "01", source, bundlecaps=bundlecaps + repo, outgoing, b"01", source, bundlecaps=bundlecaps ), ) # bundle20 case - info["bundleversion"] = 2 + info[b"bundleversion"] = 2 b2caps = {} for bcaps in bundlecaps: - if bcaps.startswith("bundle2="): - blob = urlreq.unquote(bcaps[len("bundle2=") :]) + if bcaps.startswith(b"bundle2="): + blob = urlreq.unquote(bcaps[len(b"bundle2=") :]) b2caps.update(bundle2.decodecaps(blob)) bundler = bundle2.bundle20(repo.ui, b2caps) - kwargs["heads"] = heads - kwargs["common"] = common + kwargs[b"heads"] = heads + kwargs[b"common"] = common for name in getbundle2partsorder: func = getbundle2partsmapping[name] @@ -2437,17 +2451,17 @@ **pycompat.strkwargs(kwargs) ) - info["prefercompressed"] = bundler.prefercompressed + info[b"prefercompressed"] = bundler.prefercompressed return info, bundler.getchunks() -@getbundle2partsgenerator("stream2") +@getbundle2partsgenerator(b"stream2") def _getbundlestream2(bundler, repo, *args, **kwargs): return bundle2.addpartbundlestream2(bundler, repo, **kwargs) -@getbundle2partsgenerator("changegroup") +@getbundle2partsgenerator(b"changegroup") def _getbundlechangegrouppart( bundler, repo, @@ -2462,8 +2476,8 @@ if not kwargs.get(r"cg", True): return - version = "01" - cgversions = b2caps.get("changegroup") + version = b"01" + cgversions = b2caps.get(b"changegroup") if cgversions: # 3.1 and 3.2 ship with an empty value cgversions = [ v @@ -2471,7 +2485,7 @@ if v in changegroup.supportedoutgoingversions(repo) ] if not cgversions: - raise error.Abort(_("no common changegroup version")) + raise error.Abort(_(b"no common changegroup version")) version = max(cgversions) outgoing = _computeoutgoing(repo, heads, common) @@ -2489,14 +2503,14 @@ repo, outgoing, version, source, bundlecaps=bundlecaps, matcher=matcher ) - part = bundler.newpart("changegroup", data=cgstream) + part = bundler.newpart(b"changegroup", data=cgstream) if cgversions: - part.addparam("version", version) - - part.addparam("nbchanges", "%d" % len(outgoing.missing), mandatory=False) - - if "treemanifest" in repo.requirements: - part.addparam("treemanifest", "1") + part.addparam(b"version", version) + + part.addparam(b"nbchanges", b"%d" % len(outgoing.missing), mandatory=False) + + if b"treemanifest" in repo.requirements: + part.addparam(b"treemanifest", b"1") if ( kwargs.get(r"narrow", False) @@ -2504,42 +2518,42 @@ and (include or exclude) ): # this is mandatory because otherwise ACL clients won't work - narrowspecpart = bundler.newpart("Narrow:responsespec") - narrowspecpart.data = "%s\0%s" % ( - "\n".join(include), - "\n".join(exclude), + narrowspecpart = bundler.newpart(b"Narrow:responsespec") + narrowspecpart.data = b"%s\0%s" % ( + b"\n".join(include), + b"\n".join(exclude), ) -@getbundle2partsgenerator("bookmarks") +@getbundle2partsgenerator(b"bookmarks") def _getbundlebookmarkpart( bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs ): """add a bookmark part to the requested bundle""" if not kwargs.get(r"bookmarks", False): return - if "bookmarks" not in b2caps: - raise error.Abort(_("no common bookmarks exchange method")) + if b"bookmarks" not in b2caps: + raise error.Abort(_(b"no common bookmarks exchange method")) books = bookmod.listbinbookmarks(repo) data = bookmod.binaryencode(books) if data: - bundler.newpart("bookmarks", data=data) - - -@getbundle2partsgenerator("listkeys") + bundler.newpart(b"bookmarks", data=data) + + +@getbundle2partsgenerator(b"listkeys") def _getbundlelistkeysparts( bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs ): """add parts containing listkeys namespaces to the requested bundle""" listkeys = kwargs.get(r"listkeys", ()) for namespace in listkeys: - part = bundler.newpart("listkeys") - part.addparam("namespace", namespace) + part = bundler.newpart(b"listkeys") + part.addparam(b"namespace", namespace) keys = repo.listkeys(namespace).items() part.data = pushkey.encodekeys(keys) -@getbundle2partsgenerator("obsmarkers") +@getbundle2partsgenerator(b"obsmarkers") def _getbundleobsmarkerpart( bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs ): @@ -2547,20 +2561,20 @@ if kwargs.get(r"obsmarkers", False): if heads is None: heads = repo.heads() - subset = [c.node() for c in repo.set("::%ln", heads)] + subset = [c.node() for c in repo.set(b"::%ln", heads)] markers = repo.obsstore.relevantmarkers(subset) markers = sorted(markers) bundle2.buildobsmarkerspart(bundler, markers) -@getbundle2partsgenerator("phases") +@getbundle2partsgenerator(b"phases") def _getbundlephasespart( bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs ): """add phase heads part to the requested bundle""" if kwargs.get(r"phases", False): - if not "heads" in b2caps.get("phases"): - raise error.Abort(_("no common phases exchange method")) + if not b"heads" in b2caps.get(b"phases"): + raise error.Abort(_(b"no common phases exchange method")) if heads is None: heads = repo.heads() @@ -2587,7 +2601,7 @@ if draftheads: publicheads = headsbyphase.get(phases.public, set()) - revset = "heads(only(%ln, %ln) and public())" + revset = b"heads(only(%ln, %ln) and public())" extraheads = repo.revs(revset, draftheads, publicheads) for r in extraheads: headsbyphase[phases.public].add(node(r)) @@ -2599,10 +2613,10 @@ # generate the actual part phasedata = phases.binaryencode(phasemapping) - bundler.newpart("phase-heads", data=phasedata) - - -@getbundle2partsgenerator("hgtagsfnodes") + bundler.newpart(b"phase-heads", data=phasedata) + + +@getbundle2partsgenerator(b"hgtagsfnodes") def _getbundletagsfnodes( bundler, repo, @@ -2623,14 +2637,14 @@ # Don't send unless: # - changeset are being exchanged, # - the client supports it. - if not (kwargs.get(r"cg", True) and "hgtagsfnodes" in b2caps): + if not (kwargs.get(r"cg", True) and b"hgtagsfnodes" in b2caps): return outgoing = _computeoutgoing(repo, heads, common) bundle2.addparttagsfnodescache(repo, bundler, outgoing) -@getbundle2partsgenerator("cache:rev-branch-cache") +@getbundle2partsgenerator(b"cache:rev-branch-cache") def _getbundlerevbranchcache( bundler, repo, @@ -2657,7 +2671,7 @@ # - narrow bundle isn't in play (not currently compatible). if ( not kwargs.get(r"cg", True) - or "rev-branch-cache" not in b2caps + or b"rev-branch-cache" not in b2caps or kwargs.get(r"narrow", False) or repo.ui.has_section(_NARROWACL_SECTION) ): @@ -2673,16 +2687,16 @@ Used by peer for unbundling. """ heads = repo.heads() - heads_hash = hashlib.sha1("".join(sorted(heads))).digest() + heads_hash = hashlib.sha1(b"".join(sorted(heads))).digest() if not ( - their_heads == ["force"] + their_heads == [b"force"] or their_heads == heads - or their_heads == ["hashed", heads_hash] + or their_heads == [b"hashed", heads_hash] ): # someone else committed/pushed/unbundled while we # were transferring data raise error.PushRaced( - "repository changed while %s - " "please try again" % context + b"repository changed while %s - " b"please try again" % context ) @@ -2700,17 +2714,19 @@ lockandtr = [None, None, None] recordout = None # quick fix for output mismatch with bundle2 in 3.4 - captureoutput = repo.ui.configbool("experimental", "bundle2-output-capture") - if url.startswith("remote:http:") or url.startswith("remote:https:"): + captureoutput = repo.ui.configbool( + b"experimental", b"bundle2-output-capture" + ) + if url.startswith(b"remote:http:") or url.startswith(b"remote:https:"): captureoutput = True try: # note: outside bundle1, 'heads' is expected to be empty and this # 'check_heads' call wil be a no-op - check_heads(repo, heads, "uploading changes") + check_heads(repo, heads, b"uploading changes") # push can proceed if not isinstance(cg, bundle2.unbundle20): # legacy case: bundle1 (changegroup 01) - txnname = "\n".join([source, util.hidepassword(url)]) + txnname = b"\n".join([source, util.hidepassword(url)]) with repo.lock(), repo.transaction(txnname) as tr: op = bundle2.applybundle(repo, cg, tr, source, url) r = bundle2.combinechangegroupresults(op) @@ -2724,21 +2740,23 @@ lockandtr[0] = repo.wlock() lockandtr[1] = repo.lock() lockandtr[2] = repo.transaction(source) - lockandtr[2].hookargs["source"] = source - lockandtr[2].hookargs["url"] = url - lockandtr[2].hookargs["bundle2"] = "1" + lockandtr[2].hookargs[b"source"] = source + lockandtr[2].hookargs[b"url"] = url + lockandtr[2].hookargs[b"bundle2"] = b"1" return lockandtr[2] # Do greedy locking by default until we're satisfied with lazy # locking. - if not repo.ui.configbool("experimental", "bundle2lazylocking"): + if not repo.ui.configbool( + b"experimental", b"bundle2lazylocking" + ): gettransaction() op = bundle2.bundleoperation( repo, gettransaction, captureoutput=captureoutput, - source="push", + source=b"push", ) try: op = bundle2.processbundle(repo, cg, op=op) @@ -2748,7 +2766,7 @@ repo.ui.pushbuffer(error=True, subproc=True) def recordout(output): - r.newpart("output", data=output, mandatory=False) + r.newpart(b"output", data=output, mandatory=False) if lockandtr[2] is not None: lockandtr[2].close() @@ -2759,7 +2777,7 @@ def recordout(output): part = bundle2.bundlepart( - "output", data=output, mandatory=False + b"output", data=output, mandatory=False ) parts.append(part) @@ -2777,7 +2795,7 @@ repo = pullop.repo remote = pullop.remote - if not repo.ui.configbool("ui", "clonebundles"): + if not repo.ui.configbool(b"ui", b"clonebundles"): return # Only run if local repo is empty. @@ -2787,11 +2805,11 @@ if pullop.heads: return - if not remote.capable("clonebundles"): + if not remote.capable(b"clonebundles"): return with remote.commandexecutor() as e: - res = e.callcommand("clonebundles", {}).result() + res = e.callcommand(b"clonebundles", {}).result() # If we call the wire protocol command, that's good enough to record the # attempt. @@ -2801,8 +2819,8 @@ if not entries: repo.ui.note( _( - "no clone bundles available on remote; " - "falling back to regular clone\n" + b"no clone bundles available on remote; " + b"falling back to regular clone\n" ) ) return @@ -2819,36 +2837,36 @@ # clone! repo.ui.warn( _( - "no compatible clone bundles available on server; " - "falling back to regular clone\n" + b"no compatible clone bundles available on server; " + b"falling back to regular clone\n" ) ) repo.ui.warn( - _("(you may want to report this to the server " "operator)\n") + _(b"(you may want to report this to the server " b"operator)\n") ) return entries = sortclonebundleentries(repo.ui, entries) - url = entries[0]["URL"] - repo.ui.status(_("applying clone bundle from %s\n") % url) + url = entries[0][b"URL"] + repo.ui.status(_(b"applying clone bundle from %s\n") % url) if trypullbundlefromurl(repo.ui, repo, url): - repo.ui.status(_("finished applying clone bundle\n")) + repo.ui.status(_(b"finished applying clone bundle\n")) # Bundle failed. # # We abort by default to avoid the thundering herd of # clients flooding a server that was expecting expensive # clone load to be offloaded. - elif repo.ui.configbool("ui", "clonebundlefallback"): - repo.ui.warn(_("falling back to normal clone\n")) + elif repo.ui.configbool(b"ui", b"clonebundlefallback"): + repo.ui.warn(_(b"falling back to normal clone\n")) else: raise error.Abort( - _("error applying bundle"), + _(b"error applying bundle"), hint=_( - "if this error persists, consider contacting " - "the server operator or disable clone " - "bundles via " - '"--config ui.clonebundles=false"' + b"if this error persists, consider contacting " + b"the server operator or disable clone " + b"bundles via " + b'"--config ui.clonebundles=false"' ), ) @@ -2864,9 +2882,9 @@ fields = line.split() if not fields: continue - attrs = {"URL": fields[0]} + attrs = {b"URL": fields[0]} for rawattr in fields[1:]: - key, value = rawattr.split("=", 1) + key, value = rawattr.split(b"=", 1) key = urlreq.unquote(key) value = urlreq.unquote(value) attrs[key] = value @@ -2874,11 +2892,11 @@ # Parse BUNDLESPEC into components. This makes client-side # preferences easier to specify since you can prefer a single # component of the BUNDLESPEC. - if key == "BUNDLESPEC": + if key == b"BUNDLESPEC": try: bundlespec = parsebundlespec(repo, value) - attrs["COMPRESSION"] = bundlespec.compression - attrs["VERSION"] = bundlespec.version + attrs[b"COMPRESSION"] = bundlespec.compression + attrs[b"VERSION"] = bundlespec.version except error.InvalidBundleSpecification: pass except error.UnsupportedBundleSpecification: @@ -2891,14 +2909,14 @@ def isstreamclonespec(bundlespec): # Stream clone v1 - if bundlespec.wirecompression == "UN" and bundlespec.wireversion == "s1": + if bundlespec.wirecompression == b"UN" and bundlespec.wireversion == b"s1": return True # Stream clone v2 if ( - bundlespec.wirecompression == "UN" - and bundlespec.wireversion == "02" - and bundlespec.contentopts.get("streamv2") + bundlespec.wirecompression == b"UN" + and bundlespec.wireversion == b"02" + and bundlespec.contentopts.get(b"streamv2") ): return True @@ -2917,7 +2935,7 @@ """ newentries = [] for entry in entries: - spec = entry.get("BUNDLESPEC") + spec = entry.get(b"BUNDLESPEC") if spec: try: bundlespec = parsebundlespec(repo, spec, strict=True) @@ -2926,32 +2944,32 @@ # entries. if streamclonerequested and not isstreamclonespec(bundlespec): repo.ui.debug( - "filtering %s because not a stream clone\n" - % entry["URL"] + b"filtering %s because not a stream clone\n" + % entry[b"URL"] ) continue except error.InvalidBundleSpecification as e: - repo.ui.debug(stringutil.forcebytestr(e) + "\n") + repo.ui.debug(stringutil.forcebytestr(e) + b"\n") continue except error.UnsupportedBundleSpecification as e: repo.ui.debug( - "filtering %s because unsupported bundle " - "spec: %s\n" % (entry["URL"], stringutil.forcebytestr(e)) + b"filtering %s because unsupported bundle " + b"spec: %s\n" % (entry[b"URL"], stringutil.forcebytestr(e)) ) continue # If we don't have a spec and requested a stream clone, we don't know # what the entry is so don't attempt to apply it. elif streamclonerequested: repo.ui.debug( - "filtering %s because cannot determine if a stream " - "clone bundle\n" % entry["URL"] + b"filtering %s because cannot determine if a stream " + b"clone bundle\n" % entry[b"URL"] ) continue - if "REQUIRESNI" in entry and not sslutil.hassni: + if b"REQUIRESNI" in entry and not sslutil.hassni: repo.ui.debug( - "filtering %s because SNI not supported\n" % entry["URL"] + b"filtering %s because SNI not supported\n" % entry[b"URL"] ) continue @@ -3026,11 +3044,11 @@ def sortclonebundleentries(ui, entries): - prefers = ui.configlist("ui", "clonebundleprefers") + prefers = ui.configlist(b"ui", b"clonebundleprefers") if not prefers: return list(entries) - prefers = [p.split("=", 1) for p in prefers] + prefers = [p.split(b"=", 1) for p in prefers] items = sorted(clonebundleentry(v, prefers) for v in entries) return [i.value for i in items] @@ -3038,24 +3056,24 @@ def trypullbundlefromurl(ui, repo, url): """Attempt to apply a bundle from a URL.""" - with repo.lock(), repo.transaction("bundleurl") as tr: + with repo.lock(), repo.transaction(b"bundleurl") as tr: try: fh = urlmod.open(ui, url) - cg = readbundle(ui, fh, "stream") + cg = readbundle(ui, fh, b"stream") if isinstance(cg, streamclone.streamcloneapplier): cg.apply(repo) else: - bundle2.applybundle(repo, cg, tr, "clonebundles", url) + bundle2.applybundle(repo, cg, tr, b"clonebundles", url) return True except urlerr.httperror as e: ui.warn( - _("HTTP error fetching bundle: %s\n") + _(b"HTTP error fetching bundle: %s\n") % stringutil.forcebytestr(e) ) except urlerr.urlerror as e: ui.warn( - _("error fetching bundle: %s\n") + _(b"error fetching bundle: %s\n") % stringutil.forcebytestr(e.reason) ) diff --git a/mercurial/exchangev2.py b/mercurial/exchangev2.py --- a/mercurial/exchangev2.py +++ b/mercurial/exchangev2.py @@ -39,7 +39,7 @@ # incremental pull. This is somewhat hacky and is not nearly robust enough # for long-term usage. if usingrawchangelogandmanifest: - with repo.transaction("clone"): + with repo.transaction(b"clone"): _fetchrawstorefiles(repo, remote) repo.invalidate(clearfilecache=True) @@ -51,7 +51,7 @@ repo.root, # Empty maps to nevermatcher. So always # set includes if missing. - pullop.includepats or {"path:."}, + pullop.includepats or {b"path:."}, pullop.excludepats, ) @@ -78,32 +78,32 @@ # Ensure all new changesets are draft by default. If the repo is # publishing, the phase will be adjusted by the loop below. - if csetres["added"]: - phases.registernew(repo, tr, phases.draft, csetres["added"]) + if csetres[b"added"]: + phases.registernew(repo, tr, phases.draft, csetres[b"added"]) # And adjust the phase of all changesets accordingly. for phase in phases.phasenames: - if phase == b"secret" or not csetres["nodesbyphase"][phase]: + if phase == b"secret" or not csetres[b"nodesbyphase"][phase]: continue phases.advanceboundary( repo, tr, phases.phasenames.index(phase), - csetres["nodesbyphase"][phase], + csetres[b"nodesbyphase"][phase], ) # Write bookmark updates. bookmarks.updatefromremote( repo.ui, repo, - csetres["bookmarks"], + csetres[b"bookmarks"], remote.url(), pullop.gettransaction, explicit=pullop.explicitbookmarks, ) - manres = _fetchmanifests(repo, tr, remote, csetres["manifestnodes"]) + manres = _fetchmanifests(repo, tr, remote, csetres[b"manifestnodes"]) # We don't properly support shallow changeset and manifest yet. So we apply # depth limiting locally. @@ -142,9 +142,9 @@ manifestlinkrevs[mnode] = rev else: - csetsforfiles = [n for n in csetres["added"] if csetrelevantfilter(n)] - mnodesforfiles = manres["added"] - manifestlinkrevs = manres["linkrevs"] + csetsforfiles = [n for n in csetres[b"added"] if csetrelevantfilter(n)] + mnodesforfiles = manres[b"added"] + manifestlinkrevs = manres[b"linkrevs"] # Find all file nodes referenced by added manifests and fetch those # revisions. @@ -197,7 +197,7 @@ overall = next(objs) progress = repo.ui.makeprogress( - _("clone"), total=overall[b"totalsize"], unit=_("bytes") + _(b"clone"), total=overall[b"totalsize"], unit=_(b"bytes") ) with progress: progress.update(0) @@ -330,7 +330,7 @@ def _processchangesetdata(repo, tr, objs): - repo.hook("prechangegroup", throw=True, **pycompat.strkwargs(tr.hookargs)) + repo.hook(b"prechangegroup", throw=True, **pycompat.strkwargs(tr.hookargs)) urepo = repo.unfiltered() cl = urepo.changelog @@ -342,13 +342,13 @@ meta = next(objs) progress = repo.ui.makeprogress( - _("changesets"), unit=_("chunks"), total=meta.get(b"totalitems") + _(b"changesets"), unit=_(b"chunks"), total=meta.get(b"totalitems") ) manifestnodes = {} def linkrev(node): - repo.ui.debug("add changeset %s\n" % short(node)) + repo.ui.debug(b"add changeset %s\n" % short(node)) # Linkrev for changelog is always self. return len(cl) @@ -413,10 +413,10 @@ progress.complete() return { - "added": added, - "nodesbyphase": nodesbyphase, - "bookmarks": remotebookmarks, - "manifestnodes": manifestnodes, + b"added": added, + b"nodesbyphase": nodesbyphase, + b"bookmarks": remotebookmarks, + b"manifestnodes": manifestnodes, } @@ -483,7 +483,7 @@ progress.increment() progress = repo.ui.makeprogress( - _("manifests"), unit=_("chunks"), total=len(fetchnodes) + _(b"manifests"), unit=_(b"chunks"), total=len(fetchnodes) ) commandmeta = remote.apidescriptor[b"commands"][b"manifestdata"] @@ -530,8 +530,8 @@ progress.complete() return { - "added": added, - "linkrevs": linkrevs, + b"added": added, + b"linkrevs": linkrevs, } @@ -545,7 +545,7 @@ fnodes = collections.defaultdict(dict) progress = repo.ui.makeprogress( - _("scanning manifests"), total=len(manifestnodes) + _(b"scanning manifests"), total=len(manifestnodes) ) with progress: @@ -605,8 +605,8 @@ progress.increment() progress = repo.ui.makeprogress( - _("files"), - unit=_("chunks"), + _(b"files"), + unit=_(b"chunks"), total=sum(len(v) for v in fnodes.itervalues()), ) @@ -704,8 +704,8 @@ remaining -= 1 progress = repo.ui.makeprogress( - _("files"), - unit=_("chunks"), + _(b"files"), + unit=_(b"chunks"), total=sum(len(v) for v in fnodes.itervalues()), ) diff --git a/mercurial/extensions.py b/mercurial/extensions.py --- a/mercurial/extensions.py +++ b/mercurial/extensions.py @@ -34,15 +34,15 @@ _aftercallbacks = {} _order = [] _builtin = { - "hbisect", - "bookmarks", - "color", - "parentrevspec", - "progress", - "interhg", - "inotify", - "hgcia", - "shelve", + b"hbisect", + b"bookmarks", + b"color", + b"parentrevspec", + b"progress", + b"interhg", + b"inotify", + b"hgcia", + b"shelve", } @@ -50,9 +50,9 @@ if ui: def enabled(name): - for format in ["%s", "hgext.%s"]: - conf = ui.config("extensions", format % name) - if conf is not None and not conf.startswith("!"): + for format in [b"%s", b"hgext.%s"]: + conf = ui.config(b"extensions", format % name) + if conf is not None and not conf.startswith(b"!"): return True else: @@ -70,7 +70,7 @@ mod = _extensions[name] except KeyError: for k, v in _extensions.iteritems(): - if k.endswith("." + name) or k.endswith("/" + name): + if k.endswith(b"." + name) or k.endswith(b"/" + name): mod = v break if not mod: @@ -79,7 +79,7 @@ def loadpath(path, module_name): - module_name = module_name.replace(".", "_") + module_name = module_name.replace(b".", b"_") path = util.normpath(util.expandpath(path)) module_name = pycompat.fsdecode(module_name) path = pycompat.fsdecode(path) @@ -100,7 +100,7 @@ def _importh(name): """import and return the module""" mod = __import__(pycompat.sysstr(name)) - components = name.split(".") + components = name.split(b".") for comp in components[1:]: mod = getattr(mod, comp) return mod @@ -111,18 +111,18 @@ # the module will be loaded in sys.modules # choose an unique name so that it doesn't # conflicts with other modules - mod = loadpath(path, "hgext.%s" % name) + mod = loadpath(path, b"hgext.%s" % name) else: try: - mod = _importh("hgext.%s" % name) + mod = _importh(b"hgext.%s" % name) except ImportError as err: if reportfunc: - reportfunc(err, "hgext.%s" % name, "hgext3rd.%s" % name) + reportfunc(err, b"hgext.%s" % name, b"hgext3rd.%s" % name) try: - mod = _importh("hgext3rd.%s" % name) + mod = _importh(b"hgext3rd.%s" % name) except ImportError as err: if reportfunc: - reportfunc(err, "hgext3rd.%s" % name, name) + reportfunc(err, b"hgext3rd.%s" % name, name) mod = _importh(name) return mod @@ -137,7 +137,7 @@ stringutil.forcebytestr(err), next, ) - if ui.debugflag and ui.configbool("devel", "debug.extensions"): + if ui.debugflag and ui.configbool(b"devel", b"debug.extensions"): ui.traceback() @@ -152,12 +152,12 @@ elif isinstance(xs, type(u"")): raise error.ProgrammingError( b"unicode %r found in %s" % (xs, name), - hint="use b'' to make it byte string", + hint=b"use b'' to make it byte string", ) # attributes set by registrar.command -_cmdfuncattrs = ("norepo", "optionalrepo", "inferrepo") +_cmdfuncattrs = (b"norepo", b"optionalrepo", b"inferrepo") def _validatecmdtable(ui, cmdtable): @@ -168,22 +168,22 @@ if not missing: continue raise error.ProgrammingError( - "missing attributes: %s" % ", ".join(missing), - hint="use @command decorator to register '%s'" % c, + b"missing attributes: %s" % b", ".join(missing), + hint=b"use @command decorator to register '%s'" % c, ) def _validatetables(ui, mod): """Sanity check for loadable tables provided by extension module""" - for t in ["cmdtable", "colortable", "configtable"]: + for t in [b"cmdtable", b"colortable", b"configtable"]: _rejectunicode(t, getattr(mod, t, {})) for t in [ - "filesetpredicate", - "internalmerge", - "revsetpredicate", - "templatefilter", - "templatefunc", - "templatekeyword", + b"filesetpredicate", + b"internalmerge", + b"revsetpredicate", + b"templatefilter", + b"templatefunc", + b"templatekeyword", ]: o = getattr(mod, t, None) if o: @@ -192,7 +192,7 @@ def load(ui, name, path, loadingtime=None): - if name.startswith("hgext.") or name.startswith("hgext/"): + if name.startswith(b"hgext.") or name.startswith(b"hgext/"): shortname = name[6:] else: shortname = name @@ -202,7 +202,7 @@ return _extensions[shortname] ui.log(b"extension", b" - loading extension: %s\n", shortname) _extensions[shortname] = None - with util.timedcm("load extension %s", shortname) as stats: + with util.timedcm(b"load extension %s", shortname) as stats: mod = _importext(name, path, bind(_reportimporterror, ui)) ui.log(b"extension", b" > %s extension loaded in %s\n", shortname, stats) if loadingtime is not None: @@ -215,8 +215,8 @@ minver = getattr(mod, "minimumhgversion", None) if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2): msg = _( - "(third party extension %s requires version %s or newer " - "of Mercurial (current: %s); disabling)\n" + b"(third party extension %s requires version %s or newer " + b"of Mercurial (current: %s); disabling)\n" ) ui.warn(msg % (shortname, minver, util.version())) return @@ -228,7 +228,7 @@ ui.log( b"extension", b" - invoking registered callbacks: %s\n", shortname ) - with util.timedcm("callbacks extension %s", shortname) as stats: + with util.timedcm(b"callbacks extension %s", shortname) as stats: for fn in _aftercallbacks.get(shortname, []): fn(loaded=True) ui.log(b"extension", b" > callbacks completed in %s\n", stats) @@ -243,7 +243,7 @@ except Exception as inst: ui.traceback(force=True) msg = stringutil.forcebytestr(inst) - ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) + ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg)) return False return True @@ -256,27 +256,27 @@ except Exception as inst: ui.traceback(force=True) msg = stringutil.forcebytestr(inst) - ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) + ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg)) return False return True def loadall(ui, whitelist=None): loadingtime = collections.defaultdict(int) - result = ui.configitems("extensions") + result = ui.configitems(b"extensions") if whitelist is not None: result = [(k, v) for (k, v) in result if k in whitelist] newindex = len(_order) ui.log( b"extension", b"loading %sextensions\n", - "additional " if newindex else "", + b"additional " if newindex else b"", ) ui.log(b"extension", b"- processing %d entries\n", len(result)) - with util.timedcm("load all extensions") as stats: + with util.timedcm(b"load all extensions") as stats: for (name, path) in result: if path: - if path[0:1] == "!": + if path[0:1] == b"!": if name not in _disabledextensions: ui.log( b"extension", @@ -291,16 +291,16 @@ msg = stringutil.forcebytestr(inst) if path: ui.warn( - _("*** failed to import extension %s from %s: %s\n") + _(b"*** failed to import extension %s from %s: %s\n") % (name, path, msg) ) else: ui.warn( - _("*** failed to import extension %s: %s\n") + _(b"*** failed to import extension %s: %s\n") % (name, msg) ) if isinstance(inst, error.Hint) and inst.hint: - ui.warn(_("*** (%s)\n") % inst.hint) + ui.warn(_(b"*** (%s)\n") % inst.hint) ui.traceback() ui.log( @@ -318,7 +318,7 @@ # # This one is for the list of item that must be run before running any setup earlyextraloaders = [ - ("configtable", configitems, "loadconfigtable"), + (b"configtable", configitems, b"loadconfigtable"), ] ui.log(b"extension", b"- loading configtable attributes\n") @@ -326,10 +326,10 @@ broken = set() ui.log(b"extension", b"- executing uisetup hooks\n") - with util.timedcm("all uisetup") as alluisetupstats: + with util.timedcm(b"all uisetup") as alluisetupstats: for name in _order[newindex:]: ui.log(b"extension", b" - running uisetup for %s\n", name) - with util.timedcm("uisetup %s", name) as stats: + with util.timedcm(b"uisetup %s", name) as stats: if not _runuisetup(name, ui): ui.log( b"extension", @@ -342,12 +342,12 @@ ui.log(b"extension", b"> all uisetup took %s\n", alluisetupstats) ui.log(b"extension", b"- executing extsetup hooks\n") - with util.timedcm("all extsetup") as allextetupstats: + with util.timedcm(b"all extsetup") as allextetupstats: for name in _order[newindex:]: if name in broken: continue ui.log(b"extension", b" - running extsetup for %s\n", name) - with util.timedcm("extsetup %s", name) as stats: + with util.timedcm(b"extsetup %s", name) as stats: if not _runextsetup(name, ui): ui.log( b"extension", @@ -365,7 +365,7 @@ # Call aftercallbacks that were never met. ui.log(b"extension", b"- executing remaining aftercallbacks\n") - with util.timedcm("aftercallbacks") as stats: + with util.timedcm(b"aftercallbacks") as stats: for shortname in _aftercallbacks: if shortname in _extensions: continue @@ -403,16 +403,16 @@ # which takes (ui, extensionname, extraobj) arguments ui.log(b"extension", b"- loading extension registration objects\n") extraloaders = [ - ("cmdtable", commands, "loadcmdtable"), - ("colortable", color, "loadcolortable"), - ("filesetpredicate", fileset, "loadpredicate"), - ("internalmerge", filemerge, "loadinternalmerge"), - ("revsetpredicate", revset, "loadpredicate"), - ("templatefilter", templatefilters, "loadfilter"), - ("templatefunc", templatefuncs, "loadfunction"), - ("templatekeyword", templatekw, "loadkeyword"), + (b"cmdtable", commands, b"loadcmdtable"), + (b"colortable", color, b"loadcolortable"), + (b"filesetpredicate", fileset, b"loadpredicate"), + (b"internalmerge", filemerge, b"loadinternalmerge"), + (b"revsetpredicate", revset, b"loadpredicate"), + (b"templatefilter", templatefilters, b"loadfilter"), + (b"templatefunc", templatefuncs, b"loadfunction"), + (b"templatekeyword", templatekw, b"loadkeyword"), ] - with util.timedcm("load registration objects") as stats: + with util.timedcm(b"load registration objects") as stats: _loadextra(ui, newindex, extraloaders) ui.log( b"extension", @@ -482,7 +482,7 @@ except Exception as inst: ui.traceback(force=True) ui.warn( - _("*** failed to populate ui by extension %s: %s\n") + _(b"*** failed to populate ui by extension %s: %s\n") % (name, stringutil.forcebytestr(inst)) ) @@ -709,15 +709,15 @@ exts = {} for e in files: - if e.endswith(".py"): - name = e.rsplit(".", 1)[0] + if e.endswith(b".py"): + name = e.rsplit(b".", 1)[0] path = os.path.join(extpath, e) else: name = e - path = os.path.join(extpath, e, "__init__.py") + path = os.path.join(extpath, e, b"__init__.py") if not os.path.exists(path): continue - if name in exts or name in _order or name == "__init__": + if name in exts or name in _order or name == b"__init__": continue exts[name] = path for name, path in _disabledextensions.iteritems(): @@ -737,13 +737,13 @@ result = [] line = file.readline() - while line[:1] == "#" or not line.strip(): + while line[:1] == b"#" or not line.strip(): line = file.readline() if not line: break start = line[:3] - if start == '"""' or start == "'''": + if start == b'"""' or start == b"'''": line = line[3:] while line: if line.rstrip().endswith(start): @@ -758,13 +758,13 @@ else: return None - return "".join(result) + return b"".join(result) def _disabledhelp(path): """retrieve help synopsis of a disabled extension (without importing)""" try: - with open(path, "rb") as src: + with open(path, b"rb") as src: doc = _moduledoc(src) except IOError: return @@ -772,7 +772,7 @@ if doc: # extracting localized synopsis return gettext(doc) else: - return _("(no help text available)") + return _(b"(no help text available)") def disabled(): @@ -841,7 +841,7 @@ This may raise IOError or SyntaxError. """ - with open(path, "rb") as src: + with open(path, b"rb") as src: root = ast.parse(src.read(), path) cmdtable = {} for node in _walkcommand(root): @@ -906,9 +906,9 @@ """return a dict of {name: desc} of extensions""" exts = {} for ename, ext in extensions(): - doc = gettext(ext.__doc__) or _("(no help text available)") + doc = gettext(ext.__doc__) or _(b"(no help text available)") if shortname: - ename = ename.split(".")[-1] + ename = ename.split(b".")[-1] exts[ename] = doc.splitlines()[0].strip() return exts @@ -921,17 +921,17 @@ def moduleversion(module): """return version information from given module as a string""" - if util.safehasattr(module, "getversion") and callable(module.getversion): + if util.safehasattr(module, b"getversion") and callable(module.getversion): version = module.getversion() - elif util.safehasattr(module, "__version__"): + elif util.safehasattr(module, b"__version__"): version = module.__version__ else: - version = "" + version = b"" if isinstance(version, (list, tuple)): - version = ".".join(pycompat.bytestr(o) for o in version) + version = b".".join(pycompat.bytestr(o) for o in version) return version def ismoduleinternal(module): exttestedwith = getattr(module, "testedwith", None) - return exttestedwith == "ships-with-hg-core" + return exttestedwith == b"ships-with-hg-core" diff --git a/mercurial/exthelper.py b/mercurial/exthelper.py --- a/mercurial/exthelper.py +++ b/mercurial/exthelper.py @@ -273,9 +273,9 @@ else: for opt in opts: if not isinstance(opt, tuple): - raise error.ProgrammingError("opts must be list of tuples") + raise error.ProgrammingError(b"opts must be list of tuples") if len(opt) not in (4, 5): - msg = "each opt tuple must contain 4 or 5 values" + msg = b"each opt tuple must contain 4 or 5 values" raise error.ProgrammingError(msg) def dec(wrapper): diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py --- a/mercurial/fancyopts.py +++ b/mercurial/fancyopts.py @@ -19,12 +19,12 @@ # Set of flags to not apply boolean negation logic on nevernegate = { # avoid --no-noninteractive - "noninteractive", + b"noninteractive", # These two flags are special because they cause hg to do one # thing and then exit, and so aren't suitable for use in things # like aliases anyway. - "help", - "version", + b"help", + b"version", } @@ -77,18 +77,18 @@ >>> opt(b'-:foo') ('', False, '', False) """ - if arg.startswith("--"): - flag, eq, val = arg.partition("=") + if arg.startswith(b"--"): + flag, eq, val = arg.partition(b"=") if flag[2:] in namelist: return flag, bool(eq), val, False - if flag[2:] + "=" in namelist: + if flag[2:] + b"=" in namelist: return flag, bool(eq), val, True - elif arg.startswith("-") and arg != "-" and not arg.startswith("-:"): + elif arg.startswith(b"-") and arg != b"-" and not arg.startswith(b"-:"): flag, val = arg[:2], arg[2:] i = shortlist.find(flag[1:]) if i >= 0: - return flag, bool(val), val, shortlist.startswith(":", i + 1) - return "", False, "", False + return flag, bool(val), val, shortlist.startswith(b":", i + 1) + return b"", False, b"", False def earlygetopt(args, shortlist, namelist, gnu=False, keepsep=False): @@ -178,7 +178,7 @@ pos = 0 while pos < len(args): arg = args[pos] - if arg == "--": + if arg == b"--": pos += not keepsep break flag, hasval, val, takeval = _earlyoptarg(arg, shortlist, namelist) @@ -261,7 +261,7 @@ try: return int(newparam) except ValueError: - abort(_("expected int")) + abort(_(b"expected int")) def _defaultopt(default): @@ -310,7 +310,7 @@ if optaliases is None: optaliases = {} namelist = [] - shortlist = "" + shortlist = b"" argmap = {} defmap = {} negations = {} @@ -324,11 +324,11 @@ # convert opts to getopt format onames = [name] onames.extend(optaliases.get(name, [])) - name = name.replace("-", "_") + name = name.replace(b"-", b"_") - argmap["-" + short] = name + argmap[b"-" + short] = name for n in onames: - argmap["--" + n] = name + argmap[b"--" + n] = name defmap[name] = _defaultopt(default) # copy defaults to state @@ -337,20 +337,20 @@ # does it take a parameter? if not defmap[name]._isboolopt(): if short: - short += ":" - onames = [n + "=" for n in onames] + short += b":" + onames = [n + b"=" for n in onames] elif name not in nevernegate: for n in onames: - if n.startswith("no-"): + if n.startswith(b"no-"): insert = n[3:] else: - insert = "no-" + n + insert = b"no-" + n # backout (as a practical example) has both --commit and # --no-commit options, so we don't want to allow the # negations of those flags. if insert not in alllong: - assert ("--" + n) not in negations - negations["--" + insert] = "--" + n + assert (b"--" + n) not in negations + negations[b"--" + insert] = b"--" + n namelist.append(insert) if short: shortlist += short @@ -381,7 +381,7 @@ def abort(s): raise error.Abort( - _("invalid value %r for option %s, %s") + _(b"invalid value %r for option %s, %s") % (pycompat.maybebytestr(val), opt, s) ) diff --git a/mercurial/filelog.py b/mercurial/filelog.py --- a/mercurial/filelog.py +++ b/mercurial/filelog.py @@ -27,7 +27,7 @@ class filelog(object): def __init__(self, opener, path): self._revlog = revlog.revlog( - opener, "/".join(("data", path + ".i")), censorable=True + opener, b"/".join((b"data", path + b".i")), censorable=True ) # Full name of the user visible file, relative to the repository root. # Used by LFS. @@ -144,8 +144,8 @@ if maybemissingparents: raise error.Abort( _( - "revlog storage does not support missing " - "parents write mode" + b"revlog storage does not support missing " + b"parents write mode" ) ) @@ -169,7 +169,7 @@ return storageutil.filtermetadata(self.revision(node)) def add(self, text, meta, transaction, link, p1=None, p2=None): - if meta or text.startswith("\1\n"): + if meta or text.startswith(b"\1\n"): text = storageutil.packmeta(meta, text) return self.addrevision(text, transaction, link, p1, p2) @@ -230,7 +230,7 @@ # Used by repo upgrade. def clone(self, tr, destrevlog, **kwargs): if not isinstance(destrevlog, filelog): - raise error.ProgrammingError("expected filelog to clone()") + raise error.ProgrammingError(b"expected filelog to clone()") return self._revlog.clone(tr, destrevlog._revlog, **kwargs) diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -42,15 +42,15 @@ def _toolstr(ui, tool, part, *args): - return ui.config("merge-tools", tool + "." + part, *args) + return ui.config(b"merge-tools", tool + b"." + part, *args) def _toolbool(ui, tool, part, *args): - return ui.configbool("merge-tools", tool + "." + part, *args) + return ui.configbool(b"merge-tools", tool + b"." + part, *args) def _toollist(ui, tool, part): - return ui.configlist("merge-tools", tool + "." + part) + return ui.configlist(b"merge-tools", tool + b"." + part) internals = {} @@ -69,17 +69,17 @@ # languages that may take more columns to still have a chance to fit in an # 80-column screen). _localchangedotherdeletedmsg = _( - "file '%(fd)s' was deleted in other%(o)s but was modified in local%(l)s.\n" - "You can use (c)hanged version, (d)elete, or leave (u)nresolved.\n" - "What do you want to do?" - "$$ &Changed $$ &Delete $$ &Unresolved" + b"file '%(fd)s' was deleted in other%(o)s but was modified in local%(l)s.\n" + b"You can use (c)hanged version, (d)elete, or leave (u)nresolved.\n" + b"What do you want to do?" + b"$$ &Changed $$ &Delete $$ &Unresolved" ) _otherchangedlocaldeletedmsg = _( - "file '%(fd)s' was deleted in local%(l)s but was modified in other%(o)s.\n" - "You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.\n" - "What do you want to do?" - "$$ &Changed $$ &Deleted $$ &Unresolved" + b"file '%(fd)s' was deleted in local%(l)s but was modified in other%(o)s.\n" + b"You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.\n" + b"What do you want to do?" + b"$$ &Changed $$ &Deleted $$ &Unresolved" ) @@ -120,7 +120,7 @@ ) def flags(self): - return "" + return b"" def changectx(self): return self._ctx @@ -135,34 +135,34 @@ def _findtool(ui, tool): if tool in internals: return tool - cmd = _toolstr(ui, tool, "executable", tool) - if cmd.startswith("python:"): + cmd = _toolstr(ui, tool, b"executable", tool) + if cmd.startswith(b"python:"): return cmd return findexternaltool(ui, tool) def _quotetoolpath(cmd): - if cmd.startswith("python:"): + if cmd.startswith(b"python:"): return cmd return procutil.shellquote(cmd) def findexternaltool(ui, tool): - for kn in ("regkey", "regkeyalt"): + for kn in (b"regkey", b"regkeyalt"): k = _toolstr(ui, tool, kn) if not k: continue - p = util.lookupreg(k, _toolstr(ui, tool, "regname")) + p = util.lookupreg(k, _toolstr(ui, tool, b"regname")) if p: - p = procutil.findexe(p + _toolstr(ui, tool, "regappend", "")) + p = procutil.findexe(p + _toolstr(ui, tool, b"regappend", b"")) if p: return p - exe = _toolstr(ui, tool, "executable", tool) + exe = _toolstr(ui, tool, b"executable", tool) return procutil.findexe(util.expandpath(exe)) def _picktool(repo, ui, path, binary, symlink, changedelete): - strictcheck = ui.configbool("merge", "strict-capability-check") + strictcheck = ui.configbool(b"merge", b"strict-capability-check") def hascapability(tool, capability, strict=False): if tool in internals: @@ -175,33 +175,33 @@ def check(tool, pat, symlink, binary, changedelete): tmsg = tool if pat: - tmsg = _("%s (for pattern %s)") % (tool, pat) + tmsg = _(b"%s (for pattern %s)") % (tool, pat) if not _findtool(ui, tool): if pat: # explicitly requested tool deserves a warning - ui.warn(_("couldn't find merge tool %s\n") % tmsg) + ui.warn(_(b"couldn't find merge tool %s\n") % tmsg) else: # configured but non-existing tools are more silent - ui.note(_("couldn't find merge tool %s\n") % tmsg) - elif symlink and not hascapability(tool, "symlink", strictcheck): - ui.warn(_("tool %s can't handle symlinks\n") % tmsg) - elif binary and not hascapability(tool, "binary", strictcheck): - ui.warn(_("tool %s can't handle binary\n") % tmsg) + ui.note(_(b"couldn't find merge tool %s\n") % tmsg) + elif symlink and not hascapability(tool, b"symlink", strictcheck): + ui.warn(_(b"tool %s can't handle symlinks\n") % tmsg) + elif binary and not hascapability(tool, b"binary", strictcheck): + ui.warn(_(b"tool %s can't handle binary\n") % tmsg) elif changedelete and not supportscd(tool): # the nomerge tools are the only tools that support change/delete # conflicts pass - elif not procutil.gui() and _toolbool(ui, tool, "gui"): - ui.warn(_("tool %s requires a GUI\n") % tmsg) + elif not procutil.gui() and _toolbool(ui, tool, b"gui"): + ui.warn(_(b"tool %s requires a GUI\n") % tmsg) else: return True return False # internal config: ui.forcemerge # forcemerge comes from command line arguments, highest priority - force = ui.config("ui", "forcemerge") + force = ui.config(b"ui", b"forcemerge") if force: toolpath = _findtool(ui, force) if changedelete and not supportscd(toolpath): - return ":prompt", None + return b":prompt", None else: if toolpath: return (force, _quotetoolpath(toolpath)) @@ -210,10 +210,10 @@ return (force, force) # HGMERGE takes next precedence - hgmerge = encoding.environ.get("HGMERGE") + hgmerge = encoding.environ.get(b"HGMERGE") if hgmerge: if changedelete and not supportscd(hgmerge): - return ":prompt", None + return b":prompt", None else: return (hgmerge, hgmerge) @@ -222,16 +222,16 @@ # whether binary capability should be checked strictly binarycap = binary and strictcheck - for pat, tool in ui.configitems("merge-patterns"): - mf = match.match(repo.root, "", [pat]) + for pat, tool in ui.configitems(b"merge-patterns"): + mf = match.match(repo.root, b"", [pat]) if mf(path) and check(tool, pat, symlink, binarycap, changedelete): - if binary and not hascapability(tool, "binary", strict=True): + if binary and not hascapability(tool, b"binary", strict=True): ui.warn( _( - "warning: check merge-patterns configurations," - " if %r for binary file %r is unintentional\n" - "(see 'hg help merge-tools'" - " for binary files capability)\n" + b"warning: check merge-patterns configurations," + b" if %r for binary file %r is unintentional\n" + b"(see 'hg help merge-tools'" + b" for binary files capability)\n" ) % (pycompat.bytestr(tool), pycompat.bytestr(path)) ) @@ -241,17 +241,17 @@ # then merge tools tools = {} disabled = set() - for k, v in ui.configitems("merge-tools"): - t = k.split(".")[0] + for k, v in ui.configitems(b"merge-tools"): + t = k.split(b".")[0] if t not in tools: - tools[t] = int(_toolstr(ui, t, "priority")) - if _toolbool(ui, t, "disabled"): + tools[t] = int(_toolstr(ui, t, b"priority")) + if _toolbool(ui, t, b"disabled"): disabled.add(t) names = tools.keys() tools = sorted( [(-p, tool) for tool, p in tools.items() if tool not in disabled] ) - uimerge = ui.config("ui", "merge") + uimerge = ui.config(b"ui", b"merge") if uimerge: # external tools defined in uimerge won't be able to handle # change/delete conflicts @@ -259,7 +259,7 @@ if uimerge not in names and not changedelete: return (uimerge, uimerge) tools.insert(0, (None, uimerge)) # highest priority - tools.append((None, "hgmerge")) # the old default, if found + tools.append((None, b"hgmerge")) # the old default, if found for p, t in tools: if check(t, None, symlink, binary, changedelete): toolpath = _findtool(ui, t) @@ -269,26 +269,26 @@ if symlink or binary or changedelete: if not changedelete and len(tools): # any tool is rejected by capability for symlink or binary - ui.warn(_("no tool found to merge %s\n") % path) - return ":prompt", None - return ":merge", None + ui.warn(_(b"no tool found to merge %s\n") % path) + return b":prompt", None + return b":merge", None def _eoltype(data): - "Guess the EOL type of a file" - if "\0" in data: # binary + b"Guess the EOL type of a file" + if b"\0" in data: # binary return None - if "\r\n" in data: # Windows - return "\r\n" - if "\r" in data: # Old Mac - return "\r" - if "\n" in data: # UNIX - return "\n" + if b"\r\n" in data: # Windows + return b"\r\n" + if b"\r" in data: # Old Mac + return b"\r" + if b"\n" in data: # UNIX + return b"\n" return None # unknown def _matcheol(file, back): - "Convert EOL markers in a file to match origfile" + b"Convert EOL markers in a file to match origfile" tostyle = _eoltype(back.data()) # No repo.wread filters? if tostyle: data = util.readfile(file) @@ -299,7 +299,7 @@ util.writefile(file, newdata) -@internaltool("prompt", nomerge) +@internaltool(b"prompt", nomerge) def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf, labels=None): """Asks the user which of the local `p1()` or the other `p2()` version to keep as the merged version.""" @@ -311,53 +311,53 @@ # conflicts. if fcd.changectx().isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge does not " "support file conflicts" + b"in-memory merge does not " b"support file conflicts" ) prompts = partextras(labels) - prompts["fd"] = uipathfn(fd) + prompts[b"fd"] = uipathfn(fd) try: if fco.isabsent(): index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2) - choice = ["local", "other", "unresolved"][index] + choice = [b"local", b"other", b"unresolved"][index] elif fcd.isabsent(): index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2) - choice = ["other", "local", "unresolved"][index] + choice = [b"other", b"local", b"unresolved"][index] else: # IMPORTANT: keep the last line of this prompt ("What do you want to # do?") very short, see comment next to _localchangedotherdeletedmsg # at the top of the file for details. index = ui.promptchoice( _( - "file '%(fd)s' needs to be resolved.\n" - "You can keep (l)ocal%(l)s, take (o)ther%(o)s, or leave " - "(u)nresolved.\n" - "What do you want to do?" - "$$ &Local $$ &Other $$ &Unresolved" + b"file '%(fd)s' needs to be resolved.\n" + b"You can keep (l)ocal%(l)s, take (o)ther%(o)s, or leave " + b"(u)nresolved.\n" + b"What do you want to do?" + b"$$ &Local $$ &Other $$ &Unresolved" ) % prompts, 2, ) - choice = ["local", "other", "unresolved"][index] + choice = [b"local", b"other", b"unresolved"][index] - if choice == "other": + if choice == b"other": return _iother(repo, mynode, orig, fcd, fco, fca, toolconf, labels) - elif choice == "local": + elif choice == b"local": return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf, labels) - elif choice == "unresolved": + elif choice == b"unresolved": return _ifail(repo, mynode, orig, fcd, fco, fca, toolconf, labels) except error.ResponseExpected: - ui.write("\n") + ui.write(b"\n") return _ifail(repo, mynode, orig, fcd, fco, fca, toolconf, labels) -@internaltool("local", nomerge) +@internaltool(b"local", nomerge) def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf, labels=None): """Uses the local `p1()` version of files as the merged version.""" return 0, fcd.isabsent() -@internaltool("other", nomerge) +@internaltool(b"other", nomerge) def _iother(repo, mynode, orig, fcd, fco, fca, toolconf, labels=None): """Uses the other `p2()` version of files as the merged version.""" if fco.isabsent(): @@ -370,7 +370,7 @@ return 0, deleted -@internaltool("fail", nomerge) +@internaltool(b"fail", nomerge) def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf, labels=None): """ Rather than attempting to merge files that were modified on both @@ -401,29 +401,29 @@ ui = repo.ui - validkeep = ["keep", "keep-merge3"] + validkeep = [b"keep", b"keep-merge3"] # do we attempt to simplemerge first? try: - premerge = _toolbool(ui, tool, "premerge", not binary) + premerge = _toolbool(ui, tool, b"premerge", not binary) except error.ConfigError: - premerge = _toolstr(ui, tool, "premerge", "").lower() + premerge = _toolstr(ui, tool, b"premerge", b"").lower() if premerge not in validkeep: - _valid = ", ".join(["'" + v + "'" for v in validkeep]) + _valid = b", ".join([b"'" + v + b"'" for v in validkeep]) raise error.ConfigError( - _("%s.premerge not valid " "('%s' is neither boolean nor %s)") + _(b"%s.premerge not valid " b"('%s' is neither boolean nor %s)") % (tool, premerge, _valid) ) if premerge: - if premerge == "keep-merge3": + if premerge == b"keep-merge3": if not labels: labels = _defaultconflictlabels if len(labels) < 3: - labels.append("base") + labels.append(b"base") r = simplemerge.simplemerge(ui, fcd, fca, fco, quiet=True, label=labels) if not r: - ui.debug(" premerge successful\n") + ui.debug(b" premerge successful\n") return 0 if premerge not in validkeep: # restore from backup and try again @@ -436,15 +436,15 @@ uipathfn = scmutil.getuipathfn(repo) if symlink: repo.ui.warn( - _("warning: internal %s cannot merge symlinks " "for %s\n") + _(b"warning: internal %s cannot merge symlinks " b"for %s\n") % (tool, uipathfn(fcd.path())) ) return False if fcd.isabsent() or fco.isabsent(): repo.ui.warn( _( - "warning: internal %s cannot merge change/delete " - "conflict for %s\n" + b"warning: internal %s cannot merge change/delete " + b"conflict for %s\n" ) % (tool, uipathfn(fcd.path())) ) @@ -465,11 +465,11 @@ @internaltool( - "union", + b"union", fullmerge, _( - "warning: conflicts while merging %s! " - "(edit, then use 'hg resolve --mark')\n" + b"warning: conflicts while merging %s! " + b"(edit, then use 'hg resolve --mark')\n" ), precheck=_mergecheck, ) @@ -479,16 +479,16 @@ files. It will use both left and right sides for conflict regions. No markers are inserted.""" return _merge( - repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, "union" + repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, b"union" ) @internaltool( - "merge", + b"merge", fullmerge, _( - "warning: conflicts while merging %s! " - "(edit, then use 'hg resolve --mark')\n" + b"warning: conflicts while merging %s! " + b"(edit, then use 'hg resolve --mark')\n" ), precheck=_mergecheck, ) @@ -499,16 +499,16 @@ the partially merged file. Markers will have two sections, one for each side of merge.""" return _merge( - repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, "merge" + repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, b"merge" ) @internaltool( - "merge3", + b"merge3", fullmerge, _( - "warning: conflicts while merging %s! " - "(edit, then use 'hg resolve --mark')\n" + b"warning: conflicts while merging %s! " + b"(edit, then use 'hg resolve --mark')\n" ), precheck=_mergecheck, ) @@ -521,7 +521,7 @@ if not labels: labels = _defaultconflictlabels if len(labels) < 3: - labels.append("base") + labels.append(b"base") return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels) @@ -547,31 +547,31 @@ return True, r -@internaltool("merge-local", mergeonly, precheck=_mergecheck) +@internaltool(b"merge-local", mergeonly, precheck=_mergecheck) def _imergelocal(*args, **kwargs): """ Like :merge, but resolve all conflicts non-interactively in favor of the local `p1()` changes.""" - success, status = _imergeauto(localorother="local", *args, **kwargs) + success, status = _imergeauto(localorother=b"local", *args, **kwargs) return success, status, False -@internaltool("merge-other", mergeonly, precheck=_mergecheck) +@internaltool(b"merge-other", mergeonly, precheck=_mergecheck) def _imergeother(*args, **kwargs): """ Like :merge, but resolve all conflicts non-interactively in favor of the other `p2()` changes.""" - success, status = _imergeauto(localorother="other", *args, **kwargs) + success, status = _imergeauto(localorother=b"other", *args, **kwargs) return success, status, False @internaltool( - "tagmerge", + b"tagmerge", mergeonly, _( - "automatic tag merging of %s failed! " - "(use 'hg resolve --tool :merge' or another merge " - "tool of your choice)\n" + b"automatic tag merging of %s failed! " + b"(use 'hg resolve --tool :merge' or another merge " + b"tool of your choice)\n" ), ) def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): @@ -582,7 +582,7 @@ return success, status, False -@internaltool("dump", fullmerge, binary=True, symlink=True) +@internaltool(b"dump", fullmerge, binary=True, symlink=True) def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): """ Creates three versions of the files to merge, containing the @@ -602,16 +602,16 @@ if isinstance(fcd, context.overlayworkingfilectx): raise error.InMemoryMergeConflictsError( - "in-memory merge does not " "support the :dump tool." + b"in-memory merge does not " b"support the :dump tool." ) - util.writefile(a + ".local", fcd.decodeddata()) - repo.wwrite(fd + ".other", fco.data(), fco.flags()) - repo.wwrite(fd + ".base", fca.data(), fca.flags()) + util.writefile(a + b".local", fcd.decodeddata()) + repo.wwrite(fd + b".other", fco.data(), fco.flags()) + repo.wwrite(fd + b".base", fca.data(), fca.flags()) return False, 1, False -@internaltool("forcedump", mergeonly, binary=True, symlink=True) +@internaltool(b"forcedump", mergeonly, binary=True, symlink=True) def _forcedump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): """ Creates three versions of the files as same as :dump, but omits premerge. @@ -631,50 +631,50 @@ # directory and tell the user how to get it is my best idea, but it's # clunky.) raise error.InMemoryMergeConflictsError( - "in-memory merge does not support " "external merge tools" + b"in-memory merge does not support " b"external merge tools" ) def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args): - tmpl = ui.config("ui", "pre-merge-tool-output-template") + tmpl = ui.config(b"ui", b"pre-merge-tool-output-template") if not tmpl: return mappingdict = templateutil.mappingdict props = { - "ctx": fcl.changectx(), - "node": hex(mynode), - "path": fcl.path(), - "local": mappingdict( + b"ctx": fcl.changectx(), + b"node": hex(mynode), + b"path": fcl.path(), + b"local": mappingdict( { - "ctx": fcl.changectx(), - "fctx": fcl, - "node": hex(mynode), - "name": _("local"), - "islink": "l" in fcl.flags(), - "label": env["HG_MY_LABEL"], + b"ctx": fcl.changectx(), + b"fctx": fcl, + b"node": hex(mynode), + b"name": _(b"local"), + b"islink": b"l" in fcl.flags(), + b"label": env[b"HG_MY_LABEL"], } ), - "base": mappingdict( + b"base": mappingdict( { - "ctx": fcb.changectx(), - "fctx": fcb, - "name": _("base"), - "islink": "l" in fcb.flags(), - "label": env["HG_BASE_LABEL"], + b"ctx": fcb.changectx(), + b"fctx": fcb, + b"name": _(b"base"), + b"islink": b"l" in fcb.flags(), + b"label": env[b"HG_BASE_LABEL"], } ), - "other": mappingdict( + b"other": mappingdict( { - "ctx": fco.changectx(), - "fctx": fco, - "name": _("other"), - "islink": "l" in fco.flags(), - "label": env["HG_OTHER_LABEL"], + b"ctx": fco.changectx(), + b"fctx": fco, + b"name": _(b"other"), + b"islink": b"l" in fco.flags(), + b"label": env[b"HG_OTHER_LABEL"], } ), - "toolpath": toolpath, - "toolargs": args, + b"toolpath": toolpath, + b"toolargs": args, } # TODO: make all of this something that can be specified on a per-tool basis @@ -694,50 +694,50 @@ uipathfn = scmutil.getuipathfn(repo) if fcd.isabsent() or fco.isabsent(): repo.ui.warn( - _("warning: %s cannot merge change/delete conflict " "for %s\n") + _(b"warning: %s cannot merge change/delete conflict " b"for %s\n") % (tool, uipathfn(fcd.path())) ) return False, 1, None unused, unused, unused, back = files localpath = _workingpath(repo, fcd) - args = _toolstr(repo.ui, tool, "args") + args = _toolstr(repo.ui, tool, b"args") with _maketempfiles( - repo, fco, fca, repo.wvfs.join(back.path()), "$output" in args + repo, fco, fca, repo.wvfs.join(back.path()), b"$output" in args ) as temppaths: basepath, otherpath, localoutputpath = temppaths - outpath = "" + outpath = b"" mylabel, otherlabel = labels[:2] if len(labels) >= 3: baselabel = labels[2] else: - baselabel = "base" + baselabel = b"base" env = { - "HG_FILE": fcd.path(), - "HG_MY_NODE": short(mynode), - "HG_OTHER_NODE": short(fco.changectx().node()), - "HG_BASE_NODE": short(fca.changectx().node()), - "HG_MY_ISLINK": "l" in fcd.flags(), - "HG_OTHER_ISLINK": "l" in fco.flags(), - "HG_BASE_ISLINK": "l" in fca.flags(), - "HG_MY_LABEL": mylabel, - "HG_OTHER_LABEL": otherlabel, - "HG_BASE_LABEL": baselabel, + b"HG_FILE": fcd.path(), + b"HG_MY_NODE": short(mynode), + b"HG_OTHER_NODE": short(fco.changectx().node()), + b"HG_BASE_NODE": short(fca.changectx().node()), + b"HG_MY_ISLINK": b"l" in fcd.flags(), + b"HG_OTHER_ISLINK": b"l" in fco.flags(), + b"HG_BASE_ISLINK": b"l" in fca.flags(), + b"HG_MY_LABEL": mylabel, + b"HG_OTHER_LABEL": otherlabel, + b"HG_BASE_LABEL": baselabel, } ui = repo.ui - if "$output" in args: + if b"$output" in args: # read input from backup, write to original outpath = localpath localpath = localoutputpath replace = { - "local": localpath, - "base": basepath, - "other": otherpath, - "output": outpath, - "labellocal": mylabel, - "labelother": otherlabel, - "labelbase": baselabel, + b"local": localpath, + b"base": basepath, + b"other": otherpath, + b"output": outpath, + b"labellocal": mylabel, + b"labelother": otherlabel, + b"labelbase": baselabel, } args = util.interpolate( br"\$", @@ -745,47 +745,47 @@ args, lambda s: procutil.shellquote(util.localpath(s)), ) - if _toolbool(ui, tool, "gui"): + if _toolbool(ui, tool, b"gui"): repo.ui.status( - _("running merge tool %s for file %s\n") + _(b"running merge tool %s for file %s\n") % (tool, uipathfn(fcd.path())) ) if scriptfn is None: - cmd = toolpath + " " + args - repo.ui.debug("launching merge tool: %s\n" % cmd) + cmd = toolpath + b" " + args + repo.ui.debug(b"launching merge tool: %s\n" % cmd) _describemerge(ui, repo, mynode, fcd, fca, fco, env, toolpath, args) r = ui.system( - cmd, cwd=repo.root, environ=env, blockedtag="mergetool" + cmd, cwd=repo.root, environ=env, blockedtag=b"mergetool" ) else: repo.ui.debug( - "launching python merge script: %s:%s\n" % (toolpath, scriptfn) + b"launching python merge script: %s:%s\n" % (toolpath, scriptfn) ) r = 0 try: # avoid cycle cmdutil->merge->filemerge->extensions->cmdutil from . import extensions - mod = extensions.loadpath(toolpath, "hgmerge.%s" % tool) + mod = extensions.loadpath(toolpath, b"hgmerge.%s" % tool) except Exception: raise error.Abort( - _("loading python merge script failed: %s") % toolpath + _(b"loading python merge script failed: %s") % toolpath ) mergefn = getattr(mod, scriptfn, None) if mergefn is None: raise error.Abort( - _("%s does not have function: %s") % (toolpath, scriptfn) + _(b"%s does not have function: %s") % (toolpath, scriptfn) ) argslist = procutil.shellsplit(args) # avoid cycle cmdutil->merge->filemerge->hook->extensions->cmdutil from . import hook ret, raised = hook.pythonhook( - ui, repo, "merge", toolpath, mergefn, {"args": argslist}, True + ui, repo, b"merge", toolpath, mergefn, {b"args": argslist}, True ) if raised: r = 1 - repo.ui.debug("merge tool returned: %d\n" % r) + repo.ui.debug(b"merge tool returned: %d\n" % r) return True, r, False @@ -798,11 +798,11 @@ if ctx.node() is None: ctx = ctx.p1() - props = {"ctx": ctx} + props = {b"ctx": ctx} templateresult = template.renderdefault(props) - label = ("%s:" % label).ljust(pad + 1) - mark = "%s %s" % (label, templateresult) + label = (b"%s:" % label).ljust(pad + 1) + mark = b"%s %s" % (label, templateresult) if mark: mark = mark.splitlines()[0] # split for safety @@ -811,7 +811,7 @@ return stringutil.ellipsis(mark, 80 - 8) -_defaultconflictlabels = ["local", "other"] +_defaultconflictlabels = [b"local", b"other"] def _formatlabels(repo, fcd, fco, fca, labels, tool=None): @@ -824,9 +824,9 @@ ca = fca.changectx() ui = repo.ui - template = ui.config("ui", "mergemarkertemplate") + template = ui.config(b"ui", b"mergemarkertemplate") if tool is not None: - template = _toolstr(ui, tool, "mergemarkertemplate", template) + template = _toolstr(ui, tool, b"mergemarkertemplate", template) template = templater.unquotestring(template) tres = formatter.templateresources(ui, repo) tmpl = formatter.maketemplater( @@ -851,13 +851,13 @@ """ if labels is None: return { - "l": "", - "o": "", + b"l": b"", + b"o": b"", } return { - "l": " [%s]" % labels[0], - "o": " [%s]" % labels[1], + b"l": b" [%s]" % labels[0], + b"o": b" [%s]" % labels[1], } @@ -919,20 +919,20 @@ use them. """ tmproot = None - tmprootprefix = repo.ui.config("experimental", "mergetempdirprefix") + tmprootprefix = repo.ui.config(b"experimental", b"mergetempdirprefix") if tmprootprefix: tmproot = pycompat.mkdtemp(prefix=tmprootprefix) def maketempfrompath(prefix, path): fullbase, ext = os.path.splitext(path) - pre = "%s~%s" % (os.path.basename(fullbase), prefix) + pre = b"%s~%s" % (os.path.basename(fullbase), prefix) if tmproot: name = os.path.join(tmproot, pre) if ext: name += ext f = open(name, r"wb") else: - fd, name = pycompat.mkstemp(prefix=pre + ".", suffix=ext) + fd, name = pycompat.mkstemp(prefix=pre + b".", suffix=ext) f = os.fdopen(fd, r"wb") return f, name @@ -943,16 +943,16 @@ f.close() return name - b = tempfromcontext("base", fca) - c = tempfromcontext("other", fco) + b = tempfromcontext(b"base", fca) + c = tempfromcontext(b"other", fco) d = localpath if uselocalpath: # We start off with this being the backup filename, so remove the .orig # to make syntax-highlighting more likely. - if d.endswith(".orig"): + if d.endswith(b".orig"): d, _ = os.path.splitext(d) - f, d = maketempfrompath("local", d) - with open(localpath, "rb") as src: + f, d = maketempfrompath(b"local", d) + with open(localpath, b"rb") as src: f.write(src.read()) f.close() @@ -991,29 +991,29 @@ uipathfn = scmutil.getuipathfn(repo) fduipath = uipathfn(fd) binary = fcd.isbinary() or fco.isbinary() or fca.isbinary() - symlink = "l" in fcd.flags() + fco.flags() + symlink = b"l" in fcd.flags() + fco.flags() changedelete = fcd.isabsent() or fco.isabsent() tool, toolpath = _picktool(repo, ui, fd, binary, symlink, changedelete) scriptfn = None - if tool in internals and tool.startswith("internal:"): + if tool in internals and tool.startswith(b"internal:"): # normalize to new-style names (':merge' etc) - tool = tool[len("internal") :] - if toolpath and toolpath.startswith("python:"): + tool = tool[len(b"internal") :] + if toolpath and toolpath.startswith(b"python:"): invalidsyntax = False - if toolpath.count(":") >= 2: - script, scriptfn = toolpath[7:].rsplit(":", 1) + if toolpath.count(b":") >= 2: + script, scriptfn = toolpath[7:].rsplit(b":", 1) if not scriptfn: invalidsyntax = True # missing :callable can lead to spliting on windows drive letter - if "\\" in scriptfn or "/" in scriptfn: + if b"\\" in scriptfn or b"/" in scriptfn: invalidsyntax = True else: invalidsyntax = True if invalidsyntax: - raise error.Abort(_("invalid 'python:' syntax: %s") % toolpath) + raise error.Abort(_(b"invalid 'python:' syntax: %s") % toolpath) toolpath = script ui.debug( - "picked tool '%s' for %s (binary %s symlink %s changedelete %s)\n" + b"picked tool '%s' for %s (binary %s symlink %s changedelete %s)\n" % ( tool, fduipath, @@ -1035,7 +1035,7 @@ else: func = _xmerge mergetype = fullmerge - onfailure = _("merging %s failed!\n") + onfailure = _(b"merging %s failed!\n") precheck = None isexternal = True @@ -1048,19 +1048,19 @@ if premerge: if orig != fco.path(): ui.status( - _("merging %s and %s to %s\n") + _(b"merging %s and %s to %s\n") % (uipathfn(orig), uipathfn(fco.path()), fduipath) ) else: - ui.status(_("merging %s\n") % fduipath) + ui.status(_(b"merging %s\n") % fduipath) - ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca)) + ui.debug(b"my %s other %s ancestor %s\n" % (fcd, fco, fca)) if precheck and not precheck(repo, mynode, orig, fcd, fco, fca, toolconf): if onfailure: if wctx.isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge does " "not support merge " "conflicts" + b"in-memory merge does " b"not support merge " b"conflicts" ) ui.warn(onfailure % fduipath) return True, 1, False @@ -1069,16 +1069,16 @@ files = (None, None, None, back) r = 1 try: - internalmarkerstyle = ui.config("ui", "mergemarkers") + internalmarkerstyle = ui.config(b"ui", b"mergemarkers") if isexternal: - markerstyle = _toolstr(ui, tool, "mergemarkers") + markerstyle = _toolstr(ui, tool, b"mergemarkers") else: markerstyle = internalmarkerstyle if not labels: labels = _defaultconflictlabels formattedlabels = labels - if markerstyle != "basic": + if markerstyle != b"basic": formattedlabels = _formatlabels( repo, fcd, fco, fca, labels, tool=tool ) @@ -1091,11 +1091,11 @@ # in conflict markers if premerge is 'keep' or 'keep-merge3'. premergelabels = labels labeltool = None - if markerstyle != "basic": + if markerstyle != b"basic": # respect 'tool's mergemarkertemplate (which defaults to # ui.mergemarkertemplate) labeltool = tool - if internalmarkerstyle != "basic" or markerstyle != "basic": + if internalmarkerstyle != b"basic" or markerstyle != b"basic": premergelabels = _formatlabels( repo, fcd, fco, fca, premergelabels, tool=labeltool ) @@ -1125,7 +1125,9 @@ if onfailure: if wctx.isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge " "does not support " "merge conflicts" + b"in-memory merge " + b"does not support " + b"merge conflicts" ) ui.warn(onfailure % fduipath) _onfilemergefailure(ui) @@ -1137,24 +1139,24 @@ def _haltmerge(): - msg = _("merge halted after failed merge (see hg resolve)") + msg = _(b"merge halted after failed merge (see hg resolve)") raise error.InterventionRequired(msg) def _onfilemergefailure(ui): - action = ui.config("merge", "on-failure") - if action == "prompt": - msg = _("continue merge operation (yn)?" "$$ &Yes $$ &No") + action = ui.config(b"merge", b"on-failure") + if action == b"prompt": + msg = _(b"continue merge operation (yn)?" b"$$ &Yes $$ &No") if ui.promptchoice(msg, 0) == 1: _haltmerge() - if action == "halt": + if action == b"halt": _haltmerge() # default action is 'continue', in which case we neither prompt nor halt def hasconflictmarkers(data): return bool( - re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", data, re.MULTILINE) + re.search(b"^(<<<<<<< .*|=======|>>>>>>> .*)$", data, re.MULTILINE) ) @@ -1164,17 +1166,17 @@ unused, unused, unused, back = files if not r and ( - _toolbool(ui, tool, "checkconflicts") - or "conflicts" in _toollist(ui, tool, "check") + _toolbool(ui, tool, b"checkconflicts") + or b"conflicts" in _toollist(ui, tool, b"check") ): if hasconflictmarkers(fcd.data()): r = 1 checked = False - if "prompt" in _toollist(ui, tool, "check"): + if b"prompt" in _toollist(ui, tool, b"check"): checked = True if ui.promptchoice( - _("was merge of '%s' successful (yn)?" "$$ &Yes $$ &No") + _(b"was merge of '%s' successful (yn)?" b"$$ &Yes $$ &No") % uipathfn(fd), 1, ): @@ -1184,23 +1186,23 @@ not r and not checked and ( - _toolbool(ui, tool, "checkchanged") - or "changed" in _toollist(ui, tool, "check") + _toolbool(ui, tool, b"checkchanged") + or b"changed" in _toollist(ui, tool, b"check") ) ): if back is not None and not fcd.cmp(back): if ui.promptchoice( _( - " output file %s appears unchanged\n" - "was merge successful (yn)?" - "$$ &Yes $$ &No" + b" output file %s appears unchanged\n" + b"was merge successful (yn)?" + b"$$ &Yes $$ &No" ) % uipathfn(fd), 1, ): r = 1 - if back is not None and _toolbool(ui, tool, "fixeol"): + if back is not None and _toolbool(ui, tool, b"fixeol"): _matcheol(_workingpath(repo, fcd), back) return r @@ -1226,27 +1228,29 @@ """Load internal merge tool from specified registrarobj """ for name, func in registrarobj._table.iteritems(): - fullname = ":" + name + fullname = b":" + name internals[fullname] = func - internals["internal:" + name] = func + internals[b"internal:" + name] = func internalsdoc[fullname] = func capabilities = sorted([k for k, v in func.capabilities.items() if v]) if capabilities: - capdesc = " (actual capabilities: %s)" % ", ".join(capabilities) - func.__doc__ = func.__doc__ + pycompat.sysstr("\n\n%s" % capdesc) + capdesc = b" (actual capabilities: %s)" % b", ".join( + capabilities + ) + func.__doc__ = func.__doc__ + pycompat.sysstr(b"\n\n%s" % capdesc) # to put i18n comments into hg.pot for automatically generated texts # i18n: "binary" and "symlink" are keywords # i18n: this text is added automatically - _(" (actual capabilities: binary, symlink)") + _(b" (actual capabilities: binary, symlink)") # i18n: "binary" is keyword # i18n: this text is added automatically - _(" (actual capabilities: binary)") + _(b" (actual capabilities: binary)") # i18n: "symlink" is keyword # i18n: this text is added automatically - _(" (actual capabilities: symlink)") + _(b" (actual capabilities: symlink)") # load built-in merge tools explicitly to setup internalsdoc diff --git a/mercurial/fileset.py b/mercurial/fileset.py --- a/mercurial/fileset.py +++ b/mercurial/fileset.py @@ -39,12 +39,12 @@ def getmatch(mctx, x): if not x: - raise error.ParseError(_("missing argument")) + raise error.ParseError(_(b"missing argument")) return methods[x[0]](mctx, *x[1:]) def getmatchwithstatus(mctx, x, hint): - keys = set(getstring(hint, "status hint must be a string").split()) + keys = set(getstring(hint, b"status hint must be a string").split()) return getmatch(mctx.withstatus(keys), x) @@ -56,7 +56,7 @@ return stringmatch( mctx, _getkindpat( - x, y, matchmod.allpatternkinds, _("pattern must be a string") + x, y, matchmod.allpatternkinds, _(b"pattern must be a string") ), ) @@ -64,7 +64,7 @@ def patternsmatch(mctx, *xs): allkinds = matchmod.allpatternkinds patterns = [ - getpattern(x, allkinds, _("pattern must be a string")) for x in xs + getpattern(x, allkinds, _(b"pattern must be a string")) for x in xs ] return mctx.matcher(patterns) @@ -82,7 +82,7 @@ def notmatch(mctx, x): m = getmatch(mctx, x) - return mctx.predicate(lambda f: not m(f), predrepr=("", m)) + return mctx.predicate(lambda f: not m(f), predrepr=(b"", m)) def minusmatch(mctx, x, y): @@ -93,8 +93,8 @@ def listmatch(mctx, *xs): raise error.ParseError( - _("can't use a list in this context"), - hint=_("see 'hg help \"filesets.x or y\"'"), + _(b"can't use a list in this context"), + hint=_(b"see 'hg help \"filesets.x or y\"'"), ) @@ -119,186 +119,186 @@ predicate = registrar.filesetpredicate(symbols) -@predicate("modified()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"modified()", callstatus=True, weight=_WEIGHT_STATUS) def modified(mctx, x): """File that is modified according to :hg:`status`. """ # i18n: "modified" is a keyword - getargs(x, 0, 0, _("modified takes no arguments")) + getargs(x, 0, 0, _(b"modified takes no arguments")) s = set(mctx.status().modified) - return mctx.predicate(s.__contains__, predrepr="modified") + return mctx.predicate(s.__contains__, predrepr=b"modified") -@predicate("added()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"added()", callstatus=True, weight=_WEIGHT_STATUS) def added(mctx, x): """File that is added according to :hg:`status`. """ # i18n: "added" is a keyword - getargs(x, 0, 0, _("added takes no arguments")) + getargs(x, 0, 0, _(b"added takes no arguments")) s = set(mctx.status().added) - return mctx.predicate(s.__contains__, predrepr="added") + return mctx.predicate(s.__contains__, predrepr=b"added") -@predicate("removed()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"removed()", callstatus=True, weight=_WEIGHT_STATUS) def removed(mctx, x): """File that is removed according to :hg:`status`. """ # i18n: "removed" is a keyword - getargs(x, 0, 0, _("removed takes no arguments")) + getargs(x, 0, 0, _(b"removed takes no arguments")) s = set(mctx.status().removed) - return mctx.predicate(s.__contains__, predrepr="removed") + return mctx.predicate(s.__contains__, predrepr=b"removed") -@predicate("deleted()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"deleted()", callstatus=True, weight=_WEIGHT_STATUS) def deleted(mctx, x): """Alias for ``missing()``. """ # i18n: "deleted" is a keyword - getargs(x, 0, 0, _("deleted takes no arguments")) + getargs(x, 0, 0, _(b"deleted takes no arguments")) s = set(mctx.status().deleted) - return mctx.predicate(s.__contains__, predrepr="deleted") + return mctx.predicate(s.__contains__, predrepr=b"deleted") -@predicate("missing()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"missing()", callstatus=True, weight=_WEIGHT_STATUS) def missing(mctx, x): """File that is missing according to :hg:`status`. """ # i18n: "missing" is a keyword - getargs(x, 0, 0, _("missing takes no arguments")) + getargs(x, 0, 0, _(b"missing takes no arguments")) s = set(mctx.status().deleted) - return mctx.predicate(s.__contains__, predrepr="deleted") + return mctx.predicate(s.__contains__, predrepr=b"deleted") -@predicate("unknown()", callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) +@predicate(b"unknown()", callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) def unknown(mctx, x): """File that is unknown according to :hg:`status`.""" # i18n: "unknown" is a keyword - getargs(x, 0, 0, _("unknown takes no arguments")) + getargs(x, 0, 0, _(b"unknown takes no arguments")) s = set(mctx.status().unknown) - return mctx.predicate(s.__contains__, predrepr="unknown") + return mctx.predicate(s.__contains__, predrepr=b"unknown") -@predicate("ignored()", callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) +@predicate(b"ignored()", callstatus=True, weight=_WEIGHT_STATUS_THOROUGH) def ignored(mctx, x): """File that is ignored according to :hg:`status`.""" # i18n: "ignored" is a keyword - getargs(x, 0, 0, _("ignored takes no arguments")) + getargs(x, 0, 0, _(b"ignored takes no arguments")) s = set(mctx.status().ignored) - return mctx.predicate(s.__contains__, predrepr="ignored") + return mctx.predicate(s.__contains__, predrepr=b"ignored") -@predicate("clean()", callstatus=True, weight=_WEIGHT_STATUS) +@predicate(b"clean()", callstatus=True, weight=_WEIGHT_STATUS) def clean(mctx, x): """File that is clean according to :hg:`status`. """ # i18n: "clean" is a keyword - getargs(x, 0, 0, _("clean takes no arguments")) + getargs(x, 0, 0, _(b"clean takes no arguments")) s = set(mctx.status().clean) - return mctx.predicate(s.__contains__, predrepr="clean") + return mctx.predicate(s.__contains__, predrepr=b"clean") -@predicate("tracked()") +@predicate(b"tracked()") def tracked(mctx, x): """File that is under Mercurial control.""" # i18n: "tracked" is a keyword - getargs(x, 0, 0, _("tracked takes no arguments")) - return mctx.predicate(mctx.ctx.__contains__, predrepr="tracked") + getargs(x, 0, 0, _(b"tracked takes no arguments")) + return mctx.predicate(mctx.ctx.__contains__, predrepr=b"tracked") -@predicate("binary()", weight=_WEIGHT_READ_CONTENTS) +@predicate(b"binary()", weight=_WEIGHT_READ_CONTENTS) def binary(mctx, x): """File that appears to be binary (contains NUL bytes). """ # i18n: "binary" is a keyword - getargs(x, 0, 0, _("binary takes no arguments")) + getargs(x, 0, 0, _(b"binary takes no arguments")) return mctx.fpredicate( - lambda fctx: fctx.isbinary(), predrepr="binary", cache=True + lambda fctx: fctx.isbinary(), predrepr=b"binary", cache=True ) -@predicate("exec()") +@predicate(b"exec()") def exec_(mctx, x): """File that is marked as executable. """ # i18n: "exec" is a keyword - getargs(x, 0, 0, _("exec takes no arguments")) + getargs(x, 0, 0, _(b"exec takes no arguments")) ctx = mctx.ctx - return mctx.predicate(lambda f: ctx.flags(f) == "x", predrepr="exec") + return mctx.predicate(lambda f: ctx.flags(f) == b"x", predrepr=b"exec") -@predicate("symlink()") +@predicate(b"symlink()") def symlink(mctx, x): """File that is marked as a symlink. """ # i18n: "symlink" is a keyword - getargs(x, 0, 0, _("symlink takes no arguments")) + getargs(x, 0, 0, _(b"symlink takes no arguments")) ctx = mctx.ctx - return mctx.predicate(lambda f: ctx.flags(f) == "l", predrepr="symlink") + return mctx.predicate(lambda f: ctx.flags(f) == b"l", predrepr=b"symlink") -@predicate("resolved()", weight=_WEIGHT_STATUS) +@predicate(b"resolved()", weight=_WEIGHT_STATUS) def resolved(mctx, x): """File that is marked resolved according to :hg:`resolve -l`. """ # i18n: "resolved" is a keyword - getargs(x, 0, 0, _("resolved takes no arguments")) + getargs(x, 0, 0, _(b"resolved takes no arguments")) if mctx.ctx.rev() is not None: return mctx.never() ms = merge.mergestate.read(mctx.ctx.repo()) return mctx.predicate( - lambda f: f in ms and ms[f] == "r", predrepr="resolved" + lambda f: f in ms and ms[f] == b"r", predrepr=b"resolved" ) -@predicate("unresolved()", weight=_WEIGHT_STATUS) +@predicate(b"unresolved()", weight=_WEIGHT_STATUS) def unresolved(mctx, x): """File that is marked unresolved according to :hg:`resolve -l`. """ # i18n: "unresolved" is a keyword - getargs(x, 0, 0, _("unresolved takes no arguments")) + getargs(x, 0, 0, _(b"unresolved takes no arguments")) if mctx.ctx.rev() is not None: return mctx.never() ms = merge.mergestate.read(mctx.ctx.repo()) return mctx.predicate( - lambda f: f in ms and ms[f] == "u", predrepr="unresolved" + lambda f: f in ms and ms[f] == b"u", predrepr=b"unresolved" ) -@predicate("hgignore()", weight=_WEIGHT_STATUS) +@predicate(b"hgignore()", weight=_WEIGHT_STATUS) def hgignore(mctx, x): """File that matches the active .hgignore pattern. """ # i18n: "hgignore" is a keyword - getargs(x, 0, 0, _("hgignore takes no arguments")) + getargs(x, 0, 0, _(b"hgignore takes no arguments")) return mctx.ctx.repo().dirstate._ignore -@predicate("portable()", weight=_WEIGHT_CHECK_FILENAME) +@predicate(b"portable()", weight=_WEIGHT_CHECK_FILENAME) def portable(mctx, x): """File that has a portable name. (This doesn't include filenames with case collisions.) """ # i18n: "portable" is a keyword - getargs(x, 0, 0, _("portable takes no arguments")) + getargs(x, 0, 0, _(b"portable takes no arguments")) return mctx.predicate( - lambda f: util.checkwinfilename(f) is None, predrepr="portable" + lambda f: util.checkwinfilename(f) is None, predrepr=b"portable" ) -@predicate("grep(regex)", weight=_WEIGHT_READ_CONTENTS) +@predicate(b"grep(regex)", weight=_WEIGHT_READ_CONTENTS) def grep(mctx, x): """File contains the given regular expression. """ try: # i18n: "grep" is a keyword - r = re.compile(getstring(x, _("grep requires a pattern"))) + r = re.compile(getstring(x, _(b"grep requires a pattern"))) except re.error as e: raise error.ParseError( - _("invalid match pattern: %s") % stringutil.forcebytestr(e) + _(b"invalid match pattern: %s") % stringutil.forcebytestr(e) ) return mctx.fpredicate( lambda fctx: r.search(fctx.data()), - predrepr=("grep(%r)", r.pattern), + predrepr=(b"grep(%r)", r.pattern), cache=True, ) @@ -311,33 +311,33 @@ # max(4k) = 5k - 1, max(4.5k) = 4.6k - 1 n = s[: -len(k)] inc = 1.0 - if "." in n: - inc /= 10 ** len(n.split(".")[1]) + if b"." in n: + inc /= 10 ** len(n.split(b".")[1]) return int((float(n) + inc) * v) - 1 # no extension, this is a precise value return int(s) except ValueError: - raise error.ParseError(_("couldn't parse size: %s") % s) + raise error.ParseError(_(b"couldn't parse size: %s") % s) def sizematcher(expr): """Return a function(size) -> bool from the ``size()`` expression""" expr = expr.strip() - if "-" in expr: # do we have a range? - a, b = expr.split("-", 1) + if b"-" in expr: # do we have a range? + a, b = expr.split(b"-", 1) a = util.sizetoint(a) b = util.sizetoint(b) return lambda x: x >= a and x <= b - elif expr.startswith("<="): + elif expr.startswith(b"<="): a = util.sizetoint(expr[2:]) return lambda x: x <= a - elif expr.startswith("<"): + elif expr.startswith(b"<"): a = util.sizetoint(expr[1:]) return lambda x: x < a - elif expr.startswith(">="): + elif expr.startswith(b">="): a = util.sizetoint(expr[2:]) return lambda x: x >= a - elif expr.startswith(">"): + elif expr.startswith(b">"): a = util.sizetoint(expr[1:]) return lambda x: x > a else: @@ -346,7 +346,7 @@ return lambda x: x >= a and x <= b -@predicate("size(expression)", weight=_WEIGHT_STATUS) +@predicate(b"size(expression)", weight=_WEIGHT_STATUS) def size(mctx, x): """File size matches the given expression. Examples: @@ -356,14 +356,14 @@ - size('4k - 1MB') - files from 4096 bytes to 1048576 bytes """ # i18n: "size" is a keyword - expr = getstring(x, _("size requires an expression")) + expr = getstring(x, _(b"size requires an expression")) m = sizematcher(expr) return mctx.fpredicate( - lambda fctx: m(fctx.size()), predrepr=("size(%r)", expr), cache=True + lambda fctx: m(fctx.size()), predrepr=(b"size(%r)", expr), cache=True ) -@predicate("encoding(name)", weight=_WEIGHT_READ_CONTENTS) +@predicate(b"encoding(name)", weight=_WEIGHT_READ_CONTENTS) def encoding(mctx, x): """File can be successfully decoded with the given character encoding. May not be useful for encodings other than ASCII and @@ -371,7 +371,7 @@ """ # i18n: "encoding" is a keyword - enc = getstring(x, _("encoding requires an encoding name")) + enc = getstring(x, _(b"encoding requires an encoding name")) def encp(fctx): d = fctx.data() @@ -379,14 +379,14 @@ d.decode(pycompat.sysstr(enc)) return True except LookupError: - raise error.Abort(_("unknown encoding '%s'") % enc) + raise error.Abort(_(b"unknown encoding '%s'") % enc) except UnicodeDecodeError: return False - return mctx.fpredicate(encp, predrepr=("encoding(%r)", enc), cache=True) + return mctx.fpredicate(encp, predrepr=(b"encoding(%r)", enc), cache=True) -@predicate("eol(style)", weight=_WEIGHT_READ_CONTENTS) +@predicate(b"eol(style)", weight=_WEIGHT_READ_CONTENTS) def eol(mctx, x): """File contains newlines of the given style (dos, unix, mac). Binary files are excluded, files with mixed line endings match multiple @@ -394,46 +394,46 @@ """ # i18n: "eol" is a keyword - enc = getstring(x, _("eol requires a style name")) + enc = getstring(x, _(b"eol requires a style name")) def eolp(fctx): if fctx.isbinary(): return False d = fctx.data() - if (enc == "dos" or enc == "win") and "\r\n" in d: + if (enc == b"dos" or enc == b"win") and b"\r\n" in d: return True - elif enc == "unix" and re.search("(? 127: # gather up a symbol/keyword s = pos @@ -91,30 +93,30 @@ if sym in keywords: # operator keywords yield (sym, None, s) else: - yield ("symbol", sym, s) + yield (b"symbol", sym, s) pos -= 1 else: - raise error.ParseError(_("syntax error"), pos) + raise error.ParseError(_(b"syntax error"), pos) pos += 1 - yield ("end", None, pos) + yield (b"end", None, pos) def parse(expr): p = parser.parser(elements) tree, pos = p.parse(tokenize(expr)) if pos != len(expr): - raise error.ParseError(_("invalid token"), pos) - return parser.simplifyinfixops(tree, {"list", "or"}) + raise error.ParseError(_(b"invalid token"), pos) + return parser.simplifyinfixops(tree, {b"list", b"or"}) def getsymbol(x): - if x and x[0] == "symbol": + if x and x[0] == b"symbol": return x[1] - raise error.ParseError(_("not a symbol")) + raise error.ParseError(_(b"not a symbol")) def getstring(x, err): - if x and (x[0] == "string" or x[0] == "symbol"): + if x and (x[0] == b"string" or x[0] == b"symbol"): return x[1] raise error.ParseError(err) @@ -123,12 +125,12 @@ kind = getsymbol(x) pat = getstring(y, err) if kind not in allkinds: - raise error.ParseError(_("invalid pattern kind: %s") % kind) - return "%s:%s" % (kind, pat) + raise error.ParseError(_(b"invalid pattern kind: %s") % kind) + return b"%s:%s" % (kind, pat) def getpattern(x, allkinds, err): - if x and x[0] == "kindpat": + if x and x[0] == b"kindpat": return getkindpat(x[1], x[2], allkinds, err) return getstring(x, err) @@ -136,7 +138,7 @@ def getlist(x): if not x: return [] - if x[0] == "list": + if x[0] == b"list": return list(x[1:]) return [x] @@ -153,33 +155,33 @@ return x op = x[0] - if op in {"string", "symbol"}: + if op in {b"string", b"symbol"}: return x - if op == "kindpat": + if op == b"kindpat": getsymbol(x[1]) # kind must be a symbol t = _analyze(x[2]) return (op, x[1], t) - if op == "group": + if op == b"group": return _analyze(x[1]) - if op == "negate": - raise error.ParseError(_("can't use negate operator in this context")) - if op == "not": + if op == b"negate": + raise error.ParseError(_(b"can't use negate operator in this context")) + if op == b"not": t = _analyze(x[1]) return (op, t) - if op == "and": + if op == b"and": ta = _analyze(x[1]) tb = _analyze(x[2]) return (op, ta, tb) - if op == "minus": - return _analyze(("and", x[1], ("not", x[2]))) - if op in {"list", "or"}: + if op == b"minus": + return _analyze((b"and", x[1], (b"not", x[2]))) + if op in {b"list", b"or"}: ts = tuple(_analyze(y) for y in x[1:]) return (op,) + ts - if op == "func": + if op == b"func": getsymbol(x[1]) # function name must be a symbol ta = _analyze(x[2]) return (op, x[1], ta) - raise error.ProgrammingError("invalid operator %r" % op) + raise error.ProgrammingError(b"invalid operator %r" % op) def _insertstatushints(x): @@ -195,35 +197,35 @@ return (), x op = x[0] - if op in {"string", "symbol", "kindpat"}: + if op in {b"string", b"symbol", b"kindpat"}: return (), x - if op == "not": + if op == b"not": h, t = _insertstatushints(x[1]) return h, (op, t) - if op == "and": + if op == b"and": ha, ta = _insertstatushints(x[1]) hb, tb = _insertstatushints(x[2]) hr = ha + hb if ha and hb: - return hr, ("withstatus", (op, ta, tb), ("string", " ".join(hr))) + return hr, (b"withstatus", (op, ta, tb), (b"string", b" ".join(hr))) return hr, (op, ta, tb) - if op == "or": + if op == b"or": hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) hr = sum(hs, ()) if sum(bool(h) for h in hs) > 1: - return hr, ("withstatus", (op,) + ts, ("string", " ".join(hr))) + return hr, (b"withstatus", (op,) + ts, (b"string", b" ".join(hr))) return hr, (op,) + ts - if op == "list": + if op == b"list": hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) return sum(hs, ()), (op,) + ts - if op == "func": + if op == b"func": f = getsymbol(x[1]) # don't propagate 'ha' crossing a function boundary ha, ta = _insertstatushints(x[2]) if getattr(symbols.get(f), "_callstatus", False): - return (f,), ("withstatus", (op, x[1], ta), ("string", f)) + return (f,), (b"withstatus", (op, x[1], ta), (b"string", f)) return (), (op, x[1], ta) - raise error.ProgrammingError("invalid operator %r" % op) + raise error.ProgrammingError(b"invalid operator %r" % op) def _mergestatushints(x, instatus): @@ -235,29 +237,29 @@ return x op = x[0] - if op == "withstatus": + if op == b"withstatus": if instatus: # drop redundant hint node return _mergestatushints(x[1], instatus) t = _mergestatushints(x[1], instatus=True) return (op, t, x[2]) - if op in {"string", "symbol", "kindpat"}: + if op in {b"string", b"symbol", b"kindpat"}: return x - if op == "not": + if op == b"not": t = _mergestatushints(x[1], instatus) return (op, t) - if op == "and": + if op == b"and": ta = _mergestatushints(x[1], instatus) tb = _mergestatushints(x[2], instatus) return (op, ta, tb) - if op in {"list", "or"}: + if op in {b"list", b"or"}: ts = tuple(_mergestatushints(y, instatus) for y in x[1:]) return (op,) + ts - if op == "func": + if op == b"func": # don't propagate 'instatus' crossing a function boundary ta = _mergestatushints(x[2], instatus=False) return (op, x[1], ta) - raise error.ProgrammingError("invalid operator %r" % op) + raise error.ProgrammingError(b"invalid operator %r" % op) def analyze(x): @@ -273,8 +275,8 @@ def _optimizeandops(op, ta, tb): - if tb is not None and tb[0] == "not": - return ("minus", ta, tb[1]) + if tb is not None and tb[0] == b"not": + return (b"minus", ta, tb[1]) return (op, ta, tb) @@ -283,14 +285,14 @@ ws, ts, ss = [], [], [] for x in xs: w, t = _optimize(x) - if t is not None and t[0] in {"string", "symbol", "kindpat"}: + if t is not None and t[0] in {b"string", b"symbol", b"kindpat"}: ss.append(t) continue ws.append(w) ts.append(t) if ss: ws.append(WEIGHT_CHECK_FILENAME) - ts.append(("patterns",) + tuple(ss)) + ts.append((b"patterns",) + tuple(ss)) return ws, ts @@ -299,25 +301,25 @@ return 0, x op = x[0] - if op == "withstatus": + if op == b"withstatus": w, t = _optimize(x[1]) return w, (op, t, x[2]) - if op in {"string", "symbol"}: + if op in {b"string", b"symbol"}: return WEIGHT_CHECK_FILENAME, x - if op == "kindpat": + if op == b"kindpat": w, t = _optimize(x[2]) return w, (op, x[1], t) - if op == "not": + if op == b"not": w, t = _optimize(x[1]) return w, (op, t) - if op == "and": + if op == b"and": wa, ta = _optimize(x[1]) wb, tb = _optimize(x[2]) if wa <= wb: return wa, _optimizeandops(op, ta, tb) else: return wb, _optimizeandops(op, tb, ta) - if op == "or": + if op == b"or": ws, ts = _optimizeunion(x[1:]) if len(ts) == 1: return ws[0], ts[0] # 'or' operation is fully optimized out @@ -325,15 +327,15 @@ it[1] for it in sorted(enumerate(ts), key=lambda it: ws[it[0]]) ) return max(ws), (op,) + ts - if op == "list": + if op == b"list": ws, ts = zip(*(_optimize(y) for y in x[1:])) return sum(ws), (op,) + ts - if op == "func": + if op == b"func": f = getsymbol(x[1]) w = getattr(symbols.get(f), "_weight", 1) wa, ta = _optimize(x[2]) return w + wa, (op, x[1], ta) - raise error.ProgrammingError("invalid operator %r" % op) + raise error.ProgrammingError(b"invalid operator %r" % op) def optimize(x): @@ -346,4 +348,4 @@ def prettyformat(tree): - return parser.prettyformat(tree, ("string", "symbol")) + return parser.prettyformat(tree, (b"string", b"symbol")) diff --git a/mercurial/formatter.py b/mercurial/formatter.py --- a/mercurial/formatter.py +++ b/mercurial/formatter.py @@ -193,15 +193,15 @@ self._showitem() self._item = {} - def formatdate(self, date, fmt="%a %b %d %H:%M:%S %Y %1%2"): + def formatdate(self, date, fmt=b"%a %b %d %H:%M:%S %Y %1%2"): """convert date tuple to appropriate format""" return self._converter.formatdate(date, fmt) - def formatdict(self, data, key="key", value="value", fmt=None, sep=" "): + def formatdict(self, data, key=b"key", value=b"value", fmt=None, sep=b" "): """convert dict or key-value pairs to appropriate dict format""" return self._converter.formatdict(data, key, value, fmt, sep) - def formatlist(self, data, name, fmt=None, sep=" "): + def formatlist(self, data, name, fmt=None, sep=b" "): """convert iterable to appropriate list format""" # name is mandatory argument for now, but it could be optional if # we have default template keyword, e.g. {item} @@ -210,13 +210,13 @@ def context(self, **ctxs): """insert context objects to be used to render template keywords""" ctxs = pycompat.byteskwargs(ctxs) - assert all(k in {"repo", "ctx", "fctx"} for k in ctxs) + assert all(k in {b"repo", b"ctx", b"fctx"} for k in ctxs) if self._converter.storecontext: # populate missing resources in fctx -> ctx -> repo order - if "fctx" in ctxs and "ctx" not in ctxs: - ctxs["ctx"] = ctxs["fctx"].changectx() - if "ctx" in ctxs and "repo" not in ctxs: - ctxs["repo"] = ctxs["ctx"].repo() + if b"fctx" in ctxs and b"ctx" not in ctxs: + ctxs[b"ctx"] = ctxs[b"fctx"].changectx() + if b"ctx" in ctxs and b"repo" not in ctxs: + ctxs[b"repo"] = ctxs[b"ctx"].repo() self._item.update(ctxs) def datahint(self): @@ -247,7 +247,7 @@ """check for plain formatter usage""" return False - def nested(self, field, tmpl=None, sep=""): + def nested(self, field, tmpl=None, sep=b""): """sub formatter to store nested data in the specified field""" data = [] self._item[field] = self._converter.wrapnested(data, tmpl, sep) @@ -268,7 +268,9 @@ """build sub items and store them in the parent formatter""" def __init__(self, ui, converter, data): - baseformatter.__init__(self, ui, topic="", opts={}, converter=converter) + baseformatter.__init__( + self, ui, topic=b"", opts={}, converter=converter + ) self._data = data def _showitem(self): @@ -289,7 +291,7 @@ @staticmethod def wrapnested(data, tmpl, sep): - raise error.ProgrammingError("plainformatter should never be nested") + raise error.ProgrammingError(b"plainformatter should never be nested") @staticmethod def formatdate(date, fmt): @@ -301,7 +303,7 @@ """stringify key-value pairs separated by sep""" prefmt = pycompat.identity if fmt is None: - fmt = "%s=%s" + fmt = b"%s=%s" prefmt = pycompat.bytestr return sep.join( fmt % (prefmt(k), prefmt(v)) for k, v in _iteritems(data) @@ -312,7 +314,7 @@ """stringify iterable separated by sep""" prefmt = pycompat.identity if fmt is None: - fmt = "%s" + fmt = b"%s" prefmt = pycompat.bytestr return sep.join(fmt % prefmt(e) for e in data) @@ -351,7 +353,7 @@ def isplain(self): return True - def nested(self, field, tmpl=None, sep=""): + def nested(self, field, tmpl=None, sep=b""): # nested data will be directly written to ui return self @@ -363,16 +365,16 @@ def __init__(self, ui, out, topic, opts): baseformatter.__init__(self, ui, topic, opts, _nullconverter) self._out = out - self._out.write("%s = [\n" % self._topic) + self._out.write(b"%s = [\n" % self._topic) def _showitem(self): self._out.write( - " %s,\n" % stringutil.pprint(self._item, indent=4, level=1) + b" %s,\n" % stringutil.pprint(self._item, indent=4, level=1) ) def end(self): baseformatter.end(self) - self._out.write("]\n") + self._out.write(b"]\n") class pickleformatter(baseformatter): @@ -409,29 +411,29 @@ def __init__(self, ui, out, topic, opts): baseformatter.__init__(self, ui, topic, opts, _nullconverter) self._out = out - self._out.write("[") + self._out.write(b"[") self._first = True def _showitem(self): if self._first: self._first = False else: - self._out.write(",") + self._out.write(b",") - self._out.write("\n {\n") + self._out.write(b"\n {\n") first = True for k, v in sorted(self._item.items()): if first: first = False else: - self._out.write(",\n") + self._out.write(b",\n") u = templatefilters.json(v, paranoid=False) - self._out.write(' "%s": %s' % (k, u)) - self._out.write("\n }") + self._out.write(b' "%s": %s' % (k, u)) + self._out.write(b"\n }") def end(self): baseformatter.end(self) - self._out.write("\n]\n") + self._out.write(b"\n]\n") class _templateconverter(object): @@ -476,7 +478,7 @@ def __init__(self, ui, out, topic, opts): baseformatter.__init__(self, ui, topic, opts, _templateconverter) self._out = out - spec = lookuptemplate(ui, topic, opts.get("template", "")) + spec = lookuptemplate(ui, topic, opts.get(b"template", b"")) self._tref = spec.ref self._t = loadtemplater( ui, @@ -486,16 +488,16 @@ cache=templatekw.defaulttempl, ) self._parts = templatepartsmap( - spec, self._t, ["docheader", "docfooter", "separator"] + spec, self._t, [b"docheader", b"docfooter", b"separator"] ) self._counter = itertools.count() - self._renderitem("docheader", {}) + self._renderitem(b"docheader", {}) def _showitem(self): item = self._item.copy() - item["index"] = index = next(self._counter) + item[b"index"] = index = next(self._counter) if index > 0: - self._renderitem("separator", {}) + self._renderitem(b"separator", {}) self._renderitem(self._tref, item) def _renderitem(self, part, item): @@ -514,7 +516,7 @@ def end(self): baseformatter.end(self) - self._renderitem("docfooter", {}) + self._renderitem(b"docfooter", {}) @attr.s(frozen=True) @@ -544,36 +546,36 @@ """ # looks like a literal template? - if "{" in tmpl: - return templatespec("", tmpl, None) + if b"{" in tmpl: + return templatespec(b"", tmpl, None) # perhaps a stock style? if not os.path.split(tmpl)[0]: mapname = templater.templatepath( - "map-cmdline." + tmpl + b"map-cmdline." + tmpl ) or templater.templatepath(tmpl) if mapname and os.path.isfile(mapname): return templatespec(topic, None, mapname) # perhaps it's a reference to [templates] - if ui.config("templates", tmpl): + if ui.config(b"templates", tmpl): return templatespec(tmpl, None, None) - if tmpl == "list": - ui.write(_("available styles: %s\n") % templater.stylelist()) - raise error.Abort(_("specify a template")) + if tmpl == b"list": + ui.write(_(b"available styles: %s\n") % templater.stylelist()) + raise error.Abort(_(b"specify a template")) # perhaps it's a path to a map or a template - if ("/" in tmpl or "\\" in tmpl) and os.path.isfile(tmpl): + if (b"/" in tmpl or b"\\" in tmpl) and os.path.isfile(tmpl): # is it a mapfile for a style? - if os.path.basename(tmpl).startswith("map-"): + if os.path.basename(tmpl).startswith(b"map-"): return templatespec(topic, None, os.path.realpath(tmpl)) - with util.posixfile(tmpl, "rb") as f: + with util.posixfile(tmpl, b"rb") as f: tmpl = f.read() - return templatespec("", tmpl, None) + return templatespec(b"", tmpl, None) # constant string? - return templatespec("", tmpl, None) + return templatespec(b"", tmpl, None) def templatepartsmap(spec, t, partnames): @@ -583,7 +585,7 @@ partsmap.update((p, p) for p in partnames if p in t) elif spec.ref: for part in partnames: - ref = "%s:%s" % (spec.ref, part) # select config sub-section + ref = b"%s:%s" % (spec.ref, part) # select config sub-section if ref in t: partsmap[part] = ref return partsmap @@ -605,15 +607,15 @@ def maketemplater(ui, tmpl, defaults=None, resources=None, cache=None): """Create a templater from a string template 'tmpl'""" - aliases = ui.configitems("templatealias") + aliases = ui.configitems(b"templatealias") t = templater.templater( defaults=defaults, resources=resources, cache=cache, aliases=aliases ) t.cache.update( - (k, templater.unquotestring(v)) for k, v in ui.configitems("templates") + (k, templater.unquotestring(v)) for k, v in ui.configitems(b"templates") ) if tmpl: - t.cache[""] = tmpl + t.cache[b""] = tmpl return t @@ -627,9 +629,9 @@ def __init__(self, ui, repo=None): self._resmap = { - "cache": {}, # for templatekw/funcs to store reusable data - "repo": repo, - "ui": ui, + b"cache": {}, # for templatekw/funcs to store reusable data + b"repo": repo, + b"ui": ui, } def availablekeys(self, mapping): @@ -638,7 +640,7 @@ } def knownkeys(self): - return {"cache", "ctx", "fctx", "repo", "revcache", "ui"} + return {b"cache", b"ctx", b"fctx", b"repo", b"revcache", b"ui"} def lookup(self, mapping, key): if key not in self.knownkeys(): @@ -651,16 +653,16 @@ def populatemap(self, context, origmapping, newmapping): mapping = {} if self._hasnodespec(newmapping): - mapping["revcache"] = {} # per-ctx cache + mapping[b"revcache"] = {} # per-ctx cache if self._hasnodespec(origmapping) and self._hasnodespec(newmapping): - orignode = templateutil.runsymbol(context, origmapping, "node") - mapping["originalnode"] = orignode + orignode = templateutil.runsymbol(context, origmapping, b"node") + mapping[b"originalnode"] = orignode # put marker to override 'ctx'/'fctx' in mapping if any, and flag # its existence to be reported by availablekeys() - if "ctx" not in newmapping and self._hasliteral(newmapping, "node"): - mapping["ctx"] = _placeholder - if "fctx" not in newmapping and self._hasliteral(newmapping, "path"): - mapping["fctx"] = _placeholder + if b"ctx" not in newmapping and self._hasliteral(newmapping, b"node"): + mapping[b"ctx"] = _placeholder + if b"fctx" not in newmapping and self._hasliteral(newmapping, b"path"): + mapping[b"fctx"] = _placeholder return mapping def _getsome(self, mapping, key): @@ -682,11 +684,11 @@ def _hasnodespec(self, mapping): """Test if context revision is set or unset in the given mapping""" - return "node" in mapping or "ctx" in mapping + return b"node" in mapping or b"ctx" in mapping def _loadctx(self, mapping): - repo = self._getsome(mapping, "repo") - node = self._getliteral(mapping, "node") + repo = self._getsome(mapping, b"repo") + node = self._getliteral(mapping, b"node") if repo is None or node is None: return try: @@ -695,8 +697,8 @@ return None # maybe hidden/non-existent node def _loadfctx(self, mapping): - ctx = self._getsome(mapping, "ctx") - path = self._getliteral(mapping, "path") + ctx = self._getsome(mapping, b"ctx") + path = self._getliteral(mapping, b"path") if ctx is None or path is None: return None try: @@ -705,28 +707,28 @@ return None # maybe removed file? _loadermap = { - "ctx": _loadctx, - "fctx": _loadfctx, + b"ctx": _loadctx, + b"fctx": _loadfctx, } def formatter(ui, out, topic, opts): - template = opts.get("template", "") - if template == "cbor": + template = opts.get(b"template", b"") + if template == b"cbor": return cborformatter(ui, out, topic, opts) - elif template == "json": + elif template == b"json": return jsonformatter(ui, out, topic, opts) - elif template == "pickle": + elif template == b"pickle": return pickleformatter(ui, out, topic, opts) - elif template == "debug": + elif template == b"debug": return debugformatter(ui, out, topic, opts) - elif template != "": + elif template != b"": return templateformatter(ui, out, topic, opts) # developer config: ui.formatdebug - elif ui.configbool("ui", "formatdebug"): + elif ui.configbool(b"ui", b"formatdebug"): return debugformatter(ui, out, topic, opts) # deprecated config: ui.formatjson - elif ui.configbool("ui", "formatjson"): + elif ui.configbool(b"ui", b"formatjson"): return jsonformatter(ui, out, topic, opts) return plainformatter(ui, out, topic, opts) @@ -737,7 +739,7 @@ Must be invoked using the 'with' statement. """ - with util.posixfile(filename, "wb") as out: + with util.posixfile(filename, b"wb") as out: with formatter(ui, out, topic, opts) as fm: yield fm diff --git a/mercurial/graphmod.py b/mercurial/graphmod.py --- a/mercurial/graphmod.py +++ b/mercurial/graphmod.py @@ -27,15 +27,15 @@ util, ) -CHANGESET = "C" -PARENT = "P" -GRANDPARENT = "G" -MISSINGPARENT = "M" +CHANGESET = b"C" +PARENT = b"P" +GRANDPARENT = b"G" +MISSINGPARENT = b"M" # Style of line to draw. None signals a line that ends and is removed at this # point. A number prefix means only the last N characters of the current block # will use that style, the rest will use the PARENT style. Add a - sign # (so making N negative) and all but the first N characters use that style. -EDGES = {PARENT: "|", GRANDPARENT: ":", MISSINGPARENT: None} +EDGES = {PARENT: b"|", GRANDPARENT: b":", MISSINGPARENT: None} def dagwalker(repo, revs): @@ -118,13 +118,13 @@ newcolor = 1 config = {} - for key, val in repo.ui.configitems("graph"): - if "." in key: - branch, setting = key.rsplit(".", 1) + for key, val in repo.ui.configitems(b"graph"): + if b"." in key: + branch, setting = key.rsplit(b".", 1) # Validation - if setting == "width" and val.isdigit(): + if setting == b"width" and val.isdigit(): config.setdefault(branch, {})[setting] = int(val) - elif setting == "color" and val.isalnum(): + elif setting == b"color" and val.isalnum(): config.setdefault(branch, {})[setting] = val if config: @@ -168,8 +168,8 @@ ecol, next.index(eid), colors[eid], - bconf.get("width", -1), - bconf.get("color", ""), + bconf.get(b"width", -1), + bconf.get(b"color", b""), ) ) elif eid == cur: @@ -180,8 +180,8 @@ ecol, next.index(p), color, - bconf.get("width", -1), - bconf.get("color", ""), + bconf.get(b"width", -1), + bconf.get(b"color", b""), ) ) @@ -192,7 +192,7 @@ def asciiedges(type, char, state, rev, parents): """adds edge info to changelog DAG walk suitable for ascii()""" - seen = state["seen"] + seen = state[b"seen"] if rev not in seen: seen.append(rev) nodeidx = seen.index(rev) @@ -207,7 +207,7 @@ knownparents.append(parent) else: newparents.append(parent) - state["edges"][parent] = state["styles"].get(ptype, "|") + state[b"edges"][parent] = state[b"styles"].get(ptype, b"|") ncols = len(seen) width = 1 + ncols * 2 @@ -226,7 +226,7 @@ nmorecols = 1 width += 2 yield (type, char, width, (nodeidx, edges, ncols, nmorecols)) - char = "\\" + char = b"\\" nodeidx += 1 ncols += 1 edges = [] @@ -240,7 +240,7 @@ if nmorecols > 0: width += 2 # remove current node from edge characters, no longer needed - state["edges"].pop(rev, None) + state[b"edges"].pop(rev, None) yield (type, char, width, (nodeidx, edges, ncols, nmorecols)) @@ -256,10 +256,10 @@ if coldiff == -1: start = max(idx + 1, pidx) tail = echars[idx * 2 : (start - 1) * 2] - tail.extend(["/", " "] * (ncols - start)) + tail.extend([b"/", b" "] * (ncols - start)) return tail else: - return ["\\", " "] * (ncols - idx - 1) + return [b"\\", b" "] * (ncols - idx - 1) else: remainder = ncols - idx - 1 return echars[-(remainder * 2) :] if remainder > 0 else [] @@ -268,20 +268,20 @@ def _drawedges(echars, edges, nodeline, interline): for (start, end) in edges: if start == end + 1: - interline[2 * end + 1] = "/" + interline[2 * end + 1] = b"/" elif start == end - 1: - interline[2 * start + 1] = "\\" + interline[2 * start + 1] = b"\\" elif start == end: interline[2 * start] = echars[2 * start] else: if 2 * end >= len(nodeline): continue - nodeline[2 * end] = "+" + nodeline[2 * end] = b"+" if start > end: (start, end) = (end, start) for i in range(2 * start + 1, 2 * end): - if nodeline[i] != "+": - nodeline[i] = "-" + if nodeline[i] != b"+": + nodeline[i] = b"-" def _getpaddingline(echars, idx, ncols, edges): @@ -297,7 +297,7 @@ # | | | | | | line.extend(echars[idx * 2 : (idx + 1) * 2]) else: - line.extend([" ", " "]) + line.extend([b" ", b" "]) # all edges to the right of the current node remainder = ncols - idx - 1 if remainder > 0: @@ -322,7 +322,7 @@ while edgechars and edgechars[-1] is None: edgechars.pop() shift_size = max((edgechars.count(None) * 2) - 1, 0) - minlines = 3 if not state["graphshorten"] else 2 + minlines = 3 if not state[b"graphshorten"] else 2 while len(lines) < minlines + shift_size: lines.append(extra[:]) @@ -338,17 +338,17 @@ targets = list(range(first_empty, first_empty + len(toshift) * 2, 2)) positions = toshift[:] for line in lines[-shift_size:]: - line[first_empty:] = [" "] * (len(line) - first_empty) + line[first_empty:] = [b" "] * (len(line) - first_empty) for i in range(len(positions)): pos = positions[i] - 1 positions[i] = max(pos, targets[i]) - line[pos] = "/" if pos > targets[i] else extra[toshift[i]] + line[pos] = b"/" if pos > targets[i] else extra[toshift[i]] - map = {1: "|", 2: "~"} if not state["graphshorten"] else {1: "~"} + map = {1: b"|", 2: b"~"} if not state[b"graphshorten"] else {1: b"~"} for i, line in enumerate(lines): if None not in line: continue - line[:] = [c or map.get(i, " ") for c in line] + line[:] = [c or map.get(i, b" ") for c in line] # remove edges that ended remove = [p for p, c in edgemap.items() if c is None] @@ -360,12 +360,12 @@ def asciistate(): """returns the initial value for the "state" argument to ascii()""" return { - "seen": [], - "edges": {}, - "lastcoldiff": 0, - "lastindex": 0, - "styles": EDGES.copy(), - "graphshorten": False, + b"seen": [], + b"edges": {}, + b"lastcoldiff": 0, + b"lastindex": 0, + b"styles": EDGES.copy(), + b"graphshorten": False, } @@ -383,7 +383,7 @@ without needing to mimic all of the edge-fixup logic in ascii() """ for (ln, logstr) in graph: - ui.write((ln + logstr).rstrip() + "\n") + ui.write((ln + logstr).rstrip() + b"\n") def ascii(ui, state, type, char, text, coldata): @@ -409,11 +409,11 @@ idx, edges, ncols, coldiff = coldata assert -2 < coldiff < 2 - edgemap, seen = state["edges"], state["seen"] + edgemap, seen = state[b"edges"], state[b"seen"] # Be tolerant of history issues; make sure we have at least ncols + coldiff # elements to work with. See test-glog.t for broken history test cases. - echars = [c for p in seen for c in (edgemap.get(p, "|"), " ")] - echars.extend(("|", " ") * max(ncols + coldiff - len(seen), 0)) + echars = [c for p in seen for c in (edgemap.get(p, b"|"), b" ")] + echars.extend((b"|", b" ") * max(ncols + coldiff - len(seen), 0)) if coldiff == -1: # Transform @@ -446,16 +446,16 @@ # nodeline is the line containing the node character (typically o) nodeline = echars[: idx * 2] - nodeline.extend([char, " "]) + nodeline.extend([char, b" "]) nodeline.extend( _getnodelineedgestail( echars, idx, - state["lastindex"], + state[b"lastindex"], ncols, coldiff, - state["lastcoldiff"], + state[b"lastcoldiff"], fix_nodeline_tail, ) ) @@ -464,16 +464,16 @@ # edges between this entry and the next shift_interline = echars[: idx * 2] for i in pycompat.xrange(2 + coldiff): - shift_interline.append(" ") + shift_interline.append(b" ") count = ncols - idx - 1 if coldiff == -1: for i in pycompat.xrange(count): - shift_interline.extend(["/", " "]) + shift_interline.extend([b"/", b" "]) elif coldiff == 0: shift_interline.extend(echars[(idx + 1) * 2 : ncols * 2]) else: for i in pycompat.xrange(count): - shift_interline.extend(["\\", " "]) + shift_interline.extend([b"\\", b" "]) # draw edges from the current node to its parents _drawedges(echars, edges, nodeline, shift_interline) @@ -485,7 +485,7 @@ # If 'graphshorten' config, only draw shift_interline # when there is any non vertical flow in graph. - if state["graphshorten"]: + if state[b"graphshorten"]: if any(c in br"\/" for c in shift_interline if c): lines.append(shift_interline) # Else, no 'graphshorten' config so draw shift_interline. @@ -502,13 +502,15 @@ _drawendinglines(lines, extra_interline, edgemap, seen, state) while len(text) < len(lines): - text.append("") + text.append(b"") # print lines indentation_level = max(ncols, ncols + coldiff) - lines = ["%-*s " % (2 * indentation_level, "".join(line)) for line in lines] + lines = [ + b"%-*s " % (2 * indentation_level, b"".join(line)) for line in lines + ] outputgraph(ui, zip(lines, text)) # ... and start over - state["lastcoldiff"] = coldiff - state["lastindex"] = idx + state[b"lastcoldiff"] = coldiff + state[b"lastindex"] = idx diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py --- a/mercurial/hbisect.py +++ b/mercurial/hbisect.py @@ -34,32 +34,32 @@ repo = repo.unfiltered() changelog = repo.changelog clparents = changelog.parentrevs - skip = {changelog.rev(n) for n in state["skip"]} + skip = {changelog.rev(n) for n in state[b"skip"]} def buildancestors(bad, good): badrev = min([changelog.rev(n) for n in bad]) ancestors = collections.defaultdict(lambda: None) - for rev in repo.revs("descendants(%ln) - ancestors(%ln)", good, good): + for rev in repo.revs(b"descendants(%ln) - ancestors(%ln)", good, good): ancestors[rev] = [] if ancestors[badrev] is None: return badrev, None return badrev, ancestors good = False - badrev, ancestors = buildancestors(state["bad"], state["good"]) + badrev, ancestors = buildancestors(state[b"bad"], state[b"good"]) if not ancestors: # looking for bad to good transition? good = True - badrev, ancestors = buildancestors(state["good"], state["bad"]) + badrev, ancestors = buildancestors(state[b"good"], state[b"bad"]) bad = changelog.node(badrev) if not ancestors: # now we're confused if ( - len(state["bad"]) == 1 - and len(state["good"]) == 1 - and state["bad"] != state["good"] + len(state[b"bad"]) == 1 + and len(state[b"good"]) == 1 + and state[b"bad"] != state[b"good"] ): - raise error.Abort(_("starting revisions are not directly related")) + raise error.Abort(_(b"starting revisions are not directly related")) raise error.Abort( - _("inconsistent state, %d:%s is good and bad") + _(b"inconsistent state, %d:%s is good and bad") % (badrev, short(bad)) ) @@ -133,9 +133,9 @@ parents = repo[nodes[0]].parents() if len(parents) > 1: if good: - side = state["bad"] + side = state[b"bad"] else: - side = state["good"] + side = state[b"good"] num = len(set(i.node() for i in parents) & set(side)) if num == 1: return parents[0].ancestor(parents[1]) @@ -143,41 +143,41 @@ def load_state(repo): - state = {"current": [], "good": [], "bad": [], "skip": []} - for l in repo.vfs.tryreadlines("bisect.state"): + state = {b"current": [], b"good": [], b"bad": [], b"skip": []} + for l in repo.vfs.tryreadlines(b"bisect.state"): kind, node = l[:-1].split() node = repo.unfiltered().lookup(node) if kind not in state: - raise error.Abort(_("unknown bisect kind %s") % kind) + raise error.Abort(_(b"unknown bisect kind %s") % kind) state[kind].append(node) return state def save_state(repo, state): - f = repo.vfs("bisect.state", "w", atomictemp=True) + f = repo.vfs(b"bisect.state", b"w", atomictemp=True) with repo.wlock(): for kind in sorted(state): for node in state[kind]: - f.write("%s %s\n" % (kind, hex(node))) + f.write(b"%s %s\n" % (kind, hex(node))) f.close() def resetstate(repo): """remove any bisect state from the repository""" - if repo.vfs.exists("bisect.state"): - repo.vfs.unlink("bisect.state") + if repo.vfs.exists(b"bisect.state"): + repo.vfs.unlink(b"bisect.state") def checkstate(state): """check we have both 'good' and 'bad' to define a range Raise Abort exception otherwise.""" - if state["good"] and state["bad"]: + if state[b"good"] and state[b"bad"]: return True - if not state["good"]: - raise error.Abort(_("cannot bisect (no known good revisions)")) + if not state[b"good"]: + raise error.Abort(_(b"cannot bisect (no known good revisions)")) else: - raise error.Abort(_("cannot bisect (no known bad revisions)")) + raise error.Abort(_(b"cannot bisect (no known bad revisions)")) def get(repo, status): @@ -193,7 +193,7 @@ - ``current`` : the cset currently being bisected """ state = load_state(repo) - if status in ("good", "bad", "skip", "current"): + if status in (b"good", b"bad", b"skip", b"current"): return map(repo.unfiltered().changelog.rev, state[status]) else: # In the following sets, we do *not* call 'bisect()' with more @@ -204,77 +204,77 @@ # 'range' is all csets that make the bisection: # - have a good ancestor and a bad descendant, or conversely # that's because the bisection can go either way - range = "( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )" + range = b"( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )" - _t = repo.revs("bisect(good)::bisect(bad)") + _t = repo.revs(b"bisect(good)::bisect(bad)") # The sets of topologically good or bad csets if len(_t) == 0: # Goods are topologically after bads - goods = "bisect(good)::" # Pruned good csets - bads = "::bisect(bad)" # Pruned bad csets + goods = b"bisect(good)::" # Pruned good csets + bads = b"::bisect(bad)" # Pruned bad csets else: # Goods are topologically before bads - goods = "::bisect(good)" # Pruned good csets - bads = "bisect(bad)::" # Pruned bad csets + goods = b"::bisect(good)" # Pruned good csets + bads = b"bisect(bad)::" # Pruned bad csets # 'pruned' is all csets whose fate is already known: good, bad, skip - skips = "bisect(skip)" # Pruned skipped csets - pruned = "( (%s) | (%s) | (%s) )" % (goods, bads, skips) + skips = b"bisect(skip)" # Pruned skipped csets + pruned = b"( (%s) | (%s) | (%s) )" % (goods, bads, skips) # 'untested' is all cset that are- in 'range', but not in 'pruned' - untested = "( (%s) - (%s) )" % (range, pruned) + untested = b"( (%s) - (%s) )" % (range, pruned) # 'ignored' is all csets that were not used during the bisection # due to DAG topology, but may however have had an impact. # E.g., a branch merged between bads and goods, but whose branch- # point is out-side of the range. - iba = "::bisect(bad) - ::bisect(good)" # Ignored bads' ancestors - iga = "::bisect(good) - ::bisect(bad)" # Ignored goods' ancestors - ignored = "( ( (%s) | (%s) ) - (%s) )" % (iba, iga, range) + iba = b"::bisect(bad) - ::bisect(good)" # Ignored bads' ancestors + iga = b"::bisect(good) - ::bisect(bad)" # Ignored goods' ancestors + ignored = b"( ( (%s) | (%s) ) - (%s) )" % (iba, iga, range) - if status == "range": + if status == b"range": return repo.revs(range) - elif status == "pruned": + elif status == b"pruned": return repo.revs(pruned) - elif status == "untested": + elif status == b"untested": return repo.revs(untested) - elif status == "ignored": + elif status == b"ignored": return repo.revs(ignored) - elif status == "goods": + elif status == b"goods": return repo.revs(goods) - elif status == "bads": + elif status == b"bads": return repo.revs(bads) else: - raise error.ParseError(_("invalid bisect state")) + raise error.ParseError(_(b"invalid bisect state")) def label(repo, node): rev = repo.changelog.rev(node) # Try explicit sets - if rev in get(repo, "good"): + if rev in get(repo, b"good"): # i18n: bisect changeset status - return _("good") - if rev in get(repo, "bad"): + return _(b"good") + if rev in get(repo, b"bad"): # i18n: bisect changeset status - return _("bad") - if rev in get(repo, "skip"): + return _(b"bad") + if rev in get(repo, b"skip"): # i18n: bisect changeset status - return _("skipped") - if rev in get(repo, "untested") or rev in get(repo, "current"): + return _(b"skipped") + if rev in get(repo, b"untested") or rev in get(repo, b"current"): # i18n: bisect changeset status - return _("untested") - if rev in get(repo, "ignored"): + return _(b"untested") + if rev in get(repo, b"ignored"): # i18n: bisect changeset status - return _("ignored") + return _(b"ignored") # Try implicit sets - if rev in get(repo, "goods"): + if rev in get(repo, b"goods"): # i18n: bisect changeset status - return _("good (implicit)") - if rev in get(repo, "bads"): + return _(b"good (implicit)") + if rev in get(repo, b"bads"): # i18n: bisect changeset status - return _("bad (implicit)") + return _(b"bad (implicit)") return None @@ -284,17 +284,17 @@ if len(nodes) == 1: # narrowed it down to a single revision if good: - ui.write(_("The first good revision is:\n")) + ui.write(_(b"The first good revision is:\n")) else: - ui.write(_("The first bad revision is:\n")) + ui.write(_(b"The first bad revision is:\n")) displayer.show(repo[nodes[0]]) extendnode = extendrange(repo, state, nodes, good) if extendnode is not None: ui.write( _( - "Not all ancestors of this changeset have been" - " checked.\nUse bisect --extend to continue the " - "bisection from\nthe common ancestor, %s.\n" + b"Not all ancestors of this changeset have been" + b" checked.\nUse bisect --extend to continue the " + b"bisection from\nthe common ancestor, %s.\n" ) % extendnode ) @@ -303,15 +303,15 @@ if good: ui.write( _( - "Due to skipped revisions, the first " - "good revision could be any of:\n" + b"Due to skipped revisions, the first " + b"good revision could be any of:\n" ) ) else: ui.write( _( - "Due to skipped revisions, the first " - "bad revision could be any of:\n" + b"Due to skipped revisions, the first " + b"bad revision could be any of:\n" ) ) for n in nodes: diff --git a/mercurial/help.py b/mercurial/help.py --- a/mercurial/help.py +++ b/mercurial/help.py @@ -38,15 +38,15 @@ from .utils import compression _exclkeywords = { - "(ADVANCED)", - "(DEPRECATED)", - "(EXPERIMENTAL)", + b"(ADVANCED)", + b"(DEPRECATED)", + b"(EXPERIMENTAL)", # i18n: "(ADVANCED)" is a keyword, must be translated consistently - _("(ADVANCED)"), + _(b"(ADVANCED)"), # i18n: "(DEPRECATED)" is a keyword, must be translated consistently - _("(DEPRECATED)"), + _(b"(DEPRECATED)"), # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently - _("(EXPERIMENTAL)"), + _(b"(EXPERIMENTAL)"), } # The order in which command categories will be displayed. @@ -72,28 +72,28 @@ # Human-readable category names. These are translated. # Extensions with custom categories should add their names here. CATEGORY_NAMES = { - registrar.command.CATEGORY_REPO_CREATION: "Repository creation", - registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT: "Remote repository management", - registrar.command.CATEGORY_COMMITTING: "Change creation", - registrar.command.CATEGORY_CHANGE_NAVIGATION: "Change navigation", - registrar.command.CATEGORY_CHANGE_MANAGEMENT: "Change manipulation", - registrar.command.CATEGORY_CHANGE_ORGANIZATION: "Change organization", - registrar.command.CATEGORY_WORKING_DIRECTORY: "Working directory management", - registrar.command.CATEGORY_FILE_CONTENTS: "File content management", - registrar.command.CATEGORY_IMPORT_EXPORT: "Change import/export", - registrar.command.CATEGORY_MAINTENANCE: "Repository maintenance", - registrar.command.CATEGORY_HELP: "Help", - registrar.command.CATEGORY_MISC: "Miscellaneous commands", - registrar.command.CATEGORY_NONE: "Uncategorized commands", + registrar.command.CATEGORY_REPO_CREATION: b"Repository creation", + registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT: b"Remote repository management", + registrar.command.CATEGORY_COMMITTING: b"Change creation", + registrar.command.CATEGORY_CHANGE_NAVIGATION: b"Change navigation", + registrar.command.CATEGORY_CHANGE_MANAGEMENT: b"Change manipulation", + registrar.command.CATEGORY_CHANGE_ORGANIZATION: b"Change organization", + registrar.command.CATEGORY_WORKING_DIRECTORY: b"Working directory management", + registrar.command.CATEGORY_FILE_CONTENTS: b"File content management", + registrar.command.CATEGORY_IMPORT_EXPORT: b"Change import/export", + registrar.command.CATEGORY_MAINTENANCE: b"Repository maintenance", + registrar.command.CATEGORY_HELP: b"Help", + registrar.command.CATEGORY_MISC: b"Miscellaneous commands", + registrar.command.CATEGORY_NONE: b"Uncategorized commands", } # Topic categories. -TOPIC_CATEGORY_IDS = "ids" -TOPIC_CATEGORY_OUTPUT = "output" -TOPIC_CATEGORY_CONFIG = "config" -TOPIC_CATEGORY_CONCEPTS = "concepts" -TOPIC_CATEGORY_MISC = "misc" -TOPIC_CATEGORY_NONE = "none" +TOPIC_CATEGORY_IDS = b"ids" +TOPIC_CATEGORY_OUTPUT = b"output" +TOPIC_CATEGORY_CONFIG = b"config" +TOPIC_CATEGORY_CONCEPTS = b"concepts" +TOPIC_CATEGORY_MISC = b"misc" +TOPIC_CATEGORY_NONE = b"none" # The order in which topic categories will be displayed. # Extensions with custom categories should insert them into this list @@ -110,12 +110,12 @@ # Human-readable topic category names. These are translated. TOPIC_CATEGORY_NAMES = { - TOPIC_CATEGORY_IDS: "Mercurial identifiers", - TOPIC_CATEGORY_OUTPUT: "Mercurial output", - TOPIC_CATEGORY_CONFIG: "Mercurial configuration", - TOPIC_CATEGORY_CONCEPTS: "Concepts", - TOPIC_CATEGORY_MISC: "Miscellaneous", - TOPIC_CATEGORY_NONE: "Uncategorized topics", + TOPIC_CATEGORY_IDS: b"Mercurial identifiers", + TOPIC_CATEGORY_OUTPUT: b"Mercurial output", + TOPIC_CATEGORY_CONFIG: b"Mercurial configuration", + TOPIC_CATEGORY_CONCEPTS: b"Concepts", + TOPIC_CATEGORY_MISC: b"Miscellaneous", + TOPIC_CATEGORY_NONE: b"Uncategorized topics", } @@ -126,27 +126,27 @@ for name, desc in sorted(exts.iteritems()): if not showdeprecated and any(w in desc for w in _exclkeywords): continue - rst.append("%s:%s: %s\n" % (" " * indent, name, desc)) + rst.append(b"%s:%s: %s\n" % (b" " * indent, name, desc)) if rst: - rst.insert(0, "\n%s\n\n" % header) + rst.insert(0, b"\n%s\n\n" % header) return rst def extshelp(ui): - rst = loaddoc("extensions")(ui).splitlines(True) + rst = loaddoc(b"extensions")(ui).splitlines(True) rst.extend( listexts( - _("enabled extensions:"), extensions.enabled(), showdeprecated=True + _(b"enabled extensions:"), extensions.enabled(), showdeprecated=True ) ) rst.extend( listexts( - _("disabled extensions:"), + _(b"disabled extensions:"), extensions.disabled(), showdeprecated=ui.verbose, ) ) - doc = "".join(rst) + doc = b"".join(rst) return doc @@ -158,17 +158,17 @@ shortopt, longopt, default, desc, optlabel = option else: shortopt, longopt, default, desc = option - optlabel = _("VALUE") # default label + optlabel = _(b"VALUE") # default label if not verbose and any(w in desc for w in _exclkeywords): continue - so = "" + so = b"" if shortopt: - so = "-" + shortopt - lo = "--" + longopt + so = b"-" + shortopt + lo = b"--" + longopt if default is True: - lo = "--[no-]" + longopt + lo = b"--[no-]" + longopt if isinstance(default, fancyopts.customopt): default = default.getdefaultvalue() @@ -179,34 +179,34 @@ # then convert it to bytes. defaultstr = pycompat.bytestr(default) if default is True: - defaultstr = _("on") - desc += _(" (default: %s)") % defaultstr + defaultstr = _(b"on") + desc += _(b" (default: %s)") % defaultstr if isinstance(default, list): - lo += " %s [+]" % optlabel + lo += b" %s [+]" % optlabel multioccur = True elif (default is not None) and not isinstance(default, bool): - lo += " %s" % optlabel + lo += b" %s" % optlabel data.append((so, lo, desc)) if multioccur: - header += _(" ([+] can be repeated)") + header += _(b" ([+] can be repeated)") - rst = ["\n%s:\n\n" % header] + rst = [b"\n%s:\n\n" % header] rst.extend(minirst.maketable(data, 1)) - return "".join(rst) + return b"".join(rst) def indicateomitted(rst, omitted, notomitted=None): - rst.append("\n\n.. container:: omitted\n\n %s\n\n" % omitted) + rst.append(b"\n\n.. container:: omitted\n\n %s\n\n" % omitted) if notomitted: - rst.append("\n\n.. container:: notomitted\n\n %s\n\n" % notomitted) + rst.append(b"\n\n.. container:: notomitted\n\n %s\n\n" % notomitted) def filtercmd(ui, cmd, func, kw, doc): - if not ui.debugflag and cmd.startswith("debug") and kw != "debug": + if not ui.debugflag and cmd.startswith(b"debug") and kw != b"debug": # Debug command, and user is not looking for those. return True if not ui.verbose: @@ -219,17 +219,17 @@ if doc and any(w in doc for w in _exclkeywords): # Documentation has excluded keywords. return True - if kw == "shortlist" and not getattr(func, "helpbasic", False): + if kw == b"shortlist" and not getattr(func, "helpbasic", False): # We're presenting the short list but the command is not basic. return True - if ui.configbool("help", "hidden-command.%s" % cmd): + if ui.configbool(b"help", b"hidden-command.%s" % cmd): # Configuration explicitly hides the command. return True return False def filtertopic(ui, topic): - return ui.configbool("help", "hidden-topic.%s" % topic, False) + return ui.configbool(b"help", b"hidden-topic.%s" % topic, False) def topicmatch(ui, commands, kw): @@ -244,10 +244,10 @@ return kw in encoding.lower(container) # translated in helptable results = { - "topics": [], - "commands": [], - "extensions": [], - "extensioncommands": [], + b"topics": [], + b"commands": [], + b"extensions": [], + b"extensioncommands": [], } for topic in helptable: names, header, doc = topic[0:3] @@ -259,15 +259,15 @@ ): name = names[0] if not filtertopic(ui, name): - results["topics"].append((names[0], header)) + results[b"topics"].append((names[0], header)) for cmd, entry in commands.table.iteritems(): if len(entry) == 3: summary = entry[2] else: - summary = "" + summary = b"" # translate docs *before* searching there func = entry[0] - docs = _(pycompat.getdoc(func)) or "" + docs = _(pycompat.getdoc(func)) or b"" if kw in cmd or lowercontains(summary) or lowercontains(docs): doclines = docs.splitlines() if doclines: @@ -275,18 +275,18 @@ cmdname = cmdutil.parsealiases(cmd)[0] if filtercmd(ui, cmdname, func, kw, docs): continue - results["commands"].append((cmdname, summary)) + results[b"commands"].append((cmdname, summary)) for name, docs in itertools.chain( extensions.enabled(False).iteritems(), extensions.disabled().iteritems() ): if not docs: continue - name = name.rpartition(".")[-1] + name = name.rpartition(b".")[-1] if lowercontains(name) or lowercontains(docs): # extension docs are already translated - results["extensions"].append((name, docs.splitlines()[0])) + results[b"extensions"].append((name, docs.splitlines()[0])) try: - mod = extensions.load(ui, name, "") + mod = extensions.load(ui, name, b"") except ImportError: # debug message would be printed in extensions.load() continue @@ -298,10 +298,10 @@ if cmddoc: cmddoc = gettext(cmddoc).splitlines()[0] else: - cmddoc = _("(no help text available)") + cmddoc = _(b"(no help text available)") if filtercmd(ui, cmdname, func, kw, cmddoc): continue - results["extensioncommands"].append((cmdname, cmddoc)) + results[b"extensioncommands"].append((cmdname, cmddoc)) return results @@ -309,10 +309,10 @@ """Return a delayed loader for help/topic.txt.""" def loader(ui): - docdir = os.path.join(util.datapath, "help") + docdir = os.path.join(util.datapath, b"help") if subdir: docdir = os.path.join(docdir, subdir) - path = os.path.join(docdir, topic + ".txt") + path = os.path.join(docdir, topic + b".txt") doc = gettext(util.readfile(path)) for rewriter in helphooks.get(topic, []): doc = rewriter(ui, topic, doc) @@ -323,54 +323,54 @@ internalstable = sorted( [ - (["bundle2"], _("Bundle2"), loaddoc("bundle2", subdir="internals")), - (["bundles"], _("Bundles"), loaddoc("bundles", subdir="internals")), - (["cbor"], _("CBOR"), loaddoc("cbor", subdir="internals")), - (["censor"], _("Censor"), loaddoc("censor", subdir="internals")), + ([b"bundle2"], _(b"Bundle2"), loaddoc(b"bundle2", subdir=b"internals")), + ([b"bundles"], _(b"Bundles"), loaddoc(b"bundles", subdir=b"internals")), + ([b"cbor"], _(b"CBOR"), loaddoc(b"cbor", subdir=b"internals")), + ([b"censor"], _(b"Censor"), loaddoc(b"censor", subdir=b"internals")), ( - ["changegroups"], - _("Changegroups"), - loaddoc("changegroups", subdir="internals"), + [b"changegroups"], + _(b"Changegroups"), + loaddoc(b"changegroups", subdir=b"internals"), ), ( - ["config"], - _("Config Registrar"), - loaddoc("config", subdir="internals"), + [b"config"], + _(b"Config Registrar"), + loaddoc(b"config", subdir=b"internals"), ), ( - ["extensions", "extension"], - _("Extension API"), - loaddoc("extensions", subdir="internals"), + [b"extensions", b"extension"], + _(b"Extension API"), + loaddoc(b"extensions", subdir=b"internals"), ), ( - ["mergestate"], - _("Mergestate"), - loaddoc("mergestate", subdir="internals"), + [b"mergestate"], + _(b"Mergestate"), + loaddoc(b"mergestate", subdir=b"internals"), ), ( - ["requirements"], - _("Repository Requirements"), - loaddoc("requirements", subdir="internals"), + [b"requirements"], + _(b"Repository Requirements"), + loaddoc(b"requirements", subdir=b"internals"), ), ( - ["revlogs"], - _("Revision Logs"), - loaddoc("revlogs", subdir="internals"), + [b"revlogs"], + _(b"Revision Logs"), + loaddoc(b"revlogs", subdir=b"internals"), ), ( - ["wireprotocol"], - _("Wire Protocol"), - loaddoc("wireprotocol", subdir="internals"), + [b"wireprotocol"], + _(b"Wire Protocol"), + loaddoc(b"wireprotocol", subdir=b"internals"), ), ( - ["wireprotocolrpc"], - _("Wire Protocol RPC"), - loaddoc("wireprotocolrpc", subdir="internals"), + [b"wireprotocolrpc"], + _(b"Wire Protocol RPC"), + loaddoc(b"wireprotocolrpc", subdir=b"internals"), ), ( - ["wireprotocolv2"], - _("Wire Protocol Version 2"), - loaddoc("wireprotocolv2", subdir="internals"), + [b"wireprotocolv2"], + _(b"Wire Protocol Version 2"), + loaddoc(b"wireprotocolv2", subdir=b"internals"), ), ] ) @@ -379,138 +379,155 @@ def internalshelp(ui): """Generate the index for the "internals" topic.""" lines = [ - 'To access a subtopic, use "hg help internals.{subtopic-name}"\n', - "\n", + b'To access a subtopic, use "hg help internals.{subtopic-name}"\n', + b"\n", ] for names, header, doc in internalstable: - lines.append(" :%s: %s\n" % (names[0], header)) + lines.append(b" :%s: %s\n" % (names[0], header)) - return "".join(lines) + return b"".join(lines) helptable = sorted( [ ( - ["bundlespec"], - _("Bundle File Formats"), - loaddoc("bundlespec"), + [b"bundlespec"], + _(b"Bundle File Formats"), + loaddoc(b"bundlespec"), TOPIC_CATEGORY_CONCEPTS, ), ( - ["color"], - _("Colorizing Outputs"), - loaddoc("color"), + [b"color"], + _(b"Colorizing Outputs"), + loaddoc(b"color"), TOPIC_CATEGORY_OUTPUT, ), ( - ["config", "hgrc"], - _("Configuration Files"), - loaddoc("config"), + [b"config", b"hgrc"], + _(b"Configuration Files"), + loaddoc(b"config"), TOPIC_CATEGORY_CONFIG, ), ( - ["deprecated"], - _("Deprecated Features"), - loaddoc("deprecated"), + [b"deprecated"], + _(b"Deprecated Features"), + loaddoc(b"deprecated"), TOPIC_CATEGORY_MISC, ), - (["dates"], _("Date Formats"), loaddoc("dates"), TOPIC_CATEGORY_OUTPUT), ( - ["flags"], - _("Command-line flags"), - loaddoc("flags"), + [b"dates"], + _(b"Date Formats"), + loaddoc(b"dates"), + TOPIC_CATEGORY_OUTPUT, + ), + ( + [b"flags"], + _(b"Command-line flags"), + loaddoc(b"flags"), TOPIC_CATEGORY_CONFIG, ), ( - ["patterns"], - _("File Name Patterns"), - loaddoc("patterns"), + [b"patterns"], + _(b"File Name Patterns"), + loaddoc(b"patterns"), TOPIC_CATEGORY_IDS, ), ( - ["environment", "env"], - _("Environment Variables"), - loaddoc("environment"), + [b"environment", b"env"], + _(b"Environment Variables"), + loaddoc(b"environment"), TOPIC_CATEGORY_CONFIG, ), ( - ["revisions", "revs", "revsets", "revset", "multirevs", "mrevs"], - _("Specifying Revisions"), - loaddoc("revisions"), + [ + b"revisions", + b"revs", + b"revsets", + b"revset", + b"multirevs", + b"mrevs", + ], + _(b"Specifying Revisions"), + loaddoc(b"revisions"), TOPIC_CATEGORY_IDS, ), ( - ["filesets", "fileset"], - _("Specifying File Sets"), - loaddoc("filesets"), + [b"filesets", b"fileset"], + _(b"Specifying File Sets"), + loaddoc(b"filesets"), TOPIC_CATEGORY_IDS, ), - (["diffs"], _("Diff Formats"), loaddoc("diffs"), TOPIC_CATEGORY_OUTPUT), ( - ["merge-tools", "mergetools", "mergetool"], - _("Merge Tools"), - loaddoc("merge-tools"), + [b"diffs"], + _(b"Diff Formats"), + loaddoc(b"diffs"), + TOPIC_CATEGORY_OUTPUT, + ), + ( + [b"merge-tools", b"mergetools", b"mergetool"], + _(b"Merge Tools"), + loaddoc(b"merge-tools"), TOPIC_CATEGORY_CONFIG, ), ( - ["templating", "templates", "template", "style"], - _("Template Usage"), - loaddoc("templates"), + [b"templating", b"templates", b"template", b"style"], + _(b"Template Usage"), + loaddoc(b"templates"), TOPIC_CATEGORY_OUTPUT, ), - (["urls"], _("URL Paths"), loaddoc("urls"), TOPIC_CATEGORY_IDS), + ([b"urls"], _(b"URL Paths"), loaddoc(b"urls"), TOPIC_CATEGORY_IDS), ( - ["extensions"], - _("Using Additional Features"), + [b"extensions"], + _(b"Using Additional Features"), extshelp, TOPIC_CATEGORY_CONFIG, ), ( - ["subrepos", "subrepo"], - _("Subrepositories"), - loaddoc("subrepos"), + [b"subrepos", b"subrepo"], + _(b"Subrepositories"), + loaddoc(b"subrepos"), TOPIC_CATEGORY_CONCEPTS, ), ( - ["hgweb"], - _("Configuring hgweb"), - loaddoc("hgweb"), + [b"hgweb"], + _(b"Configuring hgweb"), + loaddoc(b"hgweb"), TOPIC_CATEGORY_CONFIG, ), ( - ["glossary"], - _("Glossary"), - loaddoc("glossary"), + [b"glossary"], + _(b"Glossary"), + loaddoc(b"glossary"), TOPIC_CATEGORY_CONCEPTS, ), ( - ["hgignore", "ignore"], - _("Syntax for Mercurial Ignore Files"), - loaddoc("hgignore"), + [b"hgignore", b"ignore"], + _(b"Syntax for Mercurial Ignore Files"), + loaddoc(b"hgignore"), TOPIC_CATEGORY_IDS, ), ( - ["phases"], - _("Working with Phases"), - loaddoc("phases"), + [b"phases"], + _(b"Working with Phases"), + loaddoc(b"phases"), TOPIC_CATEGORY_CONCEPTS, ), ( - ["scripting"], - _("Using Mercurial from scripts and automation"), - loaddoc("scripting"), + [b"scripting"], + _(b"Using Mercurial from scripts and automation"), + loaddoc(b"scripting"), TOPIC_CATEGORY_MISC, ), ( - ["internals"], - _("Technical implementation topics"), + [b"internals"], + _(b"Technical implementation topics"), internalshelp, TOPIC_CATEGORY_MISC, ), ( - ["pager"], - _("Pager Support"), - loaddoc("pager"), + [b"pager"], + _(b"Pager Support"), + loaddoc(b"pager"), TOPIC_CATEGORY_CONFIG, ), ] @@ -518,7 +535,7 @@ # Maps topics with sub-topics to a list of their sub-topics. subtopics = { - "internals": internalstable, + b"internals": internalstable, } # Map topics to lists of callable taking the current topic help and @@ -536,7 +553,7 @@ """ entries = [] for name in sorted(items): - text = (pycompat.getdoc(items[name]) or "").rstrip() + text = (pycompat.getdoc(items[name]) or b"").rstrip() if not text or not ui.verbose and any(w in text for w in _exclkeywords): continue text = gettext(text) @@ -547,14 +564,14 @@ doclines = [(lines[0])] for l in lines[1:]: # Stop once we find some Python doctest - if l.strip().startswith(">>>"): + if l.strip().startswith(b">>>"): break if dedent: doclines.append(l.rstrip()) else: - doclines.append(" " + l.strip()) - entries.append("\n".join(doclines)) - entries = "\n\n".join(entries) + doclines.append(b" " + l.strip()) + entries.append(b"\n".join(doclines)) + entries = b"\n\n".join(entries) return doc.replace(marker, entries) @@ -566,33 +583,35 @@ addtopicsymbols( - "bundlespec", - ".. bundlecompressionmarker", + b"bundlespec", + b".. bundlecompressionmarker", compression.bundlecompressiontopics(), ) -addtopicsymbols("filesets", ".. predicatesmarker", fileset.symbols) -addtopicsymbols("merge-tools", ".. internaltoolsmarker", filemerge.internalsdoc) -addtopicsymbols("revisions", ".. predicatesmarker", revset.symbols) -addtopicsymbols("templates", ".. keywordsmarker", templatekw.keywords) -addtopicsymbols("templates", ".. filtersmarker", templatefilters.filters) -addtopicsymbols("templates", ".. functionsmarker", templatefuncs.funcs) +addtopicsymbols(b"filesets", b".. predicatesmarker", fileset.symbols) addtopicsymbols( - "hgweb", ".. webcommandsmarker", webcommands.commands, dedent=True + b"merge-tools", b".. internaltoolsmarker", filemerge.internalsdoc +) +addtopicsymbols(b"revisions", b".. predicatesmarker", revset.symbols) +addtopicsymbols(b"templates", b".. keywordsmarker", templatekw.keywords) +addtopicsymbols(b"templates", b".. filtersmarker", templatefilters.filters) +addtopicsymbols(b"templates", b".. functionsmarker", templatefuncs.funcs) +addtopicsymbols( + b"hgweb", b".. webcommandsmarker", webcommands.commands, dedent=True ) def inserttweakrc(ui, topic, doc): - marker = ".. tweakdefaultsmarker" + marker = b".. tweakdefaultsmarker" repl = uimod.tweakrc def sub(m): lines = [m.group(1) + s for s in repl.splitlines()] - return "\n".join(lines) + return b"\n".join(lines) return re.sub(br"( *)%s" % re.escape(marker), sub, doc) -addtopichook("config", inserttweakrc) +addtopichook(b"config", inserttweakrc) def help_( @@ -629,7 +648,7 @@ # check if it's an invalid alias and display its error if it is if getattr(entry[0], "badalias", None): - rst.append(entry[0].badalias + "\n") + rst.append(entry[0].badalias + b"\n") if entry[0].unknowncmd: try: rst.extend(helpextcmd(entry[0].cmdname)) @@ -639,31 +658,31 @@ # synopsis if len(entry) > 2: - if entry[2].startswith("hg"): - rst.append("%s\n" % entry[2]) + if entry[2].startswith(b"hg"): + rst.append(b"%s\n" % entry[2]) else: - rst.append("hg %s %s\n" % (aliases[0], entry[2])) + rst.append(b"hg %s %s\n" % (aliases[0], entry[2])) else: - rst.append("hg %s\n" % aliases[0]) + rst.append(b"hg %s\n" % aliases[0]) # aliases if full and not ui.quiet and len(aliases) > 1: - rst.append(_("\naliases: %s\n") % ", ".join(aliases[1:])) - rst.append("\n") + rst.append(_(b"\naliases: %s\n") % b", ".join(aliases[1:])) + rst.append(b"\n") # description doc = gettext(pycompat.getdoc(entry[0])) if not doc: - doc = _("(no help text available)") - if util.safehasattr(entry[0], "definition"): # aliased command + doc = _(b"(no help text available)") + if util.safehasattr(entry[0], b"definition"): # aliased command source = entry[0].source - if entry[0].definition.startswith("!"): # shell alias - doc = _("shell alias for: %s\n\n%s\n\ndefined by: %s\n") % ( + if entry[0].definition.startswith(b"!"): # shell alias + doc = _(b"shell alias for: %s\n\n%s\n\ndefined by: %s\n") % ( entry[0].definition[1:], doc, source, ) else: - doc = _("alias for: hg %s\n\n%s\n\ndefined by: %s\n") % ( + doc = _(b"alias for: hg %s\n\n%s\n\ndefined by: %s\n") % ( entry[0].definition, doc, source, @@ -673,38 +692,39 @@ rst.append(doc[0]) else: rst.extend(doc) - rst.append("\n") + rst.append(b"\n") # check if this command shadows a non-trivial (multi-line) # extension help text try: mod = extensions.find(name) - doc = gettext(pycompat.getdoc(mod)) or "" - if "\n" in doc.strip(): + doc = gettext(pycompat.getdoc(mod)) or b"" + if b"\n" in doc.strip(): msg = _( - "(use 'hg help -e %s' to show help for " "the %s extension)" + b"(use 'hg help -e %s' to show help for " + b"the %s extension)" ) % (name, name) - rst.append("\n%s\n" % msg) + rst.append(b"\n%s\n" % msg) except KeyError: pass # options if not ui.quiet and entry[1]: - rst.append(optrst(_("options"), entry[1], ui.verbose)) + rst.append(optrst(_(b"options"), entry[1], ui.verbose)) if ui.verbose: rst.append( - optrst(_("global options"), commands.globalopts, ui.verbose) + optrst(_(b"global options"), commands.globalopts, ui.verbose) ) if not ui.verbose: if not full: - rst.append(_("\n(use 'hg %s -h' to show more help)\n") % name) + rst.append(_(b"\n(use 'hg %s -h' to show more help)\n") % name) elif not ui.quiet: rst.append( _( - "\n(some details hidden, use --verbose " - "to show complete help)" + b"\n(some details hidden, use --verbose " + b"to show complete help)" ) ) @@ -720,7 +740,7 @@ for c, e in commands.table.iteritems(): fs = cmdutil.parsealiases(c) f = fs[0] - syns[f] = ", ".join(fs) + syns[f] = b", ".join(fs) func = e[0] if select and not select(f): continue @@ -729,7 +749,7 @@ continue doc = gettext(doc) if not doc: - doc = _("(no help text available)") + doc = _(b"(no help text available)") h[f] = doc.splitlines()[0].rstrip() cat = getattr(func, "helpcategory", None) or ( @@ -740,27 +760,27 @@ rst = [] if not h: if not ui.quiet: - rst.append(_("no commands defined\n")) + rst.append(_(b"no commands defined\n")) return rst # Output top header. if not ui.quiet: - if name == "shortlist": - rst.append(_("basic commands:\n\n")) - elif name == "debug": - rst.append(_("debug commands (internal and unsupported):\n\n")) + if name == b"shortlist": + rst.append(_(b"basic commands:\n\n")) + elif name == b"debug": + rst.append(_(b"debug commands (internal and unsupported):\n\n")) else: - rst.append(_("list of commands:\n")) + rst.append(_(b"list of commands:\n")) def appendcmds(cmds): cmds = sorted(cmds) for c in cmds: if ui.verbose: - rst.append(" :%s: %s\n" % (syns[c], h[c])) + rst.append(b" :%s: %s\n" % (syns[c], h[c])) else: - rst.append(" :%s: %s\n" % (c, h[c])) + rst.append(b" :%s: %s\n" % (c, h[c])) - if name in ("shortlist", "debug"): + if name in (b"shortlist", b"debug"): # List without categories. appendcmds(h) else: @@ -768,7 +788,7 @@ missing_order = set(cats.keys()) - set(CATEGORY_ORDER) if missing_order: ui.develwarn( - "help categories missing from CATEGORY_ORDER: %s" + b"help categories missing from CATEGORY_ORDER: %s" % missing_order ) @@ -778,23 +798,23 @@ if catfns: if len(cats) > 1: catname = gettext(CATEGORY_NAMES[cat]) - rst.append("\n%s:\n" % catname) - rst.append("\n") + rst.append(b"\n%s:\n" % catname) + rst.append(b"\n") appendcmds(catfns) ex = opts.get anyopts = ex(r"keyword") or not (ex(r"command") or ex(r"extension")) if not name and anyopts: exts = listexts( - _("enabled extensions:"), + _(b"enabled extensions:"), extensions.enabled(), showdeprecated=ui.verbose, ) if exts: - rst.append("\n") + rst.append(b"\n") rst.extend(exts) - rst.append(_("\nadditional help topics:\n")) + rst.append(_(b"\nadditional help topics:\n")) # Group commands by category. topiccats = {} for topic in helptable: @@ -814,7 +834,7 @@ missing_order = set(topiccats.keys()) - set(TOPIC_CATEGORY_ORDER) if missing_order: ui.develwarn( - "help categories missing from TOPIC_CATEGORY_ORDER: %s" + b"help categories missing from TOPIC_CATEGORY_ORDER: %s" % missing_order ) @@ -824,50 +844,50 @@ if topics: if len(topiccats) > 1: catname = gettext(TOPIC_CATEGORY_NAMES[cat]) - rst.append("\n%s:\n" % catname) - rst.append("\n") + rst.append(b"\n%s:\n" % catname) + rst.append(b"\n") for t, desc in topics: - rst.append(" :%s: %s\n" % (t, desc)) + rst.append(b" :%s: %s\n" % (t, desc)) if ui.quiet: pass elif ui.verbose: rst.append( - "\n%s\n" - % optrst(_("global options"), commands.globalopts, ui.verbose) + b"\n%s\n" + % optrst(_(b"global options"), commands.globalopts, ui.verbose) ) - if name == "shortlist": + if name == b"shortlist": rst.append( - _("\n(use 'hg help' for the full list " "of commands)\n") + _(b"\n(use 'hg help' for the full list " b"of commands)\n") ) else: - if name == "shortlist": + if name == b"shortlist": rst.append( _( - "\n(use 'hg help' for the full list of commands " - "or 'hg -v' for details)\n" + b"\n(use 'hg help' for the full list of commands " + b"or 'hg -v' for details)\n" ) ) elif name and not full: rst.append( - _("\n(use 'hg help %s' to show the full help " "text)\n") + _(b"\n(use 'hg help %s' to show the full help " b"text)\n") % name ) elif name and syns and name in syns.keys(): rst.append( _( - "\n(use 'hg help -v -e %s' to show built-in " - "aliases and global options)\n" + b"\n(use 'hg help -v -e %s' to show built-in " + b"aliases and global options)\n" ) % name ) else: rst.append( _( - "\n(use 'hg help -v%s' to show built-in aliases " - "and global options)\n" + b"\n(use 'hg help -v%s' to show built-in aliases " + b"and global options)\n" ) - % (name and " " + name or "") + % (name and b" " + name or b"") ) return rst @@ -893,20 +913,21 @@ # description if not doc: - rst.append(" %s\n" % _("(no help text available)")) + rst.append(b" %s\n" % _(b"(no help text available)")) if callable(doc): - rst += [" %s\n" % l for l in doc(ui).splitlines()] + rst += [b" %s\n" % l for l in doc(ui).splitlines()] if not ui.verbose: omitted = _( - "(some details hidden, use --verbose" " to show complete help)" + b"(some details hidden, use --verbose" + b" to show complete help)" ) indicateomitted(rst, omitted) try: cmdutil.findcmd(name, commands.table) rst.append( - _("\nuse 'hg help -c %s' to see help for " "the %s command\n") + _(b"\nuse 'hg help -c %s' to see help for " b"the %s command\n") % (name, name) ) except error.UnknownCommand: @@ -916,25 +937,26 @@ def helpext(name, subtopic=None): try: mod = extensions.find(name) - doc = gettext(pycompat.getdoc(mod)) or _("no help text available") + doc = gettext(pycompat.getdoc(mod)) or _(b"no help text available") except KeyError: mod = None doc = extensions.disabledext(name) if not doc: raise error.UnknownCommand(name) - if "\n" not in doc: - head, tail = doc, "" + if b"\n" not in doc: + head, tail = doc, b"" else: - head, tail = doc.split("\n", 1) - rst = [_("%s extension - %s\n\n") % (name.rpartition(".")[-1], head)] + head, tail = doc.split(b"\n", 1) + rst = [_(b"%s extension - %s\n\n") % (name.rpartition(b".")[-1], head)] if tail: rst.extend(tail.splitlines(True)) - rst.append("\n") + rst.append(b"\n") if not ui.verbose: omitted = _( - "(some details hidden, use --verbose" " to show complete help)" + b"(some details hidden, use --verbose" + b" to show complete help)" ) indicateomitted(rst, omitted) @@ -943,70 +965,70 @@ ct = mod.cmdtable except AttributeError: ct = {} - modcmds = {c.partition("|")[0] for c in ct} + modcmds = {c.partition(b"|")[0] for c in ct} rst.extend(helplist(modcmds.__contains__)) else: rst.append( _( - "(use 'hg help extensions' for information on enabling" - " extensions)\n" + b"(use 'hg help extensions' for information on enabling" + b" extensions)\n" ) ) return rst def helpextcmd(name, subtopic=None): cmd, ext, doc = extensions.disabledcmd( - ui, name, ui.configbool("ui", "strict") + ui, name, ui.configbool(b"ui", b"strict") ) doc = doc.splitlines()[0] rst = listexts( - _("'%s' is provided by the following " "extension:") % cmd, + _(b"'%s' is provided by the following " b"extension:") % cmd, {ext: doc}, indent=4, showdeprecated=True, ) - rst.append("\n") + rst.append(b"\n") rst.append( _( - "(use 'hg help extensions' for information on enabling " - "extensions)\n" + b"(use 'hg help extensions' for information on enabling " + b"extensions)\n" ) ) return rst rst = [] - kw = opts.get("keyword") + kw = opts.get(b"keyword") if kw or name is None and any(opts[o] for o in opts): - matches = topicmatch(ui, commands, name or "") + matches = topicmatch(ui, commands, name or b"") helpareas = [] - if opts.get("extension"): - helpareas += [("extensions", _("Extensions"))] - if opts.get("command"): - helpareas += [("commands", _("Commands"))] + if opts.get(b"extension"): + helpareas += [(b"extensions", _(b"Extensions"))] + if opts.get(b"command"): + helpareas += [(b"commands", _(b"Commands"))] if not helpareas: helpareas = [ - ("topics", _("Topics")), - ("commands", _("Commands")), - ("extensions", _("Extensions")), - ("extensioncommands", _("Extension Commands")), + (b"topics", _(b"Topics")), + (b"commands", _(b"Commands")), + (b"extensions", _(b"Extensions")), + (b"extensioncommands", _(b"Extension Commands")), ] for t, title in helpareas: if matches[t]: - rst.append("%s:\n\n" % title) + rst.append(b"%s:\n\n" % title) rst.extend(minirst.maketable(sorted(matches[t]), 1)) - rst.append("\n") + rst.append(b"\n") if not rst: - msg = _("no matches") - hint = _("try 'hg help' for a list of topics") + msg = _(b"no matches") + hint = _(b"try 'hg help' for a list of topics") raise error.Abort(msg, hint=hint) - elif name and name != "shortlist": + elif name and name != b"shortlist": queries = [] if unknowncmd: queries += [helpextcmd] - if opts.get("extension"): + if opts.get(b"extension"): queries += [helpext] - if opts.get("command"): + if opts.get(b"command"): queries += [helpcmd] if not queries: queries = (helptopic, helpcmd, helpext, helpextcmd) @@ -1028,16 +1050,16 @@ hintname = subtopic else: hintname = name - msg = _("no such help topic: %s") % formatname - hint = _("try 'hg help --keyword %s'") % hintname + msg = _(b"no such help topic: %s") % formatname + hint = _(b"try 'hg help --keyword %s'") % hintname raise error.Abort(msg, hint=hint) else: # program name if not ui.quiet: - rst = [_("Mercurial Distributed SCM\n"), "\n"] + rst = [_(b"Mercurial Distributed SCM\n"), b"\n"] rst.extend(helplist(None, **pycompat.strkwargs(opts))) - return "".join(rst) + return b"".join(rst) def formattedhelp( @@ -1055,14 +1077,14 @@ # := [.] name = subtopic = section = None if fullname is not None: - nameparts = fullname.split(".") + nameparts = fullname.split(b".") name = nameparts.pop(0) if nameparts and name in subtopics: subtopic = nameparts.pop(0) if nameparts: - section = encoding.lower(".".join(nameparts)) + section = encoding.lower(b".".join(nameparts)) - textwidth = ui.configint("ui", "textwidth") + textwidth = ui.configint(b"ui", b"textwidth") termwidth = ui.termwidth() - 2 if textwidth <= 0 or termwidth < textwidth: textwidth = termwidth @@ -1078,10 +1100,10 @@ ) blocks, pruned = minirst.parse(text, keep=keep) - if "verbose" in pruned: - keep.append("omitted") + if b"verbose" in pruned: + keep.append(b"omitted") else: - keep.append("notomitted") + keep.append(b"notomitted") blocks, pruned = minirst.parse(text, keep=keep) if section: blocks = minirst.filtersections(blocks, section) @@ -1090,6 +1112,6 @@ # to look for, or we could have simply failed to found "foo.bar" # because bar isn't a section of foo if section and not (blocks and name): - raise error.Abort(_("help section not found: %s") % fullname) + raise error.Abort(_(b"help section not found: %s") % fullname) return minirst.formatplain(blocks, textwidth) diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -53,7 +53,7 @@ release = lock.release # shared features -sharedbookmarks = "bookmarks" +sharedbookmarks = b"bookmarks" def _local(path): @@ -64,7 +64,7 @@ # Python 2 raises TypeError, Python 3 ValueError. except (TypeError, ValueError) as e: raise error.Abort( - _("invalid path %s: %s") % (path, pycompat.bytestr(e)) + _(b"invalid path %s: %s") % (path, pycompat.bytestr(e)) ) return isfile and bundlerepo or localrepo @@ -85,19 +85,19 @@ else: revs = [] - if not peer.capable("branchmap"): + if not peer.capable(b"branchmap"): if branches: - raise error.Abort(_("remote branch lookup not supported")) + raise error.Abort(_(b"remote branch lookup not supported")) revs.append(hashbranch) return revs, revs[0] with peer.commandexecutor() as e: - branchmap = e.callcommand("branchmap", {}).result() + branchmap = e.callcommand(b"branchmap", {}).result() def primary(branch): - if branch == ".": + if branch == b".": if not lrepo: - raise error.Abort(_("dirstate branch not accessible")) + raise error.Abort(_(b"dirstate branch not accessible")) branch = lrepo.dirstate.branch() if branch in branchmap: revs.extend(node.hex(r) for r in reversed(branchmap[branch])) @@ -107,7 +107,7 @@ for branch in branches: if not primary(branch): - raise error.RepoLookupError(_("unknown branch '%s'") % branch) + raise error.RepoLookupError(_(b"unknown branch '%s'") % branch) if hashbranch: if not primary(hashbranch): revs.append(hashbranch) @@ -126,26 +126,26 @@ schemes = { - "bundle": bundlerepo, - "union": unionrepo, - "file": _local, - "http": httppeer, - "https": httppeer, - "ssh": sshpeer, - "static-http": statichttprepo, + b"bundle": bundlerepo, + b"union": unionrepo, + b"file": _local, + b"http": httppeer, + b"https": httppeer, + b"ssh": sshpeer, + b"static-http": statichttprepo, } def _peerlookup(path): u = util.url(path) - scheme = u.scheme or "file" - thing = schemes.get(scheme) or schemes["file"] + scheme = u.scheme or b"file" + thing = schemes.get(scheme) or schemes[b"file"] try: return thing(path) except TypeError: # we can't test callable(thing) because 'thing' can be an unloaded # module that implements __call__ - if not util.safehasattr(thing, "instance"): + if not util.safehasattr(thing, b"instance"): raise return thing @@ -164,7 +164,7 @@ """open path with open if local, url.open if remote""" pathurl = util.url(path, parsequery=False, parsefragment=False) if pathurl.islocal(): - return util.posixfile(pathurl.localpath(), "rb") + return util.posixfile(pathurl.localpath(), b"rb") else: return url.open(ui, path, sendaccept=sendaccept) @@ -184,12 +184,12 @@ for f in presetupfuncs or []: f(ui, obj) ui.log(b"extension", b"- executing reposetup hooks\n") - with util.timedcm("all reposetup") as allreposetupstats: + with util.timedcm(b"all reposetup") as allreposetupstats: for name, module in extensions.extensions(ui): ui.log(b"extension", b" - running reposetup for %s\n", name) hook = getattr(module, "reposetup", None) if hook: - with util.timedcm("reposetup %r", name) as stats: + with util.timedcm(b"reposetup %r", name) as stats: hook(ui, obj) ui.log( b"extension", b" > reposetup for %s took %s\n", name, stats @@ -202,7 +202,12 @@ def repository( - ui, path="", create=False, presetupfuncs=None, intents=None, createopts=None + ui, + path=b"", + create=False, + presetupfuncs=None, + intents=None, + createopts=None, ): """return a repository object for the specified path""" peer = _peerorrepo( @@ -216,9 +221,9 @@ repo = peer.local() if not repo: raise error.Abort( - _("repository '%s' is not local") % (path or peer.url()) + _(b"repository '%s' is not local") % (path or peer.url()) ) - return repo.filtered("visible") + return repo.filtered(b"visible") def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None): @@ -247,7 +252,7 @@ """ path = util.url(source).path if not path: - return "" + return b"" return os.path.basename(os.path.normpath(path)) @@ -259,7 +264,7 @@ if repo.sharedpath == repo.path: return None - if util.safehasattr(repo, "srcrepo") and repo.srcrepo: + if util.safehasattr(repo, b"srcrepo") and repo.srcrepo: return repo.srcrepo # the sharedpath always ends in the .hg; we want the path to the repo @@ -282,7 +287,7 @@ """create a shared repository""" if not islocal(source): - raise error.Abort(_("can only share local repositories")) + raise error.Abort(_(b"can only share local repositories")) if not dest: dest = defaultdest(source) @@ -307,9 +312,9 @@ dest, create=True, createopts={ - "sharedrepo": srcrepo, - "sharedrelative": relative, - "shareditems": shareditems, + b"sharedrepo": srcrepo, + b"sharedrelative": relative, + b"shareditems": shareditems, }, ) @@ -338,11 +343,11 @@ destlock = copystore(ui, repo, repo.path) with destlock or util.nullcontextmanager(): - sharefile = repo.vfs.join("sharedpath") - util.rename(sharefile, sharefile + ".old") + sharefile = repo.vfs.join(b"sharedpath") + util.rename(sharefile, sharefile + b".old") - repo.requirements.discard("shared") - repo.requirements.discard("relshared") + repo.requirements.discard(b"shared") + repo.requirements.discard(b"relshared") repo._writerequirements() # Removing share changes some fundamental properties of the repo instance. @@ -352,7 +357,7 @@ # TODO: figure out how to access subrepos that exist, but were previously # removed from .hgsub - c = newrepo["."] + c = newrepo[b"."] subs = c.substate for s in sorted(subs): c.sub(s).unshare() @@ -371,10 +376,10 @@ Extensions can wrap this function and write additional entries to destrepo/.hg/shared to indicate additional pieces of data to be shared. """ - default = defaultpath or sourcerepo.ui.config("paths", "default") + default = defaultpath or sourcerepo.ui.config(b"paths", b"default") if default: - template = "[paths]\n" "default = %s\n" - destrepo.vfs.write("hgrc", util.tonativeeol(template % default)) + template = b"[paths]\n" b"default = %s\n" + destrepo.vfs.write(b"hgrc", util.tonativeeol(template % default)) if repositorymod.NARROW_REQUIREMENT in sourcerepo.requirements: with destrepo.wlock(): narrowspec.copytoworkingcopy(destrepo) @@ -388,10 +393,10 @@ if not update: return - repo.ui.status(_("updating working directory\n")) + repo.ui.status(_(b"updating working directory\n")) if update is not True: checkout = update - for test in (checkout, "default", "tip"): + for test in (checkout, b"default", b"tip"): if test is None: continue try: @@ -410,22 +415,22 @@ destlock = None try: hardlink = None - topic = _("linking") if hardlink else _("copying") - with ui.makeprogress(topic, unit=_("files")) as progress: + topic = _(b"linking") if hardlink else _(b"copying") + with ui.makeprogress(topic, unit=_(b"files")) as progress: num = 0 srcpublishing = srcrepo.publishing() srcvfs = vfsmod.vfs(srcrepo.sharedpath) dstvfs = vfsmod.vfs(destpath) for f in srcrepo.store.copylist(): - if srcpublishing and f.endswith("phaseroots"): + if srcpublishing and f.endswith(b"phaseroots"): continue dstbase = os.path.dirname(f) if dstbase and not dstvfs.exists(dstbase): dstvfs.mkdir(dstbase) if srcvfs.exists(f): - if f.endswith("data"): + if f.endswith(b"data"): # 'dstbase' may be empty (e.g. revlog format 0) - lockfile = os.path.join(dstbase, "lock") + lockfile = os.path.join(dstbase, b"lock") # lock to avoid premature writing to the target destlock = lock.lock(dstvfs, lockfile) hardlink, n = util.copyfiles( @@ -433,9 +438,9 @@ ) num += n if hardlink: - ui.debug("linked %d files\n" % num) + ui.debug(b"linked %d files\n" % num) else: - ui.debug("copied %d files\n" % num) + ui.debug(b"copied %d files\n" % num) return destlock except: # re-raises release(destlock) @@ -463,12 +468,12 @@ """ revs = None if rev: - if not srcpeer.capable("lookup"): + if not srcpeer.capable(b"lookup"): raise error.Abort( _( - "src repository does not support " - "revision lookup and so doesn't " - "support clone by revision" + b"src repository does not support " + b"revision lookup and so doesn't " + b"support clone by revision" ) ) @@ -476,7 +481,9 @@ remoterevs = [] for r in rev: with srcpeer.commandexecutor() as e: - remoterevs.append(e.callcommand("lookup", {"key": r,}).result()) + remoterevs.append( + e.callcommand(b"lookup", {b"key": r,}).result() + ) revs = remoterevs # Obtain a lock before checking for or cloning the pooled repo otherwise @@ -492,13 +499,15 @@ poolvfs = vfsmod.vfs(pooldir) basename = os.path.basename(sharepath) - with lock.lock(poolvfs, "%s.lock" % basename): + with lock.lock(poolvfs, b"%s.lock" % basename): if os.path.exists(sharepath): ui.status( - _("(sharing from existing pooled repository %s)\n") % basename + _(b"(sharing from existing pooled repository %s)\n") % basename ) else: - ui.status(_("(sharing from new pooled repository %s)\n") % basename) + ui.status( + _(b"(sharing from new pooled repository %s)\n") % basename + ) # Always use pull mode because hardlinks in share mode don't work # well. Never update because working copies aren't necessary in # share mode. @@ -545,7 +554,7 @@ # so just copy it def _copycache(srcrepo, dstcachedir, fname): """copy a cache from srcrepo to destcachedir (if it exists)""" - srcbranchcache = srcrepo.vfs.join("cache/%s" % fname) + srcbranchcache = srcrepo.vfs.join(b"cache/%s" % fname) dstbranchcache = os.path.join(dstcachedir, fname) if os.path.exists(srcbranchcache): if not os.path.exists(dstcachedir): @@ -631,7 +640,7 @@ if dest is None: dest = defaultdest(source) if dest: - ui.status(_("destination directory: %s\n") % dest) + ui.status(_(b"destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) @@ -639,14 +648,14 @@ source = util.urllocalpath(source) if not dest: - raise error.Abort(_("empty destination path is not valid")) + raise error.Abort(_(b"empty destination path is not valid")) destvfs = vfsmod.vfs(dest, expandpath=True) if destvfs.lexists(): if not destvfs.isdir(): - raise error.Abort(_("destination '%s' already exists") % dest) + raise error.Abort(_(b"destination '%s' already exists") % dest) elif destvfs.listdir(): - raise error.Abort(_("destination '%s' is not empty") % dest) + raise error.Abort(_(b"destination '%s' is not empty") % dest) createopts = {} narrow = False @@ -662,12 +671,12 @@ if narrow: # Include everything by default if only exclusion patterns defined. if storeexcludepats and not storeincludepats: - storeincludepats = {"path:."} + storeincludepats = {b"path:."} - createopts["narrowfiles"] = True + createopts[b"narrowfiles"] = True if depth: - createopts["shallowfilestore"] = True + createopts[b"shallowfilestore"] = True if srcpeer.capable(b"lfs-serve"): # Repository creation honors the config if it disabled the extension, so @@ -677,65 +686,67 @@ # requirement is added. If the extension is explicitly disabled but the # requirement is set, the clone aborts early, before transferring any # data. - createopts["lfs"] = True + createopts[b"lfs"] = True - if extensions.disabledext("lfs"): + if extensions.disabledext(b"lfs"): ui.status( _( - "(remote is using large file support (lfs), but it is " - "explicitly disabled in the local configuration)\n" + b"(remote is using large file support (lfs), but it is " + b"explicitly disabled in the local configuration)\n" ) ) else: ui.status( _( - "(remote is using large file support (lfs); lfs will " - "be enabled for this repository)\n" + b"(remote is using large file support (lfs); lfs will " + b"be enabled for this repository)\n" ) ) shareopts = shareopts or {} - sharepool = shareopts.get("pool") - sharenamemode = shareopts.get("mode") + sharepool = shareopts.get(b"pool") + sharenamemode = shareopts.get(b"mode") if sharepool and islocal(dest): sharepath = None - if sharenamemode == "identity": + if sharenamemode == b"identity": # Resolve the name from the initial changeset in the remote # repository. This returns nullid when the remote is empty. It # raises RepoLookupError if revision 0 is filtered or otherwise # not available. If we fail to resolve, sharing is not enabled. try: with srcpeer.commandexecutor() as e: - rootnode = e.callcommand("lookup", {"key": "0",}).result() + rootnode = e.callcommand( + b"lookup", {b"key": b"0",} + ).result() if rootnode != node.nullid: sharepath = os.path.join(sharepool, node.hex(rootnode)) else: ui.status( _( - "(not using pooled storage: " - "remote appears to be empty)\n" + b"(not using pooled storage: " + b"remote appears to be empty)\n" ) ) except error.RepoLookupError: ui.status( _( - "(not using pooled storage: " - "unable to resolve identity of remote)\n" + b"(not using pooled storage: " + b"unable to resolve identity of remote)\n" ) ) - elif sharenamemode == "remote": + elif sharenamemode == b"remote": sharepath = os.path.join( sharepool, node.hex(hashlib.sha1(source).digest()) ) else: raise error.Abort( - _("unknown share naming mode: %s") % sharenamemode + _(b"unknown share naming mode: %s") % sharenamemode ) # TODO this is a somewhat arbitrary restriction. if narrow: - ui.status(_("(pooled storage not supported for narrow clones)\n")) + ui.status(_(b"(pooled storage not supported for narrow clones)\n")) sharepath = None if sharepath: @@ -786,8 +797,8 @@ copy = False if copy: - srcrepo.hook("preoutgoing", throw=True, source="clone") - hgdir = os.path.realpath(os.path.join(dest, ".hg")) + srcrepo.hook(b"preoutgoing", throw=True, source=b"clone") + hgdir = os.path.realpath(os.path.join(dest, b".hg")) if not os.path.exists(dest): util.makedirs(dest) else: @@ -800,25 +811,27 @@ if inst.errno == errno.EEXIST: cleandir = None raise error.Abort( - _("destination '%s' already exists") % dest + _(b"destination '%s' already exists") % dest ) raise destlock = copystore(ui, srcrepo, destpath) # copy bookmarks over - srcbookmarks = srcrepo.vfs.join("bookmarks") - dstbookmarks = os.path.join(destpath, "bookmarks") + srcbookmarks = srcrepo.vfs.join(b"bookmarks") + dstbookmarks = os.path.join(destpath, b"bookmarks") if os.path.exists(srcbookmarks): util.copyfile(srcbookmarks, dstbookmarks) - dstcachedir = os.path.join(destpath, "cache") + dstcachedir = os.path.join(destpath, b"cache") for cache in cacheutil.cachetocopy(srcrepo): _copycache(srcrepo, dstcachedir, cache) # we need to re-init the repo after manually copying the data # into it destpeer = peer(srcrepo, peeropts, dest) - srcrepo.hook("outgoing", source="clone", node=node.hex(node.nullid)) + srcrepo.hook( + b"outgoing", source=b"clone", node=node.hex(node.nullid) + ) else: try: # only pass ui when no srcrepo @@ -833,17 +846,17 @@ if inst.errno == errno.EEXIST: cleandir = None raise error.Abort( - _("destination '%s' already exists") % dest + _(b"destination '%s' already exists") % dest ) raise if revs: - if not srcpeer.capable("lookup"): + if not srcpeer.capable(b"lookup"): raise error.Abort( _( - "src repository does not support " - "revision lookup and so doesn't " - "support clone by revision" + b"src repository does not support " + b"revision lookup and so doesn't " + b"support clone by revision" ) ) @@ -852,7 +865,7 @@ for rev in revs: with srcpeer.commandexecutor() as e: remoterevs.append( - e.callcommand("lookup", {"key": rev,}).result() + e.callcommand(b"lookup", {b"key": rev,}).result() ) revs = remoterevs @@ -868,15 +881,15 @@ u = util.url(abspath) defaulturl = bytes(u) - local.ui.setconfig("paths", "default", defaulturl, "clone") + local.ui.setconfig(b"paths", b"default", defaulturl, b"clone") if not stream: if pull: stream = False else: stream = None # internal config: ui.quietbookmarkmove - overrides = {("ui", "quietbookmarkmove"): True} - with local.ui.configoverride(overrides, "clone"): + overrides = {(b"ui", b"quietbookmarkmove"): True} + with local.ui.configoverride(overrides, b"clone"): exchange.pull( local, srcpeer, @@ -892,8 +905,8 @@ if narrow: raise error.Abort( _( - "narrow clone not available for " - "remote destinations" + b"narrow clone not available for " + b"remote destinations" ) ) @@ -905,28 +918,28 @@ ) else: raise error.Abort( - _("clone from remote to remote not supported") + _(b"clone from remote to remote not supported") ) cleandir = None destrepo = destpeer.local() if destrepo: - template = uimod.samplehgrcs["cloned"] + template = uimod.samplehgrcs[b"cloned"] u = util.url(abspath) u.passwd = None defaulturl = bytes(u) - destrepo.vfs.write("hgrc", util.tonativeeol(template % defaulturl)) - destrepo.ui.setconfig("paths", "default", defaulturl, "clone") + destrepo.vfs.write(b"hgrc", util.tonativeeol(template % defaulturl)) + destrepo.ui.setconfig(b"paths", b"default", defaulturl, b"clone") - if ui.configbool("experimental", "remotenames"): + if ui.configbool(b"experimental", b"remotenames"): logexchange.pullremotenames(destrepo, srcpeer) if update: if update is not True: with srcpeer.commandexecutor() as e: checkout = e.callcommand( - "lookup", {"key": update,} + b"lookup", {b"key": update,} ).result() uprev = None @@ -948,23 +961,23 @@ pass if uprev is None: try: - uprev = destrepo._bookmarks["@"] - update = "@" + uprev = destrepo._bookmarks[b"@"] + update = b"@" bn = destrepo[uprev].branch() - if bn == "default": - status = _("updating to bookmark @\n") + if bn == b"default": + status = _(b"updating to bookmark @\n") else: status = ( - _("updating to bookmark @ on branch %s\n") % bn + _(b"updating to bookmark @ on branch %s\n") % bn ) except KeyError: try: - uprev = destrepo.branchtip("default") + uprev = destrepo.branchtip(b"default") except error.RepoLookupError: - uprev = destrepo.lookup("tip") + uprev = destrepo.lookup(b"tip") if not status: bn = destrepo[uprev].branch() - status = _("updating to branch %s\n") % bn + status = _(b"updating to branch %s\n") % bn destrepo.ui.status(status) _update(destrepo, uprev) if update in destrepo._bookmarks: @@ -983,8 +996,8 @@ return repo.ui.status( _( - "%d files updated, %d files merged, " - "%d files removed, %d files unresolved\n" + b"%d files updated, %d files merged, " + b"%d files removed, %d files unresolved\n" ) % ( stats.updatedcount, @@ -1006,7 +1019,7 @@ node, branchmerge=False, force=overwrite, - labels=["working copy", "destination"], + labels=[b"working copy", b"destination"], updatecheck=updatecheck, ) @@ -1016,7 +1029,7 @@ stats = updaterepo(repo, node, False, updatecheck=updatecheck) _showstats(repo, stats, quietempty) if stats.unresolvedcount: - repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n")) + repo.ui.status(_(b"use 'hg resolve' to retry unresolved file merges\n")) return stats.unresolvedcount > 0 @@ -1027,7 +1040,7 @@ def clean(repo, node, show_stats=True, quietempty=False): """forcibly switch the working directory to node, clobbering changes""" stats = updaterepo(repo, node, True) - repo.vfs.unlinkpath("graftstate", ignoremissing=True) + repo.vfs.unlinkpath(b"graftstate", ignoremissing=True) if show_stats: _showstats(repo, stats, quietempty) return stats.unresolvedcount > 0 @@ -1071,7 +1084,7 @@ This returns whether conflict is detected at updating or not. """ if updatecheck is None: - updatecheck = ui.config("commands", "update.check") + updatecheck = ui.config(b"commands", b"update.check") if updatecheck not in _VALID_UPDATECHECKS: # If not configured, or invalid value configured updatecheck = mergemod.UPDATECHECK_LINEAR @@ -1097,25 +1110,25 @@ ret = _update(repo, checkout, updatecheck=updatecheck) if not ret and movemarkfrom: - if movemarkfrom == repo["."].node(): + if movemarkfrom == repo[b"."].node(): pass # no-op update - elif bookmarks.update(repo, [movemarkfrom], repo["."].node()): - b = ui.label(repo._activebookmark, "bookmarks.active") - ui.status(_("updating bookmark %s\n") % b) + elif bookmarks.update(repo, [movemarkfrom], repo[b"."].node()): + b = ui.label(repo._activebookmark, b"bookmarks.active") + ui.status(_(b"updating bookmark %s\n") % b) else: # this can happen with a non-linear update - b = ui.label(repo._activebookmark, "bookmarks") - ui.status(_("(leaving bookmark %s)\n") % b) + b = ui.label(repo._activebookmark, b"bookmarks") + ui.status(_(b"(leaving bookmark %s)\n") % b) bookmarks.deactivate(repo) elif brev in repo._bookmarks: if brev != repo._activebookmark: - b = ui.label(brev, "bookmarks.active") - ui.status(_("(activating bookmark %s)\n") % b) + b = ui.label(brev, b"bookmarks.active") + ui.status(_(b"(activating bookmark %s)\n") % b) bookmarks.activate(repo, brev) elif brev: if repo._activebookmark: - b = ui.label(repo._activebookmark, "bookmarks") - ui.status(_("(leaving bookmark %s)\n") % b) + b = ui.label(repo._activebookmark, b"bookmarks") + ui.status(_(b"(leaving bookmark %s)\n") % b) bookmarks.deactivate(repo) if warndest: @@ -1150,12 +1163,12 @@ if stats.unresolvedcount: repo.ui.status( _( - "use 'hg resolve' to retry unresolved file merges " - "or 'hg merge --abort' to abandon\n" + b"use 'hg resolve' to retry unresolved file merges " + b"or 'hg merge --abort' to abandon\n" ) ) elif remind: - repo.ui.status(_("(branch merge, don't forget to commit)\n")) + repo.ui.status(_(b"(branch merge, don't forget to commit)\n")) return stats.unresolvedcount > 0 @@ -1166,10 +1179,10 @@ node = ms.localctx.hex() else: # there were no conficts, mergestate was not stored - node = repo["."].hex() + node = repo[b"."].hex() repo.ui.status( - _("aborting the merge, updating back to" " %s\n") % node[:12] + _(b"aborting the merge, updating back to" b" %s\n") % node[:12] ) stats = mergemod.update(repo, node, branchmerge=False, force=True) _showstats(repo, stats) @@ -1185,21 +1198,21 @@ (remoterepo, incomingchangesetlist, displayer) parameters, and is supposed to contain only code that can't be unified. """ - source, branches = parseurl(ui.expandpath(source), opts.get("branch")) + source, branches = parseurl(ui.expandpath(source), opts.get(b"branch")) other = peer(repo, opts, source) - ui.status(_("comparing with %s\n") % util.hidepassword(source)) - revs, checkout = addbranchrevs(repo, other, branches, opts.get("rev")) + ui.status(_(b"comparing with %s\n") % util.hidepassword(source)) + revs, checkout = addbranchrevs(repo, other, branches, opts.get(b"rev")) if revs: revs = [other.lookup(rev) for rev in revs] other, chlist, cleanupfn = bundlerepo.getremotechanges( - ui, repo, other, revs, opts["bundle"], opts["force"] + ui, repo, other, revs, opts[b"bundle"], opts[b"force"] ) try: if not chlist: - ui.status(_("no changes found\n")) + ui.status(_(b"no changes found\n")) return subreporecurse() - ui.pager("incoming") + ui.pager(b"incoming") displayer = logcmdutil.changesetdisplayer( ui, other, opts, buffered=buffered ) @@ -1214,7 +1227,7 @@ def incoming(ui, repo, source, opts): def subreporecurse(): ret = 1 - if opts.get("subrepos"): + if opts.get(b"subrepos"): ctx = repo[None] for subpath in sorted(ctx.substate): sub = ctx.sub(subpath) @@ -1223,14 +1236,14 @@ def display(other, chlist, displayer): limit = logcmdutil.getlimit(opts) - if opts.get("newest_first"): + if opts.get(b"newest_first"): chlist.reverse() count = 0 for n in chlist: if limit is not None and count >= limit: break parents = [p for p in other.changelog.parents(n) if p != nullid] - if opts.get("no_merges") and len(parents) == 2: + if opts.get(b"no_merges") and len(parents) == 2: continue count += 1 displayer.show(other[n]) @@ -1239,23 +1252,23 @@ def _outgoing(ui, repo, dest, opts): - path = ui.paths.getpath(dest, default=("default-push", "default")) + path = ui.paths.getpath(dest, default=(b"default-push", b"default")) if not path: raise error.Abort( - _("default repository not configured!"), - hint=_("see 'hg help config.paths'"), + _(b"default repository not configured!"), + hint=_(b"see 'hg help config.paths'"), ) dest = path.pushloc or path.loc - branches = path.branch, opts.get("branch") or [] + branches = path.branch, opts.get(b"branch") or [] - ui.status(_("comparing with %s\n") % util.hidepassword(dest)) - revs, checkout = addbranchrevs(repo, repo, branches, opts.get("rev")) + ui.status(_(b"comparing with %s\n") % util.hidepassword(dest)) + revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b"rev")) if revs: revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)] other = peer(repo, opts, dest) outgoing = discovery.findcommonoutgoing( - repo, other, revs, force=opts.get("force") + repo, other, revs, force=opts.get(b"force") ) o = outgoing.missing if not o: @@ -1266,7 +1279,7 @@ def outgoing(ui, repo, dest, opts): def recurse(): ret = 1 - if opts.get("subrepos"): + if opts.get(b"subrepos"): ctx = repo[None] for subpath in sorted(ctx.substate): sub = ctx.sub(subpath) @@ -1279,16 +1292,16 @@ cmdutil.outgoinghooks(ui, repo, other, opts, o) return recurse() - if opts.get("newest_first"): + if opts.get(b"newest_first"): o.reverse() - ui.pager("outgoing") + ui.pager(b"outgoing") displayer = logcmdutil.changesetdisplayer(ui, repo, opts) count = 0 for n in o: if limit is not None and count >= limit: break parents = [p for p in repo.changelog.parents(n) if p != nullid] - if opts.get("no_merges") and len(parents) == 2: + if opts.get(b"no_merges") and len(parents) == 2: continue count += 1 displayer.show(repo[n]) @@ -1308,11 +1321,11 @@ # pathto() is needed for -R case revs = repo.revs( - "filelog(%s)", util.pathto(repo.root, repo.getcwd(), ".hgsubstate") + b"filelog(%s)", util.pathto(repo.root, repo.getcwd(), b".hgsubstate") ) if revs: - repo.ui.status(_("checking subrepo links\n")) + repo.ui.status(_(b"checking subrepo links\n")) for rev in revs: ctx = repo[rev] try: @@ -1322,10 +1335,10 @@ ctx.sub(subpath, allowcreate=False).verify() or ret ) except error.RepoError as e: - repo.ui.warn("%d: %s\n" % (rev, e)) + repo.ui.warn(b"%d: %s\n" % (rev, e)) except Exception: repo.ui.warn( - _(".hgsubstate is corrupt in revision %s\n") + _(b".hgsubstate is corrupt in revision %s\n") % node.short(ctx.node()) ) @@ -1333,31 +1346,31 @@ def remoteui(src, opts): - "build a remote ui from ui or repo and opts" - if util.safehasattr(src, "baseui"): # looks like a repository + b"build a remote ui from ui or repo and opts" + if util.safehasattr(src, b"baseui"): # looks like a repository dst = src.baseui.copy() # drop repo-specific config src = src.ui # copy target options from repo else: # assume it's a global ui object dst = src.copy() # keep all global options # copy ssh-specific options - for o in "ssh", "remotecmd": - v = opts.get(o) or src.config("ui", o) + for o in b"ssh", b"remotecmd": + v = opts.get(o) or src.config(b"ui", o) if v: - dst.setconfig("ui", o, v, "copied") + dst.setconfig(b"ui", o, v, b"copied") # copy bundle-specific options - r = src.config("bundle", "mainreporoot") + r = src.config(b"bundle", b"mainreporoot") if r: - dst.setconfig("bundle", "mainreporoot", r, "copied") + dst.setconfig(b"bundle", b"mainreporoot", r, b"copied") # copy selected local settings to the remote ui - for sect in ("auth", "hostfingerprints", "hostsecurity", "http_proxy"): + for sect in (b"auth", b"hostfingerprints", b"hostsecurity", b"http_proxy"): for key, val in src.configitems(sect): - dst.setconfig(sect, key, val, "copied") - v = src.config("web", "cacerts") + dst.setconfig(sect, key, val, b"copied") + v = src.config(b"web", b"cacerts") if v: - dst.setconfig("web", "cacerts", util.expandpath(v), "copied") + dst.setconfig(b"web", b"cacerts", util.expandpath(v), b"copied") return dst @@ -1366,10 +1379,10 @@ # Used to check if the repository has changed looking at mtime and size of # these files. foi = [ - ("spath", "00changelog.i"), - ("spath", "phaseroots"), # ! phase can change content at the same size - ("spath", "obsstore"), - ("path", "bookmarks"), # ! bookmark can change content at the same size + (b"spath", b"00changelog.i"), + (b"spath", b"phaseroots"), # ! phase can change content at the same size + (b"spath", b"obsstore"), + (b"path", b"bookmarks"), # ! bookmark can change content at the same size ] diff --git a/mercurial/hgweb/__init__.py b/mercurial/hgweb/__init__.py --- a/mercurial/hgweb/__init__.py +++ b/mercurial/hgweb/__init__.py @@ -39,7 +39,7 @@ if isinstance(config, pycompat.unicode): raise error.ProgrammingError( - "Mercurial only supports encoded strings: %r" % config + b"Mercurial only supports encoded strings: %r" % config ) if ( (isinstance(config, bytes) and not os.path.isdir(config)) @@ -66,16 +66,16 @@ self.httpd = server.create_server(self.ui, self.app) if ( - self.opts["port"] + self.opts[b"port"] and not self.ui.verbose - and not self.opts["print_url"] + and not self.opts[b"print_url"] ): return if self.httpd.prefix: - prefix = self.httpd.prefix.strip("/") + "/" + prefix = self.httpd.prefix.strip(b"/") + b"/" else: - prefix = "" + prefix = b"" port = r":%d" % self.httpd.port if port == r":80": @@ -91,20 +91,20 @@ if r":" in fqaddr: fqaddr = r"[%s]" % fqaddr - url = "http://%s%s/%s" % ( + url = b"http://%s%s/%s" % ( pycompat.sysbytes(fqaddr), pycompat.sysbytes(port), prefix, ) - if self.opts["print_url"]: - self.ui.write("%s\n" % url) + if self.opts[b"print_url"]: + self.ui.write(b"%s\n" % url) else: - if self.opts["port"]: + if self.opts[b"port"]: write = self.ui.status else: write = self.ui.write write( - _("listening at %s (bound to %s:%d)\n") + _(b"listening at %s (bound to %s:%d)\n") % (url, pycompat.sysbytes(bindaddr), self.httpd.port) ) self.ui.flush() # avoid buffering of status message @@ -119,6 +119,6 @@ else: if not repo: raise error.RepoError( - _("there is no Mercurial repository" " here (.hg not found)") + _(b"there is no Mercurial repository" b" here (.hg not found)") ) return hgweb_mod.hgweb(repo, baseui=baseui) diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py --- a/mercurial/hgweb/common.py +++ b/mercurial/hgweb/common.py @@ -42,7 +42,7 @@ Can be overridden by extensions to provide more complex authorization schemes. """ - return userlist == ["*"] or username in userlist + return userlist == [b"*"] or username in userlist def checkauthz(hgweb, req, op): @@ -52,41 +52,41 @@ user = req.remoteuser - deny_read = hgweb.configlist("web", "deny_read") + deny_read = hgweb.configlist(b"web", b"deny_read") if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)): - raise ErrorResponse(HTTP_UNAUTHORIZED, "read not authorized") + raise ErrorResponse(HTTP_UNAUTHORIZED, b"read not authorized") - allow_read = hgweb.configlist("web", "allow_read") + allow_read = hgweb.configlist(b"web", b"allow_read") if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)): - raise ErrorResponse(HTTP_UNAUTHORIZED, "read not authorized") + raise ErrorResponse(HTTP_UNAUTHORIZED, b"read not authorized") - if op == "pull" and not hgweb.allowpull: - raise ErrorResponse(HTTP_UNAUTHORIZED, "pull not authorized") - elif op == "pull" or op is None: # op is None for interface requests + if op == b"pull" and not hgweb.allowpull: + raise ErrorResponse(HTTP_UNAUTHORIZED, b"pull not authorized") + elif op == b"pull" or op is None: # op is None for interface requests return # Allow LFS uploading via PUT requests - if op == "upload": - if req.method != "PUT": - msg = "upload requires PUT request" + if op == b"upload": + if req.method != b"PUT": + msg = b"upload requires PUT request" raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg) # enforce that you can only push using POST requests - elif req.method != "POST": - msg = "push requires POST request" + elif req.method != b"POST": + msg = b"push requires POST request" raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg) # require ssl by default for pushing, auth info cannot be sniffed # and replayed - if hgweb.configbool("web", "push_ssl") and req.urlscheme != "https": - raise ErrorResponse(HTTP_FORBIDDEN, "ssl required") + if hgweb.configbool(b"web", b"push_ssl") and req.urlscheme != b"https": + raise ErrorResponse(HTTP_FORBIDDEN, b"ssl required") - deny = hgweb.configlist("web", "deny_push") + deny = hgweb.configlist(b"web", b"deny_push") if deny and (not user or ismember(hgweb.repo.ui, user, deny)): - raise ErrorResponse(HTTP_UNAUTHORIZED, "push not authorized") + raise ErrorResponse(HTTP_UNAUTHORIZED, b"push not authorized") - allow = hgweb.configlist("web", "allow-push") + allow = hgweb.configlist(b"web", b"allow-push") if not (allow and ismember(hgweb.repo.ui, user, allow)): - raise ErrorResponse(HTTP_UNAUTHORIZED, "push not authorized") + raise ErrorResponse(HTTP_UNAUTHORIZED, b"push not authorized") # Hooks for hgweb permission checks; extensions can add hooks here. @@ -128,11 +128,11 @@ def read(self, amt=-1): if not self.continued: self.continued = True - self._write("HTTP/1.1 100 Continue\r\n\r\n") + self._write(b"HTTP/1.1 100 Continue\r\n\r\n") return self.f.read(amt) def __getattr__(self, attr): - if attr in ("close", "readline", "readlines", "__iter__"): + if attr in (b"close", b"readline", b"readlines", b"__iter__"): return getattr(self.f, attr) raise AttributeError @@ -145,7 +145,7 @@ def statusmessage(code, message=None): - return "%d %s" % (code, message or _statusmessage(code)) + return b"%d %s" % (code, message or _statusmessage(code)) def get_stat(spath, fn): @@ -158,15 +158,15 @@ def get_mtime(spath): - return get_stat(spath, "00changelog.i")[stat.ST_MTIME] + return get_stat(spath, b"00changelog.i")[stat.ST_MTIME] def ispathsafe(path): """Determine if a path is safe to use for filesystem access.""" - parts = path.split("/") + parts = path.split(b"/") for part in parts: if ( - part in ("", pycompat.oscurdir, pycompat.ospardir) + part in (b"", pycompat.oscurdir, pycompat.ospardir) or pycompat.ossep in part or pycompat.osaltsep is not None and pycompat.osaltsep in part @@ -188,7 +188,7 @@ if not ispathsafe(fname): return - fpath = os.path.join(*fname.split("/")) + fpath = os.path.join(*fname.split(b"/")) if isinstance(directory, str): directory = [directory] for d in directory: @@ -200,14 +200,14 @@ ct = pycompat.sysbytes( mimetypes.guess_type(pycompat.fsdecode(path))[0] or r"text/plain" ) - with open(path, "rb") as fh: + with open(path, b"rb") as fh: data = fh.read() - res.headers["Content-Type"] = ct + res.headers[b"Content-Type"] = ct res.setbodybytes(data) return res except TypeError: - raise ErrorResponse(HTTP_SERVER_ERROR, "illegal filename") + raise ErrorResponse(HTTP_SERVER_ERROR, b"illegal filename") except OSError as err: if err.errno == errno.ENOENT: raise ErrorResponse(HTTP_NOT_FOUND) @@ -241,10 +241,10 @@ ui.username or $EMAIL as a fallback to display something useful. """ return ( - config("web", "contact") - or config("ui", "username") - or encoding.environ.get("EMAIL") - or "" + config(b"web", b"contact") + or config(b"ui", b"username") + or encoding.environ.get(b"EMAIL") + or b"" ) @@ -275,11 +275,11 @@ # Don't allow untrusted CSP setting since it be disable protections # from a trusted/global source. - csp = ui.config("web", "csp", untrusted=False) + csp = ui.config(b"web", b"csp", untrusted=False) nonce = None - if csp and "%nonce%" in csp: - nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip("=") - csp = csp.replace("%nonce%", nonce) + if csp and b"%nonce%" in csp: + nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip(b"=") + csp = csp.replace(b"%nonce%", nonce) return csp, nonce diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -48,35 +48,35 @@ def getstyle(req, configfn, templatepath): styles = ( - req.qsparams.get("style", None), - configfn("web", "style"), - "paper", + req.qsparams.get(b"style", None), + configfn(b"web", b"style"), + b"paper", ) return styles, templater.stylemap(styles, templatepath) -def makebreadcrumb(url, prefix=""): +def makebreadcrumb(url, prefix=b""): """Return a 'URL breadcrumb' list A 'URL breadcrumb' is a list of URL-name pairs, corresponding to each of the path items on a URL. This can be used to create path navigation entries. """ - if url.endswith("/"): + if url.endswith(b"/"): url = url[:-1] if prefix: - url = "/" + prefix + url + url = b"/" + prefix + url relpath = url - if relpath.startswith("/"): + if relpath.startswith(b"/"): relpath = relpath[1:] breadcrumb = [] urlel = url - pathitems = [""] + relpath.split("/") + pathitems = [b""] + relpath.split(b"/") for pathel in reversed(pathitems): if not pathel or not urlel: break - breadcrumb.append({"url": urlel, "name": pathel}) + breadcrumb.append({b"url": urlel, b"name": pathel}) urlel = os.path.dirname(urlel) return templateutil.mappinglist(reversed(breadcrumb)) @@ -95,16 +95,16 @@ self.req = req self.res = res - self.maxchanges = self.configint("web", "maxchanges") - self.stripecount = self.configint("web", "stripes") - self.maxshortchanges = self.configint("web", "maxshortchanges") - self.maxfiles = self.configint("web", "maxfiles") - self.allowpull = self.configbool("web", "allow-pull") + self.maxchanges = self.configint(b"web", b"maxchanges") + self.stripecount = self.configint(b"web", b"stripes") + self.maxshortchanges = self.configint(b"web", b"maxshortchanges") + self.maxfiles = self.configint(b"web", b"maxfiles") + self.allowpull = self.configbool(b"web", b"allow-pull") # we use untrusted=False to prevent a repo owner from using # web.templates in .hg/hgrc to get access to any file readable # by the user running the CGI script - self.templatepath = self.config("web", "templates", untrusted=False) + self.templatepath = self.config(b"web", b"templates", untrusted=False) # This object is more expensive to build than simple config values. # It is shared across requests. The app will replace the object @@ -140,27 +140,27 @@ def templater(self, req): # determine scheme, port and server name # this is needed to create absolute urls - logourl = self.config("web", "logourl") - logoimg = self.config("web", "logoimg") + logourl = self.config(b"web", b"logourl") + logoimg = self.config(b"web", b"logoimg") staticurl = ( - self.config("web", "staticurl") - or req.apppath.rstrip("/") + "/static/" + self.config(b"web", b"staticurl") + or req.apppath.rstrip(b"/") + b"/static/" ) - if not staticurl.endswith("/"): - staticurl += "/" + if not staticurl.endswith(b"/"): + staticurl += b"/" # figure out which style to use vars = {} styles, (style, mapfile) = getstyle(req, self.config, self.templatepath) if style == styles[0]: - vars["style"] = style + vars[b"style"] = style - sessionvars = webutil.sessionvars(vars, "?") + sessionvars = webutil.sessionvars(vars, b"?") if not self.reponame: self.reponame = ( - self.config("web", "name", "") + self.config(b"web", b"name", b"") or req.reponame or req.apppath or self.repo.root @@ -169,30 +169,30 @@ filters = {} templatefilter = registrar.templatefilter(filters) - @templatefilter("websub", intype=bytes) + @templatefilter(b"websub", intype=bytes) def websubfilter(text): return templatefilters.websub(text, self.websubtable) # create the templater # TODO: export all keywords: defaults = templatekw.keywords.copy() defaults = { - "url": req.apppath + "/", - "logourl": logourl, - "logoimg": logoimg, - "staticurl": staticurl, - "urlbase": req.advertisedbaseurl, - "repo": self.reponame, - "encoding": encoding.encoding, - "sessionvars": sessionvars, - "pathdef": makebreadcrumb(req.apppath), - "style": style, - "nonce": self.nonce, + b"url": req.apppath + b"/", + b"logourl": logourl, + b"logoimg": logoimg, + b"staticurl": staticurl, + b"urlbase": req.advertisedbaseurl, + b"repo": self.reponame, + b"encoding": encoding.encoding, + b"sessionvars": sessionvars, + b"pathdef": makebreadcrumb(req.apppath), + b"style": style, + b"nonce": self.nonce, } templatekeyword = registrar.templatekeyword(defaults) - @templatekeyword("motd", requires=()) + @templatekeyword(b"motd", requires=()) def motd(context, mapping): - yield self.config("web", "motd") + yield self.config(b"web", b"motd") tres = formatter.templateresources(self.repo.ui, self.repo) tmpl = templater.templater.frommapfile( @@ -232,23 +232,23 @@ # we trust caller to give us a private copy r = repo - r.ui.setconfig("ui", "report_untrusted", "off", "hgweb") - r.baseui.setconfig("ui", "report_untrusted", "off", "hgweb") - r.ui.setconfig("ui", "nontty", "true", "hgweb") - r.baseui.setconfig("ui", "nontty", "true", "hgweb") + r.ui.setconfig(b"ui", b"report_untrusted", b"off", b"hgweb") + r.baseui.setconfig(b"ui", b"report_untrusted", b"off", b"hgweb") + r.ui.setconfig(b"ui", b"nontty", b"true", b"hgweb") + r.baseui.setconfig(b"ui", b"nontty", b"true", b"hgweb") # resolve file patterns relative to repo root - r.ui.setconfig("ui", "forcecwd", r.root, "hgweb") - r.baseui.setconfig("ui", "forcecwd", r.root, "hgweb") + r.ui.setconfig(b"ui", b"forcecwd", r.root, b"hgweb") + r.baseui.setconfig(b"ui", b"forcecwd", r.root, b"hgweb") # it's unlikely that we can replace signal handlers in WSGI server, # and mod_wsgi issues a big warning. a plain hgweb process (with no # threading) could replace signal handlers, but we don't bother # conditionally enabling it. - r.ui.setconfig("ui", "signal-safe-lock", "false", "hgweb") - r.baseui.setconfig("ui", "signal-safe-lock", "false", "hgweb") + r.ui.setconfig(b"ui", b"signal-safe-lock", b"false", b"hgweb") + r.baseui.setconfig(b"ui", b"signal-safe-lock", b"false", b"hgweb") # displaying bundling progress bar while serving feel wrong and may # break some wsgi implementation. - r.ui.setconfig("progress", "disable", "true", "hgweb") - r.baseui.setconfig("progress", "disable", "true", "hgweb") + r.ui.setconfig(b"progress", b"disable", b"true", b"hgweb") + r.baseui.setconfig(b"progress", b"disable", b"true", b"hgweb") self._repos = [hg.cachedlocalrepo(self._webifyrepo(r))] self._lastrepo = self._repos[0] hook.redirect(True) @@ -294,12 +294,12 @@ Modern servers should be using WSGI and should avoid this method, if possible. """ - if not encoding.environ.get("GATEWAY_INTERFACE", "").startswith( - "CGI/1." + if not encoding.environ.get(b"GATEWAY_INTERFACE", b"").startswith( + b"CGI/1." ): raise RuntimeError( - "This function is only intended to be " - "called while running as a CGI script." + b"This function is only intended to be " + b"called while running as a CGI script." ) wsgicgi.launch(self) @@ -320,7 +320,7 @@ should be using instances of this class as the WSGI application. """ with self._obtainrepo() as repo: - profile = repo.ui.configbool("profiling", "enabled") + profile = repo.ui.configbool(b"profiling", b"enabled") with profiling.profile(repo.ui, enabled=profile): for r in self._runwsgi(req, res, repo): yield r @@ -329,19 +329,19 @@ rctx = requestcontext(self, repo, req, res) # This state is global across all threads. - encoding.encoding = rctx.config("web", "encoding") + encoding.encoding = rctx.config(b"web", b"encoding") rctx.repo.ui.environ = req.rawenv if rctx.csp: # hgwebdir may have added CSP header. Since we generate our own, # replace it. - res.headers["Content-Security-Policy"] = rctx.csp + res.headers[b"Content-Security-Policy"] = rctx.csp # /api/* is reserved for various API implementations. Dispatch # accordingly. But URL paths can conflict with subrepos and virtual # repos in hgwebdir. So until we have a workaround for this, only # expose the URLs if the feature is enabled. - apienabled = rctx.repo.ui.configbool("experimental", "web.apiserver") + apienabled = rctx.repo.ui.configbool(b"experimental", b"web.apiserver") if apienabled and req.dispatchparts and req.dispatchparts[0] == b"api": wireprotoserver.handlewsgiapirequest( rctx, req, res, self.check_perm @@ -361,70 +361,70 @@ if req.dispatchpath is not None: query = req.dispatchpath else: - query = req.querystring.partition("&")[0].partition(";")[0] + query = req.querystring.partition(b"&")[0].partition(b";")[0] # translate user-visible url structure to internal structure - args = query.split("/", 2) - if "cmd" not in req.qsparams and args and args[0]: + args = query.split(b"/", 2) + if b"cmd" not in req.qsparams and args and args[0]: cmd = args.pop(0) - style = cmd.rfind("-") + style = cmd.rfind(b"-") if style != -1: - req.qsparams["style"] = cmd[:style] + req.qsparams[b"style"] = cmd[:style] cmd = cmd[style + 1 :] # avoid accepting e.g. style parameter as command if util.safehasattr(webcommands, cmd): - req.qsparams["cmd"] = cmd + req.qsparams[b"cmd"] = cmd - if cmd == "static": - req.qsparams["file"] = "/".join(args) + if cmd == b"static": + req.qsparams[b"file"] = b"/".join(args) else: if args and args[0]: - node = args.pop(0).replace("%2F", "/") - req.qsparams["node"] = node + node = args.pop(0).replace(b"%2F", b"/") + req.qsparams[b"node"] = node if args: - if "file" in req.qsparams: - del req.qsparams["file"] + if b"file" in req.qsparams: + del req.qsparams[b"file"] for a in args: - req.qsparams.add("file", a) + req.qsparams.add(b"file", a) - ua = req.headers.get("User-Agent", "") - if cmd == "rev" and "mercurial" in ua: - req.qsparams["style"] = "raw" + ua = req.headers.get(b"User-Agent", b"") + if cmd == b"rev" and b"mercurial" in ua: + req.qsparams[b"style"] = b"raw" - if cmd == "archive": - fn = req.qsparams["node"] + if cmd == b"archive": + fn = req.qsparams[b"node"] for type_, spec in webutil.archivespecs.iteritems(): ext = spec[2] if fn.endswith(ext): - req.qsparams["node"] = fn[: -len(ext)] - req.qsparams["type"] = type_ + req.qsparams[b"node"] = fn[: -len(ext)] + req.qsparams[b"type"] = type_ else: - cmd = req.qsparams.get("cmd", "") + cmd = req.qsparams.get(b"cmd", b"") # process the web interface request try: rctx.tmpl = rctx.templater(req) ctype = rctx.tmpl.render( - "mimetype", {"encoding": encoding.encoding} + b"mimetype", {b"encoding": encoding.encoding} ) # check read permissions non-static content - if cmd != "static": + if cmd != b"static": self.check_perm(rctx, req, None) - if cmd == "": - req.qsparams["cmd"] = rctx.tmpl.render("default", {}) - cmd = req.qsparams["cmd"] + if cmd == b"": + req.qsparams[b"cmd"] = rctx.tmpl.render(b"default", {}) + cmd = req.qsparams[b"cmd"] # Don't enable caching if using a CSP nonce because then it wouldn't # be a nonce. - if rctx.configbool("web", "cache") and not rctx.nonce: - tag = 'W/"%d"' % self.mtime - if req.headers.get("If-None-Match") == tag: - res.status = "304 Not Modified" + if rctx.configbool(b"web", b"cache") and not rctx.nonce: + tag = b'W/"%d"' % self.mtime + if req.headers.get(b"If-None-Match") == tag: + res.status = b"304 Not Modified" # Content-Type may be defined globally. It isn't valid on a # 304, so discard it. try: @@ -432,45 +432,45 @@ except KeyError: pass # Response body not allowed on 304. - res.setbodybytes("") + res.setbodybytes(b"") return res.sendresponse() - res.headers["ETag"] = tag + res.headers[b"ETag"] = tag if cmd not in webcommands.__all__: - msg = "no such method: %s" % cmd + msg = b"no such method: %s" % cmd raise ErrorResponse(HTTP_BAD_REQUEST, msg) else: # Set some globals appropriate for web handlers. Commands can # override easily enough. - res.status = "200 Script output follows" - res.headers["Content-Type"] = ctype + res.status = b"200 Script output follows" + res.headers[b"Content-Type"] = ctype return getattr(webcommands, cmd)(rctx) except (error.LookupError, error.RepoLookupError) as err: msg = pycompat.bytestr(err) - if util.safehasattr(err, "name") and not isinstance( + if util.safehasattr(err, b"name") and not isinstance( err, error.ManifestLookupError ): - msg = "revision not found: %s" % err.name + msg = b"revision not found: %s" % err.name - res.status = "404 Not Found" - res.headers["Content-Type"] = ctype - return rctx.sendtemplate("error", error=msg) + res.status = b"404 Not Found" + res.headers[b"Content-Type"] = ctype + return rctx.sendtemplate(b"error", error=msg) except (error.RepoError, error.StorageError) as e: - res.status = "500 Internal Server Error" - res.headers["Content-Type"] = ctype - return rctx.sendtemplate("error", error=pycompat.bytestr(e)) + res.status = b"500 Internal Server Error" + res.headers[b"Content-Type"] = ctype + return rctx.sendtemplate(b"error", error=pycompat.bytestr(e)) except error.Abort as e: - res.status = "403 Forbidden" - res.headers["Content-Type"] = ctype - return rctx.sendtemplate("error", error=pycompat.bytestr(e)) + res.status = b"403 Forbidden" + res.headers[b"Content-Type"] = ctype + return rctx.sendtemplate(b"error", error=pycompat.bytestr(e)) except ErrorResponse as e: for k, v in e.headers: res.headers[k] = v res.status = statusmessage(e.code, pycompat.bytestr(e)) - res.headers["Content-Type"] = ctype - return rctx.sendtemplate("error", error=pycompat.bytestr(e)) + res.headers[b"Content-Type"] = ctype + return rctx.sendtemplate(b"error", error=pycompat.bytestr(e)) def check_perm(self, rctx, req, op): for permhook in permhooks: @@ -489,10 +489,10 @@ The option has been around undocumented since Mercurial 2.5, but no user ever asked about it. So we better keep it undocumented for now.""" # experimental config: web.view - viewconfig = repo.ui.config("web", "view", untrusted=True) - if viewconfig == "all": + viewconfig = repo.ui.config(b"web", b"view", untrusted=True) + if viewconfig == b"all": return repo.unfiltered() elif viewconfig in repoview.filtertable: return repo.filtered(viewconfig) else: - return repo.filtered("served") + return repo.filtered(b"served") diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -52,7 +52,7 @@ def cleannames(items): - return [(util.pconvert(name).strip("/"), path) for name, path in items] + return [(util.pconvert(name).strip(b"/"), path) for name, path in items] def findrepos(paths): @@ -64,7 +64,7 @@ # '*' will not search inside dirs with .hg (except .hg/patches), # '**' will search inside dirs with .hg (and thus also find subrepos). try: - recurse = {"*": False, "**": True}[roottail] + recurse = {b"*": False, b"**": True}[roottail] except KeyError: repos.append((prefix, root)) continue @@ -86,8 +86,8 @@ for path in paths: path = os.path.normpath(path) yield ( - prefix + "/" + util.pconvert(path[len(roothead) :]).lstrip("/") - ).strip("/"), path + prefix + b"/" + util.pconvert(path[len(roothead) :]).lstrip(b"/") + ).strip(b"/"), path def readallowed(ui, req): @@ -101,11 +101,11 @@ user = req.remoteuser - deny_read = ui.configlist("web", "deny_read", untrusted=True) + deny_read = ui.configlist(b"web", b"deny_read", untrusted=True) if deny_read and (not user or ismember(ui, user, deny_read)): return False - allow_read = ui.configlist("web", "allow_read", untrusted=True) + allow_read = ui.configlist(b"web", b"allow_read", untrusted=True) # by default, allow reading if no allow_read option has been set if not allow_read or ismember(ui, user, allow_read): return True @@ -113,9 +113,9 @@ return False -def rawindexentries(ui, repos, req, subdir=""): - descend = ui.configbool("web", "descend") - collapse = ui.configbool("web", "collapse") +def rawindexentries(ui, repos, req, subdir=b""): + descend = ui.configbool(b"web", b"descend") + collapse = ui.configbool(b"web", b"collapse") seenrepos = set() seendirs = set() for name, path in repos: @@ -125,11 +125,11 @@ name = name[len(subdir) :] directory = False - if "/" in name: + if b"/" in name: if not descend: continue - nameparts = name.split("/") + nameparts = name.split(b"/") rootname = nameparts[0] if not collapse: @@ -143,7 +143,7 @@ name = rootname # redefine the path to refer to the directory - discarded = "/".join(nameparts[1:]) + discarded = b"/".join(nameparts[1:]) # remove name parts plus accompanying slash path = path[: -len(discarded) - 1] @@ -155,11 +155,11 @@ pass parts = [ - req.apppath.strip("/"), - subdir.strip("/"), - name.strip("/"), + req.apppath.strip(b"/"), + subdir.strip(b"/"), + name.strip(b"/"), ] - url = "/" + "/".join(p for p in parts if p) + "/" + url = b"/" + b"/".join(p for p in parts if p) + b"/" # show either a directory entry or a repository if directory: @@ -172,18 +172,18 @@ # add '/' to the name to make it obvious that # the entry is a directory, not a regular repository row = { - "contact": "", - "contact_sort": "", - "name": name + "/", - "name_sort": name, - "url": url, - "description": "", - "description_sort": "", - "lastchange": d, - "lastchange_sort": d[1] - d[0], - "archives": templateutil.mappinglist([]), - "isdirectory": True, - "labels": templateutil.hybridlist([], name="label"), + b"contact": b"", + b"contact_sort": b"", + b"name": name + b"/", + b"name_sort": name, + b"url": url, + b"description": b"", + b"description_sort": b"", + b"lastchange": d, + b"lastchange_sort": d[1] - d[0], + b"archives": templateutil.mappinglist([]), + b"isdirectory": True, + b"labels": templateutil.hybridlist([], name=b"label"), } seendirs.add(name) @@ -192,15 +192,15 @@ u = ui.copy() try: - u.readconfig(os.path.join(path, ".hg", "hgrc")) + u.readconfig(os.path.join(path, b".hg", b"hgrc")) except Exception as e: - u.warn(_("error reading %s/.hg/hgrc: %s\n") % (path, e)) + u.warn(_(b"error reading %s/.hg/hgrc: %s\n") % (path, e)) continue def get(section, name, default=uimod._unset): return u.config(section, name, default, untrusted=True) - if u.configbool("web", "hidden", untrusted=True): + if u.configbool(b"web", b"hidden", untrusted=True): continue if not readallowed(u, req): @@ -210,10 +210,10 @@ try: r = hg.repository(ui, path) except IOError: - u.warn(_("error accessing repository at %s\n") % path) + u.warn(_(b"error accessing repository at %s\n") % path) continue except error.RepoError: - u.warn(_("error accessing repository at %s\n") % path) + u.warn(_(b"error accessing repository at %s\n") % path) continue try: d = (get_mtime(r.spath), dateutil.makedate()[1]) @@ -221,23 +221,23 @@ continue contact = get_contact(get) - description = get("web", "description") + description = get(b"web", b"description") seenrepos.add(name) - name = get("web", "name", name) - labels = u.configlist("web", "labels", untrusted=True) + name = get(b"web", b"name", name) + labels = u.configlist(b"web", b"labels", untrusted=True) row = { - "contact": contact or "unknown", - "contact_sort": contact.upper() or "unknown", - "name": name, - "name_sort": name, - "url": url, - "description": description or "unknown", - "description_sort": description.upper() or "unknown", - "lastchange": d, - "lastchange_sort": d[1] - d[0], - "archives": webutil.archivelist(u, "tip", url), - "isdirectory": None, - "labels": templateutil.hybridlist(labels, name="label"), + b"contact": contact or b"unknown", + b"contact_sort": contact.upper() or b"unknown", + b"name": name, + b"name_sort": name, + b"url": url, + b"description": description or b"unknown", + b"description_sort": description.upper() or b"unknown", + b"lastchange": d, + b"lastchange_sort": d[1] - d[0], + b"archives": webutil.archivelist(u, b"tip", url), + b"isdirectory": None, + b"labels": templateutil.hybridlist(labels, name=b"label"), } yield row @@ -251,16 +251,16 @@ sortdefault = None, False if sortcolumn and sortdefault != (sortcolumn, descending): - sortkey = "%s_sort" % sortcolumn + sortkey = b"%s_sort" % sortcolumn rows = sorted(rows, key=lambda x: x[sortkey], reverse=descending) for row, parity in zip(rows, paritygen(stripecount)): - row["parity"] = parity + row[b"parity"] = parity yield row def indexentries( - ui, repos, req, stripecount, sortcolumn="", descending=False, subdir="" + ui, repos, req, stripecount, sortcolumn=b"", descending=False, subdir=b"" ): args = (ui, repos, req, stripecount, sortcolumn, descending, subdir) return templateutil.mappinggenerator(_indexentriesgen, args=args) @@ -289,9 +289,9 @@ def refresh(self): if self.ui: - refreshinterval = self.ui.configint("web", "refreshinterval") + refreshinterval = self.ui.configint(b"web", b"refreshinterval") else: - item = configitems.coreitems["web"]["refreshinterval"] + item = configitems.coreitems[b"web"][b"refreshinterval"] refreshinterval = item.default # refreshinterval <= 0 means to always refresh. @@ -305,20 +305,20 @@ u = self.baseui.copy() else: u = uimod.ui.load() - u.setconfig("ui", "report_untrusted", "off", "hgwebdir") - u.setconfig("ui", "nontty", "true", "hgwebdir") + u.setconfig(b"ui", b"report_untrusted", b"off", b"hgwebdir") + u.setconfig(b"ui", b"nontty", b"true", b"hgwebdir") # displaying bundling progress bar while serving feels wrong and may # break some wsgi implementations. - u.setconfig("progress", "disable", "true", "hgweb") + u.setconfig(b"progress", b"disable", b"true", b"hgweb") if not isinstance(self.conf, (dict, list, tuple)): - map = {"paths": "hgweb-paths"} + map = {b"paths": b"hgweb-paths"} if not os.path.exists(self.conf): - raise error.Abort(_("config file %s not found!") % self.conf) + raise error.Abort(_(b"config file %s not found!") % self.conf) u.readconfig(self.conf, remap=map, trust=True) paths = [] - for name, ignored in u.configitems("hgweb-paths"): - for path in u.configlist("hgweb-paths", name): + for name, ignored in u.configitems(b"hgweb-paths"): + for path in u.configlist(b"hgweb-paths", name): paths.append((name, path)) elif isinstance(self.conf, (list, tuple)): paths = self.conf @@ -327,50 +327,52 @@ extensions.populateui(u) repos = findrepos(paths) - for prefix, root in u.configitems("collections"): + for prefix, root in u.configitems(b"collections"): prefix = util.pconvert(prefix) for path in scmutil.walkrepos(root, followsym=True): repo = os.path.normpath(path) name = util.pconvert(repo) if name.startswith(prefix): name = name[len(prefix) :] - repos.append((name.lstrip("/"), repo)) + repos.append((name.lstrip(b"/"), repo)) self.repos = repos self.ui = u - encoding.encoding = self.ui.config("web", "encoding") - self.style = self.ui.config("web", "style") - self.templatepath = self.ui.config("web", "templates", untrusted=False) - self.stripecount = self.ui.config("web", "stripes") + encoding.encoding = self.ui.config(b"web", b"encoding") + self.style = self.ui.config(b"web", b"style") + self.templatepath = self.ui.config( + b"web", b"templates", untrusted=False + ) + self.stripecount = self.ui.config(b"web", b"stripes") if self.stripecount: self.stripecount = int(self.stripecount) - prefix = self.ui.config("web", "prefix") - if prefix.startswith("/"): + prefix = self.ui.config(b"web", b"prefix") + if prefix.startswith(b"/"): prefix = prefix[1:] - if prefix.endswith("/"): + if prefix.endswith(b"/"): prefix = prefix[:-1] self.prefix = prefix self.lastrefresh = time.time() def run(self): - if not encoding.environ.get("GATEWAY_INTERFACE", "").startswith( - "CGI/1." + if not encoding.environ.get(b"GATEWAY_INTERFACE", b"").startswith( + b"CGI/1." ): raise RuntimeError( - "This function is only intended to be " - "called while running as a CGI script." + b"This function is only intended to be " + b"called while running as a CGI script." ) wsgicgi.launch(self) def __call__(self, env, respond): - baseurl = self.ui.config("web", "baseurl") + baseurl = self.ui.config(b"web", b"baseurl") req = requestmod.parserequestfromenv(env, altbaseurl=baseurl) res = requestmod.wsgiresponse(req, respond) return self.run_wsgi(req, res) def run_wsgi(self, req, res): - profile = self.ui.configbool("profiling", "enabled") + profile = self.ui.configbool(b"profiling", b"enabled") with profiling.profile(self.ui, enabled=profile): try: for r in self._runwsgi(req, res): @@ -391,28 +393,28 @@ csp, nonce = cspvalues(self.ui) if csp: - res.headers["Content-Security-Policy"] = csp + res.headers[b"Content-Security-Policy"] = csp - virtual = req.dispatchpath.strip("/") + virtual = req.dispatchpath.strip(b"/") tmpl = self.templater(req, nonce) - ctype = tmpl.render("mimetype", {"encoding": encoding.encoding}) + ctype = tmpl.render(b"mimetype", {b"encoding": encoding.encoding}) # Global defaults. These can be overridden by any handler. - res.status = "200 Script output follows" - res.headers["Content-Type"] = ctype + res.status = b"200 Script output follows" + res.headers[b"Content-Type"] = ctype # a static file - if virtual.startswith("static/") or "static" in req.qsparams: - if virtual.startswith("static/"): + if virtual.startswith(b"static/") or b"static" in req.qsparams: + if virtual.startswith(b"static/"): fname = virtual[7:] else: - fname = req.qsparams["static"] - static = self.ui.config("web", "static", untrusted=False) + fname = req.qsparams[b"static"] + static = self.ui.config(b"web", b"static", untrusted=False) if not static: tp = self.templatepath or templater.templatepaths() if isinstance(tp, str): tp = [tp] - static = [os.path.join(p, "static") for p in tp] + static = [os.path.join(p, b"static") for p in tp] staticfile(static, fname, res) return res.sendresponse() @@ -421,13 +423,13 @@ repos = dict(self.repos) - if (not virtual or virtual == "index") and virtual not in repos: + if (not virtual or virtual == b"index") and virtual not in repos: return self.makeindex(req, res, tmpl) # nested indexes and hgwebs - if virtual.endswith("/index") and virtual not in repos: - subdir = virtual[: -len("index")] + if virtual.endswith(b"/index") and virtual not in repos: + subdir = virtual[: -len(b"index")] if any(r.startswith(subdir) for r in repos): return self.makeindex(req, res, tmpl, subdir) @@ -450,7 +452,7 @@ req = requestmod.parserequestfromenv( uenv, reponame=virtualrepo, - altbaseurl=self.ui.config("web", "baseurl"), + altbaseurl=self.ui.config(b"web", b"baseurl"), # Reuse wrapped body file object otherwise state # tracking can get confused. bodyfh=req.bodyfh, @@ -466,40 +468,42 @@ raise ErrorResponse(HTTP_SERVER_ERROR, bytes(inst)) # browse subdirectories - subdir = virtual + "/" + subdir = virtual + b"/" if [r for r in repos if r.startswith(subdir)]: return self.makeindex(req, res, tmpl, subdir) # prefixes not found - res.status = "404 Not Found" - res.setbodygen(tmpl.generate("notfound", {"repo": virtual})) + res.status = b"404 Not Found" + res.setbodygen(tmpl.generate(b"notfound", {b"repo": virtual})) return res.sendresponse() except ErrorResponse as e: res.status = statusmessage(e.code, pycompat.bytestr(e)) - res.setbodygen(tmpl.generate("error", {"error": e.message or ""})) + res.setbodygen( + tmpl.generate(b"error", {b"error": e.message or b""}) + ) return res.sendresponse() finally: tmpl = None - def makeindex(self, req, res, tmpl, subdir=""): + def makeindex(self, req, res, tmpl, subdir=b""): self.refresh() - sortable = ["name", "description", "contact", "lastchange"] + sortable = [b"name", b"description", b"contact", b"lastchange"] sortcolumn, descending = None, False - if "sort" in req.qsparams: - sortcolumn = req.qsparams["sort"] - descending = sortcolumn.startswith("-") + if b"sort" in req.qsparams: + sortcolumn = req.qsparams[b"sort"] + descending = sortcolumn.startswith(b"-") if descending: sortcolumn = sortcolumn[1:] if sortcolumn not in sortable: - sortcolumn = "" + sortcolumn = b"" sort = [ ( - "sort_%s" % column, - "%s%s" + b"sort_%s" % column, + b"%s%s" % ( - (not descending and column == sortcolumn) and "-" or "", + (not descending and column == sortcolumn) and b"-" or b"", column, ), ) @@ -519,14 +523,14 @@ ) mapping = { - "entries": entries, - "subdir": subdir, - "pathdef": hgweb_mod.makebreadcrumb("/" + subdir, self.prefix), - "sortcolumn": sortcolumn, - "descending": descending, + b"entries": entries, + b"subdir": subdir, + b"pathdef": hgweb_mod.makebreadcrumb(b"/" + subdir, self.prefix), + b"sortcolumn": sortcolumn, + b"descending": descending, } mapping.update(sort) - res.setbodygen(tmpl.generate("index", mapping)) + res.setbodygen(tmpl.generate(b"index", mapping)) return res.sendresponse() def templater(self, req, nonce): @@ -538,35 +542,36 @@ req, config, self.templatepath ) if style == styles[0]: - vars["style"] = style + vars[b"style"] = style - sessionvars = webutil.sessionvars(vars, "?") - logourl = config("web", "logourl") - logoimg = config("web", "logoimg") + sessionvars = webutil.sessionvars(vars, b"?") + logourl = config(b"web", b"logourl") + logoimg = config(b"web", b"logoimg") staticurl = ( - config("web", "staticurl") or req.apppath.rstrip("/") + "/static/" + config(b"web", b"staticurl") + or req.apppath.rstrip(b"/") + b"/static/" ) - if not staticurl.endswith("/"): - staticurl += "/" + if not staticurl.endswith(b"/"): + staticurl += b"/" defaults = { - "encoding": encoding.encoding, - "url": req.apppath + "/", - "logourl": logourl, - "logoimg": logoimg, - "staticurl": staticurl, - "sessionvars": sessionvars, - "style": style, - "nonce": nonce, + b"encoding": encoding.encoding, + b"url": req.apppath + b"/", + b"logourl": logourl, + b"logoimg": logoimg, + b"staticurl": staticurl, + b"sessionvars": sessionvars, + b"style": style, + b"nonce": nonce, } templatekeyword = registrar.templatekeyword(defaults) - @templatekeyword("motd", requires=()) + @templatekeyword(b"motd", requires=()) def motd(context, mapping): if self.motd is not None: yield self.motd else: - yield config("web", "motd") + yield config(b"web", b"motd") tmpl = templater.templater.frommapfile(mapfile, defaults=defaults) return tmpl diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -69,7 +69,7 @@ vals = self._items[key] if len(vals) > 1: - raise KeyError("multiple values for %r" % key) + raise KeyError(b"multiple values for %r" % key) return vals[0] @@ -172,7 +172,7 @@ # to an hgweb instance using this environment variable. This was always # checked prior to d7fd203e36cc; keep doing so to avoid breaking them. if not reponame: - reponame = env.get("REPO_NAME") + reponame = env.get(b"REPO_NAME") if altbaseurl: altbaseurl = util.url(altbaseurl) @@ -181,114 +181,114 @@ # the environment variables. # https://www.python.org/dev/peps/pep-0333/#url-reconstruction defines # how URLs are reconstructed. - fullurl = env["wsgi.url_scheme"] + "://" + fullurl = env[b"wsgi.url_scheme"] + b"://" if altbaseurl and altbaseurl.scheme: - advertisedfullurl = altbaseurl.scheme + "://" + advertisedfullurl = altbaseurl.scheme + b"://" else: advertisedfullurl = fullurl def addport(s, port): - if s.startswith("https://"): - if port != "443": - s += ":" + port + if s.startswith(b"https://"): + if port != b"443": + s += b":" + port else: - if port != "80": - s += ":" + port + if port != b"80": + s += b":" + port return s - if env.get("HTTP_HOST"): - fullurl += env["HTTP_HOST"] + if env.get(b"HTTP_HOST"): + fullurl += env[b"HTTP_HOST"] else: - fullurl += env["SERVER_NAME"] - fullurl = addport(fullurl, env["SERVER_PORT"]) + fullurl += env[b"SERVER_NAME"] + fullurl = addport(fullurl, env[b"SERVER_PORT"]) if altbaseurl and altbaseurl.host: advertisedfullurl += altbaseurl.host if altbaseurl.port: port = altbaseurl.port - elif altbaseurl.scheme == "http" and not altbaseurl.port: - port = "80" - elif altbaseurl.scheme == "https" and not altbaseurl.port: - port = "443" + elif altbaseurl.scheme == b"http" and not altbaseurl.port: + port = b"80" + elif altbaseurl.scheme == b"https" and not altbaseurl.port: + port = b"443" else: - port = env["SERVER_PORT"] + port = env[b"SERVER_PORT"] advertisedfullurl = addport(advertisedfullurl, port) else: - advertisedfullurl += env["SERVER_NAME"] - advertisedfullurl = addport(advertisedfullurl, env["SERVER_PORT"]) + advertisedfullurl += env[b"SERVER_NAME"] + advertisedfullurl = addport(advertisedfullurl, env[b"SERVER_PORT"]) baseurl = fullurl advertisedbaseurl = advertisedfullurl - fullurl += util.urlreq.quote(env.get("SCRIPT_NAME", "")) - fullurl += util.urlreq.quote(env.get("PATH_INFO", "")) + fullurl += util.urlreq.quote(env.get(b"SCRIPT_NAME", b"")) + fullurl += util.urlreq.quote(env.get(b"PATH_INFO", b"")) if altbaseurl: - path = altbaseurl.path or "" - if path and not path.startswith("/"): - path = "/" + path + path = altbaseurl.path or b"" + if path and not path.startswith(b"/"): + path = b"/" + path advertisedfullurl += util.urlreq.quote(path) else: - advertisedfullurl += util.urlreq.quote(env.get("SCRIPT_NAME", "")) + advertisedfullurl += util.urlreq.quote(env.get(b"SCRIPT_NAME", b"")) - advertisedfullurl += util.urlreq.quote(env.get("PATH_INFO", "")) + advertisedfullurl += util.urlreq.quote(env.get(b"PATH_INFO", b"")) - if env.get("QUERY_STRING"): - fullurl += "?" + env["QUERY_STRING"] - advertisedfullurl += "?" + env["QUERY_STRING"] + if env.get(b"QUERY_STRING"): + fullurl += b"?" + env[b"QUERY_STRING"] + advertisedfullurl += b"?" + env[b"QUERY_STRING"] # If ``reponame`` is defined, that must be a prefix on PATH_INFO # that represents the repository being dispatched to. When computing # the dispatch info, we ignore these leading path components. if altbaseurl: - apppath = altbaseurl.path or "" - if apppath and not apppath.startswith("/"): - apppath = "/" + apppath + apppath = altbaseurl.path or b"" + if apppath and not apppath.startswith(b"/"): + apppath = b"/" + apppath else: - apppath = env.get("SCRIPT_NAME", "") + apppath = env.get(b"SCRIPT_NAME", b"") if reponame: - repoprefix = "/" + reponame.strip("/") + repoprefix = b"/" + reponame.strip(b"/") - if not env.get("PATH_INFO"): - raise error.ProgrammingError("reponame requires PATH_INFO") + if not env.get(b"PATH_INFO"): + raise error.ProgrammingError(b"reponame requires PATH_INFO") - if not env["PATH_INFO"].startswith(repoprefix): + if not env[b"PATH_INFO"].startswith(repoprefix): raise error.ProgrammingError( - "PATH_INFO does not begin with repo " - "name: %s (%s)" % (env["PATH_INFO"], reponame) + b"PATH_INFO does not begin with repo " + b"name: %s (%s)" % (env[b"PATH_INFO"], reponame) ) - dispatchpath = env["PATH_INFO"][len(repoprefix) :] + dispatchpath = env[b"PATH_INFO"][len(repoprefix) :] - if dispatchpath and not dispatchpath.startswith("/"): + if dispatchpath and not dispatchpath.startswith(b"/"): raise error.ProgrammingError( - "reponame prefix of PATH_INFO does " - "not end at path delimiter: %s (%s)" - % (env["PATH_INFO"], reponame) + b"reponame prefix of PATH_INFO does " + b"not end at path delimiter: %s (%s)" + % (env[b"PATH_INFO"], reponame) ) - apppath = apppath.rstrip("/") + repoprefix - dispatchparts = dispatchpath.strip("/").split("/") - dispatchpath = "/".join(dispatchparts) + apppath = apppath.rstrip(b"/") + repoprefix + dispatchparts = dispatchpath.strip(b"/").split(b"/") + dispatchpath = b"/".join(dispatchparts) - elif "PATH_INFO" in env: - if env["PATH_INFO"].strip("/"): - dispatchparts = env["PATH_INFO"].strip("/").split("/") - dispatchpath = "/".join(dispatchparts) + elif b"PATH_INFO" in env: + if env[b"PATH_INFO"].strip(b"/"): + dispatchparts = env[b"PATH_INFO"].strip(b"/").split(b"/") + dispatchpath = b"/".join(dispatchparts) else: dispatchparts = [] - dispatchpath = "" + dispatchpath = b"" else: dispatchparts = [] dispatchpath = None - querystring = env.get("QUERY_STRING", "") + querystring = env.get(b"QUERY_STRING", b"") # We store as a list so we have ordering information. We also store as # a dict to facilitate fast lookup. @@ -301,8 +301,8 @@ # so keys match what likely went over the wire. headers = [] for k, v in env.iteritems(): - if k.startswith("HTTP_"): - headers.append((k[len("HTTP_") :].replace("_", "-"), v)) + if k.startswith(b"HTTP_"): + headers.append((k[len(b"HTTP_") :].replace(b"_", b"-"), v)) from . import wsgiheaders # avoid cycle @@ -312,28 +312,28 @@ # sent. But for all intents and purposes it should be OK to lie about # this, since a consumer will either either value to determine how many # bytes are available to read. - if "CONTENT_LENGTH" in env and "HTTP_CONTENT_LENGTH" not in env: - headers["Content-Length"] = env["CONTENT_LENGTH"] + if b"CONTENT_LENGTH" in env and b"HTTP_CONTENT_LENGTH" not in env: + headers[b"Content-Length"] = env[b"CONTENT_LENGTH"] - if "CONTENT_TYPE" in env and "HTTP_CONTENT_TYPE" not in env: - headers["Content-Type"] = env["CONTENT_TYPE"] + if b"CONTENT_TYPE" in env and b"HTTP_CONTENT_TYPE" not in env: + headers[b"Content-Type"] = env[b"CONTENT_TYPE"] if bodyfh is None: - bodyfh = env["wsgi.input"] - if "Content-Length" in headers: + bodyfh = env[b"wsgi.input"] + if b"Content-Length" in headers: bodyfh = util.cappedreader( - bodyfh, int(headers["Content-Length"] or "0") + bodyfh, int(headers[b"Content-Length"] or b"0") ) return parsedrequest( - method=env["REQUEST_METHOD"], + method=env[b"REQUEST_METHOD"], url=fullurl, baseurl=baseurl, advertisedurl=advertisedfullurl, advertisedbaseurl=advertisedbaseurl, - urlscheme=env["wsgi.url_scheme"], - remoteuser=env.get("REMOTE_USER"), - remotehost=env.get("REMOTE_HOST"), + urlscheme=env[b"wsgi.url_scheme"], + remoteuser=env.get(b"REMOTE_USER"), + remotehost=env.get(b"REMOTE_HOST"), apppath=apppath, dispatchparts=dispatchparts, dispatchpath=dispatchpath, @@ -421,7 +421,7 @@ or self._bodygen is not None or self._bodywillwrite ): - raise error.ProgrammingError("cannot define body multiple times") + raise error.ProgrammingError(b"cannot define body multiple times") def setbodybytes(self, b): """Define the response body as static bytes. @@ -430,7 +430,7 @@ """ self._verifybody() self._bodybytes = b - self.headers["Content-Length"] = "%d" % len(b) + self.headers[b"Content-Length"] = b"%d" % len(b) def setbodygen(self, gen): """Define the response body as a generator of bytes.""" @@ -463,19 +463,21 @@ Calling this method multiple times is not allowed. """ if self._started: - raise error.ProgrammingError("sendresponse() called multiple times") + raise error.ProgrammingError( + b"sendresponse() called multiple times" + ) self._started = True if not self.status: - raise error.ProgrammingError("status line not defined") + raise error.ProgrammingError(b"status line not defined") if ( self._bodybytes is None and self._bodygen is None and not self._bodywillwrite ): - raise error.ProgrammingError("response body not defined") + raise error.ProgrammingError(b"response body not defined") # RFC 7232 Section 4.1 states that a 304 MUST generate one of # {Cache-Control, Content-Location, Date, ETag, Expires, Vary} @@ -484,11 +486,11 @@ # states that no response body can be issued. Content-Length can # be sent. But if it is present, it should be the size of the response # that wasn't transferred. - if self.status.startswith("304 "): + if self.status.startswith(b"304 "): # setbodybytes('') will set C-L to 0. This doesn't conform with the # spec. So remove it. - if self.headers.get("Content-Length") == "0": - del self.headers["Content-Length"] + if self.headers.get(b"Content-Length") == b"0": + del self.headers[b"Content-Length"] # Strictly speaking, this is too strict. But until it causes # problems, let's be strict. @@ -497,24 +499,24 @@ for k in self.headers.keys() if k.lower() not in ( - "date", - "etag", - "expires", - "cache-control", - "content-location", - "content-security-policy", - "vary", + b"date", + b"etag", + b"expires", + b"cache-control", + b"content-location", + b"content-security-policy", + b"vary", ) } if badheaders: raise error.ProgrammingError( - "illegal header on 304 response: %s" - % ", ".join(sorted(badheaders)) + b"illegal header on 304 response: %s" + % b", ".join(sorted(badheaders)) ) if self._bodygen is not None or self._bodywillwrite: raise error.ProgrammingError( - "must use setbodybytes('') with " "304 responses" + b"must use setbodybytes('') with " b"304 responses" ) # Various HTTP clients (notably httplib) won't read the HTTP response @@ -530,12 +532,12 @@ # If the client sent Expect: 100-continue, we assume it is smart enough # to deal with the server sending a response before reading the request. # (httplib doesn't do this.) - if self._req.headers.get("Expect", "").lower() == "100-continue": + if self._req.headers.get(b"Expect", b"").lower() == b"100-continue": pass # Only tend to request methods that have bodies. Strictly speaking, # we should sniff for a body. But this is fine for our existing # WSGI applications. - elif self._req.method not in ("POST", "PUT"): + elif self._req.method not in (b"POST", b"PUT"): pass else: # If we don't know how much data to read, there's no guarantee @@ -555,7 +557,7 @@ drain = True if close: - self.headers["Connection"] = "Close" + self.headers[b"Connection"] = b"Close" if drain: assert isinstance(self._req.bodyfh, util.cappedreader) @@ -584,7 +586,7 @@ elif self._bodywillwrite: self._bodywritefn = write else: - error.ProgrammingError("do not know how to send body") + error.ProgrammingError(b"do not know how to send body") def getbodyfile(self): """Obtain a file object like object representing the response body. @@ -597,13 +599,13 @@ ``[]``. """ if not self._bodywillwrite: - raise error.ProgrammingError("must call setbodywillwrite() first") + raise error.ProgrammingError(b"must call setbodywillwrite() first") if not self._started: raise error.ProgrammingError( - "must call sendresponse() first; did " - "you remember to consume it since it " - "is a generator?" + b"must call sendresponse() first; did " + b"you remember to consume it since it " + b"is a generator?" ) assert self._bodywritefn diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py --- a/mercurial/hgweb/server.py +++ b/mercurial/hgweb/server.py @@ -53,7 +53,7 @@ pass def write(self, str): - self.writelines(str.split("\n")) + self.writelines(str.split(b"\n")) def writelines(self, seq): for msg in seq: @@ -62,7 +62,7 @@ class _httprequesthandler(httpservermod.basehttprequesthandler): - url_scheme = "http" + url_scheme = b"http" @staticmethod def preparehttpserver(httpserver, ui): @@ -82,7 +82,7 @@ format % args, ) ) - + "\n" + + b"\n" ) fp.flush() @@ -94,7 +94,7 @@ def log_request(self, code=r"-", size=r"-"): xheaders = [] - if util.safehasattr(self, "headers"): + if util.safehasattr(self, b"headers"): xheaders = [ h for h in self.headers.items() if h[0].startswith(r"x-") ] @@ -155,7 +155,7 @@ self.server.prefix + b"/" ): self._start_response(pycompat.strurl(common.statusmessage(404)), []) - if self.command == "POST": + if self.command == b"POST": # Paranoia: tell the client we're going to close the # socket so they don't try and reuse a socket that # might have a POST body waiting to confuse us. We do @@ -205,7 +205,7 @@ env[r"SERVER_PROTOCOL"] = self.request_version env[r"wsgi.version"] = (1, 0) env[r"wsgi.url_scheme"] = pycompat.sysstr(self.url_scheme) - if env.get(r"HTTP_EXPECT", "").lower() == "100-continue": + if env.get(r"HTTP_EXPECT", b"").lower() == b"100-continue": self.rfile = common.continuereader(self.rfile, self.wfile.write) env[r"wsgi.input"] = self.rfile @@ -213,7 +213,7 @@ env[r"wsgi.multithread"] = isinstance( self.server, socketserver.ThreadingMixIn ) - if util.safehasattr(socketserver, "ForkingMixIn"): + if util.safehasattr(socketserver, b"ForkingMixIn"): env[r"wsgi.multiprocess"] = isinstance( self.server, socketserver.ForkingMixIn ) @@ -237,7 +237,7 @@ def send_headers(self): if not self.saved_status: raise AssertionError( - "Sending headers before " "start_response() called" + b"Sending headers before " b"start_response() called" ) saved_status = self.saved_status.split(None, 1) saved_status[0] = int(saved_status[0]) @@ -273,24 +273,24 @@ def _write(self, data): if not self.saved_status: - raise AssertionError("data written before start_response() called") + raise AssertionError(b"data written before start_response() called") elif not self.sent_headers: self.send_headers() if self.length is not None: if len(data) > self.length: raise AssertionError( - "Content-length header sent, but more " - "bytes than specified are being written." + b"Content-length header sent, but more " + b"bytes than specified are being written." ) self.length = self.length - len(data) elif self._chunked and data: - data = "%x\r\n%s\r\n" % (len(data), data) + data = b"%x\r\n%s\r\n" % (len(data), data) self.wfile.write(data) self.wfile.flush() def _done(self): if self._chunked: - self.wfile.write("0\r\n\r\n") + self.wfile.write(b"0\r\n\r\n") self.wfile.flush() def version_string(self): @@ -302,7 +302,7 @@ class _httprequesthandlerssl(_httprequesthandler): """HTTPS handler based on Python's ssl module""" - url_scheme = "https" + url_scheme = b"https" @staticmethod def preparehttpserver(httpserver, ui): @@ -311,14 +311,14 @@ sslutil.modernssl except ImportError: - raise error.Abort(_("SSL support is unavailable")) + raise error.Abort(_(b"SSL support is unavailable")) - certfile = ui.config("web", "certificate") + certfile = ui.config(b"web", b"certificate") # These config options are currently only meant for testing. Use # at your own risk. - cafile = ui.config("devel", "servercafile") - reqcert = ui.configbool("devel", "serverrequirecert") + cafile = ui.config(b"devel", b"servercafile") + reqcert = ui.configbool(b"devel", b"serverrequirecert") httpserver.socket = sslutil.wrapserversocket( httpserver.socket, @@ -340,7 +340,7 @@ threading.activeCount() # silence pyflakes and bypass demandimport _mixin = socketserver.ThreadingMixIn except ImportError: - if util.safehasattr(os, "fork"): + if util.safehasattr(os, b"fork"): _mixin = socketserver.ForkingMixIn else: @@ -349,8 +349,8 @@ def openlog(opt, default): - if opt and opt != "-": - return open(opt, "ab") + if opt and opt != b"-": + return open(opt, b"ab") return default @@ -367,20 +367,20 @@ handler.preparehttpserver(self, ui) - prefix = ui.config("web", "prefix") + prefix = ui.config(b"web", b"prefix") if prefix: - prefix = "/" + prefix.strip("/") + prefix = b"/" + prefix.strip(b"/") self.prefix = prefix - alog = openlog(ui.config("web", "accesslog"), ui.fout) - elog = openlog(ui.config("web", "errorlog"), ui.ferr) + alog = openlog(ui.config(b"web", b"accesslog"), ui.fout) + elog = openlog(ui.config(b"web", b"errorlog"), ui.ferr) self.accesslog = alog self.errorlog = elog self.addr, self.port = self.socket.getsockname()[0:2] self.fqaddr = socket.getfqdn(addr[0]) - self.serverheader = ui.config("web", "server-header") + self.serverheader = ui.config(b"web", b"server-header") class IPv6HTTPServer(MercurialHTTPServer): @@ -388,18 +388,18 @@ def __init__(self, *args, **kwargs): if self.address_family is None: - raise error.RepoError(_("IPv6 is not available on this system")) + raise error.RepoError(_(b"IPv6 is not available on this system")) super(IPv6HTTPServer, self).__init__(*args, **kwargs) def create_server(ui, app): - if ui.config("web", "certificate"): + if ui.config(b"web", b"certificate"): handler = _httprequesthandlerssl else: handler = _httprequesthandler - if ui.configbool("web", "ipv6"): + if ui.configbool(b"web", b"ipv6"): cls = IPv6HTTPServer else: cls = MercurialHTTPServer @@ -418,16 +418,16 @@ sys.argv # unwrap demand-loader so that reload() works reload(sys) # resurrect sys.setdefaultencoding() oldenc = sys.getdefaultencoding() - sys.setdefaultencoding("latin1") # or any full 8-bit encoding + sys.setdefaultencoding(b"latin1") # or any full 8-bit encoding mimetypes.init() sys.setdefaultencoding(oldenc) - address = ui.config("web", "address") - port = util.getport(ui.config("web", "port")) + address = ui.config(b"web", b"address") + port = util.getport(ui.config(b"web", b"port")) try: return cls(ui, app, (address, port), handler) except socket.error as inst: raise error.Abort( - _("cannot start server at '%s:%d': %s") + _(b"cannot start server at '%s:%d': %s") % (address, port, encoding.strtolocal(inst.args[1])) ) diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py +++ b/mercurial/hgweb/webcommands.py @@ -79,7 +79,7 @@ return func -@webcommand("log") +@webcommand(b"log") def log(web): """ /log[/{revision}[/{path}]] @@ -96,17 +96,17 @@ file will be shown. This form is equivalent to the ``filelog`` handler. """ - if web.req.qsparams.get("file"): + if web.req.qsparams.get(b"file"): return filelog(web) else: return changelog(web) -@webcommand("rawfile") +@webcommand(b"rawfile") def rawfile(web): - guessmime = web.configbool("web", "guessmime") + guessmime = web.configbool(b"web", b"guessmime") - path = webutil.cleanpath(web.repo, web.req.qsparams.get("file", "")) + path = webutil.cleanpath(web.repo, web.req.qsparams.get(b"file", b"")) if not path: return manifest(web) @@ -120,25 +120,27 @@ path = fctx.path() text = fctx.data() - mt = "application/binary" + mt = b"application/binary" if guessmime: mt = mimetypes.guess_type(pycompat.fsdecode(path))[0] if mt is None: if stringutil.binary(text): - mt = "application/binary" + mt = b"application/binary" else: - mt = "text/plain" + mt = b"text/plain" else: mt = pycompat.sysbytes(mt) - if mt.startswith("text/"): - mt += '; charset="%s"' % encoding.encoding + if mt.startswith(b"text/"): + mt += b'; charset="%s"' % encoding.encoding - web.res.headers["Content-Type"] = mt + web.res.headers[b"Content-Type"] = mt filename = ( - path.rpartition("/")[-1].replace("\\", "\\\\").replace('"', '\\"') + path.rpartition(b"/")[-1].replace(b"\\", b"\\\\").replace(b'"', b'\\"') ) - web.res.headers["Content-Disposition"] = 'inline; filename="%s"' % filename + web.res.headers[b"Content-Disposition"] = ( + b'inline; filename="%s"' % filename + ) web.res.setbodybytes(text) return web.res.sendresponse() @@ -154,19 +156,19 @@ mimetypes.guess_type(pycompat.fsdecode(f))[0] or r"application/octet-stream" ) - text = "(binary:%s)" % mt + text = b"(binary:%s)" % mt def lines(context): for lineno, t in enumerate(text.splitlines(True)): yield { - "line": t, - "lineid": "l%d" % (lineno + 1), - "linenumber": "% 6d" % (lineno + 1), - "parity": next(parity), + b"line": t, + b"lineid": b"l%d" % (lineno + 1), + b"linenumber": b"% 6d" % (lineno + 1), + b"parity": next(parity), } return web.sendtemplate( - "filerevision", + b"filerevision", file=f, path=webutil.up(f), text=templateutil.mappinggenerator(lines), @@ -178,7 +180,7 @@ ) -@webcommand("file") +@webcommand(b"file") def file(web): """ /file/{revision}[/{path}] @@ -198,10 +200,10 @@ If ``path`` is not defined, information about the root directory will be rendered. """ - if web.req.qsparams.get("style") == "raw": + if web.req.qsparams.get(b"style") == b"raw": return rawfile(web) - path = webutil.cleanpath(web.repo, web.req.qsparams.get("file", "")) + path = webutil.cleanpath(web.repo, web.req.qsparams.get(b"file", b"")) if not path: return manifest(web) try: @@ -214,9 +216,9 @@ def _search(web): - MODE_REVISION = "rev" - MODE_KEYWORD = "keyword" - MODE_REVSET = "revset" + MODE_REVISION = b"rev" + MODE_KEYWORD = b"keyword" + MODE_REVSET = b"revset" def revsearch(ctx): yield ctx @@ -242,7 +244,7 @@ if not ( q in lower(ctx.user()) or q in lower(ctx.description()) - or q in lower(" ".join(ctx.files())) + or q in lower(b" ".join(ctx.files())) ): miss = 1 break @@ -256,9 +258,9 @@ yield web.repo[r] searchfuncs = { - MODE_REVISION: (revsearch, "exact revision search"), - MODE_KEYWORD: (keywordsearch, "literal keyword search"), - MODE_REVSET: (revsetsearch, "revset expression search"), + MODE_REVISION: (revsearch, b"exact revision search"), + MODE_KEYWORD: (keywordsearch, b"literal keyword search"), + MODE_REVSET: (revsetsearch, b"revset expression search"), } def getsearchmode(query): @@ -271,7 +273,7 @@ else: return MODE_REVISION, ctx - revdef = "reverse(%s)" % query + revdef = b"reverse(%s)" % query try: tree = revsetlang.parse(revdef) except error.ParseError: @@ -283,7 +285,7 @@ return MODE_KEYWORD, query if any( - (token, (value or "")[:3]) == ("string", "re:") + (token, (value or b"")[:3]) == (b"string", b"re:") for token, value, pos in revsetlang.tokenize(revdef) ): return MODE_KEYWORD, query @@ -316,15 +318,15 @@ for ctx in searchfunc[0](funcarg): count += 1 n = scmutil.binnode(ctx) - showtags = webutil.showtag(web.repo, "changelogtag", n) + showtags = webutil.showtag(web.repo, b"changelogtag", n) files = webutil.listfilediffs(ctx.files(), n, web.maxfiles) lm = webutil.commonentry(web.repo, ctx) lm.update( { - "parity": next(parity), - "changelogtag": showtags, - "files": files, + b"parity": next(parity), + b"changelogtag": showtags, + b"files": files, } ) yield lm @@ -332,27 +334,27 @@ if count >= revcount: break - query = web.req.qsparams["rev"] + query = web.req.qsparams[b"rev"] revcount = web.maxchanges - if "revcount" in web.req.qsparams: + if b"revcount" in web.req.qsparams: try: - revcount = int(web.req.qsparams.get("revcount", revcount)) + revcount = int(web.req.qsparams.get(b"revcount", revcount)) revcount = max(revcount, 1) - web.tmpl.defaults["sessionvars"]["revcount"] = revcount + web.tmpl.defaults[b"sessionvars"][b"revcount"] = revcount except ValueError: pass - lessvars = copy.copy(web.tmpl.defaults["sessionvars"]) - lessvars["revcount"] = max(revcount // 2, 1) - lessvars["rev"] = query - morevars = copy.copy(web.tmpl.defaults["sessionvars"]) - morevars["revcount"] = revcount * 2 - morevars["rev"] = query + lessvars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + lessvars[b"revcount"] = max(revcount // 2, 1) + lessvars[b"rev"] = query + morevars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + morevars[b"revcount"] = revcount * 2 + morevars[b"rev"] = query mode, funcarg = getsearchmode(query) - if "forcekw" in web.req.qsparams: - showforcekw = "" + if b"forcekw" in web.req.qsparams: + showforcekw = b"" showunforcekw = searchfuncs[mode][1] mode = MODE_KEYWORD funcarg = query @@ -360,21 +362,21 @@ if mode != MODE_KEYWORD: showforcekw = searchfuncs[MODE_KEYWORD][1] else: - showforcekw = "" - showunforcekw = "" + showforcekw = b"" + showunforcekw = b"" searchfunc = searchfuncs[mode] - tip = web.repo["tip"] + tip = web.repo[b"tip"] parity = paritygen(web.stripecount) return web.sendtemplate( - "search", + b"search", query=query, node=tip.hex(), - symrev="tip", - entries=templateutil.mappinggenerator(changelist, name="searchentry"), - archives=web.archivelist("tip"), + symrev=b"tip", + entries=templateutil.mappinggenerator(changelist, name=b"searchentry"), + archives=web.archivelist(b"tip"), morevars=morevars, lessvars=lessvars, modedesc=searchfunc[1], @@ -383,7 +385,7 @@ ) -@webcommand("changelog") +@webcommand(b"changelog") def changelog(web, shortlog=False): """ /changelog[/{revision}] @@ -409,15 +411,15 @@ For non-searches, the ``changelog`` template will be rendered. """ - query = "" - if "node" in web.req.qsparams: + query = b"" + if b"node" in web.req.qsparams: ctx = webutil.changectx(web.repo, web.req) symrev = webutil.symrevorshortnode(web.req, ctx) - elif "rev" in web.req.qsparams: + elif b"rev" in web.req.qsparams: return _search(web) else: - ctx = web.repo["tip"] - symrev = "tip" + ctx = web.repo[b"tip"] + symrev = b"tip" def changelist(maxcount): revs = [] @@ -432,18 +434,18 @@ else: revcount = web.maxchanges - if "revcount" in web.req.qsparams: + if b"revcount" in web.req.qsparams: try: - revcount = int(web.req.qsparams.get("revcount", revcount)) + revcount = int(web.req.qsparams.get(b"revcount", revcount)) revcount = max(revcount, 1) - web.tmpl.defaults["sessionvars"]["revcount"] = revcount + web.tmpl.defaults[b"sessionvars"][b"revcount"] = revcount except ValueError: pass - lessvars = copy.copy(web.tmpl.defaults["sessionvars"]) - lessvars["revcount"] = max(revcount // 2, 1) - morevars = copy.copy(web.tmpl.defaults["sessionvars"]) - morevars["revcount"] = revcount * 2 + lessvars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + lessvars[b"revcount"] = max(revcount // 2, 1) + morevars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + morevars[b"revcount"] = revcount * 2 count = len(web.repo) pos = ctx.rev() @@ -460,7 +462,7 @@ nextentry = [] return web.sendtemplate( - "shortlog" if shortlog else "changelog", + b"shortlog" if shortlog else b"changelog", changenav=changenav, node=ctx.hex(), rev=pos, @@ -469,7 +471,7 @@ entries=templateutil.mappinglist(entries), latestentry=templateutil.mappinglist(latestentry), nextentry=templateutil.mappinglist(nextentry), - archives=web.archivelist("tip"), + archives=web.archivelist(b"tip"), revcount=revcount, morevars=morevars, lessvars=lessvars, @@ -477,7 +479,7 @@ ) -@webcommand("shortlog") +@webcommand(b"shortlog") def shortlog(web): """ /shortlog @@ -492,7 +494,7 @@ return changelog(web, shortlog=True) -@webcommand("changeset") +@webcommand(b"changeset") def changeset(web): """ /changeset[/{revision}] @@ -510,10 +512,10 @@ """ ctx = webutil.changectx(web.repo, web.req) - return web.sendtemplate("changeset", **webutil.changesetentry(web, ctx)) + return web.sendtemplate(b"changeset", **webutil.changesetentry(web, ctx)) -rev = webcommand("rev")(changeset) +rev = webcommand(b"rev")(changeset) def decodepath(path): @@ -525,7 +527,7 @@ return path -@webcommand("manifest") +@webcommand(b"manifest") def manifest(web): """ /manifest[/{revision}[/{path}]] @@ -542,13 +544,13 @@ The ``manifest`` template will be rendered for this handler. """ - if "node" in web.req.qsparams: + if b"node" in web.req.qsparams: ctx = webutil.changectx(web.repo, web.req) symrev = webutil.symrevorshortnode(web.req, ctx) else: - ctx = web.repo["tip"] - symrev = "tip" - path = webutil.cleanpath(web.repo, web.req.qsparams.get("file", "")) + ctx = web.repo[b"tip"] + symrev = b"tip" + path = webutil.cleanpath(web.repo, web.req.qsparams.get(b"file", b"")) mf = ctx.manifest() node = scmutil.binnode(ctx) @@ -556,10 +558,10 @@ dirs = {} parity = paritygen(web.stripecount) - if path and path[-1:] != "/": - path += "/" + if path and path[-1:] != b"/": + path += b"/" l = len(path) - abspath = "/" + path + abspath = b"/" + path for full, n in mf.iteritems(): # the virtual path (working copy path) used for the full @@ -569,7 +571,7 @@ if f[:l] != path: continue remain = f[l:] - elements = remain.split("/") + elements = remain.split(b"/") if len(elements) == 1: files[remain] = full else: @@ -583,7 +585,7 @@ h[None] = None # denotes files present if mf and not files and not dirs: - raise ErrorResponse(HTTP_NOT_FOUND, "path not found: " + path) + raise ErrorResponse(HTTP_NOT_FOUND, b"path not found: " + path) def filelist(context): for f in sorted(files): @@ -591,12 +593,12 @@ fctx = ctx.filectx(full) yield { - "file": full, - "parity": next(parity), - "basename": f, - "date": fctx.date(), - "size": fctx.size(), - "permissions": mf.flags(full), + b"file": full, + b"parity": next(parity), + b"basename": f, + b"date": fctx.date(), + b"size": fctx.size(), + b"permissions": mf.flags(full), } def dirlist(context): @@ -610,16 +612,16 @@ emptydirs.append(k) h = v - path = "%s%s" % (abspath, d) + path = b"%s%s" % (abspath, d) yield { - "parity": next(parity), - "path": path, - "emptydirs": "/".join(emptydirs), - "basename": d, + b"parity": next(parity), + b"path": path, + b"emptydirs": b"/".join(emptydirs), + b"basename": d, } return web.sendtemplate( - "manifest", + b"manifest", symrev=symrev, path=abspath, up=webutil.up(abspath), @@ -631,7 +633,7 @@ ) -@webcommand("tags") +@webcommand(b"tags") def tags(web): """ /tags @@ -649,19 +651,19 @@ def entries(context, notip, latestonly): t = i if notip: - t = [(k, n) for k, n in i if k != "tip"] + t = [(k, n) for k, n in i if k != b"tip"] if latestonly: t = t[:1] for k, n in t: yield { - "parity": next(parity), - "tag": k, - "date": web.repo[n].date(), - "node": hex(n), + b"parity": next(parity), + b"tag": k, + b"date": web.repo[n].date(), + b"node": hex(n), } return web.sendtemplate( - "tags", + b"tags", node=hex(web.repo.changelog.tip()), entries=templateutil.mappinggenerator(entries, args=(False, False)), entriesnotip=templateutil.mappinggenerator(entries, args=(True, False)), @@ -669,7 +671,7 @@ ) -@webcommand("bookmarks") +@webcommand(b"bookmarks") def bookmarks(web): """ /bookmarks @@ -692,10 +694,10 @@ t = i[:1] for k, n in t: yield { - "parity": next(parity), - "bookmark": k, - "date": web.repo[n].date(), - "node": hex(n), + b"parity": next(parity), + b"bookmark": k, + b"date": web.repo[n].date(), + b"node": hex(n), } if i: @@ -705,15 +707,15 @@ lastdate = web.repo[latestrev].date() return web.sendtemplate( - "bookmarks", + b"bookmarks", node=hex(web.repo.changelog.tip()), - lastchange=templateutil.mappinglist([{"date": lastdate}]), + lastchange=templateutil.mappinglist([{b"date": lastdate}]), entries=templateutil.mappinggenerator(entries, args=(False,)), latestentry=templateutil.mappinggenerator(entries, args=(True,)), ) -@webcommand("branches") +@webcommand(b"branches") def branches(web): """ /branches @@ -731,14 +733,14 @@ latestentry = webutil.branchentries(web.repo, web.stripecount, 1) return web.sendtemplate( - "branches", + b"branches", node=hex(web.repo.changelog.tip()), entries=entries, latestentry=latestentry, ) -@webcommand("summary") +@webcommand(b"summary") def summary(web): """ /summary @@ -757,7 +759,7 @@ parity = paritygen(web.stripecount) count = 0 for k, n in i: - if k == "tip": # skip tip + if k == b"tip": # skip tip continue count += 1 @@ -765,10 +767,10 @@ break yield { - "parity": next(parity), - "tag": k, - "node": hex(n), - "date": web.repo[n].date(), + b"parity": next(parity), + b"tag": k, + b"node": hex(n), + b"date": web.repo[n].date(), } def bookmarks(context): @@ -778,10 +780,10 @@ marks = sorted(marks, key=sortkey, reverse=True) for k, n in marks[:10]: # limit to 10 bookmarks yield { - "parity": next(parity), - "bookmark": k, - "date": web.repo[n].date(), - "node": hex(n), + b"parity": next(parity), + b"bookmark": k, + b"date": web.repo[n].date(), + b"node": hex(n), } def changelist(context): @@ -793,41 +795,41 @@ for i in revs: ctx = web.repo[i] lm = webutil.commonentry(web.repo, ctx) - lm["parity"] = next(parity) + lm[b"parity"] = next(parity) l.append(lm) for entry in reversed(l): yield entry - tip = web.repo["tip"] + tip = web.repo[b"tip"] count = len(web.repo) start = max(0, count - web.maxchanges) end = min(count, start + web.maxchanges) - desc = web.config("web", "description") + desc = web.config(b"web", b"description") if not desc: - desc = "unknown" - labels = web.configlist("web", "labels") + desc = b"unknown" + labels = web.configlist(b"web", b"labels") return web.sendtemplate( - "summary", + b"summary", desc=desc, - owner=get_contact(web.config) or "unknown", + owner=get_contact(web.config) or b"unknown", lastchange=tip.date(), - tags=templateutil.mappinggenerator(tagentries, name="tagentry"), + tags=templateutil.mappinggenerator(tagentries, name=b"tagentry"), bookmarks=templateutil.mappinggenerator(bookmarks), branches=webutil.branchentries(web.repo, web.stripecount, 10), shortlog=templateutil.mappinggenerator( - changelist, name="shortlogentry" + changelist, name=b"shortlogentry" ), node=tip.hex(), - symrev="tip", - archives=web.archivelist("tip"), - labels=templateutil.hybridlist(labels, name="label"), + symrev=b"tip", + archives=web.archivelist(b"tip"), + labels=templateutil.hybridlist(labels, name=b"label"), ) -@webcommand("filediff") +@webcommand(b"filediff") def filediff(web): """ /diff/{revision}/{path} @@ -845,7 +847,7 @@ fctx = webutil.filectx(web.repo, web.req) except LookupError: ctx = webutil.changectx(web.repo, web.req) - path = webutil.cleanpath(web.repo, web.req.qsparams["file"]) + path = webutil.cleanpath(web.repo, web.req.qsparams[b"file"]) if path not in ctx.files(): raise @@ -854,9 +856,9 @@ ctx = fctx.changectx() basectx = ctx.p1() - style = web.config("web", "style") - if "style" in web.req.qsparams: - style = web.req.qsparams["style"] + style = web.config(b"web", b"style") + if b"style" in web.req.qsparams: + style = web.req.qsparams[b"style"] diffs = webutil.diffs(web, ctx, basectx, [path], style) if fctx is not None: @@ -867,7 +869,7 @@ ctx = ctx return web.sendtemplate( - "filediff", + b"filediff", file=path, symrev=webutil.symrevorshortnode(web.req, ctx), rename=rename, @@ -876,10 +878,10 @@ ) -diff = webcommand("diff")(filediff) +diff = webcommand(b"diff")(filediff) -@webcommand("comparison") +@webcommand(b"comparison") def comparison(web): """ /comparison/{revision}/{path} @@ -897,15 +899,15 @@ The ``filecomparison`` template is rendered. """ ctx = webutil.changectx(web.repo, web.req) - if "file" not in web.req.qsparams: - raise ErrorResponse(HTTP_NOT_FOUND, "file not given") - path = webutil.cleanpath(web.repo, web.req.qsparams["file"]) + if b"file" not in web.req.qsparams: + raise ErrorResponse(HTTP_NOT_FOUND, b"file not given") + path = webutil.cleanpath(web.repo, web.req.qsparams[b"file"]) - parsecontext = lambda v: v == "full" and -1 or int(v) - if "context" in web.req.qsparams: - context = parsecontext(web.req.qsparams["context"]) + parsecontext = lambda v: v == b"full" and -1 or int(v) + if b"context" in web.req.qsparams: + context = parsecontext(web.req.qsparams[b"context"]) else: - context = parsecontext(web.config("web", "comparisoncontext")) + context = parsecontext(web.config(b"web", b"comparisoncontext")) def filelines(f): if f.isbinary(): @@ -913,7 +915,7 @@ mimetypes.guess_type(pycompat.fsdecode(f.path()))[0] or r"application/octet-stream" ) - return [_("(binary file %s, hash: %s)") % (mt, hex(f.filenode()))] + return [_(b"(binary file %s, hash: %s)") % (mt, hex(f.filenode()))] return f.data().splitlines() fctx = None @@ -944,7 +946,7 @@ ctx = ctx return web.sendtemplate( - "filecomparison", + b"filecomparison", file=path, symrev=webutil.symrevorshortnode(web.req, ctx), rename=rename, @@ -957,7 +959,7 @@ ) -@webcommand("annotate") +@webcommand(b"annotate") def annotate(web): """ /annotate/{revision}/{path} @@ -991,8 +993,8 @@ parentscache[rev] = [] for p in f.parents(): entry = { - "node": p.hex(), - "rev": p.rev(), + b"node": p.hex(), + b"rev": p.rev(), } parentscache[rev].append(entry) @@ -1009,7 +1011,7 @@ dagop.annotateline( fctx=fctx.filectx(fctx.filerev()), lineno=1, - text="(binary:%s)" % mt, + text=b"(binary:%s)" % mt, ) ] else: @@ -1027,29 +1029,29 @@ blockhead = None previousrev = rev yield { - "parity": next(parity), - "node": f.hex(), - "rev": rev, - "author": f.user(), - "parents": templateutil.mappinggenerator(parents, args=(f,)), - "desc": f.description(), - "extra": f.extra(), - "file": f.path(), - "blockhead": blockhead, - "blockparity": blockparity, - "targetline": aline.lineno, - "line": aline.text, - "lineno": lineno + 1, - "lineid": "l%d" % (lineno + 1), - "linenumber": "% 6d" % (lineno + 1), - "revdate": f.date(), + b"parity": next(parity), + b"node": f.hex(), + b"rev": rev, + b"author": f.user(), + b"parents": templateutil.mappinggenerator(parents, args=(f,)), + b"desc": f.description(), + b"extra": f.extra(), + b"file": f.path(), + b"blockhead": blockhead, + b"blockparity": blockparity, + b"targetline": aline.lineno, + b"line": aline.text, + b"lineno": lineno + 1, + b"lineid": b"l%d" % (lineno + 1), + b"linenumber": b"% 6d" % (lineno + 1), + b"revdate": f.date(), } - diffopts = webutil.difffeatureopts(web.req, web.repo.ui, "annotate") + diffopts = webutil.difffeatureopts(web.req, web.repo.ui, b"annotate") diffopts = {k: getattr(diffopts, k) for k in diffopts.defaults} return web.sendtemplate( - "fileannotate", + b"fileannotate", file=f, annotate=templateutil.mappinggenerator(annotate), path=webutil.up(f), @@ -1062,7 +1064,7 @@ ) -@webcommand("filelog") +@webcommand(b"filelog") def filelog(web): """ /filelog/{revision}/{path} @@ -1081,7 +1083,7 @@ f = fctx.path() fl = fctx.filelog() except error.LookupError: - f = webutil.cleanpath(web.repo, web.req.qsparams["file"]) + f = webutil.cleanpath(web.repo, web.req.qsparams[b"file"]) fl = web.repo.file(f) numrevs = len(fl) if not numrevs: # file doesn't exist at all @@ -1096,27 +1098,29 @@ fctx = web.repo.filectx(f, fl.linkrev(frev)) revcount = web.maxshortchanges - if "revcount" in web.req.qsparams: + if b"revcount" in web.req.qsparams: try: - revcount = int(web.req.qsparams.get("revcount", revcount)) + revcount = int(web.req.qsparams.get(b"revcount", revcount)) revcount = max(revcount, 1) - web.tmpl.defaults["sessionvars"]["revcount"] = revcount + web.tmpl.defaults[b"sessionvars"][b"revcount"] = revcount except ValueError: pass lrange = webutil.linerange(web.req) - lessvars = copy.copy(web.tmpl.defaults["sessionvars"]) - lessvars["revcount"] = max(revcount // 2, 1) - morevars = copy.copy(web.tmpl.defaults["sessionvars"]) - morevars["revcount"] = revcount * 2 + lessvars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + lessvars[b"revcount"] = max(revcount // 2, 1) + morevars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + morevars[b"revcount"] = revcount * 2 - patch = "patch" in web.req.qsparams + patch = b"patch" in web.req.qsparams if patch: - lessvars["patch"] = morevars["patch"] = web.req.qsparams["patch"] - descend = "descend" in web.req.qsparams + lessvars[b"patch"] = morevars[b"patch"] = web.req.qsparams[b"patch"] + descend = b"descend" in web.req.qsparams if descend: - lessvars["descend"] = morevars["descend"] = web.req.qsparams["descend"] + lessvars[b"descend"] = morevars[b"descend"] = web.req.qsparams[ + b"descend" + ] count = fctx.filerev() + 1 start = max(0, count - revcount) # first rev on this page @@ -1132,9 +1136,9 @@ ] entries = [] - diffstyle = web.config("web", "style") - if "style" in web.req.qsparams: - diffstyle = web.req.qsparams["style"] + diffstyle = web.config(b"web", b"style") + if b"style" in web.req.qsparams: + diffstyle = web.req.qsparams[b"style"] def diff(fctx, linerange=None): ctx = fctx.changectx() @@ -1147,7 +1151,7 @@ [path], diffstyle, linerange=linerange, - lineidprefix="%s-" % ctx.hex()[:12], + lineidprefix=b"%s-" % ctx.hex()[:12], ) linerange = None @@ -1169,19 +1173,19 @@ lm = webutil.commonentry(repo, c) lm.update( { - "parity": next(parity), - "filerev": c.rev(), - "file": path, - "diff": diffs, - "linerange": webutil.formatlinerange(*lr), - "rename": templateutil.mappinglist([]), + b"parity": next(parity), + b"filerev": c.rev(), + b"file": path, + b"diff": diffs, + b"linerange": webutil.formatlinerange(*lr), + b"rename": templateutil.mappinglist([]), } ) entries.append(lm) if i == revcount: break - lessvars["linerange"] = webutil.formatlinerange(*lrange) - morevars["linerange"] = lessvars["linerange"] + lessvars[b"linerange"] = webutil.formatlinerange(*lrange) + morevars[b"linerange"] = lessvars[b"linerange"] else: for i in revs: iterfctx = fctx.filectx(i) @@ -1191,11 +1195,11 @@ lm = webutil.commonentry(repo, iterfctx) lm.update( { - "parity": next(parity), - "filerev": i, - "file": f, - "diff": diffs, - "rename": webutil.renamelink(iterfctx), + b"parity": next(parity), + b"filerev": i, + b"file": f, + b"diff": diffs, + b"rename": webutil.renamelink(iterfctx), } ) entries.append(lm) @@ -1206,7 +1210,7 @@ latestentry = entries[:1] return web.sendtemplate( - "filelog", + b"filelog", file=f, nav=nav, symrev=webutil.symrevorshortnode(web.req, fctx), @@ -1222,7 +1226,7 @@ ) -@webcommand("archive") +@webcommand(b"archive") def archive(web): """ /archive/{revision}.{format}[/{path}] @@ -1243,54 +1247,54 @@ No template is used for this handler. Raw, binary content is generated. """ - type_ = web.req.qsparams.get("type") - allowed = web.configlist("web", "allow-archive") - key = web.req.qsparams["node"] + type_ = web.req.qsparams.get(b"type") + allowed = web.configlist(b"web", b"allow-archive") + key = web.req.qsparams[b"node"] if type_ not in webutil.archivespecs: - msg = "Unsupported archive type: %s" % stringutil.pprint(type_) + msg = b"Unsupported archive type: %s" % stringutil.pprint(type_) raise ErrorResponse(HTTP_NOT_FOUND, msg) - if not ((type_ in allowed or web.configbool("web", "allow" + type_))): - msg = "Archive type not allowed: %s" % type_ + if not ((type_ in allowed or web.configbool(b"web", b"allow" + type_))): + msg = b"Archive type not allowed: %s" % type_ raise ErrorResponse(HTTP_FORBIDDEN, msg) - reponame = re.sub(br"\W+", "-", os.path.basename(web.reponame)) + reponame = re.sub(br"\W+", b"-", os.path.basename(web.reponame)) cnode = web.repo.lookup(key) arch_version = key - if cnode == key or key == "tip": + if cnode == key or key == b"tip": arch_version = short(cnode) - name = "%s-%s" % (reponame, arch_version) + name = b"%s-%s" % (reponame, arch_version) ctx = webutil.changectx(web.repo, web.req) pats = [] match = scmutil.match(ctx, []) - file = web.req.qsparams.get("file") + file = web.req.qsparams.get(b"file") if file: - pats = ["path:" + file] - match = scmutil.match(ctx, pats, default="path") + pats = [b"path:" + file] + match = scmutil.match(ctx, pats, default=b"path") if pats: files = [f for f in ctx.manifest().keys() if match(f)] if not files: raise ErrorResponse( - HTTP_NOT_FOUND, "file(s) not found: %s" % file + HTTP_NOT_FOUND, b"file(s) not found: %s" % file ) mimetype, artype, extension, encoding = webutil.archivespecs[type_] - web.res.headers["Content-Type"] = mimetype - web.res.headers["Content-Disposition"] = "attachment; filename=%s%s" % ( + web.res.headers[b"Content-Type"] = mimetype + web.res.headers[b"Content-Disposition"] = b"attachment; filename=%s%s" % ( name, extension, ) if encoding: - web.res.headers["Content-Encoding"] = encoding + web.res.headers[b"Content-Encoding"] = encoding web.res.setbodywillwrite() if list(web.res.sendresponse()): raise error.ProgrammingError( - "sendresponse() should not emit data " "if writing later" + b"sendresponse() should not emit data " b"if writing later" ) bodyfh = web.res.getbodyfile() @@ -1302,29 +1306,29 @@ artype, prefix=name, match=match, - subrepos=web.configbool("web", "archivesubrepos"), + subrepos=web.configbool(b"web", b"archivesubrepos"), ) return [] -@webcommand("static") +@webcommand(b"static") def static(web): - fname = web.req.qsparams["file"] + fname = web.req.qsparams[b"file"] # a repo owner may set web.static in .hg/hgrc to get any file # readable by the user running the CGI script - static = web.config("web", "static", untrusted=False) + static = web.config(b"web", b"static", untrusted=False) if not static: tp = web.templatepath or templater.templatepaths() if isinstance(tp, str): tp = [tp] - static = [os.path.join(p, "static") for p in tp] + static = [os.path.join(p, b"static") for p in tp] staticfile(static, fname, web.res) return web.res.sendresponse() -@webcommand("graph") +@webcommand(b"graph") def graph(web): """ /graph[/{revision}] @@ -1348,32 +1352,32 @@ This handler will render the ``graph`` template. """ - if "node" in web.req.qsparams: + if b"node" in web.req.qsparams: ctx = webutil.changectx(web.repo, web.req) symrev = webutil.symrevorshortnode(web.req, ctx) else: - ctx = web.repo["tip"] - symrev = "tip" + ctx = web.repo[b"tip"] + symrev = b"tip" rev = ctx.rev() bg_height = 39 revcount = web.maxshortchanges - if "revcount" in web.req.qsparams: + if b"revcount" in web.req.qsparams: try: - revcount = int(web.req.qsparams.get("revcount", revcount)) + revcount = int(web.req.qsparams.get(b"revcount", revcount)) revcount = max(revcount, 1) - web.tmpl.defaults["sessionvars"]["revcount"] = revcount + web.tmpl.defaults[b"sessionvars"][b"revcount"] = revcount except ValueError: pass - lessvars = copy.copy(web.tmpl.defaults["sessionvars"]) - lessvars["revcount"] = max(revcount // 2, 1) - morevars = copy.copy(web.tmpl.defaults["sessionvars"]) - morevars["revcount"] = revcount * 2 + lessvars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + lessvars[b"revcount"] = max(revcount // 2, 1) + morevars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + morevars[b"revcount"] = revcount * 2 - graphtop = web.req.qsparams.get("graphtop", ctx.hex()) - graphvars = copy.copy(web.tmpl.defaults["sessionvars"]) - graphvars["graphtop"] = graphtop + graphtop = web.req.qsparams.get(b"graphtop", ctx.hex()) + graphvars = copy.copy(web.tmpl.defaults[b"sessionvars"]) + graphvars[b"graphtop"] = graphtop count = len(web.repo) pos = rev @@ -1426,10 +1430,10 @@ def jsdata(context): for (id, type, ctx, vtx, edges) in fulltree(): yield { - "node": pycompat.bytestr(ctx), - "graphnode": webutil.getgraphnode(web.repo, ctx), - "vertex": vtx, - "edges": edges, + b"node": pycompat.bytestr(ctx), + b"graphnode": webutil.getgraphnode(web.repo, ctx), + b"vertex": vtx, + b"edges": edges, } def nodes(context): @@ -1438,23 +1442,23 @@ entry = webutil.commonentry(web.repo, ctx) edgedata = [ { - "col": edge[0], - "nextcol": edge[1], - "color": (edge[2] - 1) % 6 + 1, - "width": edge[3], - "bcolor": edge[4], + b"col": edge[0], + b"nextcol": edge[1], + b"color": (edge[2] - 1) % 6 + 1, + b"width": edge[3], + b"bcolor": edge[4], } for edge in edges ] entry.update( { - "col": vtx[0], - "color": (vtx[1] - 1) % 6 + 1, - "parity": next(parity), - "edges": templateutil.mappinglist(edgedata), - "row": row, - "nextrow": row + 1, + b"col": vtx[0], + b"color": (vtx[1] - 1) % 6 + 1, + b"parity": next(parity), + b"edges": templateutil.mappinglist(edgedata), + b"row": row, + b"nextrow": row + 1, } ) @@ -1463,7 +1467,7 @@ rows = len(tree) return web.sendtemplate( - "graph", + b"graph", rev=rev, symrev=symrev, revcount=revcount, @@ -1479,7 +1483,7 @@ jsdata=templateutil.mappinggenerator(jsdata), nodes=templateutil.mappinggenerator(nodes), node=ctx.hex(), - archives=web.archivelist("tip"), + archives=web.archivelist(b"tip"), changenav=changenav, ) @@ -1487,13 +1491,13 @@ def _getdoc(e): doc = e[0].__doc__ if doc: - doc = _(doc).partition("\n")[0] + doc = _(doc).partition(b"\n")[0] else: - doc = _("(no help text available)") + doc = _(b"(no help text available)") return doc -@webcommand("help") +@webcommand(b"help") def help(web): """ /help[/{topic}] @@ -1510,19 +1514,19 @@ """ from .. import commands, help as helpmod # avoid cycle - topicname = web.req.qsparams.get("node") + topicname = web.req.qsparams.get(b"node") if not topicname: def topics(context): for h in helpmod.helptable: entries, summary, _doc = h[0:3] - yield {"topic": entries[0], "summary": summary} + yield {b"topic": entries[0], b"summary": summary} early, other = [], [] - primary = lambda s: s.partition("|")[0] + primary = lambda s: s.partition(b"|")[0] for c, e in commands.table.iteritems(): doc = _getdoc(e) - if "DEPRECATED" in doc or c.startswith("debug"): + if b"DEPRECATED" in doc or c.startswith(b"debug"): continue cmd = primary(c) if getattr(e[0], "helpbasic", False): @@ -1535,18 +1539,18 @@ def earlycommands(context): for c, doc in early: - yield {"topic": c, "summary": doc} + yield {b"topic": c, b"summary": doc} def othercommands(context): for c, doc in other: - yield {"topic": c, "summary": doc} + yield {b"topic": c, b"summary": doc} return web.sendtemplate( - "helptopics", + b"helptopics", topics=templateutil.mappinggenerator(topics), earlycommands=templateutil.mappinggenerator(earlycommands), othercommands=templateutil.mappinggenerator(othercommands), - title="Index", + title=b"Index", ) # Render an index of sub-topics. @@ -1555,14 +1559,14 @@ for entries, summary, _doc in helpmod.subtopics[topicname]: topics.append( { - "topic": "%s.%s" % (topicname, entries[0]), - "basename": entries[0], - "summary": summary, + b"topic": b"%s.%s" % (topicname, entries[0]), + b"basename": entries[0], + b"summary": summary, } ) return web.sendtemplate( - "helptopics", + b"helptopics", topics=templateutil.mappinglist(topics), title=topicname, subindex=True, @@ -1572,10 +1576,10 @@ u.verbose = True # Render a page from a sub-topic. - if "." in topicname: + if b"." in topicname: # TODO implement support for rendering sections, like # `hg help` works. - topic, subtopic = topicname.split(".", 1) + topic, subtopic = topicname.split(b".", 1) if topic not in helpmod.subtopics: raise ErrorResponse(HTTP_NOT_FOUND) else: @@ -1587,7 +1591,7 @@ except error.Abort: raise ErrorResponse(HTTP_NOT_FOUND) - return web.sendtemplate("help", topic=topicname, doc=doc) + return web.sendtemplate(b"help", topic=topicname, doc=doc) # tell hggettext to extract docstrings from these functions: diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py --- a/mercurial/hgweb/webutil.py +++ b/mercurial/hgweb/webutil.py @@ -45,37 +45,42 @@ archivespecs = util.sortdict( ( - ("zip", ("application/zip", "zip", ".zip", None)), - ("gz", ("application/x-gzip", "tgz", ".tar.gz", None)), - ("bz2", ("application/x-bzip2", "tbz2", ".tar.bz2", None)), + (b"zip", (b"application/zip", b"zip", b".zip", None)), + (b"gz", (b"application/x-gzip", b"tgz", b".tar.gz", None)), + (b"bz2", (b"application/x-bzip2", b"tbz2", b".tar.bz2", None)), ) ) def archivelist(ui, nodeid, url=None): - allowed = ui.configlist("web", "allow-archive", untrusted=True) + allowed = ui.configlist(b"web", b"allow-archive", untrusted=True) archives = [] for typ, spec in archivespecs.iteritems(): if typ in allowed or ui.configbool( - "web", "allow" + typ, untrusted=True + b"web", b"allow" + typ, untrusted=True ): archives.append( - {"type": typ, "extension": spec[2], "node": nodeid, "url": url,} + { + b"type": typ, + b"extension": spec[2], + b"node": nodeid, + b"url": url, + } ) return templateutil.mappinglist(archives) def up(p): - if p[0:1] != "/": - p = "/" + p - if p[-1:] == "/": + if p[0:1] != b"/": + p = b"/" + p + if p[-1:] == b"/": p = p[:-1] up = os.path.dirname(p) - if up == "/": - return "/" - return up + "/" + if up == b"/": + return b"/" + return up + b"/" def _navseq(step, firststep=None): @@ -136,8 +141,8 @@ return templateutil.mappinglist( [ { - "before": templateutil.mappinglist([]), - "after": templateutil.mappinglist([]), + b"before": templateutil.mappinglist([]), + b"after": templateutil.mappinglist([]), }, ] ) @@ -151,28 +156,28 @@ targets.sort() first = self._first() - navbefore = [{"label": "(%i)" % first, "node": self.hex(first)}] + navbefore = [{b"label": b"(%i)" % first, b"node": self.hex(first)}] navafter = [] for rev in targets: if rev not in self._revlog: continue if pos < rev < limit: navafter.append( - {"label": "+%d" % abs(rev - pos), "node": self.hex(rev)} + {b"label": b"+%d" % abs(rev - pos), b"node": self.hex(rev)} ) if 0 < rev < pos: navbefore.append( - {"label": "-%d" % abs(rev - pos), "node": self.hex(rev)} + {b"label": b"-%d" % abs(rev - pos), b"node": self.hex(rev)} ) - navafter.append({"label": "tip", "node": "tip"}) + navafter.append({b"label": b"tip", b"node": b"tip"}) # TODO: maybe this can be a scalar object supporting tomap() return templateutil.mappinglist( [ { - "before": templateutil.mappinglist(navbefore), - "after": templateutil.mappinglist(navafter), + b"before": templateutil.mappinglist(navbefore), + b"after": templateutil.mappinglist(navafter), }, ] ) @@ -199,15 +204,15 @@ def _ctxsgen(context, ctxs): for s in ctxs: d = { - "node": s.hex(), - "rev": s.rev(), - "user": s.user(), - "date": s.date(), - "description": s.description(), - "branch": s.branch(), + b"node": s.hex(), + b"rev": s.rev(), + b"user": s.user(), + b"date": s.date(), + b"description": s.description(), + b"branch": s.branch(), } - if util.safehasattr(s, "path"): - d["file"] = s.path() + if util.safehasattr(s, b"path"): + d[b"file"] = s.path() yield d @@ -225,7 +230,12 @@ ui, untrusted=True, section=section, whitespace=True ) - for k in ("ignorews", "ignorewsamount", "ignorewseol", "ignoreblanklines"): + for k in ( + b"ignorews", + b"ignorewsamount", + b"ignorewseol", + b"ignoreblanklines", + ): v = req.qsparams.get(k) if v is not None: v = stringutil.parsebool(v) @@ -235,7 +245,7 @@ def annotate(req, fctx, ui): - diffopts = difffeatureopts(req, ui, "annotate") + diffopts = difffeatureopts(req, ui, b"annotate") return fctx.annotate(follow=True, diffopts=diffopts) @@ -254,16 +264,16 @@ def renamelink(fctx): r = fctx.renamed() if r: - return templateutil.mappinglist([{"file": r[0], "node": hex(r[1])}]) + return templateutil.mappinglist([{b"file": r[0], b"node": hex(r[1])}]) return templateutil.mappinglist([]) def nodetagsdict(repo, node): - return templateutil.hybridlist(repo.nodetags(node), name="name") + return templateutil.hybridlist(repo.nodetags(node), name=b"name") def nodebookmarksdict(repo, node): - return templateutil.hybridlist(repo.nodebookmarks(node), name="name") + return templateutil.hybridlist(repo.nodebookmarks(node), name=b"name") def nodebranchdict(repo, ctx): @@ -277,7 +287,7 @@ branchnode = None if branchnode == ctx.node(): branches.append(branch) - return templateutil.hybridlist(branches, name="name") + return templateutil.hybridlist(branches, name=b"name") def nodeinbranch(repo, ctx): @@ -287,17 +297,17 @@ branchnode = repo.branchtip(branch) except error.RepoLookupError: branchnode = None - if branch != "default" and branchnode != ctx.node(): + if branch != b"default" and branchnode != ctx.node(): branches.append(branch) - return templateutil.hybridlist(branches, name="name") + return templateutil.hybridlist(branches, name=b"name") def nodebranchnodefault(ctx): branches = [] branch = ctx.branch() - if branch != "default": + if branch != b"default": branches.append(branch) - return templateutil.hybridlist(branches, name="name") + return templateutil.hybridlist(branches, name=b"name") def _nodenamesgen(context, f, node, name): @@ -306,12 +316,12 @@ def showtag(repo, t1, node=nullid): - args = (repo.nodetags, node, "tag") + args = (repo.nodetags, node, b"tag") return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1) def showbookmark(repo, t1, node=nullid): - args = (repo.nodebookmarks, node, "bookmark") + args = (repo.nodebookmarks, node, b"bookmark") return templateutil.mappinggenerator(_nodenamesgen, args=args, name=t1) @@ -331,33 +341,33 @@ return count += 1 if closed: - status = "closed" + status = b"closed" elif ctx.node() not in heads: - status = "inactive" + status = b"inactive" else: - status = "open" + status = b"open" yield { - "parity": next(parity), - "branch": ctx.branch(), - "status": status, - "node": ctx.hex(), - "date": ctx.date(), + b"parity": next(parity), + b"branch": ctx.branch(), + b"status": status, + b"node": ctx.hex(), + b"date": ctx.date(), } return templateutil.mappinggenerator(entries) def cleanpath(repo, path): - path = path.lstrip("/") + path = path.lstrip(b"/") auditor = pathutil.pathauditor(repo.root, realfs=False) - return pathutil.canonpath(repo.root, "", path, auditor=auditor) + return pathutil.canonpath(repo.root, b"", path, auditor=auditor) def changectx(repo, req): - changeid = "tip" - if "node" in req.qsparams: - changeid = req.qsparams["node"] - ipos = changeid.find(":") + changeid = b"tip" + if b"node" in req.qsparams: + changeid = req.qsparams[b"node"] + ipos = changeid.find(b":") if ipos != -1: changeid = changeid[(ipos + 1) :] @@ -365,9 +375,9 @@ def basechangectx(repo, req): - if "node" in req.qsparams: - changeid = req.qsparams["node"] - ipos = changeid.find(":") + if b"node" in req.qsparams: + changeid = req.qsparams[b"node"] + ipos = changeid.find(b":") if ipos != -1: changeid = changeid[:ipos] return scmutil.revsymbol(repo, changeid) @@ -376,15 +386,15 @@ def filectx(repo, req): - if "file" not in req.qsparams: - raise ErrorResponse(HTTP_NOT_FOUND, "file not given") - path = cleanpath(repo, req.qsparams["file"]) - if "node" in req.qsparams: - changeid = req.qsparams["node"] - elif "filenode" in req.qsparams: - changeid = req.qsparams["filenode"] + if b"file" not in req.qsparams: + raise ErrorResponse(HTTP_NOT_FOUND, b"file not given") + path = cleanpath(repo, req.qsparams[b"file"]) + if b"node" in req.qsparams: + changeid = req.qsparams[b"node"] + elif b"filenode" in req.qsparams: + changeid = req.qsparams[b"filenode"] else: - raise ErrorResponse(HTTP_NOT_FOUND, "node or filenode not given") + raise ErrorResponse(HTTP_NOT_FOUND, b"node or filenode not given") try: fctx = scmutil.revsymbol(repo, changeid)[path] except error.RepoError: @@ -394,15 +404,15 @@ def linerange(req): - linerange = req.qsparams.getall("linerange") + linerange = req.qsparams.getall(b"linerange") if not linerange: return None if len(linerange) > 1: - raise ErrorResponse(HTTP_BAD_REQUEST, "redundant linerange parameter") + raise ErrorResponse(HTTP_BAD_REQUEST, b"redundant linerange parameter") try: - fromline, toline = map(int, linerange[0].split(":", 1)) + fromline, toline = map(int, linerange[0].split(b":", 1)) except ValueError: - raise ErrorResponse(HTTP_BAD_REQUEST, "invalid linerange parameter") + raise ErrorResponse(HTTP_BAD_REQUEST, b"invalid linerange parameter") try: return util.processlinerange(fromline, toline) except error.ParseError as exc: @@ -410,15 +420,15 @@ def formatlinerange(fromline, toline): - return "%d:%d" % (fromline + 1, toline) + return b"%d:%d" % (fromline + 1, toline) def _succsandmarkersgen(context, mapping): - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") itemmappings = templatekw.showsuccsandmarkers(context, mapping) for item in itemmappings.tovalue(context, mapping): - item["successors"] = _siblings( - repo[successor] for successor in item["successors"] + item[b"successors"] = _siblings( + repo[successor] for successor in item[b"successors"] ) yield item @@ -428,17 +438,17 @@ # teach templater succsandmarkers is switched to (context, mapping) API -succsandmarkers._requires = {"repo", "ctx"} +succsandmarkers._requires = {b"repo", b"ctx"} def _whyunstablegen(context, mapping): - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") entries = obsutil.whyunstable(repo, ctx) for entry in entries: - if entry.get("divergentnodes"): - entry["divergentnodes"] = _siblings(entry["divergentnodes"]) + if entry.get(b"divergentnodes"): + entry[b"divergentnodes"] = _siblings(entry[b"divergentnodes"]) yield entry @@ -446,7 +456,7 @@ return templateutil.mappinggenerator(_whyunstablegen, args=(mapping,)) -whyunstable._requires = {"repo", "ctx"} +whyunstable._requires = {b"repo", b"ctx"} def commonentry(repo, ctx): @@ -455,27 +465,27 @@ # TODO: perhaps ctx.changectx() should be assigned if ctx is a # filectx, but I'm not pretty sure if that would always work because # fctx.parents() != fctx.changectx.parents() for example. - "ctx": ctx, - "rev": ctx.rev(), - "node": hex(node), - "author": ctx.user(), - "desc": ctx.description(), - "date": ctx.date(), - "extra": ctx.extra(), - "phase": ctx.phasestr(), - "obsolete": ctx.obsolete(), - "succsandmarkers": succsandmarkers, - "instabilities": templateutil.hybridlist( - ctx.instabilities(), name="instability" + b"ctx": ctx, + b"rev": ctx.rev(), + b"node": hex(node), + b"author": ctx.user(), + b"desc": ctx.description(), + b"date": ctx.date(), + b"extra": ctx.extra(), + b"phase": ctx.phasestr(), + b"obsolete": ctx.obsolete(), + b"succsandmarkers": succsandmarkers, + b"instabilities": templateutil.hybridlist( + ctx.instabilities(), name=b"instability" ), - "whyunstable": whyunstable, - "branch": nodebranchnodefault(ctx), - "inbranch": nodeinbranch(repo, ctx), - "branches": nodebranchdict(repo, ctx), - "tags": nodetagsdict(repo, node), - "bookmarks": nodebookmarksdict(repo, node), - "parent": lambda context, mapping: parents(ctx), - "child": lambda context, mapping: children(ctx), + b"whyunstable": whyunstable, + b"branch": nodebranchnodefault(ctx), + b"inbranch": nodeinbranch(repo, ctx), + b"branches": nodebranchdict(repo, ctx), + b"tags": nodetagsdict(repo, node), + b"bookmarks": nodebookmarksdict(repo, node), + b"parent": lambda context, mapping: parents(ctx), + b"child": lambda context, mapping: children(ctx), } @@ -488,17 +498,17 @@ repo = web.repo rev = ctx.rev() n = scmutil.binnode(ctx) - showtags = showtag(repo, "changelogtag", n) + showtags = showtag(repo, b"changelogtag", n) files = listfilediffs(ctx.files(), n, web.maxfiles) entry = commonentry(repo, ctx) entry.update( { - "allparents": lambda context, mapping: parents(ctx), - "parent": lambda context, mapping: parents(ctx, rev - 1), - "child": lambda context, mapping: children(ctx, rev + 1), - "changelogtag": showtags, - "files": files, + b"allparents": lambda context, mapping: parents(ctx), + b"parent": lambda context, mapping: parents(ctx, rev - 1), + b"child": lambda context, mapping: children(ctx, rev + 1), + b"changelogtag": showtags, + b"files": files, } ) return entry @@ -516,14 +526,14 @@ count += 1 entry = changelistentry(web, repo[rev]) - entry["parity"] = next(parityfn) + entry[b"parity"] = next(parityfn) yield entry def symrevorshortnode(req, ctx): - if "node" in req.qsparams: - return templatefilters.revescape(req.qsparams["node"]) + if b"node" in req.qsparams: + return templatefilters.revescape(req.qsparams[b"node"]) else: return short(scmutil.binnode(ctx)) @@ -531,14 +541,14 @@ def _listfilesgen(context, ctx, stripecount): parity = paritygen(stripecount) for blockno, f in enumerate(ctx.files()): - template = "filenodelink" if f in ctx else "filenolink" + template = b"filenodelink" if f in ctx else b"filenolink" yield context.process( template, { - "node": ctx.hex(), - "file": f, - "blockno": blockno + 1, - "parity": next(parity), + b"node": ctx.hex(), + b"file": f, + b"blockno": blockno + 1, + b"parity": next(parity), }, ) @@ -546,9 +556,9 @@ def changesetentry(web, ctx): """Obtain a dictionary to be used to render the "changeset" template.""" - showtags = showtag(web.repo, "changesettag", scmutil.binnode(ctx)) + showtags = showtag(web.repo, b"changesettag", scmutil.binnode(ctx)) showbookmarks = showbookmark( - web.repo, "changesetbookmark", scmutil.binnode(ctx) + web.repo, b"changesetbookmark", scmutil.binnode(ctx) ) showbranch = nodebranchnodefault(ctx) @@ -556,9 +566,9 @@ if basectx is None: basectx = ctx.p1() - style = web.config("web", "style") - if "style" in web.req.qsparams: - style = web.req.qsparams["style"] + style = web.config(b"web", b"style") + if b"style" in web.req.qsparams: + style = web.req.qsparams[b"style"] diff = diffs(web, ctx, basectx, None, style) @@ -585,9 +595,9 @@ def _listfilediffsgen(context, files, node, max): for f in files[:max]: - yield context.process("filedifflink", {"node": hex(node), "file": f}) + yield context.process(b"filedifflink", {b"node": hex(node), b"file": f}) if len(files) > max: - yield context.process("fileellipses", {}) + yield context.process(b"fileellipses", {}) def listfilediffs(files, node, max): @@ -598,22 +608,22 @@ def _prettyprintdifflines(context, lines, blockno, lineidprefix): for lineno, l in enumerate(lines, 1): - difflineno = "%d.%d" % (blockno, lineno) - if l.startswith("+"): - ltype = "difflineplus" - elif l.startswith("-"): - ltype = "difflineminus" - elif l.startswith("@"): - ltype = "difflineat" + difflineno = b"%d.%d" % (blockno, lineno) + if l.startswith(b"+"): + ltype = b"difflineplus" + elif l.startswith(b"-"): + ltype = b"difflineminus" + elif l.startswith(b"@"): + ltype = b"difflineat" else: - ltype = "diffline" + ltype = b"diffline" yield context.process( ltype, { - "line": l, - "lineno": lineno, - "lineid": lineidprefix + "l%s" % difflineno, - "linenumber": "% 8s" % difflineno, + b"line": l, + b"lineno": lineno, + b"lineid": lineidprefix + b"l%s" % difflineno, + b"linenumber": b"% 8s" % difflineno, }, ) @@ -639,9 +649,9 @@ diffhunks = patch.diffhunks(repo, basectx, ctx, m, opts=diffopts) for blockno, (fctx1, fctx2, header, hunks) in enumerate(diffhunks, 1): - if style != "raw": + if style != b"raw": header = header[1:] - lines = [h + "\n" for h in header] + lines = [h + b"\n" for h in header] for hunkrange, hunklines in hunks: if linerange is not None and hunkrange is not None: s1, l1, s2, l2 = hunkrange @@ -653,13 +663,13 @@ _prettyprintdifflines, args=(lines, blockno, lineidprefix) ) yield { - "parity": next(parity), - "blockno": blockno, - "lines": l, + b"parity": next(parity), + b"blockno": blockno, + b"lines": l, } -def diffs(web, ctx, basectx, files, style, linerange=None, lineidprefix=""): +def diffs(web, ctx, basectx, files, style, linerange=None, lineidprefix=b""): args = ( web.repo, ctx, @@ -670,23 +680,25 @@ linerange, lineidprefix, ) - return templateutil.mappinggenerator(_diffsgen, args=args, name="diffblock") + return templateutil.mappinggenerator( + _diffsgen, args=args, name=b"diffblock" + ) def _compline(type, leftlineno, leftline, rightlineno, rightline): - lineid = leftlineno and ("l%d" % leftlineno) or "" - lineid += rightlineno and ("r%d" % rightlineno) or "" - llno = "%d" % leftlineno if leftlineno else "" - rlno = "%d" % rightlineno if rightlineno else "" + lineid = leftlineno and (b"l%d" % leftlineno) or b"" + lineid += rightlineno and (b"r%d" % rightlineno) or b"" + llno = b"%d" % leftlineno if leftlineno else b"" + rlno = b"%d" % rightlineno if rightlineno else b"" return { - "type": type, - "lineid": lineid, - "leftlineno": leftlineno, - "leftlinenumber": "% 6s" % llno, - "leftline": leftline or "", - "rightlineno": rightlineno, - "rightlinenumber": "% 6s" % rlno, - "rightline": rightline or "", + b"type": type, + b"lineid": lineid, + b"leftlineno": leftlineno, + b"leftlinenumber": b"% 6s" % llno, + b"leftline": leftline or b"", + b"rightlineno": rightlineno, + b"rightlinenumber": b"% 6s" % rlno, + b"rightline": rightline or b"", } @@ -727,7 +739,7 @@ def _getcompblock(leftlines, rightlines, opcodes): args = (leftlines, rightlines, opcodes) return templateutil.mappinggenerator( - _getcompblockgen, args=args, name="comparisonline" + _getcompblockgen, args=args, name=b"comparisonline" ) @@ -736,24 +748,24 @@ s = difflib.SequenceMatcher(None, leftlines, rightlines) if contextnum < 0: l = _getcompblock(leftlines, rightlines, s.get_opcodes()) - yield {"lines": l} + yield {b"lines": l} else: for oc in s.get_grouped_opcodes(n=contextnum): l = _getcompblock(leftlines, rightlines, oc) - yield {"lines": l} + yield {b"lines": l} def compare(contextnum, leftlines, rightlines): args = (contextnum, leftlines, rightlines) return templateutil.mappinggenerator( - _comparegen, args=args, name="comparisonblock" + _comparegen, args=args, name=b"comparisonblock" ) def diffstatgen(ui, ctx, basectx): """Generator function that provides the diffstat data.""" - diffopts = patch.diffopts(ui, {"noprefix": False}) + diffopts = patch.diffopts(ui, {b"noprefix": False}) stats = patch.diffstatdata(util.iterlines(ctx.diff(basectx, opts=diffopts))) maxname, maxtotal, addtotal, removetotal, binary = patch.diffstatsum(stats) while True: @@ -764,7 +776,7 @@ """Return a short summary of the diff.""" stats, maxname, maxtotal, addtotal, removetotal, binary = next(statgen) - return _(" %d files changed, %d insertions(+), %d deletions(-)\n") % ( + return _(b" %d files changed, %d insertions(+), %d deletions(-)\n") % ( len(stats), addtotal, removetotal, @@ -782,19 +794,19 @@ fileno = 0 for filename, adds, removes, isbinary in stats: - template = "diffstatlink" if filename in files else "diffstatnolink" + template = b"diffstatlink" if filename in files else b"diffstatnolink" total = adds + removes fileno += 1 yield context.process( template, { - "node": ctx.hex(), - "file": filename, - "fileno": fileno, - "total": total, - "addpct": pct(adds), - "removepct": pct(removes), - "parity": next(parity), + b"node": ctx.hex(), + b"file": filename, + b"fileno": fileno, + b"total": total, + b"addpct": pct(adds), + b"removepct": pct(removes), + b"parity": next(parity), }, ) @@ -806,7 +818,7 @@ class sessionvars(templateutil.wrapped): - def __init__(self, vars, start="?"): + def __init__(self, vars, start=b"?"): self._start = start self._vars = vars @@ -828,31 +840,31 @@ return self._vars.get(key) def getmin(self, context, mapping): - raise error.ParseError(_("not comparable")) + raise error.ParseError(_(b"not comparable")) def getmax(self, context, mapping): - raise error.ParseError(_("not comparable")) + raise error.ParseError(_(b"not comparable")) def filter(self, context, mapping, select): # implement if necessary - raise error.ParseError(_("not filterable")) + raise error.ParseError(_(b"not filterable")) def itermaps(self, context): separator = self._start for key, value in sorted(self._vars.iteritems()): yield { - "name": key, - "value": pycompat.bytestr(value), - "separator": separator, + b"name": key, + b"value": pycompat.bytestr(value), + b"separator": separator, } - separator = "&" + separator = b"&" def join(self, context, mapping, sep): # could be '{separator}{name}={value|urlescape}' - raise error.ParseError(_("not displayable without template")) + raise error.ParseError(_(b"not displayable without template")) def show(self, context, mapping): - return self.join(context, "") + return self.join(context, b"") def tobool(self, context, mapping): return bool(self._vars) @@ -869,9 +881,9 @@ def getwebsubs(repo): websubtable = [] - websubdefs = repo.ui.configitems("websub") + websubdefs = repo.ui.configitems(b"websub") # we must maintain interhg backwards compatibility - websubdefs += repo.ui.configitems("interhg") + websubdefs += repo.ui.configitems(b"interhg") for key, pattern in websubdefs: # grab the delimiter from the character after the "s" unesc = pattern[1:2] @@ -887,7 +899,7 @@ ) if not match: repo.ui.warn( - _("websub: invalid pattern for %s: %s\n") % (key, pattern) + _(b"websub: invalid pattern for %s: %s\n") % (key, pattern) ) continue @@ -908,7 +920,7 @@ websubtable.append((regexp, format)) except re.error: repo.ui.warn( - _("websub: invalid regexp for %s: %s\n") % (key, regexp) + _(b"websub: invalid regexp for %s: %s\n") % (key, regexp) ) return websubtable diff --git a/mercurial/hgweb/wsgicgi.py b/mercurial/hgweb/wsgicgi.py --- a/mercurial/hgweb/wsgicgi.py +++ b/mercurial/hgweb/wsgicgi.py @@ -24,7 +24,7 @@ procutil.setbinary(procutil.stdout) environ = dict(os.environ.iteritems()) # re-exports - environ.setdefault(r"PATH_INFO", "") + environ.setdefault(r"PATH_INFO", b"") if environ.get(r"SERVER_SOFTWARE", r"").startswith(r"Microsoft-IIS"): # IIS includes script_name in PATH_INFO scriptname = environ[r"SCRIPT_NAME"] @@ -53,18 +53,18 @@ def write(data): if not headers_set: - raise AssertionError("write() before start_response()") + raise AssertionError(b"write() before start_response()") elif not headers_sent: # Before the first output, send the stored headers status, response_headers = headers_sent[:] = headers_set - out.write("Status: %s\r\n" % pycompat.bytesurl(status)) + out.write(b"Status: %s\r\n" % pycompat.bytesurl(status)) for hk, hv in response_headers: out.write( - "%s: %s\r\n" + b"%s: %s\r\n" % (pycompat.bytesurl(hk), pycompat.bytesurl(hv)) ) - out.write("\r\n") + out.write(b"\r\n") out.write(data) out.flush() @@ -78,7 +78,7 @@ finally: exc_info = None # avoid dangling circular ref elif headers_set: - raise AssertionError("Headers already set!") + raise AssertionError(b"Headers already set!") headers_set[:] = [status, response_headers] return write @@ -88,6 +88,6 @@ for chunk in content: write(chunk) if not headers_sent: - write("") # send headers now if body was empty + write(b"") # send headers now if body was empty finally: getattr(content, "close", lambda: None)() diff --git a/mercurial/hgweb/wsgiheaders.py b/mercurial/hgweb/wsgiheaders.py --- a/mercurial/hgweb/wsgiheaders.py +++ b/mercurial/hgweb/wsgiheaders.py @@ -22,10 +22,10 @@ """ if value is not None and len(value) > 0: if quote or tspecials.search(value): - value = value.replace("\\", "\\\\").replace('"', r"\"") - return '%s="%s"' % (param, value) + value = value.replace(b"\\", b"\\\\").replace(b'"', r"\"") + return b'%s="%s"' % (param, value) else: - return "%s=%s" % (param, value) + return b"%s=%s" % (param, value) else: return param @@ -36,7 +36,7 @@ def __init__(self, headers=None): headers = headers if headers is not None else [] if type(headers) is not list: - raise TypeError("Headers must be a list of name/value tuples") + raise TypeError(b"Headers must be a list of name/value tuples") self._headers = headers if __debug__: for k, v in headers: @@ -134,7 +134,9 @@ def __str__(self): """str() returns the formatted headers, complete with end line, suitable for direct HTTP transmission.""" - return "\r\n".join(["%s: %s" % kv for kv in self._headers] + ["", ""]) + return b"\r\n".join( + [b"%s: %s" % kv for kv in self._headers] + [b"", b""] + ) def __bytes__(self): return str(self).encode("iso-8859-1") @@ -174,10 +176,10 @@ for k, v in _params.items(): k = self._convert_string_type(k) if v is None: - parts.append(k.replace("_", "-")) + parts.append(k.replace(b"_", b"-")) else: v = self._convert_string_type(v) - parts.append(_formatparam(k.replace("_", "-"), v)) + parts.append(_formatparam(k.replace(b"_", b"-"), v)) self._headers.append( - (self._convert_string_type(_name), "; ".join(parts)) + (self._convert_string_type(_name), b"; ".join(parts)) ) diff --git a/mercurial/hook.py b/mercurial/hook.py --- a/mercurial/hook.py +++ b/mercurial/hook.py @@ -39,10 +39,10 @@ obj = funcname funcname = pycompat.sysbytes(obj.__module__ + r"." + obj.__name__) else: - d = funcname.rfind(".") + d = funcname.rfind(b".") if d == -1: raise error.HookLoadError( - _('%s hook is invalid: "%s" not in a module') + _(b'%s hook is invalid: "%s" not in a module') % (hname, funcname) ) modname = funcname[:d] @@ -66,77 +66,78 @@ if ui.tracebackflag: ui.warn( _( - "exception from first failed import " - "attempt:\n" + b"exception from first failed import " + b"attempt:\n" ) ) ui.traceback(e1) if ui.tracebackflag: ui.warn( _( - "exception from second failed import " - "attempt:\n" + b"exception from second failed import " + b"attempt:\n" ) ) ui.traceback(e2) if not ui.tracebackflag: tracebackhint = _( - "run with --traceback for stack trace" + b"run with --traceback for stack trace" ) else: tracebackhint = None raise error.HookLoadError( - _('%s hook is invalid: import of "%s" failed') + _(b'%s hook is invalid: import of "%s" failed') % (hname, modname), hint=tracebackhint, ) sys.path = oldpaths try: - for p in funcname.split(".")[1:]: + for p in funcname.split(b".")[1:]: obj = getattr(obj, p) except AttributeError: raise error.HookLoadError( - _('%s hook is invalid: "%s" is not defined') % (hname, funcname) + _(b'%s hook is invalid: "%s" is not defined') + % (hname, funcname) ) if not callable(obj): raise error.HookLoadError( - _('%s hook is invalid: "%s" is not callable') + _(b'%s hook is invalid: "%s" is not callable') % (hname, funcname) ) - ui.note(_("calling hook %s: %s\n") % (hname, funcname)) + ui.note(_(b"calling hook %s: %s\n") % (hname, funcname)) starttime = util.timer() try: r = obj(ui=ui, repo=repo, hooktype=htype, **pycompat.strkwargs(args)) except Exception as exc: if isinstance(exc, error.Abort): - ui.warn(_("error: %s hook failed: %s\n") % (hname, exc.args[0])) + ui.warn(_(b"error: %s hook failed: %s\n") % (hname, exc.args[0])) else: ui.warn( - _("error: %s hook raised an exception: " "%s\n") + _(b"error: %s hook raised an exception: " b"%s\n") % (hname, stringutil.forcebytestr(exc)) ) if throw: raise if not ui.tracebackflag: - ui.warn(_("(run with --traceback for stack trace)\n")) + ui.warn(_(b"(run with --traceback for stack trace)\n")) ui.traceback() return True, True finally: duration = util.timer() - starttime ui.log( - "pythonhook", - "pythonhook-%s: %s finished in %0.2f seconds\n", + b"pythonhook", + b"pythonhook-%s: %s finished in %0.2f seconds\n", htype, funcname, duration, ) if r: if throw: - raise error.HookAbort(_("%s hook failed") % hname) - ui.warn(_("warning: %s hook failed\n") % hname) + raise error.HookAbort(_(b"%s hook failed") % hname) + ui.warn(_(b"warning: %s hook failed\n") % hname) return r, False @@ -149,35 +150,35 @@ tr = repo.currenttransaction() repo.dirstate.write(tr) if tr and tr.writepending(): - env["HG_PENDING"] = repo.root - env["HG_HOOKTYPE"] = htype - env["HG_HOOKNAME"] = name + env[b"HG_PENDING"] = repo.root + env[b"HG_HOOKTYPE"] = htype + env[b"HG_HOOKNAME"] = name for k, v in args.iteritems(): if callable(v): v = v() if isinstance(v, (dict, list)): v = stringutil.pprint(v) - env["HG_" + k.upper()] = v + env[b"HG_" + k.upper()] = v - if ui.configbool("hooks", "tonative.%s" % name, False): + if ui.configbool(b"hooks", b"tonative.%s" % name, False): oldcmd = cmd cmd = procutil.shelltonative(cmd, env) if cmd != oldcmd: - ui.note(_('converting hook "%s" to native\n') % name) + ui.note(_(b'converting hook "%s" to native\n') % name) - ui.note(_("running hook %s: %s\n") % (name, cmd)) + ui.note(_(b"running hook %s: %s\n") % (name, cmd)) if repo: cwd = repo.root else: cwd = encoding.getcwd() - r = ui.system(cmd, environ=env, cwd=cwd, blockedtag="exthook-%s" % (name,)) + r = ui.system(cmd, environ=env, cwd=cwd, blockedtag=b"exthook-%s" % (name,)) duration = util.timer() - starttime ui.log( - "exthook", - "exthook-%s: %s finished in %0.2f seconds\n", + b"exthook", + b"exthook-%s: %s finished in %0.2f seconds\n", name, cmd, duration, @@ -185,8 +186,8 @@ if r: desc = procutil.explainexit(r) if throw: - raise error.HookAbort(_("%s hook %s") % (name, desc)) - ui.warn(_("warning: %s hook %s\n") % (name, desc)) + raise error.HookAbort(_(b"%s hook %s") % (name, desc)) + ui.warn(_(b"warning: %s hook %s\n") % (name, desc)) return r @@ -213,11 +214,11 @@ def _hookitems(ui, _untrusted=False): """return all hooks items ready to be sorted""" hooks = {} - for name, cmd in ui.configitems("hooks", untrusted=_untrusted): - if name.startswith("priority.") or name.startswith("tonative."): + for name, cmd in ui.configitems(b"hooks", untrusted=_untrusted): + if name.startswith(b"priority.") or name.startswith(b"tonative."): continue - priority = ui.configint("hooks", "priority.%s" % name, 0) + priority = ui.configint(b"hooks", b"priority.%s" % name, 0) hooks[name] = (-priority, len(hooks), name, cmd) return hooks @@ -235,7 +236,7 @@ if not ui.callhooks: return False for hname, cmd in _allhooks(ui): - if hname.split(".")[0] == htype and cmd: + if hname.split(b".")[0] == htype and cmd: return True return False @@ -246,7 +247,7 @@ hooks = [] for hname, cmd in _allhooks(ui): - if hname.split(".")[0] == htype and cmd: + if hname.split(b".")[0] == htype and cmd: hooks.append((hname, cmd)) res = runhooks(ui, repo, htype, hooks, throw=throw, **args) @@ -279,24 +280,24 @@ if cmd is _fromuntrusted: if throw: raise error.HookAbort( - _("untrusted hook %s not executed") % hname, - hint=_("see 'hg help config.trusted'"), + _(b"untrusted hook %s not executed") % hname, + hint=_(b"see 'hg help config.trusted'"), ) - ui.warn(_("warning: untrusted hook %s not executed\n") % hname) + ui.warn(_(b"warning: untrusted hook %s not executed\n") % hname) r = 1 raised = False elif callable(cmd): r, raised = pythonhook(ui, repo, htype, hname, cmd, args, throw) - elif cmd.startswith("python:"): - if cmd.count(":") >= 2: - path, cmd = cmd[7:].rsplit(":", 1) + elif cmd.startswith(b"python:"): + if cmd.count(b":") >= 2: + path, cmd = cmd[7:].rsplit(b":", 1) path = util.expandpath(path) if repo: path = os.path.join(repo.root, path) try: - mod = extensions.loadpath(path, "hghook.%s" % hname) + mod = extensions.loadpath(path, b"hghook.%s" % hname) except Exception: - ui.write(_("loading %s hook failed:\n") % hname) + ui.write(_(b"loading %s hook failed:\n") % hname) raise hookfn = getattr(mod, cmd) else: diff --git a/mercurial/httpconnection.py b/mercurial/httpconnection.py --- a/mercurial/httpconnection.py +++ b/mercurial/httpconnection.py @@ -44,7 +44,7 @@ # once whether authentication will be required, just lie to # the user and maybe the push succeeds suddenly at 50%. self._progress = ui.makeprogress( - _("sending"), unit=_("kb"), total=(self.length // 1024 * 2) + _(b"sending"), unit=_(b"kb"), total=(self.length // 1024 * 2) ) def read(self, *args, **kwargs): @@ -68,30 +68,30 @@ uri = pycompat.bytesurl(uri) # Read configuration groups = {} - for key, val in ui.configitems("auth"): - if key in ("cookiefile",): + for key, val in ui.configitems(b"auth"): + if key in (b"cookiefile",): continue - if "." not in key: - ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) + if b"." not in key: + ui.warn(_(b"ignoring invalid [auth] key '%s'\n") % key) continue - group, setting = key.rsplit(".", 1) + group, setting = key.rsplit(b".", 1) gdict = groups.setdefault(group, {}) - if setting in ("username", "cert", "key"): + if setting in (b"username", b"cert", b"key"): val = util.expandpath(val) gdict[setting] = val # Find the best match - scheme, hostpath = uri.split("://", 1) + scheme, hostpath = uri.split(b"://", 1) bestuser = None bestlen = 0 bestauth = None for group, auth in groups.iteritems(): - if user and user != auth.get("username", user): + if user and user != auth.get(b"username", user): # If a username was set in the URI, the entry username # must either match it or be unset continue - prefix = auth.get("prefix") + prefix = auth.get(b"prefix") if not prefix: continue @@ -106,26 +106,26 @@ prefixurl.user = None prefix = bytes(prefixurl) - p = prefix.split("://", 1) + p = prefix.split(b"://", 1) if len(p) > 1: schemes, prefix = [p[0]], p[1] else: - schemes = (auth.get("schemes") or "https").split() + schemes = (auth.get(b"schemes") or b"https").split() if ( - (prefix == "*" or hostpath.startswith(prefix)) + (prefix == b"*" or hostpath.startswith(prefix)) and ( len(prefix) > bestlen or ( len(prefix) == bestlen and not bestuser - and "username" in auth + and b"username" in auth ) ) and scheme in schemes ): bestlen = len(prefix) bestauth = group, auth - bestuser = auth.get("username") + bestuser = auth.get(b"username") if user and not bestuser: - auth["username"] = user + auth[b"username"] = user return bestauth diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -62,7 +62,7 @@ # and using an r-string to make it portable between Python 2 and 3 # doesn't work because then the \r is a literal backslash-r # instead of a carriage return. - valuelen = limit - len(fmt % r"000") - len(": \r\n") + valuelen = limit - len(fmt % r"000") - len(b": \r\n") result = [] n = 0 @@ -76,10 +76,10 @@ class _multifile(object): def __init__(self, *fileobjs): for f in fileobjs: - if not util.safehasattr(f, "length"): + if not util.safehasattr(f, b"length"): raise ValueError( - "_multifile only supports file objects that " - "have a length but this one does not:", + b"_multifile only supports file objects that " + b"have a length but this one does not:", type(f), f, ) @@ -92,7 +92,7 @@ def read(self, amt=None): if amt <= 0: - return "".join(f.read() for f in self._fileobjs) + return b"".join(f.read() for f in self._fileobjs) parts = [] while amt and self._index < len(self._fileobjs): parts.append(self._fileobjs[self._index].read(amt)) @@ -100,18 +100,18 @@ if got < amt: self._index += 1 amt -= got - return "".join(parts) + return b"".join(parts) def seek(self, offset, whence=os.SEEK_SET): if whence != os.SEEK_SET: raise NotImplementedError( - "_multifile does not support anything other" - " than os.SEEK_SET for whence on seek()" + b"_multifile does not support anything other" + b" than os.SEEK_SET for whence on seek()" ) if offset != 0: raise NotImplementedError( - "_multifile only supports seeking to start, but that " - "could be fixed if you need it" + b"_multifile only supports seeking to start, but that " + b"could be fixed if you need it" ) for f in self._fileobjs: f.seek(0) @@ -131,18 +131,18 @@ ``cmd``, ``args``, and ``data`` define the command, its arguments, and raw data to pass to it. """ - if cmd == "pushkey": - args["data"] = "" - data = args.pop("data", None) - headers = args.pop("headers", {}) + if cmd == b"pushkey": + args[b"data"] = b"" + data = args.pop(b"data", None) + headers = args.pop(b"headers", {}) - ui.debug("sending %s command\n" % cmd) - q = [("cmd", cmd)] + ui.debug(b"sending %s command\n" % cmd) + q = [(b"cmd", cmd)] headersize = 0 # Important: don't use self.capable() here or else you end up # with infinite recursion when trying to look up capabilities # for the first time. - postargsok = caps is not None and "httppostargs" in caps + postargsok = caps is not None and b"httppostargs" in caps # Send arguments via POST. if postargsok and args: @@ -162,27 +162,27 @@ # Calling self.capable() can infinite loop if we are calling # "capabilities". But that command should never accept wire # protocol arguments. So this should never happen. - assert cmd != "capabilities" - httpheader = capablefn("httpheader") + assert cmd != b"capabilities" + httpheader = capablefn(b"httpheader") if httpheader: - headersize = int(httpheader.split(",", 1)[0]) + headersize = int(httpheader.split(b",", 1)[0]) # Send arguments via HTTP headers. if headersize > 0: # The headers can typically carry more data than the URL. encargs = urlreq.urlencode(sorted(args.items())) for header, value in encodevalueinheaders( - encargs, "X-HgArg", headersize + encargs, b"X-HgArg", headersize ): headers[header] = value # Send arguments via query string (Mercurial <1.9). else: q += sorted(args.items()) - qs = "?%s" % urlreq.urlencode(q) - cu = "%s%s" % (repobaseurl, qs) + qs = b"?%s" % urlreq.urlencode(q) + cu = b"%s%s" % (repobaseurl, qs) size = 0 - if util.safehasattr(data, "length"): + if util.safehasattr(data, b"length"): size = data.length elif data is not None: size = len(data) @@ -198,17 +198,17 @@ mediatypes = set() if caps is not None: - mt = capablefn("httpmediatype") + mt = capablefn(b"httpmediatype") if mt: - protoparams.add("0.1") - mediatypes = set(mt.split(",")) + protoparams.add(b"0.1") + mediatypes = set(mt.split(b",")) - protoparams.add("partial-pull") + protoparams.add(b"partial-pull") - if "0.2tx" in mediatypes: - protoparams.add("0.2") + if b"0.2tx" in mediatypes: + protoparams.add(b"0.2") - if "0.2tx" in mediatypes and capablefn("compression"): + if b"0.2tx" in mediatypes and capablefn(b"compression"): # We /could/ compare supported compression formats and prune # non-mutually supported or error if nothing is mutually supported. # For now, send the full list to the server and have it error. @@ -216,11 +216,11 @@ e.wireprotosupport().name for e in util.compengines.supportedwireengines(util.CLIENTROLE) ] - protoparams.add("comp=%s" % ",".join(comps)) + protoparams.add(b"comp=%s" % b",".join(comps)) if protoparams: protoheaders = encodevalueinheaders( - " ".join(sorted(protoparams)), "X-HgProto", headersize or 1024 + b" ".join(sorted(protoparams)), b"X-HgProto", headersize or 1024 ) for header, value in protoheaders: headers[header] = value @@ -236,7 +236,7 @@ req = requestbuilder(pycompat.strurl(cu), data, headers) if data is not None: - ui.debug("sending %d bytes\n" % size) + ui.debug(b"sending %d bytes\n" % size) req.add_unredirected_header(r"Content-Length", r"%d" % size) return req, cu, qs @@ -257,11 +257,11 @@ Returns the response object. """ dbg = ui.debug - if ui.debugflag and ui.configbool("devel", "debug.peer-request"): - line = "devel-peer-request: %s\n" + if ui.debugflag and ui.configbool(b"devel", b"debug.peer-request"): + line = b"devel-peer-request: %s\n" dbg( line - % "%s %s" + % b"%s %s" % ( pycompat.bytesurl(req.get_method()), pycompat.bytesurl(req.get_full_url()), @@ -272,17 +272,17 @@ for header, value in sorted(req.header_items()): header = pycompat.bytesurl(header) value = pycompat.bytesurl(value) - if header.startswith("X-hgarg-"): + if header.startswith(b"X-hgarg-"): if hgargssize is None: hgargssize = 0 hgargssize += len(value) else: - dbg(line % " %s %s" % (header, value)) + dbg(line % b" %s %s" % (header, value)) if hgargssize is not None: dbg( line - % " %d bytes of commands arguments in headers" + % b" %d bytes of commands arguments in headers" % hgargssize ) data = _reqdata(req) @@ -290,7 +290,7 @@ length = getattr(data, "length", None) if length is None: length = len(data) - dbg(line % " %d bytes of data" % length) + dbg(line % b" %d bytes of data" % length) start = util.timer() @@ -299,20 +299,21 @@ res = opener.open(req) except urlerr.httperror as inst: if inst.code == 401: - raise error.Abort(_("authorization failed")) + raise error.Abort(_(b"authorization failed")) raise except httplib.HTTPException as inst: ui.debug( - "http error requesting %s\n" % util.hidepassword(req.get_full_url()) + b"http error requesting %s\n" + % util.hidepassword(req.get_full_url()) ) ui.traceback() raise IOError(None, inst) finally: - if ui.debugflag and ui.configbool("devel", "debug.peer-request"): + if ui.debugflag and ui.configbool(b"devel", b"debug.peer-request"): code = res.code if res else -1 dbg( line - % " finished in %.4f seconds (%d)" + % b" finished in %.4f seconds (%d)" % (util.timer() - start, code) ) @@ -340,10 +341,10 @@ else: qsdropped = True - if baseurl.rstrip("/") != respurl.rstrip("/"): + if baseurl.rstrip(b"/") != respurl.rstrip(b"/"): redirected = True if not ui.quiet: - ui.warn(_("real URL is %s\n") % respurl) + ui.warn(_(b"real URL is %s\n") % respurl) try: proto = pycompat.bytesurl(resp.getheader(r"content-type", r"")) @@ -351,17 +352,17 @@ proto = pycompat.bytesurl(resp.headers.get(r"content-type", r"")) safeurl = util.hidepassword(baseurl) - if proto.startswith("application/hg-error"): + if proto.startswith(b"application/hg-error"): raise error.OutOfBandError(resp.read()) # Pre 1.0 versions of Mercurial used text/plain and # application/hg-changegroup. We don't support such old servers. - if not proto.startswith("application/mercurial-"): - ui.debug("requested URL: '%s'\n" % util.hidepassword(requrl)) + if not proto.startswith(b"application/mercurial-"): + ui.debug(b"requested URL: '%s'\n" % util.hidepassword(requrl)) msg = _( - "'%s' does not appear to be an hg repository:\n" - "---%%<--- (%s)\n%s\n---%%<---\n" - ) % (safeurl, proto or "no content-type", resp.read(1024)) + b"'%s' does not appear to be an hg repository:\n" + b"---%%<--- (%s)\n%s\n---%%<---\n" + ) % (safeurl, proto or b"no content-type", resp.read(1024)) # Some servers may strip the query string from the redirect. We # raise a special error type so callers can react to this specially. @@ -371,23 +372,23 @@ raise error.RepoError(msg) try: - subtype = proto.split("-", 1)[1] + subtype = proto.split(b"-", 1)[1] # Unless we end up supporting CBOR in the legacy wire protocol, # this should ONLY be encountered for the initial capabilities # request during handshake. - if subtype == "cbor": + if subtype == b"cbor": if allowcbor: return respurl, proto, resp else: raise error.RepoError( - _("unexpected CBOR response from " "server") + _(b"unexpected CBOR response from " b"server") ) - version_info = tuple([int(n) for n in subtype.split(".")]) + version_info = tuple([int(n) for n in subtype.split(b".")]) except ValueError: raise error.RepoError( - _("'%s' sent a broken Content-Type " "header (%s)") + _(b"'%s' sent a broken Content-Type " b"header (%s)") % (safeurl, proto) ) @@ -395,19 +396,19 @@ # generators. if version_info == (0, 1): if compressible: - resp = util.compengines["zlib"].decompressorreader(resp) + resp = util.compengines[b"zlib"].decompressorreader(resp) elif version_info == (0, 2): # application/mercurial-0.2 always identifies the compression # engine in the payload header. - elen = struct.unpack("B", util.readexactly(resp, 1))[0] + elen = struct.unpack(b"B", util.readexactly(resp, 1))[0] ename = util.readexactly(resp, elen) engine = util.compengines.forwiretype(ename) resp = engine.decompressorreader(resp) else: raise error.RepoError( - _("'%s' uses newer protocol %s") % (safeurl, subtype) + _(b"'%s' uses newer protocol %s") % (safeurl, subtype) ) return respurl, proto, resp @@ -419,7 +420,7 @@ self._path = path self._url = url self._caps = caps - self.limitedarguments = caps is not None and "httppostargs" not in caps + self.limitedarguments = caps is not None and b"httppostargs" not in caps self._urlopener = opener self._requestbuilder = requestbuilder @@ -453,8 +454,8 @@ return self.ui.note( _( - "(sent %d HTTP requests and %d bytes; " - "received %d bytes in responses)\n" + b"(sent %d HTTP requests and %d bytes; " + b"received %d bytes in responses)\n" ) % (reqs, sent, recv) ) @@ -501,28 +502,28 @@ # have to stream bundle to a temp file because we do not have # http 1.1 chunked transfer. - types = self.capable("unbundle") + types = self.capable(b"unbundle") try: - types = types.split(",") + types = types.split(b",") except AttributeError: # servers older than d1b16a746db6 will send 'unbundle' as a # boolean capability. They only support headerless/uncompressed # bundles. - types = [""] + types = [b""] for x in types: if x in bundle2.bundletypes: type = x break tempname = bundle2.writebundle(self.ui, cg, None, type) - fp = httpconnection.httpsendfile(self.ui, tempname, "rb") + fp = httpconnection.httpsendfile(self.ui, tempname, b"rb") headers = {r"Content-Type": r"application/mercurial-0.1"} try: r = self._call(cmd, data=fp, headers=headers, **args) - vals = r.split("\n", 1) + vals = r.split(b"\n", 1) if len(vals) < 2: - raise error.ResponseError(_("unexpected response:"), r) + raise error.ResponseError(_(b"unexpected response:"), r) return vals except urlerr.httperror: # Catch and re-raise these so we don't try and treat them @@ -531,7 +532,7 @@ raise except socket.error as err: if err.args[0] in (errno.ECONNRESET, errno.EPIPE): - raise error.Abort(_("push failed: %s") % err.args[1]) + raise error.Abort(_(b"push failed: %s") % err.args[1]) raise error.Abort(err.args[1]) finally: fp.close() @@ -541,14 +542,14 @@ filename = None try: # dump bundle to disk - fd, filename = pycompat.mkstemp(prefix="hg-bundle-", suffix=".hg") + fd, filename = pycompat.mkstemp(prefix=b"hg-bundle-", suffix=b".hg") with os.fdopen(fd, r"wb") as fh: d = fp.read(4096) while d: fh.write(d) d = fp.read(4096) # start http push - with httpconnection.httpsendfile(self.ui, filename, "rb") as fp_: + with httpconnection.httpsendfile(self.ui, filename, b"rb") as fp_: headers = {r"Content-Type": r"application/mercurial-0.1"} return self._callstream(cmd, data=fp_, headers=headers, **args) finally: @@ -598,17 +599,17 @@ ui, reactor, opener=opener, requestbuilder=requestbuilder ) - url = "%s/%s" % (apiurl, permission) + url = b"%s/%s" % (apiurl, permission) if len(requests) > 1: - url += "/multirequest" + url += b"/multirequest" else: - url += "/%s" % requests[0][0] + url += b"/%s" % requests[0][0] - ui.debug("sending %d commands\n" % len(requests)) + ui.debug(b"sending %d commands\n" % len(requests)) for command, args, f in requests: ui.debug( - "sending command %s: %s\n" + b"sending command %s: %s\n" % (command, stringutil.pprint(args, indent=2)) ) assert not list( @@ -631,7 +632,7 @@ res = opener.open(req) except urlerr.httperror as e: if e.code == 401: - raise error.Abort(_("authorization failed")) + raise error.Abort(_(b"authorization failed")) raise except httplib.HTTPException as e: @@ -683,32 +684,32 @@ def callcommand(self, command, args): if self._sent: raise error.ProgrammingError( - "callcommand() cannot be used after " "commands are sent" + b"callcommand() cannot be used after " b"commands are sent" ) if self._closed: raise error.ProgrammingError( - "callcommand() cannot be used after " "close()" + b"callcommand() cannot be used after " b"close()" ) # The service advertises which commands are available. So if we attempt # to call an unknown command or pass an unknown argument, we can screen # for this. - if command not in self._descriptor["commands"]: + if command not in self._descriptor[b"commands"]: raise error.ProgrammingError( - "wire protocol command %s is not available" % command + b"wire protocol command %s is not available" % command ) - cmdinfo = self._descriptor["commands"][command] - unknownargs = set(args.keys()) - set(cmdinfo.get("args", {})) + cmdinfo = self._descriptor[b"commands"][command] + unknownargs = set(args.keys()) - set(cmdinfo.get(b"args", {})) if unknownargs: raise error.ProgrammingError( - "wire protocol command %s does not accept argument: %s" - % (command, ", ".join(sorted(unknownargs))) + b"wire protocol command %s does not accept argument: %s" + % (command, b", ".join(sorted(unknownargs))) ) - self._neededpermissions |= set(cmdinfo["permissions"]) + self._neededpermissions |= set(cmdinfo[b"permissions"]) # TODO we /could/ also validate types here, since the API descriptor # includes types... @@ -756,16 +757,16 @@ permissions = set(self._neededpermissions) - if "push" in permissions and "pull" in permissions: - permissions.remove("pull") + if b"push" in permissions and b"pull" in permissions: + permissions.remove(b"pull") if len(permissions) > 1: raise error.RepoError( - _("cannot make request requiring multiple " "permissions: %s") - % _(", ").join(sorted(permissions)) + _(b"cannot make request requiring multiple " b"permissions: %s") + % _(b", ").join(sorted(permissions)) ) - permission = {"push": "rw", "pull": "ro",}[permissions.pop()] + permission = {b"push": b"rw", b"pull": b"ro",}[permissions.pop()] handler, resp = sendv2request( self._ui, @@ -809,7 +810,7 @@ for f in self._futures: if not f.done(): f.set_exception( - error.ResponseError(_("unfulfilled command response")) + error.ResponseError(_(b"unfulfilled command response")) ) self._futures = None @@ -832,12 +833,12 @@ self.ui = ui self.apidescriptor = apidescriptor - if repourl.endswith("/"): + if repourl.endswith(b"/"): repourl = repourl[:-1] self._url = repourl self._apipath = apipath - self._apiurl = "%s/%s" % (repourl, apipath) + self._apiurl = b"%s/%s" % (repourl, apipath) self._opener = opener self._requestbuilder = requestbuilder @@ -861,8 +862,8 @@ def close(self): self.ui.note( _( - "(sent %d HTTP requests and %d bytes; " - "received %d bytes in responses)\n" + b"(sent %d HTTP requests and %d bytes; " + b"received %d bytes in responses)\n" ) % ( self._opener.requestscount, @@ -881,16 +882,22 @@ # version 2 of that command works differently. # Maps to commands that are available. - if name in ("branchmap", "getbundle", "known", "lookup", "pushkey"): + if name in ( + b"branchmap", + b"getbundle", + b"known", + b"lookup", + b"pushkey", + ): return True # Other concepts. - if name in "bundle2": + if name in b"bundle2": return True # Alias command-* to presence of command of that name. - if name.startswith("command-"): - return name[len("command-") :] in self.apidescriptor["commands"] + if name.startswith(b"command-"): + return name[len(b"command-") :] in self.apidescriptor[b"commands"] return False @@ -900,8 +907,8 @@ raise error.CapabilityError( _( - "cannot %s; client or remote repository does not support the " - "'%s' capability" + b"cannot %s; client or remote repository does not support the " + b"'%s' capability" ) % (purpose, name) ) @@ -935,7 +942,7 @@ # Integer priority for the service. If we could choose from multiple # services, we choose the one with the highest priority. API_PEERS = { - wireprototypes.HTTP_WIREPROTO_V2: {"init": httpv2peer, "priority": 50,}, + wireprototypes.HTTP_WIREPROTO_V2: {b"init": httpv2peer, b"priority": 50,}, } @@ -945,7 +952,7 @@ caps = None def capable(x): - raise error.ProgrammingError("should not be called") + raise error.ProgrammingError(b"should not be called") args = {} @@ -954,17 +961,17 @@ # X-HgProto-* header advertising which serializing formats it supports. # We only support the HTTP version 2 transport and CBOR responses for # now. - advertisev2 = ui.configbool("experimental", "httppeer.advertise-v2") + advertisev2 = ui.configbool(b"experimental", b"httppeer.advertise-v2") if advertisev2: - args["headers"] = { + args[b"headers"] = { r"X-HgProto-1": r"cbor", } - args["headers"].update( + args[b"headers"].update( encodevalueinheaders( - " ".join(sorted(API_PEERS)), - "X-HgUpgrade", + b" ".join(sorted(API_PEERS)), + b"X-HgUpgrade", # We don't know the header limit this early. # So make it small. 1024, @@ -972,7 +979,7 @@ ) req, requrl, qs = makev1commandrequest( - ui, requestbuilder, caps, capable, url, "capabilities", args + ui, requestbuilder, caps, capable, url, b"capabilities", args ) resp = sendrequest(ui, opener, req) @@ -994,7 +1001,7 @@ ) except RedirectedRepoError as e: req, requrl, qs = makev1commandrequest( - ui, requestbuilder, caps, capable, e.respurl, "capabilities", args + ui, requestbuilder, caps, capable, e.respurl, b"capabilities", args ) resp = sendrequest(ui, opener, req) respurl, ct, resp = parsev1commandresponse( @@ -1006,32 +1013,32 @@ finally: resp.close() - if not ct.startswith("application/mercurial-"): - raise error.ProgrammingError("unexpected content-type: %s" % ct) + if not ct.startswith(b"application/mercurial-"): + raise error.ProgrammingError(b"unexpected content-type: %s" % ct) if advertisev2: - if ct == "application/mercurial-cbor": + if ct == b"application/mercurial-cbor": try: info = cborutil.decodeall(rawdata)[0] except cborutil.CBORDecodeError: raise error.Abort( - _("error decoding CBOR from remote server"), + _(b"error decoding CBOR from remote server"), hint=_( - "try again and consider contacting " - "the server operator" + b"try again and consider contacting " + b"the server operator" ), ) # We got a legacy response. That's fine. - elif ct in ("application/mercurial-0.1", "application/mercurial-0.2"): - info = {"v1capabilities": set(rawdata.split())} + elif ct in (b"application/mercurial-0.1", b"application/mercurial-0.2"): + info = {b"v1capabilities": set(rawdata.split())} else: raise error.RepoError( - _("unexpected response type from server: %s") % ct + _(b"unexpected response type from server: %s") % ct ) else: - info = {"v1capabilities": set(rawdata.split())} + info = {b"v1capabilities": set(rawdata.split())} return respurl, info @@ -1048,12 +1055,12 @@ u = util.url(path) if u.query or u.fragment: raise error.Abort( - _('unsupported URL component: "%s"') % (u.query or u.fragment) + _(b'unsupported URL component: "%s"') % (u.query or u.fragment) ) # urllib cannot handle URLs with embedded user or passwd. url, authinfo = u.authinfo() - ui.debug("using %s\n" % url) + ui.debug(b"using %s\n" % url) opener = opener or urlmod.opener(ui, authinfo) @@ -1068,32 +1075,32 @@ # capabilities, we could filter out services not meeting the # requirements. Possibly by consulting the interfaces defined by the # peer type. - apipeerchoices = set(info.get("apis", {}).keys()) & set(API_PEERS.keys()) + apipeerchoices = set(info.get(b"apis", {}).keys()) & set(API_PEERS.keys()) preferredchoices = sorted( - apipeerchoices, key=lambda x: API_PEERS[x]["priority"], reverse=True + apipeerchoices, key=lambda x: API_PEERS[x][b"priority"], reverse=True ) for service in preferredchoices: - apipath = "%s/%s" % (info["apibase"].rstrip("/"), service) + apipath = b"%s/%s" % (info[b"apibase"].rstrip(b"/"), service) - return API_PEERS[service]["init"]( - ui, respurl, apipath, opener, requestbuilder, info["apis"][service] + return API_PEERS[service][b"init"]( + ui, respurl, apipath, opener, requestbuilder, info[b"apis"][service] ) # Failed to construct an API peer. Fall back to legacy. return httppeer( - ui, path, respurl, opener, requestbuilder, info["v1capabilities"] + ui, path, respurl, opener, requestbuilder, info[b"v1capabilities"] ) def instance(ui, path, create, intents=None, createopts=None): if create: - raise error.Abort(_("cannot create new http repository")) + raise error.Abort(_(b"cannot create new http repository")) try: - if path.startswith("https:") and not urlmod.has_https: + if path.startswith(b"https:") and not urlmod.has_https: raise error.Abort( - _("Python support for SSL and HTTPS " "is not installed") + _(b"Python support for SSL and HTTPS " b"is not installed") ) inst = makepeer(ui, path) @@ -1101,8 +1108,8 @@ return inst except error.RepoError as httpexception: try: - r = statichttprepo.instance(ui, "static-" + path, create) - ui.note(_("(falling back to static-http)\n")) + r = statichttprepo.instance(ui, b"static-" + path, create) + ui.note(_(b"(falling back to static-http)\n")) return r except error.RepoError: raise httpexception # use the original http RepoError instead diff --git a/mercurial/i18n.py b/mercurial/i18n.py --- a/mercurial/i18n.py +++ b/mercurial/i18n.py @@ -26,10 +26,10 @@ _languages = None if ( pycompat.iswindows - and "LANGUAGE" not in encoding.environ - and "LC_ALL" not in encoding.environ - and "LC_MESSAGES" not in encoding.environ - and "LANG" not in encoding.environ + and b"LANGUAGE" not in encoding.environ + and b"LC_ALL" not in encoding.environ + and b"LC_MESSAGES" not in encoding.environ + and b"LANG" not in encoding.environ ): # Try to detect UI language by "User Interface Language Management" API # if no locale variables are set. Note that locale.getdefaultlocale() @@ -83,7 +83,7 @@ else: # should be ascii, but we have unicode docstrings in test, which # are converted to utf-8 bytes on Python 3. - paragraphs = [p.decode("utf-8") for p in message.split("\n\n")] + paragraphs = [p.decode("utf-8") for p in message.split(b"\n\n")] # Be careful not to translate the empty string -- it holds the # meta data of the .po file. u = u"\n\n".join([p and _ugettext(p) or u"" for p in paragraphs]) @@ -103,12 +103,12 @@ def _plain(): if ( - "HGPLAIN" not in encoding.environ - and "HGPLAINEXCEPT" not in encoding.environ + b"HGPLAIN" not in encoding.environ + and b"HGPLAINEXCEPT" not in encoding.environ ): return False - exceptions = encoding.environ.get("HGPLAINEXCEPT", "").strip().split(",") - return "i18n" not in exceptions + exceptions = encoding.environ.get(b"HGPLAINEXCEPT", b"").strip().split(b",") + return b"i18n" not in exceptions if _plain(): diff --git a/mercurial/interfaces/dirstate.py b/mercurial/interfaces/dirstate.py --- a/mercurial/interfaces/dirstate.py +++ b/mercurial/interfaces/dirstate.py @@ -24,7 +24,7 @@ """Return a list of files containing patterns to ignore.""" def _ignorefileandline(f): - "Given a file `f`, return the ignore file and line that ignores it." + b"Given a file `f`, return the ignore file and line that ignores it." _checklink = interfaceutil.Attribute("""Callable for checking symlinks.""") _checkexec = interfaceutil.Attribute("""Callable for checking exec bits.""") diff --git a/mercurial/interfaces/repository.py b/mercurial/interfaces/repository.py --- a/mercurial/interfaces/repository.py +++ b/mercurial/interfaces/repository.py @@ -13,7 +13,7 @@ # When narrowing is finalized and no longer subject to format changes, # we should move this to just "narrow" or similar. -NARROW_REQUIREMENT = "narrowhg-experimental" +NARROW_REQUIREMENT = b"narrowhg-experimental" # Local repository feature string. @@ -352,7 +352,7 @@ if name in caps: return True - name = "%s=" % name + name = b"%s=" % name for cap in caps: if cap.startswith(name): return cap[len(name) :] @@ -365,8 +365,8 @@ raise error.CapabilityError( _( - "cannot %s; remote repository does not support the " - "'%s' capability" + b"cannot %s; remote repository does not support the " + b"'%s' capability" ) % (purpose, name) ) @@ -1025,7 +1025,7 @@ def get(path, default=None): """Obtain the node value for a path or a default value if missing.""" - def flags(path, default=""): + def flags(path, default=b""): """Return the flags value for a path or a default value if missing.""" def copy(): @@ -1746,7 +1746,7 @@ pass def commit( - text="", + text=b"", user=None, date=None, match=None, @@ -1766,7 +1766,7 @@ """Inform the repository that nodes have been destroyed.""" def status( - node1=".", + node1=b".", node2=None, match=None, ignored=False, diff --git a/mercurial/interfaces/util.py b/mercurial/interfaces/util.py --- a/mercurial/interfaces/util.py +++ b/mercurial/interfaces/util.py @@ -13,7 +13,7 @@ from .. import encoding -if encoding.environ.get("HGREALINTERFACES"): +if encoding.environ.get(b"HGREALINTERFACES"): from ..thirdparty.zope import interface as zi Attribute = zi.Attribute @@ -22,7 +22,7 @@ else: class Attribute(object): - def __init__(self, __name__, __doc__=""): + def __init__(self, __name__, __doc__=b""): pass class Interface(object): diff --git a/mercurial/keepalive.py b/mercurial/keepalive.py --- a/mercurial/keepalive.py +++ b/mercurial/keepalive.py @@ -215,7 +215,7 @@ def do_open(self, http_class, req): host = urllibcompat.gethost(req) if not host: - raise urlerr.urlerror("no host given") + raise urlerr.urlerror(b"no host given") try: h = self._cm.get_ready_conn(host) @@ -237,7 +237,7 @@ h = http_class(host, timeout=self._timeout) if DEBUG: DEBUG.info( - "creating new connection to %s (%d)", host, id(h) + b"creating new connection to %s (%d)", host, id(h) ) self._cm.add(host, h, False) self._start_transaction(h, req) @@ -246,7 +246,7 @@ # to make the error message slightly more useful. except httplib.BadStatusLine as err: raise urlerr.urlerror( - _("bad HTTP status line: %s") % pycompat.sysbytes(err.line) + _(b"bad HTTP status line: %s") % pycompat.sysbytes(err.line) ) except (socket.error, httplib.HTTPException) as err: raise urlerr.urlerror(err) @@ -258,7 +258,7 @@ self._cm.remove(h) if DEBUG: - DEBUG.info("STATUS: %s, %s", r.status, r.reason) + DEBUG.info(b"STATUS: %s, %s", r.status, r.reason) r._handler = self r._host = host r._url = req.get_full_url() @@ -295,7 +295,7 @@ # a DIFFERENT exception if DEBUG: DEBUG.error( - "unexpected exception - closing " "connection to %s (%d)", + b"unexpected exception - closing " b"connection to %s (%d)", host, id(h), ) @@ -310,12 +310,12 @@ # last used the connection. if DEBUG: DEBUG.info( - "failed to re-use connection to %s (%d)", host, id(h) + b"failed to re-use connection to %s (%d)", host, id(h) ) r = None else: if DEBUG: - DEBUG.info("re-using connection to %s (%d)", host, id(h)) + DEBUG.info(b"re-using connection to %s (%d)", host, id(h)) return r @@ -408,7 +408,7 @@ self.fileno = sock.fileno self.code = None self.receivedbytescount = 0 - self._rbuf = "" + self._rbuf = b"" self._rbufsize = 8096 self._handler = None # inserted by the handler later self._host = None # (same) @@ -460,7 +460,7 @@ # implemented using readinto(), which can duplicate self._rbuf # if it's not empty. s = self._rbuf - self._rbuf = "" + self._rbuf = b"" data = self._raw_read(amt) self.receivedbytescount += len(data) @@ -484,7 +484,7 @@ while True: if chunk_left is None: line = self.fp.readline() - i = line.find(";") + i = line.find(b";") if i >= 0: line = line[:i] # strip chunk-extensions try: @@ -493,7 +493,7 @@ # close the connection as protocol synchronization is # probably lost self.close() - raise httplib.IncompleteRead("".join(parts)) + raise httplib.IncompleteRead(b"".join(parts)) if chunk_left == 0: break if amt is None: @@ -501,12 +501,12 @@ elif amt < chunk_left: parts.append(self._safe_read(amt)) self.chunk_left = chunk_left - amt - return "".join(parts) + return b"".join(parts) elif amt == chunk_left: parts.append(self._safe_read(amt)) self._safe_read(2) # toss the CRLF at the end of the chunk self.chunk_left = None - return "".join(parts) + return b"".join(parts) else: parts.append(self._safe_read(chunk_left)) amt -= chunk_left @@ -523,17 +523,17 @@ # a vanishingly small number of sites EOF without # sending the trailer break - if line == "\r\n": + if line == b"\r\n": break # we read everything; close the "file" self.close() - return "".join(parts) + return b"".join(parts) def readline(self): # Fast path for a line is already available in read buffer. - i = self._rbuf.find("\n") + i = self._rbuf.find(b"\n") if i >= 0: i += 1 line = self._rbuf[:i] @@ -557,7 +557,7 @@ pass chunks.append(new) - i = new.find("\n") + i = new.find(b"\n") if i >= 0: break @@ -565,13 +565,13 @@ # EOF if i == -1: - self._rbuf = "" - return "".join(chunks) + self._rbuf = b"" + return b"".join(chunks) i += 1 self._rbuf = chunks[-1][i:] chunks[-1] = chunks[-1][:i] - return "".join(chunks) + return b"".join(chunks) def readlines(self, sizehint=0): total = 0 @@ -611,7 +611,7 @@ dest[0:have] = self._rbuf got += len(self._rbuf) - self._rbuf = "" + self._rbuf = b"" return got @@ -642,13 +642,13 @@ # NOTE: we DO propagate the error, though, because we cannot simply # ignore the error... the caller will know if they can retry. if self.debuglevel > 0: - print("send:", repr(str)) + print(b"send:", repr(str)) try: blocksize = 8192 read = getattr(str, "read", None) if read is not None: if self.debuglevel > 0: - print("sending a read()able") + print(b"sending a read()able") data = read(blocksize) while data: self.sock.sendall(data) @@ -710,7 +710,7 @@ def continuity(url): md5 = hashlib.md5 - format = "%25s: %s" + format = b"%25s: %s" # first fetch the file with the normal http handler opener = urlreq.buildopener() @@ -719,7 +719,7 @@ foo = fo.read() fo.close() m = md5(foo) - print(format % ("normal urllib", node.hex(m.digest()))) + print(format % (b"normal urllib", node.hex(m.digest()))) # now install the keepalive handler and try again opener = urlreq.buildopener(HTTPHandler()) @@ -729,10 +729,10 @@ foo = fo.read() fo.close() m = md5(foo) - print(format % ("keepalive read", node.hex(m.digest()))) + print(format % (b"keepalive read", node.hex(m.digest()))) fo = urlreq.urlopen(url) - foo = "" + foo = b"" while True: f = fo.readline() if f: @@ -741,26 +741,26 @@ break fo.close() m = md5(foo) - print(format % ("keepalive readline", node.hex(m.digest()))) + print(format % (b"keepalive readline", node.hex(m.digest()))) def comp(N, url): - print(" making %i connections to:\n %s" % (N, url)) + print(b" making %i connections to:\n %s" % (N, url)) - procutil.stdout.write(" first using the normal urllib handlers") + procutil.stdout.write(b" first using the normal urllib handlers") # first use normal opener opener = urlreq.buildopener() urlreq.installopener(opener) t1 = fetch(N, url) - print(" TIME: %.3f s" % t1) + print(b" TIME: %.3f s" % t1) - procutil.stdout.write(" now using the keepalive handler ") + procutil.stdout.write(b" now using the keepalive handler ") # now install the keepalive handler and try again opener = urlreq.buildopener(HTTPHandler()) urlreq.installopener(opener) t2 = fetch(N, url) - print(" TIME: %.3f s" % t2) - print(" improvement factor: %.2f" % (t1 / t2)) + print(b" TIME: %.3f s" % t2) + print(b" improvement factor: %.2f" % (t1 / t2)) def fetch(N, url, delay=0): @@ -781,7 +781,7 @@ for i in lens[1:]: j = j + 1 if not i == lens[0]: - print("WARNING: inconsistent length on read %i: %i" % (j, i)) + print(b"WARNING: inconsistent length on read %i: %i" % (j, i)) return diff @@ -797,41 +797,41 @@ info = warning = error = debug DEBUG = FakeLogger() - print(" fetching the file to establish a connection") + print(b" fetching the file to establish a connection") fo = urlreq.urlopen(url) data1 = fo.read() fo.close() i = 20 - print(" waiting %i seconds for the server to close the connection" % i) + print(b" waiting %i seconds for the server to close the connection" % i) while i > 0: - procutil.stdout.write("\r %2i" % i) + procutil.stdout.write(b"\r %2i" % i) procutil.stdout.flush() time.sleep(1) i -= 1 - procutil.stderr.write("\r") + procutil.stderr.write(b"\r") - print(" fetching the file a second time") + print(b" fetching the file a second time") fo = urlreq.urlopen(url) data2 = fo.read() fo.close() if data1 == data2: - print(" data are identical") + print(b" data are identical") else: - print(" ERROR: DATA DIFFER") + print(b" ERROR: DATA DIFFER") DEBUG = dbbackup def test(url, N=10): - print("performing continuity test (making sure stuff isn't corrupted)") + print(b"performing continuity test (making sure stuff isn't corrupted)") continuity(url) - print("") - print("performing speed comparison") + print(b"") + print(b"performing speed comparison") comp(N, url) - print("") - print("performing dropped-connection check") + print(b"") + print(b"performing dropped-connection check") test_timeout(url) @@ -842,6 +842,6 @@ N = int(sys.argv[1]) url = sys.argv[2] except (IndexError, ValueError): - print("%s " % sys.argv[0]) + print(b"%s " % sys.argv[0]) else: test(url, N) diff --git a/mercurial/linelog.py b/mercurial/linelog.py --- a/mercurial/linelog.py +++ b/mercurial/linelog.py @@ -26,7 +26,7 @@ from .thirdparty import attr from . import pycompat -_llentry = struct.Struct(">II") +_llentry = struct.Struct(b">II") class LineLogError(Exception): @@ -122,7 +122,7 @@ def __init__(self, op1, op2): if op1 != 0: - raise LineLogError("malformed JUMP, op1 must be 0, got %d" % op1) + raise LineLogError(b"malformed JUMP, op1 must be 0, got %d" % op1) self._target = op2 def __str__(self): @@ -143,9 +143,9 @@ def __init__(self, op1, op2): if op1 != 0: - raise LineLogError("malformed EOF, op1 must be 0, got %d" % op1) + raise LineLogError(b"malformed EOF, op1 must be 0, got %d" % op1) if op2 != 0: - raise LineLogError("malformed EOF, op2 must be 0, got %d" % op2) + raise LineLogError(b"malformed EOF, op2 must be 0, got %d" % op2) def __str__(self): return r"EOF" @@ -218,7 +218,7 @@ try: op1, op2 = _llentry.unpack_from(data, offset) except struct.error as e: - raise LineLogError("reading an instruction failed: %r" % e) + raise LineLogError(b"reading an instruction failed: %r" % e) opcode = op1 & 0b11 op1 = op1 >> 2 if opcode == 0: @@ -231,7 +231,7 @@ return _jl(op1, op2) elif opcode == 2: return _line(op1, op2) - raise NotImplementedError("Unimplemented opcode %r" % opcode) + raise NotImplementedError(b"Unimplemented opcode %r" % opcode) class linelog(object): @@ -255,7 +255,7 @@ ) def __repr__(self): - return "" % ( + return b"" % ( hex(id(self)), self._maxrev, len(self._program), @@ -263,7 +263,7 @@ def debugstr(self): fmt = r"%%%dd %%s" % len(str(len(self._program))) - return pycompat.sysstr("\n").join( + return pycompat.sysstr(b"\n").join( fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1) ) @@ -271,7 +271,7 @@ def fromdata(cls, buf): if len(buf) % _llentry.size != 0: raise LineLogError( - "invalid linelog buffer size %d (must be a multiple of %d)" + b"invalid linelog buffer size %d (must be a multiple of %d)" % (len(buf), _llentry.size) ) expected = len(buf) / _llentry.size @@ -283,8 +283,8 @@ numentries = fakejge._target if expected != numentries: raise LineLogError( - "corrupt linelog data: claimed" - " %d entries but given data for %d entries" + b"corrupt linelog data: claimed" + b" %d entries but given data for %d entries" % (expected, numentries) ) instructions = [_eof(0, 0)] @@ -294,7 +294,7 @@ def encode(self): hdr = _jge(self._maxrev, len(self._program)).encode() - return hdr + "".join(i.encode() for i in self._program[1:]) + return hdr + b"".join(i.encode() for i in self._program[1:]) def clear(self): self._program = [] @@ -320,7 +320,7 @@ # ar = self.annotate(self._maxrev) if a1 > len(ar.lines): raise LineLogError( - "%d contains %d lines, tried to access line %d" + b"%d contains %d lines, tried to access line %d" % (rev, len(ar.lines), a1) ) elif a1 == len(ar.lines): @@ -356,7 +356,7 @@ if a1 < a2: if a2 > len(ar.lines): raise LineLogError( - "%d contains %d lines, tried to access line %d" + b"%d contains %d lines, tried to access line %d" % (rev, len(ar.lines), a2) ) elif a2 == len(ar.lines): @@ -454,8 +454,8 @@ elif isinstance(inst, _line): lines.append((inst._rev, inst._origlineno)) else: - raise LineLogError("Illegal instruction %r" % inst) + raise LineLogError(b"Illegal instruction %r" % inst) if nextpc == end: return lines pc = nextpc - raise LineLogError("Failed to perform getalllines") + raise LineLogError(b"Failed to perform getalllines") diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -111,7 +111,7 @@ def __init__(self, *paths): super(repofilecache, self).__init__(*paths) for path in paths: - _cachedfiles.add((path, "plain")) + _cachedfiles.add((path, b"plain")) def join(self, obj, fname): return obj.vfs.join(fname) @@ -123,7 +123,7 @@ def __init__(self, *paths): super(storecache, self).__init__(*paths) for path in paths: - _cachedfiles.add((path, "")) + _cachedfiles.add((path, b"")) def join(self, obj, fname): return obj.sjoin(fname) @@ -140,12 +140,12 @@ def join(self, obj, fnameandlocation): fname, location = fnameandlocation - if location == "plain": + if location == b"plain": return obj.vfs.join(fname) else: - if location != "": + if location != b"": raise error.ProgrammingError( - "unexpected location: %s" % location + b"unexpected location: %s" % location ) return obj.sjoin(fname) @@ -193,14 +193,14 @@ moderncaps = { - "lookup", - "branchmap", - "pushkey", - "known", - "getbundle", - "unbundle", + b"lookup", + b"branchmap", + b"pushkey", + b"known", + b"getbundle", + b"unbundle", } -legacycaps = moderncaps.union({"changegroupsubset"}) +legacycaps = moderncaps.union({b"changegroupsubset"}) @interfaceutil.implementer(repository.ipeercommandexecutor) @@ -219,12 +219,12 @@ def callcommand(self, command, args): if self._sent: raise error.ProgrammingError( - "callcommand() cannot be used after " "sendcommands()" + b"callcommand() cannot be used after " b"sendcommands()" ) if self._closed: raise error.ProgrammingError( - "callcommand() cannot be used after " "close()" + b"callcommand() cannot be used after " b"close()" ) # We don't need to support anything fancy. Just call the named @@ -258,7 +258,7 @@ if caps is None: caps = moderncaps.copy() - self._repo = repo.filtered("served") + self._repo = repo.filtered(b"served") self.ui = repo.ui self._caps = repo._restrictcapabilities(caps) @@ -290,11 +290,11 @@ return self._caps def clonebundles(self): - return self._repo.tryread("clonebundles.manifest") + return self._repo.tryread(b"clonebundles.manifest") def debugwireargs(self, one, two, three=None, four=None, five=None): """Used to test argument passing over the wire""" - return "%s %s %s %s %s" % ( + return b"%s %s %s %s %s" % ( one, two, pycompat.bytestr(three), @@ -321,7 +321,7 @@ # from it in local peer. return bundle2.getunbundler(self.ui, cb) else: - return changegroup.getunbundler("01", cb, None) + return changegroup.getunbundler(b"01", cb, None) def heads(self): return self._repo.heads() @@ -340,7 +340,7 @@ def stream_out(self): raise error.Abort( - _("cannot perform stream clone against local " "peer") + _(b"cannot perform stream clone against local " b"peer") ) def unbundle(self, bundle, heads, url): @@ -350,8 +350,8 @@ try: try: bundle = exchange.readbundle(self.ui, bundle, None) - ret = exchange.unbundle(self._repo, bundle, heads, "push", url) - if util.safehasattr(ret, "getchunks"): + ret = exchange.unbundle(self._repo, bundle, heads, b"push", url) + if util.safehasattr(ret, b"getchunks"): # This is a bundle20 object, turn it into an unbundler. # This little dance should be dropped eventually when the # API is finally improved. @@ -377,7 +377,7 @@ raise except error.PushRaced as exc: raise error.ResponseError( - _("push failed:"), stringutil.forcebytestr(exc) + _(b"push failed:"), stringutil.forcebytestr(exc) ) # End of _basewirecommands interface. @@ -410,20 +410,20 @@ outgoing = discovery.outgoing( self._repo, missingroots=nodes, missingheads=self._repo.heads() ) - return changegroup.makechangegroup(self._repo, outgoing, "01", source) + return changegroup.makechangegroup(self._repo, outgoing, b"01", source) def changegroupsubset(self, bases, heads, source): outgoing = discovery.outgoing( self._repo, missingroots=bases, missingheads=heads ) - return changegroup.makechangegroup(self._repo, outgoing, "01", source) + return changegroup.makechangegroup(self._repo, outgoing, b"01", source) # End of baselegacywirecommands interface. # Increment the sub-version when the revlog v2 format changes to lock out old # clients. -REVLOGV2_REQUIREMENT = "exp-revlogv2.1" +REVLOGV2_REQUIREMENT = b"exp-revlogv2.1" # A repository with the sparserevlog feature will have delta chains that # can spread over a larger span. Sparse reading cuts these large spans into @@ -432,11 +432,11 @@ # huge amounts of memory, because the whole span would be read at once, # including all the intermediate revisions that aren't pertinent for the chain. # This is why once a repository has enabled sparse-read, it becomes required. -SPARSEREVLOG_REQUIREMENT = "sparserevlog" +SPARSEREVLOG_REQUIREMENT = b"sparserevlog" # A repository with the sidedataflag requirement will allow to store extra # information for revision without altering their original hashes. -SIDEDATA_REQUIREMENT = "exp-sidedata-flag" +SIDEDATA_REQUIREMENT = b"exp-sidedata-flag" # Functions receiving (ui, features) that extensions can register to impact # the ability to load repositories with custom requirements. Only @@ -627,7 +627,7 @@ if not isinstance(typ, type): raise error.ProgrammingError( - "unable to construct type for %s" % iface + b"unable to construct type for %s" % iface ) bases.append(typ) @@ -700,7 +700,7 @@ for name in names: if not ui.hasconfig(b"extensions", name): - ui.setconfig(b"extensions", name, b"", source="autoload") + ui.setconfig(b"extensions", name, b"", source=b"autoload") def gathersupportedrequirements(ui): @@ -721,7 +721,7 @@ engine = util.compengines[name] if engine.available() and engine.revlogheader(): supported.add(b"exp-compression-%s" % name) - if engine.name() == "zstd": + if engine.name() == b"zstd": supported.add(b"revlog-compression-zstd") return supported @@ -817,12 +817,12 @@ if b"revlogv1" in requirements or REVLOGV2_REQUIREMENT in requirements: options.update(resolverevlogstorevfsoptions(ui, requirements, features)) else: # explicitly mark repo as using revlogv0 - options["revlogv0"] = True - - writecopiesto = ui.config("experimental", "copies.write-to") - copiesextramode = ("changeset-only", "compatibility") + options[b"revlogv0"] = True + + writecopiesto = ui.config(b"experimental", b"copies.write-to") + copiesextramode = (b"changeset-only", b"compatibility") if writecopiesto in copiesextramode: - options["copies-storage"] = "extra" + options[b"copies-storage"] = b"extra" return options @@ -901,18 +901,18 @@ # # The compression used for new entries will be "the last one" prefix = r.startswith - if prefix("revlog-compression-") or prefix("exp-compression-"): - options[b"compengine"] = r.split("-", 2)[2] + if prefix(b"revlog-compression-") or prefix(b"exp-compression-"): + options[b"compengine"] = r.split(b"-", 2)[2] options[b"zlib.level"] = ui.configint(b"storage", b"revlog.zlib.level") if options[b"zlib.level"] is not None: if not (0 <= options[b"zlib.level"] <= 9): - msg = _("invalid value for `storage.revlog.zlib.level` config: %d") + msg = _(b"invalid value for `storage.revlog.zlib.level` config: %d") raise error.Abort(msg % options[b"zlib.level"]) options[b"zstd.level"] = ui.configint(b"storage", b"revlog.zstd.level") if options[b"zstd.level"] is not None: if not (0 <= options[b"zstd.level"] <= 22): - msg = _("invalid value for `storage.revlog.zstd.level` config: %d") + msg = _(b"invalid value for `storage.revlog.zstd.level` config: %d") raise error.Abort(msg % options[b"zstd.level"]) if repository.NARROW_REQUIREMENT in requirements: @@ -992,22 +992,22 @@ # being successful (repository sizes went up due to worse delta # chains), and the code was deleted in 4.6. supportedformats = { - "revlogv1", - "generaldelta", - "treemanifest", + b"revlogv1", + b"generaldelta", + b"treemanifest", REVLOGV2_REQUIREMENT, SIDEDATA_REQUIREMENT, SPARSEREVLOG_REQUIREMENT, bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT, } _basesupported = supportedformats | { - "store", - "fncache", - "shared", - "relshared", - "dotencode", - "exp-sparse", - "internal-phase", + b"store", + b"fncache", + b"shared", + b"relshared", + b"dotencode", + b"exp-sparse", + b"internal-phase", } # list of prefix for file which can be written without 'wlock' @@ -1017,17 +1017,17 @@ # two, but pretty much all the existing code assume # wlock is not needed so we keep them excluded for # now. - "hgrc", - "requires", + b"hgrc", + b"requires", # XXX cache is a complicatged business someone # should investigate this in depth at some point - "cache/", + b"cache/", # XXX shouldn't be dirstate covered by the wlock? - "dirstate", + b"dirstate", # XXX bisect was still a bit too messy at the time # this changeset was introduced. Someone should fix # the remainig bit and drop this line - "bisect.state", + b"bisect.state", } def __init__( @@ -1117,8 +1117,8 @@ self.filtername = None - if self.ui.configbool("devel", "all-warnings") or self.ui.configbool( - "devel", "check-locks" + if self.ui.configbool(b"devel", b"all-warnings") or self.ui.configbool( + b"devel", b"check-locks" ): self.vfs.audit = self._getvfsward(self.vfs.audit) # A list of callback to shape the phase if no data were found. @@ -1131,10 +1131,10 @@ self.spath = self.store.path self.svfs = self.store.vfs self.sjoin = self.store.join - if self.ui.configbool("devel", "all-warnings") or self.ui.configbool( - "devel", "check-locks" + if self.ui.configbool(b"devel", b"all-warnings") or self.ui.configbool( + b"devel", b"check-locks" ): - if util.safehasattr(self.svfs, "vfs"): # this is filtervfs + if util.safehasattr(self.svfs, b"vfs"): # this is filtervfs self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit) else: # standard vfs self.svfs.audit = self._getsvfsward(self.svfs.audit) @@ -1184,25 +1184,25 @@ repo = rref() if ( repo is None - or not util.safehasattr(repo, "_wlockref") - or not util.safehasattr(repo, "_lockref") + or not util.safehasattr(repo, b"_wlockref") + or not util.safehasattr(repo, b"_lockref") ): return - if mode in (None, "r", "rb"): + if mode in (None, b"r", b"rb"): return if path.startswith(repo.path): # truncate name relative to the repository (.hg) path = path[len(repo.path) + 1 :] - if path.startswith("cache/"): - msg = 'accessing cache with vfs instead of cachevfs: "%s"' - repo.ui.develwarn(msg % path, stacklevel=3, config="cache-vfs") - if path.startswith("journal.") or path.startswith("undo."): + if path.startswith(b"cache/"): + msg = b'accessing cache with vfs instead of cachevfs: "%s"' + repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs") + if path.startswith(b"journal.") or path.startswith(b"undo."): # journal is covered by 'lock' if repo._currentlock(repo._lockref) is None: repo.ui.develwarn( - 'write with no lock: "%s"' % path, + b'write with no lock: "%s"' % path, stacklevel=3, - config="check-locks", + config=b"check-locks", ) elif repo._currentlock(repo._wlockref) is None: # rest of vfs files are covered by 'wlock' @@ -1212,9 +1212,9 @@ if path.startswith(prefix): return repo.ui.develwarn( - 'write with no wlock: "%s"' % path, + b'write with no wlock: "%s"' % path, stacklevel=3, - config="check-locks", + config=b"check-locks", ) return ret @@ -1227,16 +1227,16 @@ def checksvfs(path, mode=None): ret = origfunc(path, mode=mode) repo = rref() - if repo is None or not util.safehasattr(repo, "_lockref"): + if repo is None or not util.safehasattr(repo, b"_lockref"): return - if mode in (None, "r", "rb"): + if mode in (None, b"r", b"rb"): return if path.startswith(repo.sharedpath): # truncate name relative to the repository (.hg) path = path[len(repo.sharedpath) + 1 :] if repo._currentlock(repo._lockref) is None: repo.ui.develwarn( - 'write with no lock: "%s"' % path, stacklevel=4 + b'write with no lock: "%s"' % path, stacklevel=4 ) return ret @@ -1250,12 +1250,12 @@ self._revbranchcache.write() def _restrictcapabilities(self, caps): - if self.ui.configbool("experimental", "bundle2-advertise"): + if self.ui.configbool(b"experimental", b"bundle2-advertise"): caps = set(caps) capsblob = bundle2.encodecaps( - bundle2.getrepocaps(self, role="client") + bundle2.getrepocaps(self, role=b"client") ) - caps.add("bundle2=" + urlreq.quote(capsblob)) + caps.add(b"bundle2=" + urlreq.quote(capsblob)) return caps def _writerequirements(self): @@ -1305,7 +1305,7 @@ ctx = self[None] parts = util.splitpath(subpath) while parts: - prefix = "/".join(parts) + prefix = b"/".join(parts) if prefix in ctx.substate: if prefix == normsubpath: return True @@ -1337,17 +1337,17 @@ In other word, there is always only one level of `repoview` "filtering". """ - if self._extrafilterid is not None and "%" not in name: - name = name + "%" + self._extrafilterid + if self._extrafilterid is not None and b"%" not in name: + name = name + b"%" + self._extrafilterid cls = repoview.newtype(self.unfiltered().__class__) return cls(self, name, visibilityexceptions) @mixedrepostorecache( - ("bookmarks", "plain"), - ("bookmarks.current", "plain"), - ("bookmarks", ""), - ("00changelog.i", ""), + (b"bookmarks", b"plain"), + (b"bookmarks.current", b"plain"), + (b"bookmarks", b""), + (b"00changelog.i", b""), ) def _bookmarks(self): # Since the multiple files involved in the transaction cannot be @@ -1403,7 +1403,7 @@ def _refreshchangelog(self): """make sure the in memory changelog match the on-disk one""" - if "changelog" in vars(self) and self.currenttransaction() is None: + if b"changelog" in vars(self) and self.currenttransaction() is None: del self.changelog @property @@ -1413,23 +1413,23 @@ # _phasesets depend on changelog. what we need is to call # _phasecache.invalidate() if '00changelog.i' was changed, but it # can't be easily expressed in filecache mechanism. - @storecache("phaseroots", "00changelog.i") + @storecache(b"phaseroots", b"00changelog.i") def _phasecache(self): return phases.phasecache(self, self._phasedefaults) - @storecache("obsstore") + @storecache(b"obsstore") def obsstore(self): return obsolete.makestore(self.ui, self) - @storecache("00changelog.i") + @storecache(b"00changelog.i") def changelog(self): return self.store.changelog(txnutil.mayhavepending(self.root)) - @storecache("00manifest.i") + @storecache(b"00manifest.i") def manifestlog(self): return self.store.manifestlog(self, self._storenarrowmatch) - @repofilecache("dirstate") + @repofilecache(b"dirstate") def dirstate(self): return self._makedirstate() @@ -1449,7 +1449,7 @@ if not self._dirstatevalidatewarned: self._dirstatevalidatewarned = True self.ui.warn( - _("warning: ignoring unknown" " working parent %s!\n") + _(b"warning: ignoring unknown" b" working parent %s!\n") % short(node) ) return nullid @@ -1516,13 +1516,13 @@ if isinstance(changeid, int): node = self.changelog.node(changeid) rev = changeid - elif changeid == "null": + elif changeid == b"null": node = nullid rev = nullrev - elif changeid == "tip": + elif changeid == b"tip": node = self.changelog.tip() rev = self.changelog.rev(node) - elif changeid == ".": + elif changeid == b".": # this is a hack to delay/avoid loading obsmarkers # when we know that '.' won't be hidden node = self.dirstate.p1() @@ -1543,7 +1543,7 @@ self.local() and changeid in self.unfiltered().dirstate.parents() ): - msg = _("working directory has unknown parent '%s'!") + msg = _(b"working directory has unknown parent '%s'!") raise error.Abort(msg % short(changeid)) changeid = hex(changeid) # for the error message raise @@ -1553,7 +1553,7 @@ rev = self.changelog.rev(node) else: raise error.ProgrammingError( - "unsupported changeid '%s' of type %s" + b"unsupported changeid '%s' of type %s" % (changeid, type(changeid)) ) @@ -1561,11 +1561,11 @@ except (error.FilteredIndexError, error.FilteredLookupError): raise error.FilteredRepoLookupError( - _("filtered revision '%s'") % pycompat.bytestr(changeid) + _(b"filtered revision '%s'") % pycompat.bytestr(changeid) ) except (IndexError, LookupError): raise error.RepoLookupError( - _("unknown revision '%s'") % pycompat.bytestr(changeid) + _(b"unknown revision '%s'") % pycompat.bytestr(changeid) ) except error.WdirUnsupported: return context.workingctx(self) @@ -1643,7 +1643,7 @@ return m(self) def url(self): - return "file:" + self.root + return b"file:" + self.root def hook(self, name, throw=False, **args): """Call a hook, passing this repo instance. @@ -1711,7 +1711,7 @@ # map tag name to (node, hist) alltags = tagsmod.findglobaltags(self.ui, self) # map tag name to tag type - tagtypes = dict((tag, "global") for tag in alltags) + tagtypes = dict((tag, b"global") for tag in alltags) tagsmod.readlocaltags(self.ui, self, alltags, tagtypes) @@ -1723,7 +1723,7 @@ for (name, (node, hist)) in alltags.iteritems(): if node != nullid: tags[encoding.tolocal(name)] = node - tags["tip"] = self.changelog.tip() + tags[b"tip"] = self.changelog.tip() tagtypes = dict( [ (encoding.tolocal(name), value) @@ -1791,14 +1791,14 @@ return self.branchmap().branchtip(branch) except KeyError: if not ignoremissing: - raise error.RepoLookupError(_("unknown branch '%s'") % branch) + raise error.RepoLookupError(_(b"unknown branch '%s'") % branch) else: pass def lookup(self, key): node = scmutil.revsymbol(self, key).node() if node is None: - raise error.RepoLookupError(_("unknown revision '%s'") % key) + raise error.RepoLookupError(_(b"unknown revision '%s'") % key) return node def lookupbranch(self, key): @@ -1824,7 +1824,7 @@ def publishing(self): # it's safe (and desirable) to trust the publish flag unconditionally # so that we don't finalize changes shared between users via ssh or nfs - return self.ui.configbool("phases", "publish", untrusted=True) + return self.ui.configbool(b"phases", b"publish", untrusted=True) def cancopy(self): # so statichttprepo's override of local() works @@ -1833,12 +1833,12 @@ if not self.publishing(): return True # if publishing we can't copy if there is filtered content - return not self.filtered("visible").changelog.filteredrevs + return not self.filtered(b"visible").changelog.filteredrevs def shared(self): """the type of shared repository (None if not shared)""" if self.sharedpath != self.path: - return "store" + return b"store" return None def wjoin(self, f, *insidef): @@ -1877,9 +1877,9 @@ if filter not in self._filterpats: l = [] for pat, cmd in self.ui.configitems(filter): - if cmd == "!": + if cmd == b"!": continue - mf = matchmod.match(self.root, "", [pat]) + mf = matchmod.match(self.root, b"", [pat]) fn = None params = cmd for name, filterfn in self._datafilters.iteritems(): @@ -1900,7 +1900,7 @@ def _filter(self, filterpats, filename, data): for mf, fn, cmd in filterpats: if mf(filename): - self.ui.debug("filtering %s through %s\n" % (filename, cmd)) + self.ui.debug(b"filtering %s through %s\n" % (filename, cmd)) data = fn(data, cmd, ui=self.ui, repo=self, filename=filename) break @@ -1908,11 +1908,11 @@ @unfilteredpropertycache def _encodefilterpats(self): - return self._loadfilter("encode") + return self._loadfilter(b"encode") @unfilteredpropertycache def _decodefilterpats(self): - return self._loadfilter("decode") + return self._loadfilter(b"decode") def adddatafilter(self, name, filter): self._datafilters[name] = filter @@ -1930,13 +1930,13 @@ This returns length of written (maybe decoded) data. """ data = self._filter(self._decodefilterpats, filename, data) - if "l" in flags: + if b"l" in flags: self.wvfs.symlink(data, filename) else: self.wvfs.write( filename, data, backgroundclose=backgroundclose, **kwargs ) - if "x" in flags: + if b"x" in flags: self.wvfs.setflags(filename, False, True) else: self.wvfs.setflags(filename, False, False) @@ -1957,26 +1957,26 @@ return None def transaction(self, desc, report=None): - if self.ui.configbool("devel", "all-warnings") or self.ui.configbool( - "devel", "check-locks" + if self.ui.configbool(b"devel", b"all-warnings") or self.ui.configbool( + b"devel", b"check-locks" ): if self._currentlock(self._lockref) is None: - raise error.ProgrammingError("transaction requires locking") + raise error.ProgrammingError(b"transaction requires locking") tr = self.currenttransaction() if tr is not None: return tr.nest(name=desc) # abort here if the journal already exists - if self.svfs.exists("journal"): + if self.svfs.exists(b"journal"): raise error.RepoError( - _("abandoned transaction found"), - hint=_("run 'hg recover' to clean up transaction"), + _(b"abandoned transaction found"), + hint=_(b"run 'hg recover' to clean up transaction"), ) - idbase = "%.40f#%f" % (random.random(), time.time()) + idbase = b"%.40f#%f" % (random.random(), time.time()) ha = hex(hashlib.sha1(idbase).digest()) - txnid = "TXN:" + ha - self.hook("pretxnopen", throw=True, txnname=desc, txnid=txnid) + txnid = b"TXN:" + ha + self.hook(b"pretxnopen", throw=True, txnname=desc, txnid=txnid) self._writejournal(desc) renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()] @@ -1984,7 +1984,7 @@ rp = report else: rp = self.ui.warn - vfsmap = {"plain": self.vfs, "store": self.svfs} # root of .hg/ + vfsmap = {b"plain": self.vfs, b"store": self.svfs} # root of .hg/ # we must avoid cyclic reference between repo and transaction. reporef = weakref.ref(self) # Code to track tag movement @@ -2022,8 +2022,10 @@ # "+M": tag is moved (new value), tracktags = lambda x: None # experimental config: experimental.hook-track-tags - shouldtracktags = self.ui.configbool("experimental", "hook-track-tags") - if desc != "strip" and shouldtracktags: + shouldtracktags = self.ui.configbool( + b"experimental", b"hook-track-tags" + ) + if desc != b"strip" and shouldtracktags: oldheads = self.changelog.headrevs() def tracktags(tr2): @@ -2035,9 +2037,9 @@ # As we do it only once buiding set would not be cheaper changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes) if changes: - tr2.hookargs["tag_moved"] = "1" + tr2.hookargs[b"tag_moved"] = b"1" with repo.vfs( - "changes/tags.changes", "w", atomictemp=True + b"changes/tags.changes", b"w", atomictemp=True ) as changesfile: # note: we do not register the file to the transaction # because we needs it to still exist on the transaction @@ -2066,35 +2068,39 @@ repo = reporef() r = repo.ui.configsuboptions( - "experimental", "single-head-per-branch" + b"experimental", b"single-head-per-branch" ) singlehead, singleheadsub = r if singlehead: - accountclosed = singleheadsub.get("account-closed-heads", False) + accountclosed = singleheadsub.get( + b"account-closed-heads", False + ) scmutil.enforcesinglehead(repo, tr2, desc, accountclosed) - if hook.hashook(repo.ui, "pretxnclose-bookmark"): - for name, (old, new) in sorted(tr.changes["bookmarks"].items()): + if hook.hashook(repo.ui, b"pretxnclose-bookmark"): + for name, (old, new) in sorted( + tr.changes[b"bookmarks"].items() + ): args = tr.hookargs.copy() args.update(bookmarks.preparehookargs(name, old, new)) repo.hook( - "pretxnclose-bookmark", + b"pretxnclose-bookmark", throw=True, **pycompat.strkwargs(args) ) - if hook.hashook(repo.ui, "pretxnclose-phase"): + if hook.hashook(repo.ui, b"pretxnclose-phase"): cl = repo.unfiltered().changelog - for rev, (old, new) in tr.changes["phases"].items(): + for rev, (old, new) in tr.changes[b"phases"].items(): args = tr.hookargs.copy() node = hex(cl.node(rev)) args.update(phases.preparehookargs(node, old, new)) repo.hook( - "pretxnclose-phase", + b"pretxnclose-phase", throw=True, **pycompat.strkwargs(args) ) repo.hook( - "pretxnclose", throw=True, **pycompat.strkwargs(tr.hookargs) + b"pretxnclose", throw=True, **pycompat.strkwargs(tr.hookargs) ) def releasefn(tr, success): @@ -2115,9 +2121,9 @@ else: # discard all changes (including ones already written # out) in this transaction - narrowspec.restorebackup(self, "journal.narrowspec") - narrowspec.restorewcbackup(self, "journal.narrowspec.dirstate") - repo.dirstate.restorebackup(None, "journal.dirstate") + narrowspec.restorebackup(self, b"journal.narrowspec") + narrowspec.restorewcbackup(self, b"journal.narrowspec.dirstate") + repo.dirstate.restorebackup(None, b"journal.dirstate") repo.invalidate(clearfilecache=True) @@ -2125,8 +2131,8 @@ rp, self.svfs, vfsmap, - "journal", - "undo", + b"journal", + b"undo", aftertrans(renames), self.store.createmode, validator=validate, @@ -2134,17 +2140,17 @@ checkambigfiles=_cachedfiles, name=desc, ) - tr.changes["origrepolen"] = len(self) - tr.changes["obsmarkers"] = set() - tr.changes["phases"] = {} - tr.changes["bookmarks"] = {} - - tr.hookargs["txnid"] = txnid - tr.hookargs["txnname"] = desc + tr.changes[b"origrepolen"] = len(self) + tr.changes[b"obsmarkers"] = set() + tr.changes[b"phases"] = {} + tr.changes[b"bookmarks"] = {} + + tr.hookargs[b"txnid"] = txnid + tr.hookargs[b"txnname"] = desc # note: writing the fncache only during finalize mean that the file is # outdated when running hooks. As fncache is used for streaming clone, # this is not expected to break anything that happen during the hooks. - tr.addfinalize("flush-fncache", self.store.write) + tr.addfinalize(b"flush-fncache", self.store.write) def txnclosehook(tr2): """To be run if transaction is successful, will schedule a hook run @@ -2157,68 +2163,68 @@ def hookfunc(): repo = reporef() - if hook.hashook(repo.ui, "txnclose-bookmark"): - bmchanges = sorted(tr.changes["bookmarks"].items()) + if hook.hashook(repo.ui, b"txnclose-bookmark"): + bmchanges = sorted(tr.changes[b"bookmarks"].items()) for name, (old, new) in bmchanges: args = tr.hookargs.copy() args.update(bookmarks.preparehookargs(name, old, new)) repo.hook( - "txnclose-bookmark", + b"txnclose-bookmark", throw=False, **pycompat.strkwargs(args) ) - if hook.hashook(repo.ui, "txnclose-phase"): + if hook.hashook(repo.ui, b"txnclose-phase"): cl = repo.unfiltered().changelog - phasemv = sorted(tr.changes["phases"].items()) + phasemv = sorted(tr.changes[b"phases"].items()) for rev, (old, new) in phasemv: args = tr.hookargs.copy() node = hex(cl.node(rev)) args.update(phases.preparehookargs(node, old, new)) repo.hook( - "txnclose-phase", + b"txnclose-phase", throw=False, **pycompat.strkwargs(args) ) repo.hook( - "txnclose", throw=False, **pycompat.strkwargs(hookargs) + b"txnclose", throw=False, **pycompat.strkwargs(hookargs) ) reporef()._afterlock(hookfunc) - tr.addfinalize("txnclose-hook", txnclosehook) + tr.addfinalize(b"txnclose-hook", txnclosehook) # Include a leading "-" to make it happen before the transaction summary # reports registered via scmutil.registersummarycallback() whose names # are 00-txnreport etc. That way, the caches will be warm when the # callbacks run. - tr.addpostclose("-warm-cache", self._buildcacheupdater(tr)) + tr.addpostclose(b"-warm-cache", self._buildcacheupdater(tr)) def txnaborthook(tr2): """To be run if transaction is aborted """ reporef().hook( - "txnabort", throw=False, **pycompat.strkwargs(tr2.hookargs) + b"txnabort", throw=False, **pycompat.strkwargs(tr2.hookargs) ) - tr.addabort("txnabort-hook", txnaborthook) + tr.addabort(b"txnabort-hook", txnaborthook) # avoid eager cache invalidation. in-memory data should be identical # to stored data if transaction has no error. - tr.addpostclose("refresh-filecachestats", self._refreshfilecachestats) + tr.addpostclose(b"refresh-filecachestats", self._refreshfilecachestats) self._transref = weakref.ref(tr) scmutil.registersummarycallback(self, tr, desc) return tr def _journalfiles(self): return ( - (self.svfs, "journal"), - (self.svfs, "journal.narrowspec"), - (self.vfs, "journal.narrowspec.dirstate"), - (self.vfs, "journal.dirstate"), - (self.vfs, "journal.branch"), - (self.vfs, "journal.desc"), - (bookmarks.bookmarksvfs(self), "journal.bookmarks"), - (self.svfs, "journal.phaseroots"), + (self.svfs, b"journal"), + (self.svfs, b"journal.narrowspec"), + (self.vfs, b"journal.narrowspec.dirstate"), + (self.vfs, b"journal.dirstate"), + (self.vfs, b"journal.branch"), + (self.vfs, b"journal.desc"), + (bookmarks.bookmarksvfs(self), b"journal.bookmarks"), + (self.svfs, b"journal.phaseroots"), ) def undofiles(self): @@ -2226,38 +2232,38 @@ @unfilteredmethod def _writejournal(self, desc): - self.dirstate.savebackup(None, "journal.dirstate") - narrowspec.savewcbackup(self, "journal.narrowspec.dirstate") - narrowspec.savebackup(self, "journal.narrowspec") + self.dirstate.savebackup(None, b"journal.dirstate") + narrowspec.savewcbackup(self, b"journal.narrowspec.dirstate") + narrowspec.savebackup(self, b"journal.narrowspec") self.vfs.write( - "journal.branch", encoding.fromlocal(self.dirstate.branch()) + b"journal.branch", encoding.fromlocal(self.dirstate.branch()) ) - self.vfs.write("journal.desc", "%d\n%s\n" % (len(self), desc)) + self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc)) bookmarksvfs = bookmarks.bookmarksvfs(self) bookmarksvfs.write( - "journal.bookmarks", bookmarksvfs.tryread("bookmarks") + b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks") ) - self.svfs.write("journal.phaseroots", self.svfs.tryread("phaseroots")) + self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots")) def recover(self): with self.lock(): - if self.svfs.exists("journal"): - self.ui.status(_("rolling back interrupted transaction\n")) + if self.svfs.exists(b"journal"): + self.ui.status(_(b"rolling back interrupted transaction\n")) vfsmap = { - "": self.svfs, - "plain": self.vfs, + b"": self.svfs, + b"plain": self.vfs, } transaction.rollback( self.svfs, vfsmap, - "journal", + b"journal", self.ui.warn, checkambigfiles=_cachedfiles, ) self.invalidate() return True else: - self.ui.warn(_("no interrupted transaction available\n")) + self.ui.warn(_(b"no interrupted transaction available\n")) return False def rollback(self, dryrun=False, force=False): @@ -2265,12 +2271,12 @@ try: wlock = self.wlock() lock = self.lock() - if self.svfs.exists("undo"): - dsguard = dirstateguard.dirstateguard(self, "rollback") + if self.svfs.exists(b"undo"): + dsguard = dirstateguard.dirstateguard(self, b"rollback") return self._rollback(dryrun, force, dsguard) else: - self.ui.warn(_("no rollback information available\n")) + self.ui.warn(_(b"no rollback information available\n")) return 1 finally: release(dsguard, lock, wlock) @@ -2279,7 +2285,7 @@ def _rollback(self, dryrun, force, dsguard): ui = self.ui try: - args = self.vfs.read("undo.desc").splitlines() + args = self.vfs.read(b"undo.desc").splitlines() (oldlen, desc, detail) = (int(args[0]), args[1], None) if len(args) >= 3: detail = args[2] @@ -2287,24 +2293,24 @@ if detail and ui.verbose: msg = _( - "repository tip rolled back to revision %d" - " (undo %s: %s)\n" + b"repository tip rolled back to revision %d" + b" (undo %s: %s)\n" ) % (oldtip, desc, detail) else: msg = _( - "repository tip rolled back to revision %d" " (undo %s)\n" + b"repository tip rolled back to revision %d" b" (undo %s)\n" ) % (oldtip, desc) except IOError: - msg = _("rolling back unknown transaction\n") + msg = _(b"rolling back unknown transaction\n") desc = None - if not force and self["."] != self["tip"] and desc == "commit": + if not force and self[b"."] != self[b"tip"] and desc == b"commit": raise error.Abort( _( - "rollback of last commit while not checked out " - "may lose data" + b"rollback of last commit while not checked out " + b"may lose data" ), - hint=_("use -f to force"), + hint=_(b"use -f to force"), ) ui.status(msg) @@ -2313,15 +2319,17 @@ parents = self.dirstate.parents() self.destroying() - vfsmap = {"plain": self.vfs, "": self.svfs} + vfsmap = {b"plain": self.vfs, b"": self.svfs} transaction.rollback( - self.svfs, vfsmap, "undo", ui.warn, checkambigfiles=_cachedfiles + self.svfs, vfsmap, b"undo", ui.warn, checkambigfiles=_cachedfiles ) bookmarksvfs = bookmarks.bookmarksvfs(self) - if bookmarksvfs.exists("undo.bookmarks"): - bookmarksvfs.rename("undo.bookmarks", "bookmarks", checkambig=True) - if self.svfs.exists("undo.phaseroots"): - self.svfs.rename("undo.phaseroots", "phaseroots", checkambig=True) + if bookmarksvfs.exists(b"undo.bookmarks"): + bookmarksvfs.rename( + b"undo.bookmarks", b"bookmarks", checkambig=True + ) + if self.svfs.exists(b"undo.phaseroots"): + self.svfs.rename(b"undo.phaseroots", b"phaseroots", checkambig=True) self.invalidate() parentgone = any(p not in self.changelog.nodemap for p in parents) @@ -2329,17 +2337,17 @@ # prevent dirstateguard from overwriting already restored one dsguard.close() - narrowspec.restorebackup(self, "undo.narrowspec") - narrowspec.restorewcbackup(self, "undo.narrowspec.dirstate") - self.dirstate.restorebackup(None, "undo.dirstate") + narrowspec.restorebackup(self, b"undo.narrowspec") + narrowspec.restorewcbackup(self, b"undo.narrowspec.dirstate") + self.dirstate.restorebackup(None, b"undo.dirstate") try: - branch = self.vfs.read("undo.branch") + branch = self.vfs.read(b"undo.branch") self.dirstate.setbranch(encoding.tolocal(branch)) except IOError: ui.warn( _( - "named branch could not be reset: " - "current branch is still '%s'\n" + b"named branch could not be reset: " + b"current branch is still '%s'\n" ) % self.dirstate.branch() ) @@ -2347,15 +2355,18 @@ parents = tuple([p.rev() for p in self[None].parents()]) if len(parents) > 1: ui.status( - _("working directory now based on " "revisions %d and %d\n") + _( + b"working directory now based on " + b"revisions %d and %d\n" + ) % parents ) else: ui.status( - _("working directory now based on " "revision %d\n") + _(b"working directory now based on " b"revision %d\n") % parents ) - mergemod.mergestate.clean(self, self["."].node()) + mergemod.mergestate.clean(self, self[b"."].node()) # TODO: if we know which new heads may result from this rollback, pass # them to destroy(), which will prevent the branchhead cache from being @@ -2390,16 +2401,16 @@ If 'full' is set, make sure all caches the function knows about have up-to-date data. Even the ones usually loaded more lazily. """ - if tr is not None and tr.hookargs.get("source") == "strip": + if tr is not None and tr.hookargs.get(b"source") == b"strip": # During strip, many caches are invalid but # later call to `destroyed` will refresh them. return - if tr is None or tr.changes["origrepolen"] < len(self): + if tr is None or tr.changes[b"origrepolen"] < len(self): # accessing the 'ser ved' branchmap should refresh all the others, - self.ui.debug("updating the branch cache\n") - self.filtered("served").branchmap() - self.filtered("served.hidden").branchmap() + self.ui.debug(b"updating the branch cache\n") + self.filtered(b"served").branchmap() + self.filtered(b"served.hidden").branchmap() if full: unfi = self.unfiltered() @@ -2409,14 +2420,14 @@ rbc.write() # ensure the working copy parents are in the manifestfulltextcache - for ctx in self["."].parents(): + for ctx in self[b"."].parents(): ctx.manifest() # accessing the manifest is enough # accessing fnode cache warms the cache tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs()) # accessing tags warm the cache self.tags() - self.filtered("served").tags() + self.filtered(b"served").tags() # The `full` arg is documented as updating even the lazily-loaded # caches immediately, so we're forcing a write to cause these caches @@ -2470,10 +2481,10 @@ unfiltered = self.unfiltered() # all file caches are stored unfiltered for k in list(self._filecache.keys()): # dirstate is invalidated separately in invalidatedirstate() - if k == "dirstate": + if k == b"dirstate": continue if ( - k == "changelog" + k == b"changelog" and self.currenttransaction() and self.changelog._delayed ): @@ -2531,10 +2542,10 @@ timeout = 0 warntimeout = 0 if wait: - timeout = self.ui.configint("ui", "timeout") - warntimeout = self.ui.configint("ui", "timeout.warn") + timeout = self.ui.configint(b"ui", b"timeout") + warntimeout = self.ui.configint(b"ui", b"timeout.warn") # internal config: ui.signal-safe-lock - signalsafe = self.ui.configbool("ui", "signal-safe-lock") + signalsafe = self.ui.configbool(b"ui", b"signal-safe-lock") l = lockmod.trylock( self.ui, @@ -2578,11 +2589,11 @@ l = self._lock( vfs=self.svfs, - lockname="lock", + lockname=b"lock", wait=wait, releasefn=None, acquirefn=self.invalidate, - desc=_("repository %s") % self.origroot, + desc=_(b"repository %s") % self.origroot, ) self._lockref = weakref.ref(l) return l @@ -2590,7 +2601,7 @@ def _wlockchecktransaction(self): if self.currenttransaction() is not None: raise error.LockInheritanceContractViolation( - "wlock cannot be inherited in the middle of a transaction" + b"wlock cannot be inherited in the middle of a transaction" ) def wlock(self, wait=True): @@ -2609,11 +2620,11 @@ # We do not need to check for non-waiting lock acquisition. Such # acquisition would not cause dead-lock as they would just fail. if wait and ( - self.ui.configbool("devel", "all-warnings") - or self.ui.configbool("devel", "check-locks") + self.ui.configbool(b"devel", b"all-warnings") + or self.ui.configbool(b"devel", b"check-locks") ): if self._currentlock(self._lockref) is not None: - self.ui.develwarn('"wlock" acquired after "lock"') + self.ui.develwarn(b'"wlock" acquired after "lock"') def unlock(): if self.dirstate.pendingparentchange(): @@ -2621,17 +2632,17 @@ else: self.dirstate.write(None) - self._filecache["dirstate"].refresh() + self._filecache[b"dirstate"].refresh() l = self._lock( self.vfs, - "wlock", + b"wlock", wait, unlock, self.invalidatedirstate, - _("working directory of %s") % self.origroot, + _(b"working directory of %s") % self.origroot, inheritchecker=self._wlockchecktransaction, - parentenvvar="HG_WLOCK_LOCKER", + parentenvvar=b"HG_WLOCK_LOCKER", ) self._wlockref = weakref.ref(l) return l @@ -2669,7 +2680,7 @@ if isinstance(fctx, context.filectx): node = fctx.filenode() if node in [fparent1, fparent2]: - self.ui.debug("reusing %s filelog entry\n" % fname) + self.ui.debug(b"reusing %s filelog entry\n" % fname) if ( fparent1 != nullid and manifest1.flags(fname) != fctx.flags() @@ -2722,16 +2733,18 @@ # behavior in this circumstance. if cnode: - self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(cnode))) + self.ui.debug( + b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)) + ) if includecopymeta: - meta["copy"] = cfname - meta["copyrev"] = hex(cnode) + meta[b"copy"] = cfname + meta[b"copyrev"] = hex(cnode) fparent1, fparent2 = nullid, newfparent else: self.ui.warn( _( - "warning: can't find ancestor for '%s' " - "copied from '%s'!\n" + b"warning: can't find ancestor for '%s' " + b"copied from '%s'!\n" ) % (fname, cfname) ) @@ -2764,24 +2777,24 @@ for f in match.files(): f = self.dirstate.normalize(f) - if f == "." or f in matched or f in wctx.substate: + if f == b"." or f in matched or f in wctx.substate: continue if f in status.deleted: - fail(f, _("file not found!")) + fail(f, _(b"file not found!")) if f in vdirs: # visited directory - d = f + "/" + d = f + b"/" for mf in matched: if mf.startswith(d): break else: - fail(f, _("no match under directory!")) + fail(f, _(b"no match under directory!")) elif f not in self.dirstate: - fail(f, _("file not tracked!")) + fail(f, _(b"file not tracked!")) @unfilteredmethod def commit( self, - text="", + text=b"", user=None, date=None, match=None, @@ -2799,7 +2812,7 @@ extra = {} def fail(f, msg): - raise error.Abort("%s: %s" % (f, msg)) + raise error.Abort(b"%s: %s" % (f, msg)) if not match: match = matchmod.always() @@ -2817,8 +2830,8 @@ if not force and merge and not match.always(): raise error.Abort( _( - "cannot partially commit a merge " - "(do not specify files or patterns)" + b"cannot partially commit a merge " + b"(do not specify files or patterns)" ) ) @@ -2844,16 +2857,16 @@ # internal config: ui.allowemptycommit allowemptycommit = ( wctx.branch() != wctx.p1().branch() - or extra.get("close") + or extra.get(b"close") or merge or cctx.files() - or self.ui.configbool("ui", "allowemptycommit") + or self.ui.configbool(b"ui", b"allowemptycommit") ) if not allowemptycommit: return None if merge and cctx.deleted(): - raise error.Abort(_("cannot commit merge with missing files")) + raise error.Abort(_(b"cannot commit merge with missing files")) ms = mergemod.mergestate.read(self) mergeutil.checkunresolved(ms) @@ -2873,7 +2886,7 @@ for s in sorted(commitsubs): sub = wctx.sub(s) self.ui.status( - _("committing subrepository %s\n") + _(b"committing subrepository %s\n") % uipathfn(subrepoutil.subrelpath(sub)) ) sr = sub.commit(cctx._text, user, date) @@ -2881,12 +2894,12 @@ subrepoutil.writestate(self, newstate) p1, p2 = self.dirstate.parents() - hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or "") + hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or b"") try: self.hook( - "precommit", throw=True, parent1=hookp1, parent2=hookp2 + b"precommit", throw=True, parent1=hookp1, parent2=hookp2 ) - with self.transaction("commit"): + with self.transaction(b"commit"): ret = self.commitctx(cctx, True) # update bookmarks, dirstate and mergestate bookmarks.update(self, [p1, p2], ret) @@ -2895,7 +2908,7 @@ except: # re-raises if edited: self.ui.write( - _("note: commit message saved in %s\n") % msgfn + _(b"note: commit message saved in %s\n") % msgfn ) raise @@ -2904,7 +2917,7 @@ # temporary commit got stripped before hook release if self.changelog.hasnode(ret): self.hook( - "commit", node=hex(ret), parent1=hookp1, parent2=hookp2 + b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2 ) self._afterlock(commithook) @@ -2930,23 +2943,23 @@ p1, p2 = ctx.p1(), ctx.p2() user = ctx.user() - writecopiesto = self.ui.config("experimental", "copies.write-to") - writefilecopymeta = writecopiesto != "changeset-only" + writecopiesto = self.ui.config(b"experimental", b"copies.write-to") + writefilecopymeta = writecopiesto != b"changeset-only" writechangesetcopy = writecopiesto in ( - "changeset-only", - "compatibility", + b"changeset-only", + b"compatibility", ) p1copies, p2copies = None, None if writechangesetcopy: p1copies = ctx.p1copies() p2copies = ctx.p2copies() filesadded, filesremoved = None, None - with self.lock(), self.transaction("commit") as tr: + with self.lock(), self.transaction(b"commit") as tr: trp = weakref.proxy(tr) if ctx.manifestnode(): # reuse an existing manifest revision - self.ui.debug("reusing known manifest\n") + self.ui.debug(b"reusing known manifest\n") mn = ctx.manifestnode() files = ctx.files() if writechangesetcopy: @@ -2966,10 +2979,10 @@ changed = [] removed = list(ctx.removed()) linkrev = len(self) - self.ui.note(_("committing files:\n")) + self.ui.note(_(b"committing files:\n")) uipathfn = scmutil.getuipathfn(self) for f in sorted(ctx.modified() + ctx.added()): - self.ui.note(uipathfn(f) + "\n") + self.ui.note(uipathfn(f) + b"\n") try: fctx = ctx[f] if fctx is None: @@ -2988,14 +3001,14 @@ m.setflag(f, fctx.flags()) except OSError: self.ui.warn( - _("trouble committing %s!\n") % uipathfn(f) + _(b"trouble committing %s!\n") % uipathfn(f) ) raise except IOError as inst: errcode = getattr(inst, "errno", errno.ENOENT) if error or errcode and errcode != errno.ENOENT: self.ui.warn( - _("trouble committing %s!\n") % uipathfn(f) + _(b"trouble committing %s!\n") % uipathfn(f) ) raise @@ -3060,11 +3073,11 @@ md = m1.diff(m, scmutil.matchfiles(self, ctx.files())) if not files and md: self.ui.debug( - "not reusing manifest (no file change in " - "changelog, but manifest differs)\n" + b"not reusing manifest (no file change in " + b"changelog, but manifest differs)\n" ) if files or md: - self.ui.note(_("committing manifest\n")) + self.ui.note(_(b"committing manifest\n")) # we're using narrowmatch here since it's already applied at # other stages (such as dirstate.walk), so we're already # ignoring things outside of narrowspec in most cases. The @@ -3089,16 +3102,16 @@ filesremoved = removed else: self.ui.debug( - "reusing manifest from p1 (listed files " - "actually unchanged)\n" + b"reusing manifest from p1 (listed files " + b"actually unchanged)\n" ) mn = p1.manifestnode() else: - self.ui.debug("reusing manifest from p1 (no file change)\n") + self.ui.debug(b"reusing manifest from p1 (no file change)\n") mn = p1.manifestnode() files = [] - if writecopiesto == "changeset-only": + if writecopiesto == b"changeset-only": # If writing only to changeset extras, use None to indicate that # no entry should be written. If writing to both, write an empty # entry to prevent the reader from falling back to reading @@ -3112,7 +3125,7 @@ files = origctx.files() # update changelog - self.ui.note(_("committing changelog\n")) + self.ui.note(_(b"committing changelog\n")) self.changelog.delayupdate(tr) n = self.changelog.add( mn, @@ -3129,9 +3142,9 @@ filesadded, filesremoved, ) - xp1, xp2 = p1.hex(), p2 and p2.hex() or "" + xp1, xp2 = p1.hex(), p2 and p2.hex() or b"" self.hook( - "pretxncommit", + b"pretxncommit", throw=True, node=hex(n), parent1=xp1, @@ -3163,7 +3176,7 @@ # When using the same lock to commit and strip, the phasecache is left # dirty after committing. Then when we strip, the repo is invalidated, # causing those changes to disappear. - if "_phasecache" in vars(self): + if b"_phasecache" in vars(self): self._phasecache.write() @unfilteredmethod @@ -3200,7 +3213,7 @@ def status( self, - node1=".", + node1=b".", node2=None, match=None, ignored=False, @@ -3331,18 +3344,18 @@ hookargs[r"key"] = key hookargs[r"old"] = old hookargs[r"new"] = new - self.hook("prepushkey", throw=True, **hookargs) + self.hook(b"prepushkey", throw=True, **hookargs) except error.HookAbort as exc: - self.ui.write_err(_("pushkey-abort: %s\n") % exc) + self.ui.write_err(_(b"pushkey-abort: %s\n") % exc) if exc.hint: - self.ui.write_err(_("(%s)\n") % exc.hint) + self.ui.write_err(_(b"(%s)\n") % exc.hint) return False - self.ui.debug('pushing key for "%s:%s"\n' % (namespace, key)) + self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key)) ret = pushkey.push(self, namespace, key, old, new) def runhook(): self.hook( - "pushkey", + b"pushkey", namespace=namespace, key=key, old=old, @@ -3354,15 +3367,15 @@ return ret def listkeys(self, namespace): - self.hook("prelistkeys", throw=True, namespace=namespace) - self.ui.debug('listing keys for "%s"\n' % namespace) + self.hook(b"prelistkeys", throw=True, namespace=namespace) + self.ui.debug(b'listing keys for "%s"\n' % namespace) values = pushkey.list(self, namespace) - self.hook("listkeys", namespace=namespace, values=values) + self.hook(b"listkeys", namespace=namespace, values=values) return values def debugwireargs(self, one, two, three=None, four=None, five=None): """used to test argument passing over the wire""" - return "%s %s %s %s %s" % ( + return b"%s %s %s %s %s" % ( one, two, pycompat.bytestr(three), @@ -3371,7 +3384,7 @@ ) def savecommitmessage(self, text): - fp = self.vfs("last-message.txt", "wb") + fp = self.vfs(b"last-message.txt", b"wb") try: fp.write(text) finally: @@ -3399,8 +3412,8 @@ def undoname(fn): base, name = os.path.split(fn) - assert name.startswith("journal") - return os.path.join(base, name.replace("journal", "undo", 1)) + assert name.startswith(b"journal") + return os.path.join(base, name.replace(b"journal", b"undo", 1)) def instance(ui, path, create, intents=None, createopts=None): @@ -3423,9 +3436,9 @@ """ createopts = dict(createopts or {}) - if "backend" not in createopts: + if b"backend" not in createopts: # experimental config: storage.new-repo-backend - createopts["backend"] = ui.config("storage", "new-repo-backend") + createopts[b"backend"] = ui.config(b"storage", b"new-repo-backend") return createopts @@ -3438,85 +3451,86 @@ """ # If the repo is being created from a shared repository, we copy # its requirements. - if "sharedrepo" in createopts: - requirements = set(createopts["sharedrepo"].requirements) - if createopts.get("sharedrelative"): - requirements.add("relshared") + if b"sharedrepo" in createopts: + requirements = set(createopts[b"sharedrepo"].requirements) + if createopts.get(b"sharedrelative"): + requirements.add(b"relshared") else: - requirements.add("shared") + requirements.add(b"shared") return requirements - if "backend" not in createopts: + if b"backend" not in createopts: raise error.ProgrammingError( - "backend key not present in createopts; " - "was defaultcreateopts() called?" + b"backend key not present in createopts; " + b"was defaultcreateopts() called?" ) - if createopts["backend"] != "revlogv1": + if createopts[b"backend"] != b"revlogv1": raise error.Abort( _( - "unable to determine repository requirements for " - "storage backend: %s" + b"unable to determine repository requirements for " + b"storage backend: %s" ) - % createopts["backend"] + % createopts[b"backend"] ) - requirements = {"revlogv1"} - if ui.configbool("format", "usestore"): - requirements.add("store") - if ui.configbool("format", "usefncache"): - requirements.add("fncache") - if ui.configbool("format", "dotencode"): - requirements.add("dotencode") - - compengine = ui.config("format", "revlog-compression") + requirements = {b"revlogv1"} + if ui.configbool(b"format", b"usestore"): + requirements.add(b"store") + if ui.configbool(b"format", b"usefncache"): + requirements.add(b"fncache") + if ui.configbool(b"format", b"dotencode"): + requirements.add(b"dotencode") + + compengine = ui.config(b"format", b"revlog-compression") if compengine not in util.compengines: raise error.Abort( _( - "compression engine %s defined by " - "format.revlog-compression not available" + b"compression engine %s defined by " + b"format.revlog-compression not available" ) % compengine, hint=_( - 'run "hg debuginstall" to list available ' "compression engines" + b'run "hg debuginstall" to list available ' + b"compression engines" ), ) # zlib is the historical default and doesn't need an explicit requirement. - elif compengine == "zstd": - requirements.add("revlog-compression-zstd") - elif compengine != "zlib": - requirements.add("exp-compression-%s" % compengine) + elif compengine == b"zstd": + requirements.add(b"revlog-compression-zstd") + elif compengine != b"zlib": + requirements.add(b"exp-compression-%s" % compengine) if scmutil.gdinitconfig(ui): - requirements.add("generaldelta") - if ui.configbool("format", "sparse-revlog"): + requirements.add(b"generaldelta") + if ui.configbool(b"format", b"sparse-revlog"): requirements.add(SPARSEREVLOG_REQUIREMENT) # experimental config: format.use-side-data - if ui.configbool("format", "use-side-data"): + if ui.configbool(b"format", b"use-side-data"): requirements.add(SIDEDATA_REQUIREMENT) - if ui.configbool("experimental", "treemanifest"): - requirements.add("treemanifest") - - revlogv2 = ui.config("experimental", "revlogv2") - if revlogv2 == "enable-unstable-format-and-corrupt-my-data": - requirements.remove("revlogv1") + if ui.configbool(b"experimental", b"treemanifest"): + requirements.add(b"treemanifest") + + revlogv2 = ui.config(b"experimental", b"revlogv2") + if revlogv2 == b"enable-unstable-format-and-corrupt-my-data": + requirements.remove(b"revlogv1") # generaldelta is implied by revlogv2. - requirements.discard("generaldelta") + requirements.discard(b"generaldelta") requirements.add(REVLOGV2_REQUIREMENT) # experimental config: format.internal-phase - if ui.configbool("format", "internal-phase"): - requirements.add("internal-phase") - - if createopts.get("narrowfiles"): + if ui.configbool(b"format", b"internal-phase"): + requirements.add(b"internal-phase") + + if createopts.get(b"narrowfiles"): requirements.add(repository.NARROW_REQUIREMENT) - if createopts.get("lfs"): - requirements.add("lfs") - - if ui.configbool("format", "bookmarks-in-store"): + if createopts.get(b"lfs"): + requirements.add(b"lfs") + + if ui.configbool(b"format", b"bookmarks-in-store"): requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT) return requirements @@ -3537,13 +3551,13 @@ they know how to handle. """ known = { - "backend", - "lfs", - "narrowfiles", - "sharedrepo", - "sharedrelative", - "shareditems", - "shallowfilestore", + b"backend", + b"lfs", + b"narrowfiles", + b"sharedrepo", + b"sharedrelative", + b"shareditems", + b"shallowfilestore", } return {k: v for k, v in createopts.items() if k not in known} @@ -3582,17 +3596,17 @@ if not isinstance(unknownopts, dict): raise error.ProgrammingError( - "filterknowncreateopts() did not return " "a dict" + b"filterknowncreateopts() did not return " b"a dict" ) if unknownopts: raise error.Abort( _( - "unable to create repository because of unknown " - "creation option: %s" + b"unable to create repository because of unknown " + b"creation option: %s" ) - % ", ".join(sorted(unknownopts)), - hint=_("is a required extension not loaded?"), + % b", ".join(sorted(unknownopts)), + hint=_(b"is a required extension not loaded?"), ) requirements = newreporequirements(ui, createopts=createopts) @@ -3601,19 +3615,19 @@ hgvfs = vfsmod.vfs(wdirvfs.join(b".hg")) if hgvfs.exists(): - raise error.RepoError(_("repository %s already exists") % path) - - if "sharedrepo" in createopts: - sharedpath = createopts["sharedrepo"].sharedpath - - if createopts.get("sharedrelative"): + raise error.RepoError(_(b"repository %s already exists") % path) + + if b"sharedrepo" in createopts: + sharedpath = createopts[b"sharedrepo"].sharedpath + + if createopts.get(b"sharedrelative"): try: sharedpath = os.path.relpath(sharedpath, hgvfs.base) except (IOError, ValueError) as e: # ValueError is raised on Windows if the drive letters differ # on each path. raise error.Abort( - _("cannot calculate relative path"), + _(b"cannot calculate relative path"), hint=stringutil.forcebytestr(e), ) @@ -3621,11 +3635,11 @@ wdirvfs.makedirs() hgvfs.makedir(notindexed=True) - if "sharedrepo" not in createopts: + if b"sharedrepo" not in createopts: hgvfs.mkdir(b"cache") hgvfs.mkdir(b"wcache") - if b"store" in requirements and "sharedrepo" not in createopts: + if b"store" in requirements and b"sharedrepo" not in createopts: hgvfs.mkdir(b"store") # We create an invalid changelog outside the store so very old @@ -3645,11 +3659,11 @@ scmutil.writerequires(hgvfs, requirements) # Write out file telling readers where to find the shared store. - if "sharedrepo" in createopts: + if b"sharedrepo" in createopts: hgvfs.write(b"sharedpath", sharedpath) - if createopts.get("shareditems"): - shared = b"\n".join(sorted(createopts["shareditems"])) + b"\n" + if createopts.get(b"shareditems"): + shared = b"\n".join(sorted(createopts[b"shareditems"])) + b"\n" hgvfs.write(b"shared", shared) @@ -3669,7 +3683,7 @@ return object.__getattribute__(self, item) raise error.ProgrammingError( - "repo instances should not be used " "after unshare" + b"repo instances should not be used " b"after unshare" ) def close(self): diff --git a/mercurial/lock.py b/mercurial/lock.py --- a/mercurial/lock.py +++ b/mercurial/lock.py @@ -35,9 +35,9 @@ extra Linux-specific pid namespace identifier. """ result = encoding.strtolocal(socket.gethostname()) - if pycompat.sysplatform.startswith("linux"): + if pycompat.sysplatform.startswith(b"linux"): try: - result += "/%x" % os.stat("/proc/self/ns/pid").st_ino + result += b"/%x" % os.stat(b"/proc/self/ns/pid").st_ino except OSError as ex: if ex.errno not in (errno.ENOENT, errno.EACCES, errno.ENOTDIR): raise @@ -76,7 +76,13 @@ try: # save handlers first so they can be restored even if a setup is # interrupted between signal.signal() and orighandlers[] =. - for name in ["CTRL_C_EVENT", "SIGINT", "SIGBREAK", "SIGHUP", "SIGTERM"]: + for name in [ + b"CTRL_C_EVENT", + b"SIGINT", + b"SIGBREAK", + b"SIGHUP", + b"SIGTERM", + ]: num = getattr(signal, name, None) if num and num not in orighandlers: orighandlers[num] = signal.getsignal(num) @@ -114,17 +120,17 @@ def printwarning(printer, locker): """issue the usual "waiting on lock" message through any channel""" # show more details for new-style locks - if ":" in locker: - host, pid = locker.split(":", 1) + if b":" in locker: + host, pid = locker.split(b":", 1) msg = _( - "waiting for lock on %s held by process %r on host %r\n" + b"waiting for lock on %s held by process %r on host %r\n" ) % ( pycompat.bytestr(l.desc), pycompat.bytestr(pid), pycompat.bytestr(host), ) else: - msg = _("waiting for lock on %s held by %r\n") % ( + msg = _(b"waiting for lock on %s held by %r\n") % ( l.desc, pycompat.bytestr(locker), ) @@ -159,9 +165,9 @@ l.delay = delay if l.delay: if 0 <= warningidx <= l.delay: - ui.warn(_("got lock after %d seconds\n") % l.delay) + ui.warn(_(b"got lock after %d seconds\n") % l.delay) else: - ui.debug("got lock after %d seconds\n" % l.delay) + ui.debug(b"got lock after %d seconds\n" % l.delay) if l.acquirefn: l.acquirefn() return l @@ -268,7 +274,7 @@ return if lock._host is None: lock._host = _getlockprefix() - lockname = "%s:%d" % (lock._host, self.pid) + lockname = b"%s:%d" % (lock._host, self.pid) retry = 5 while not self.held and retry: retry -= 1 @@ -307,7 +313,7 @@ # use empty locker to mean "busy for frequent lock/unlock # by many processes" raise error.LockHeld( - errno.EAGAIN, self.vfs.join(self.f), self.desc, "" + errno.EAGAIN, self.vfs.join(self.f), self.desc, b"" ) def _readlock(self): @@ -327,7 +333,7 @@ if locker is None: return None try: - host, pid = locker.split(":", 1) + host, pid = locker.split(b":", 1) except ValueError: return locker if host != lock._host: @@ -341,7 +347,7 @@ # if locker dead, break lock. must do this with another lock # held, or can race and break valid lock. try: - l = lock(self.vfs, self.f + ".break", timeout=0) + l = lock(self.vfs, self.f + b".break", timeout=0) self.vfs.unlink(self.f) l.release() except error.LockError: @@ -371,11 +377,11 @@ """ if not self.held: raise error.LockInheritanceContractViolation( - "inherit can only be called while lock is held" + b"inherit can only be called while lock is held" ) if self._inherited: raise error.LockInheritanceContractViolation( - "inherit cannot be called while lock is already inherited" + b"inherit cannot be called while lock is already inherited" ) if self._inheritchecker is not None: self._inheritchecker() diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py --- a/mercurial/logcmdutil.py +++ b/mercurial/logcmdutil.py @@ -44,14 +44,14 @@ def getlimit(opts): """get the log limit according to option -l/--limit""" - limit = opts.get("limit") + limit = opts.get(b"limit") if limit: try: limit = int(limit) except ValueError: - raise error.Abort(_("limit must be a positive integer")) + raise error.Abort(_(b"limit must be a positive integer")) if limit <= 0: - raise error.Abort(_("limit must be positive")) + raise error.Abort(_(b"limit must be positive")) else: limit = None return limit @@ -68,8 +68,8 @@ stat=False, fp=None, graphwidth=0, - prefix="", - root="", + prefix=b"", + root=b"", listsubrepos=False, hunksfilterfn=None, ): @@ -79,7 +79,7 @@ if root: relroot = pathutil.canonpath(repo.root, repo.getcwd(), root) else: - relroot = "" + relroot = b"" copysourcematch = None def compose(f, g): @@ -88,31 +88,31 @@ def pathfn(f): return posixpath.join(prefix, f) - if relroot != "": + if relroot != b"": # XXX relative roots currently don't work if the root is within a # subrepo uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) uirelroot = uipathfn(pathfn(relroot)) - relroot += "/" + relroot += b"/" for matchroot in match.files(): if not matchroot.startswith(relroot): ui.warn( - _("warning: %s not inside relative root %s\n") + _(b"warning: %s not inside relative root %s\n") % (uipathfn(pathfn(matchroot)), uirelroot) ) - relrootmatch = scmutil.match(ctx2, pats=[relroot], default="path") + relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b"path") match = matchmod.intersectmatchers(match, relrootmatch) copysourcematch = relrootmatch checkroot = repo.ui.configbool( - "devel", "all-warnings" - ) or repo.ui.configbool("devel", "check-relroot") + b"devel", b"all-warnings" + ) or repo.ui.configbool(b"devel", b"check-relroot") def relrootpathfn(f): if checkroot and not f.startswith(relroot): raise AssertionError( - "file %s doesn't start with relroot %s" % (f, relroot) + b"file %s doesn't start with relroot %s" % (f, relroot) ) return f[len(relroot) :] @@ -214,14 +214,14 @@ def changesetlabels(ctx): - labels = ["log.changeset", "changeset.%s" % ctx.phasestr()] + labels = [b"log.changeset", b"changeset.%s" % ctx.phasestr()] if ctx.obsolete(): - labels.append("changeset.obsolete") + labels.append(b"changeset.obsolete") if ctx.isunstable(): - labels.append("changeset.unstable") + labels.append(b"changeset.unstable") for instability in ctx.instabilities(): - labels.append("instability.%s" % instability) - return " ".join(labels) + labels.append(b"instability.%s" % instability) + return b" ".join(labels) class changesetprinter(object): @@ -233,8 +233,8 @@ self.buffered = buffered self._differ = differ or changesetdiffer() self._diffopts = patch.diffallopts(ui, diffopts) - self._includestat = diffopts and diffopts.get("stat") - self._includediff = diffopts and diffopts.get("patch") + self._includestat = diffopts and diffopts.get(b"stat") + self._includediff = diffopts and diffopts.get(b"patch") self.header = {} self.hunk = {} self.lastheader = None @@ -269,17 +269,17 @@ def _show(self, ctx, copies, props): """show a single changeset or file revision""" changenode = ctx.node() - graphwidth = props.get("graphwidth", 0) + graphwidth = props.get(b"graphwidth", 0) if self.ui.quiet: self.ui.write( - "%s\n" % scmutil.formatchangeid(ctx), label="log.node" + b"%s\n" % scmutil.formatchangeid(ctx), label=b"log.node" ) return columns = self._columns self.ui.write( - columns["changeset"] % scmutil.formatchangeid(ctx), + columns[b"changeset"] % scmutil.formatchangeid(ctx), label=changesetlabels(ctx), ) @@ -287,24 +287,26 @@ # compatibility branch = ctx.branch() # don't show the default branch name - if branch != "default": - self.ui.write(columns["branch"] % branch, label="log.branch") + if branch != b"default": + self.ui.write(columns[b"branch"] % branch, label=b"log.branch") for nsname, ns in self.repo.names.iteritems(): # branches has special logic already handled above, so here we just # skip it - if nsname == "branches": + if nsname == b"branches": continue # we will use the templatename as the color name since those two # should be the same for name in ns.names(self.repo, changenode): - self.ui.write(ns.logfmt % name, label="log.%s" % ns.colorname) + self.ui.write(ns.logfmt % name, label=b"log.%s" % ns.colorname) if self.ui.debugflag: - self.ui.write(columns["phase"] % ctx.phasestr(), label="log.phase") + self.ui.write( + columns[b"phase"] % ctx.phasestr(), label=b"log.phase" + ) for pctx in scmutil.meaningfulparents(self.repo, ctx): - label = "log.parent changeset.%s" % pctx.phasestr() + label = b"log.parent changeset.%s" % pctx.phasestr() self.ui.write( - columns["parent"] % scmutil.formatchangeid(pctx), label=label + columns[b"parent"] % scmutil.formatchangeid(pctx), label=label ) if self.ui.debugflag: @@ -315,20 +317,20 @@ else: mrev = self.repo.manifestlog.rev(mnode) self.ui.write( - columns["manifest"] + columns[b"manifest"] % scmutil.formatrevnode(self.ui, mrev, mnode), - label="ui.debug log.manifest", + label=b"ui.debug log.manifest", ) - self.ui.write(columns["user"] % ctx.user(), label="log.user") + self.ui.write(columns[b"user"] % ctx.user(), label=b"log.user") self.ui.write( - columns["date"] % dateutil.datestr(ctx.date()), label="log.date" + columns[b"date"] % dateutil.datestr(ctx.date()), label=b"log.date" ) if ctx.isunstable(): instabilities = ctx.instabilities() self.ui.write( - columns["instability"] % ", ".join(instabilities), - label="log.instability", + columns[b"instability"] % b", ".join(instabilities), + label=b"log.instability", ) elif ctx.obsolete(): @@ -338,45 +340,46 @@ if self.ui.debugflag: files = ctx.p1().status(ctx)[:3] - for key, value in zip(["files", "files+", "files-"], files): + for key, value in zip([b"files", b"files+", b"files-"], files): if value: self.ui.write( - columns[key] % " ".join(value), - label="ui.debug log.files", + columns[key] % b" ".join(value), + label=b"ui.debug log.files", ) elif ctx.files() and self.ui.verbose: self.ui.write( - columns["files"] % " ".join(ctx.files()), - label="ui.note log.files", + columns[b"files"] % b" ".join(ctx.files()), + label=b"ui.note log.files", ) if copies and self.ui.verbose: - copies = ["%s (%s)" % c for c in copies] + copies = [b"%s (%s)" % c for c in copies] self.ui.write( - columns["copies"] % " ".join(copies), label="ui.note log.copies" + columns[b"copies"] % b" ".join(copies), + label=b"ui.note log.copies", ) extra = ctx.extra() if extra and self.ui.debugflag: for key, value in sorted(extra.items()): self.ui.write( - columns["extra"] % (key, stringutil.escapestr(value)), - label="ui.debug log.extra", + columns[b"extra"] % (key, stringutil.escapestr(value)), + label=b"ui.debug log.extra", ) description = ctx.description().strip() if description: if self.ui.verbose: self.ui.write( - _("description:\n"), label="ui.note log.description" + _(b"description:\n"), label=b"ui.note log.description" ) - self.ui.write(description, label="ui.note log.description") - self.ui.write("\n\n") + self.ui.write(description, label=b"ui.note log.description") + self.ui.write(b"\n\n") else: self.ui.write( - columns["summary"] % description.splitlines()[0], - label="log.summary", + columns[b"summary"] % description.splitlines()[0], + label=b"log.summary", ) - self.ui.write("\n") + self.ui.write(b"\n") self._showpatch(ctx, graphwidth) @@ -385,16 +388,17 @@ tres = formatter.templateresources(self.repo.ui, self.repo) t = formatter.maketemplater( self.repo.ui, - '{join(obsfate, "\n")}', + b'{join(obsfate, "\n")}', defaults=templatekw.keywords, resources=tres, ) - obsfate = t.renderdefault({"ctx": ctx}).splitlines() + obsfate = t.renderdefault({b"ctx": ctx}).splitlines() if obsfate: for obsfateline in obsfate: self.ui.write( - self._columns["obsolete"] % obsfateline, label="log.obsfate" + self._columns[b"obsolete"] % obsfateline, + label=b"log.obsfate", ) def _exthook(self, ctx): @@ -407,13 +411,13 @@ self.ui, ctx, self._diffopts, graphwidth, stat=True ) if self._includestat and self._includediff: - self.ui.write("\n") + self.ui.write(b"\n") if self._includediff: self._differ.showdiff( self.ui, ctx, self._diffopts, graphwidth, stat=False ) if self._includestat or self._includediff: - self.ui.write("\n") + self.ui.write(b"\n") class changesetformatter(changesetprinter): @@ -445,10 +449,10 @@ user=ctx.user(), date=fm.formatdate(ctx.date()), desc=ctx.description(), - bookmarks=fm.formatlist(ctx.bookmarks(), name="bookmark"), - tags=fm.formatlist(ctx.tags(), name="tag"), + bookmarks=fm.formatlist(ctx.bookmarks(), name=b"bookmark"), + tags=fm.formatlist(ctx.tags(), name=b"tag"), parents=fm.formatlist( - [fm.hexfunc(c.node()) for c in ctx.parents()], name="node" + [fm.hexfunc(c.node()) for c in ctx.parents()], name=b"node" ), ) @@ -460,16 +464,16 @@ files = ctx.p1().status(ctx) fm.data( - modified=fm.formatlist(files[0], name="file"), - added=fm.formatlist(files[1], name="file"), - removed=fm.formatlist(files[2], name="file"), + modified=fm.formatlist(files[0], name=b"file"), + added=fm.formatlist(files[1], name=b"file"), + removed=fm.formatlist(files[2], name=b"file"), ) elif self.ui.verbose: - fm.data(files=fm.formatlist(ctx.files(), name="file")) + fm.data(files=fm.formatlist(ctx.files(), name=b"file")) if copies: fm.data( - copies=fm.formatdict(copies, key="name", value="source") + copies=fm.formatdict(copies, key=b"name", value=b"source") ) if self._includestat: @@ -510,21 +514,21 @@ self._tref = tmplspec.ref self._parts = { - "header": "", - "footer": "", + b"header": b"", + b"footer": b"", tmplspec.ref: tmplspec.ref, - "docheader": "", - "docfooter": "", - "separator": "", + b"docheader": b"", + b"docfooter": b"", + b"separator": b"", } if tmplspec.mapfile: # find correct templates for current mode, for backward # compatibility with 'log -v/-q/--debug' using a mapfile tmplmodes = [ - (True, ""), - (self.ui.verbose, "_verbose"), - (self.ui.quiet, "_quiet"), - (self.ui.debugflag, "_debug"), + (True, b""), + (self.ui.verbose, b"_verbose"), + (self.ui.quiet, b"_quiet"), + (self.ui.debugflag, b"_debug"), ] for mode, postfix in tmplmodes: for t in self._parts: @@ -536,33 +540,33 @@ m = formatter.templatepartsmap(tmplspec, self.t, partnames) self._parts.update(m) - if self._parts["docheader"]: - self.ui.write(self.t.render(self._parts["docheader"], {})) + if self._parts[b"docheader"]: + self.ui.write(self.t.render(self._parts[b"docheader"], {})) def close(self): - if self._parts["docfooter"]: + if self._parts[b"docfooter"]: if not self.footer: - self.footer = "" - self.footer += self.t.render(self._parts["docfooter"], {}) + self.footer = b"" + self.footer += self.t.render(self._parts[b"docfooter"], {}) return super(changesettemplater, self).close() def _show(self, ctx, copies, props): """show a single changeset or file revision""" props = props.copy() - props["ctx"] = ctx - props["index"] = index = next(self._counter) - props["revcache"] = {"copies": copies} - graphwidth = props.get("graphwidth", 0) + props[b"ctx"] = ctx + props[b"index"] = index = next(self._counter) + props[b"revcache"] = {b"copies": copies} + graphwidth = props.get(b"graphwidth", 0) # write separator, which wouldn't work well with the header part below # since there's inherently a conflict between header (across items) and # separator (per item) - if self._parts["separator"] and index > 0: - self.ui.write(self.t.render(self._parts["separator"], {})) + if self._parts[b"separator"] and index > 0: + self.ui.write(self.t.render(self._parts[b"separator"], {})) # write header - if self._parts["header"]: - h = self.t.render(self._parts["header"], props) + if self._parts[b"header"]: + h = self.t.render(self._parts[b"header"], props) if self.buffered: self.header[ctx.rev()] = h else: @@ -575,18 +579,18 @@ self.ui.write(self.t.render(key, props)) self._showpatch(ctx, graphwidth) - if self._parts["footer"]: + if self._parts[b"footer"]: if not self.footer: - self.footer = self.t.render(self._parts["footer"], props) + self.footer = self.t.render(self._parts[b"footer"], props) def templatespec(tmpl, mapfile): if pycompat.ispy3: - assert not isinstance(tmpl, str), "tmpl must not be a str" + assert not isinstance(tmpl, str), b"tmpl must not be a str" if mapfile: - return formatter.templatespec("changeset", tmpl, mapfile) + return formatter.templatespec(b"changeset", tmpl, mapfile) else: - return formatter.templatespec("", tmpl, None) + return formatter.templatespec(b"", tmpl, None) def _lookuptemplate(ui, tmpl, style): @@ -597,17 +601,17 @@ # ui settings if not tmpl and not style: # template are stronger than style - tmpl = ui.config("ui", "logtemplate") + tmpl = ui.config(b"ui", b"logtemplate") if tmpl: return templatespec(templater.unquotestring(tmpl), None) else: - style = util.expandpath(ui.config("ui", "style")) + style = util.expandpath(ui.config(b"ui", b"style")) if not tmpl and style: mapfile = style if not os.path.split(mapfile)[0]: mapname = templater.templatepath( - "map-cmdline." + mapfile + b"map-cmdline." + mapfile ) or templater.templatepath(mapfile) if mapname: mapfile = mapname @@ -616,7 +620,7 @@ if not tmpl: return templatespec(None, None) - return formatter.lookuptemplate(ui, "changeset", tmpl) + return formatter.lookuptemplate(ui, b"changeset", tmpl) def maketemplater(ui, repo, tmpl, buffered=False): @@ -638,11 +642,11 @@ regular display via changesetprinter() is done. """ postargs = (differ, opts, buffered) - if opts.get("template") in {"cbor", "json"}: - fm = ui.formatter("log", opts) + if opts.get(b"template") in {b"cbor", b"json"}: + fm = ui.formatter(b"log", opts) return changesetformatter(ui, repo, fm, *postargs) - spec = _lookuptemplate(ui, opts.get("template"), opts.get("style")) + spec = _lookuptemplate(ui, opts.get(b"template"), opts.get(b"style")) if not spec.ref and not spec.tmpl and not spec.mapfile: return changesetprinter(ui, repo, *postargs) @@ -666,11 +670,11 @@ # platforms without shell expansion (windows). wctx = repo[None] match, pats = scmutil.matchandpats(wctx, pats, opts) - slowpath = match.anypats() or (not match.always() and opts.get("removed")) + slowpath = match.anypats() or (not match.always() and opts.get(b"removed")) if not slowpath: - follow = opts.get("follow") or opts.get("follow_first") + follow = opts.get(b"follow") or opts.get(b"follow_first") startctxs = [] - if follow and opts.get("rev"): + if follow and opts.get(b"rev"): startctxs = [repo[r] for r in revs] for f in match.files(): if follow and startctxs: @@ -687,7 +691,10 @@ continue else: raise error.Abort( - _("cannot follow file not in parent " 'revision: "%s"') + _( + b"cannot follow file not in parent " + b'revision: "%s"' + ) % f ) filelog = repo.file(f) @@ -696,7 +703,7 @@ # try to find matching entries on the slow path. if follow: raise error.Abort( - _('cannot follow nonexistent file: "%s"') % f + _(b'cannot follow nonexistent file: "%s"') % f ) slowpath = True @@ -706,7 +713,7 @@ # slowpath; otherwise, we can turn off the slowpath if slowpath: for path in match.files(): - if path == "." or path in repo.store: + if path == b"." or path in repo.store: break else: slowpath = False @@ -744,15 +751,15 @@ _opt2logrevset = { - "no_merges": ("not merge()", None), - "only_merges": ("merge()", None), - "_matchfiles": (None, "_matchfiles(%ps)"), - "date": ("date(%s)", None), - "branch": ("branch(%s)", "%lr"), - "_patslog": ("filelog(%s)", "%lr"), - "keyword": ("keyword(%s)", "%lr"), - "prune": ("ancestors(%s)", "not %lr"), - "user": ("user(%s)", "%lr"), + b"no_merges": (b"not merge()", None), + b"only_merges": (b"merge()", None), + b"_matchfiles": (None, b"_matchfiles(%ps)"), + b"date": (b"date(%s)", None), + b"branch": (b"branch(%s)", b"%lr"), + b"_patslog": (b"filelog(%s)", b"%lr"), + b"keyword": (b"keyword(%s)", b"%lr"), + b"prune": (b"ancestors(%s)", b"not %lr"), + b"user": (b"user(%s)", b"%lr"), } @@ -760,12 +767,12 @@ """Return a revset string built from log options and file patterns""" opts = dict(opts) # follow or not follow? - follow = opts.get("follow") or opts.get("follow_first") + follow = opts.get(b"follow") or opts.get(b"follow_first") # branch and only_branch are really aliases and must be handled at # the same time - opts["branch"] = opts.get("branch", []) + opts.get("only_branch", []) - opts["branch"] = [repo.lookupbranch(b) for b in opts["branch"]] + opts[b"branch"] = opts.get(b"branch", []) + opts.get(b"only_branch", []) + opts[b"branch"] = [repo.lookupbranch(b) for b in opts[b"branch"]] if slowpath: # See walkchangerevs() slow path. @@ -776,16 +783,16 @@ # "a" and "b" while "file(a) and not file(b)" does # not. Besides, filesets are evaluated against the working # directory. - matchargs = ["r:", "d:relpath"] + matchargs = [b"r:", b"d:relpath"] for p in pats: - matchargs.append("p:" + p) - for p in opts.get("include", []): - matchargs.append("i:" + p) - for p in opts.get("exclude", []): - matchargs.append("x:" + p) - opts["_matchfiles"] = matchargs + matchargs.append(b"p:" + p) + for p in opts.get(b"include", []): + matchargs.append(b"i:" + p) + for p in opts.get(b"exclude", []): + matchargs.append(b"x:" + p) + opts[b"_matchfiles"] = matchargs elif not follow: - opts["_patslog"] = list(pats) + opts[b"_patslog"] = list(pats) expr = [] for op, val in sorted(opts.iteritems()): @@ -794,7 +801,7 @@ if op not in _opt2logrevset: continue revop, listop = _opt2logrevset[op] - if revop and "%" not in revop: + if revop and b"%" not in revop: expr.append(revop) elif not listop: expr.append(revsetlang.formatspec(revop, val)) @@ -804,7 +811,7 @@ expr.append(revsetlang.formatspec(listop, val)) if expr: - expr = "(" + " and ".join(expr) + ")" + expr = b"(" + b" and ".join(expr) + b")" else: expr = None return expr @@ -812,13 +819,13 @@ def _initialrevs(repo, opts): """Return the initial set of revisions to be filtered or followed""" - follow = opts.get("follow") or opts.get("follow_first") - if opts.get("rev"): - revs = scmutil.revrange(repo, opts["rev"]) + follow = opts.get(b"follow") or opts.get(b"follow_first") + if opts.get(b"rev"): + revs = scmutil.revrange(repo, opts[b"rev"]) elif follow and repo.dirstate.p1() == nullid: revs = smartset.baseset() elif follow: - revs = repo.revs(".") + revs = repo.revs(b".") else: revs = smartset.spanset(repo) revs.reverse() @@ -830,8 +837,8 @@ differ is a changesetdiffer with pre-configured file matcher. """ - follow = opts.get("follow") or opts.get("follow_first") - followfirst = opts.get("follow_first") + follow = opts.get(b"follow") or opts.get(b"follow_first") + followfirst = opts.get(b"follow_first") limit = getlimit(opts) revs = _initialrevs(repo, opts) if not revs: @@ -852,10 +859,10 @@ return match expr = _makerevset(repo, match, pats, slowpath, opts) - if opts.get("graph"): + if opts.get(b"graph"): # User-specified revs might be unsorted, but don't sort before # _makerevset because it might depend on the order of revs - if repo.ui.configbool("experimental", "log.topo"): + if repo.ui.configbool(b"experimental", b"log.topo"): if not revs.istopo(): revs = dagop.toposort(revs, repo.changelog.parentrevs) # TODO: try to iterate the set lazily @@ -878,16 +885,16 @@ (fromline, toline)). """ linerangebyfname = [] - for pat in opts.get("line_range", []): + for pat in opts.get(b"line_range", []): try: - pat, linerange = pat.rsplit(",", 1) + pat, linerange = pat.rsplit(b",", 1) except ValueError: - raise error.Abort(_("malformatted line-range pattern %s") % pat) + raise error.Abort(_(b"malformatted line-range pattern %s") % pat) try: - fromline, toline = map(int, linerange.split(":")) + fromline, toline = map(int, linerange.split(b":")) except ValueError: - raise error.Abort(_("invalid line range for %s") % pat) - msg = _("line range pattern '%s' must match exactly one file") % pat + raise error.Abort(_(b"invalid line range for %s") % pat) + msg = _(b"line range pattern '%s' must match exactly one file") % pat fname = scmutil.parsefollowlinespattern(repo, None, pat, msg) linerangebyfname.append( (fname, util.processlinerange(fromline, toline)) @@ -911,7 +918,8 @@ for fname, (fromline, toline) in _parselinerangeopt(repo, opts): if fname not in wctx: raise error.Abort( - _("cannot follow file not in parent " 'revision: "%s"') % fname + _(b"cannot follow file not in parent " b'revision: "%s"') + % fname ) fctx = wctx.filectx(fname) for fctx, linerange in dagop.blockancestors(fctx, fromline, toline): @@ -958,7 +966,7 @@ def _graphnodeformatter(ui, displayer): - spec = ui.config("ui", "graphnodetemplate") + spec = ui.config(b"ui", b"graphnodetemplate") if not spec: return templatekw.getgraphnode # fast path for "{graphnode}" @@ -973,7 +981,7 @@ ) def formatnode(repo, ctx): - props = {"ctx": ctx, "repo": repo} + props = {b"ctx": ctx, b"repo": repo} return templ.renderdefault(props) return formatnode @@ -983,28 +991,28 @@ props = props or {} formatnode = _graphnodeformatter(ui, displayer) state = graphmod.asciistate() - styles = state["styles"] + styles = state[b"styles"] # only set graph styling if HGPLAIN is not set. - if ui.plain("graph"): + if ui.plain(b"graph"): # set all edge styles to |, the default pre-3.8 behaviour - styles.update(dict.fromkeys(styles, "|")) + styles.update(dict.fromkeys(styles, b"|")) else: edgetypes = { - "parent": graphmod.PARENT, - "grandparent": graphmod.GRANDPARENT, - "missing": graphmod.MISSINGPARENT, + b"parent": graphmod.PARENT, + b"grandparent": graphmod.GRANDPARENT, + b"missing": graphmod.MISSINGPARENT, } for name, key in edgetypes.items(): # experimental config: experimental.graphstyle.* styles[key] = ui.config( - "experimental", "graphstyle.%s" % name, styles[key] + b"experimental", b"graphstyle.%s" % name, styles[key] ) if not styles[key]: styles[key] = None # experimental config: experimental.graphshorten - state["graphshorten"] = ui.configbool("experimental", "graphshorten") + state[b"graphshorten"] = ui.configbool(b"experimental", b"graphshorten") for rev, type, ctx, parents in dag: char = formatnode(repo, ctx) @@ -1015,7 +1023,7 @@ displayer.show( ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props) ) - lines = displayer.hunk.pop(rev).split("\n") + lines = displayer.hunk.pop(rev).split(b"\n") if not lines[-1]: del lines[-1] displayer.flush(ctx) @@ -1040,11 +1048,11 @@ def checkunsupportedgraphflags(pats, opts): - for op in ["newest_first"]: + for op in [b"newest_first"]: if op in opts and opts[op]: raise error.Abort( - _("-G/--graph option is incompatible with --%s") - % op.replace("_", "-") + _(b"-G/--graph option is incompatible with --%s") + % op.replace(b"_", b"-") ) diff --git a/mercurial/logexchange.py b/mercurial/logexchange.py --- a/mercurial/logexchange.py +++ b/mercurial/logexchange.py @@ -16,7 +16,7 @@ ) # directory name in .hg/ in which remotenames files will be present -remotenamedir = "logexchange" +remotenamedir = b"logexchange" def readremotenamefile(repo, filename): @@ -39,7 +39,7 @@ if lineno == 0: lineno += 1 try: - node, remote, rname = line.split("\0") + node, remote, rname = line.split(b"\0") yield node, remote, rname except ValueError: pass @@ -55,32 +55,32 @@ information, call the respective functions. """ - for bmentry in readremotenamefile(repo, "bookmarks"): + for bmentry in readremotenamefile(repo, b"bookmarks"): yield bmentry - for branchentry in readremotenamefile(repo, "branches"): + for branchentry in readremotenamefile(repo, b"branches"): yield branchentry def writeremotenamefile(repo, remotepath, names, nametype): vfs = vfsmod.vfs(repo.vfs.join(remotenamedir)) - f = vfs(nametype, "w", atomictemp=True) + f = vfs(nametype, b"w", atomictemp=True) # write the storage version info on top of file # version '0' represents the very initial version of the storage format - f.write("0\n\n") + f.write(b"0\n\n") olddata = set(readremotenamefile(repo, nametype)) # re-save the data from a different remote than this one. for node, oldpath, rname in sorted(olddata): if oldpath != remotepath: - f.write("%s\0%s\0%s\n" % (node, oldpath, rname)) + f.write(b"%s\0%s\0%s\n" % (node, oldpath, rname)) for name, node in sorted(names.iteritems()): - if nametype == "branches": + if nametype == b"branches": for n in node: - f.write("%s\0%s\0%s\n" % (n, remotepath, name)) - elif nametype == "bookmarks": + f.write(b"%s\0%s\0%s\n" % (n, remotepath, name)) + elif nametype == b"bookmarks": if node: - f.write("%s\0%s\0%s\n" % (node, remotepath, name)) + f.write(b"%s\0%s\0%s\n" % (node, remotepath, name)) f.close() @@ -93,9 +93,9 @@ wlock = repo.wlock() try: if bookmarks: - writeremotenamefile(repo, remotepath, bookmarks, "bookmarks") + writeremotenamefile(repo, remotepath, bookmarks, b"bookmarks") if branches: - writeremotenamefile(repo, remotepath, branches, "branches") + writeremotenamefile(repo, remotepath, branches, b"branches") finally: wlock.release() @@ -114,7 +114,7 @@ rpath = remote._url # represent the remotepath with user defined path name if exists - for path, url in repo.ui.configitems("paths"): + for path, url in repo.ui.configitems(b"paths"): # remove auth info from user defined url noauthurl = util.removeauth(url) @@ -140,7 +140,7 @@ with remoterepo.commandexecutor() as e: bookmarks = e.callcommand( - "listkeys", {"namespace": "bookmarks",} + b"listkeys", {b"namespace": b"bookmarks",} ).result() # on a push, we don't want to keep obsolete heads since @@ -151,7 +151,7 @@ repo = localrepo.unfiltered() with remoterepo.commandexecutor() as e: - branchmap = e.callcommand("branchmap", {}).result() + branchmap = e.callcommand(b"branchmap", {}).result() for branch, nodes in branchmap.iteritems(): bmap[branch] = [] diff --git a/mercurial/loggingutil.py b/mercurial/loggingutil.py --- a/mercurial/loggingutil.py +++ b/mercurial/loggingutil.py @@ -31,7 +31,7 @@ except OSError as err: if err.errno != errno.ENOENT: ui.debug( - "warning: cannot remove '%s': %s\n" + b"warning: cannot remove '%s': %s\n" % (newpath, err.strerror) ) try: @@ -40,7 +40,7 @@ except OSError as err: if err.errno != errno.ENOENT: ui.debug( - "warning: cannot rename '%s' to '%s': %s\n" + b"warning: cannot rename '%s' to '%s': %s\n" % (newpath, oldpath, err.strerror) ) @@ -54,11 +54,11 @@ path = vfs.join(name) for i in pycompat.xrange(maxfiles - 1, 1, -1): rotate( - oldpath="%s.%d" % (path, i - 1), - newpath="%s.%d" % (path, i), + oldpath=b"%s.%d" % (path, i - 1), + newpath=b"%s.%d" % (path, i), ) - rotate(oldpath=path, newpath=maxfiles > 0 and path + ".1") - return vfs(name, "a", makeparentdirs=False) + rotate(oldpath=path, newpath=maxfiles > 0 and path + b".1") + return vfs(name, b"a", makeparentdirs=False) def _formatlogline(msg): diff --git a/mercurial/lsprof.py b/mercurial/lsprof.py --- a/mercurial/lsprof.py +++ b/mercurial/lsprof.py @@ -8,7 +8,7 @@ # PyPy doesn't expose profiler_entry from the module. profiler_entry = getattr(_lsprof, "profiler_entry", None) -__all__ = ["profile", "Stats"] +__all__ = [b"profile", b"Stats"] def profile(f, *args, **kwds): @@ -33,9 +33,9 @@ # profiler_entries isn't defined when running under PyPy. if profiler_entry: if crit not in profiler_entry.__dict__: - raise ValueError("Can't sort by %s" % crit) + raise ValueError(b"Can't sort by %s" % crit) elif self.data and not getattr(self.data[0], crit, None): - raise ValueError("Can't sort by %s" % crit) + raise ValueError(b"Can't sort by %s" % crit) self.data.sort(key=lambda x: getattr(x, crit), reverse=True) for e in self.data: @@ -49,16 +49,16 @@ d = self.data if top is not None: d = d[:top] - cols = "% 12d %12d %11.4f %11.4f %s\n" - hcols = "% 12s %12s %12s %12s %s\n" + cols = b"% 12d %12d %11.4f %11.4f %s\n" + hcols = b"% 12s %12s %12s %12s %s\n" file.write( hcols % ( - "CallCount", - "Recursive", - "Total(s)", - "Inline(s)", - "module:lineno(function)", + b"CallCount", + b"Recursive", + b"Total(s)", + b"Inline(s)", + b"module:lineno(function)", ) ) count = 0 @@ -86,7 +86,7 @@ se.reccallcount, se.totaltime, se.inlinetime, - " %s" % label(se.code), + b" %s" % label(se.code), ) ) count += 1 @@ -147,7 +147,7 @@ sys.argv = sys.argv[1:] if not sys.argv: - print("usage: lsprof.py ") -_paranoidjsonmap[0x3E] = "\\u003e" # '>' +_paranoidjsonmap[0x3C] = b"\\u003c" # '<' (e.g. escape "") +_paranoidjsonmap[0x3E] = b"\\u003e" # '>' _jsonmap.extend(pycompat.bytechr(x) for x in range(128, 256)) @@ -63,7 +63,7 @@ else: jm = _jsonmap try: - return "".join(jm[x] for x in bytearray(u8chars)) + return b"".join(jm[x] for x in bytearray(u8chars)) except IndexError: raise ValueError @@ -87,4 +87,4 @@ u16b = u8chars.decode("utf-8", _utf8strict).encode("utf-16", _utf8strict) u16codes = array.array(r"H", u16b) u16codes.pop(0) # drop BOM - return "".join(jm[x] if x < 128 else "\\u%04x" % x for x in u16codes) + return b"".join(jm[x] if x < 128 else b"\\u%04x" % x for x in u16codes) diff --git a/mercurial/pure/mpatch.py b/mercurial/pure/mpatch.py --- a/mercurial/pure/mpatch.py +++ b/mercurial/pure/mpatch.py @@ -97,9 +97,9 @@ while pos < end: m.seek(pos) try: - p1, p2, l = struct.unpack(">lll", m.read(12)) + p1, p2, l = struct.unpack(b">lll", m.read(12)) except struct.error: - raise mpatchError("patch cannot be decoded") + raise mpatchError(b"patch cannot be decoded") _pull(new, frags, p1 - last) # what didn't change _pull([], frags, p2 - p1) # what got deleted new.append((l, pos + 12)) # what got added @@ -120,7 +120,7 @@ while data <= binend: decode = delta[bin : bin + 12] - start, end, length = struct.unpack(">lll", decode) + start, end, length = struct.unpack(b">lll", decode) if start > end: break bin = data + length @@ -130,7 +130,7 @@ outlen += length if bin != binend: - raise mpatchError("patch cannot be decoded") + raise mpatchError(b"patch cannot be decoded") outlen += orig - last return outlen diff --git a/mercurial/pure/osutil.py b/mercurial/pure/osutil.py --- a/mercurial/pure/osutil.py +++ b/mercurial/pure/osutil.py @@ -74,7 +74,7 @@ _SCM_RIGHTS = 0x01 _socklen_t = ctypes.c_uint - if pycompat.sysplatform.startswith("linux"): + if pycompat.sysplatform.startswith(b"linux"): # socket.h says "the type should be socklen_t but the definition of # the kernel is incompatible with this." _cmsg_len_t = ctypes.c_size_t @@ -122,7 +122,7 @@ else: # recvmsg isn't always provided by libc; such systems are unsupported def _recvmsg(sockfd, msg, flags): - raise NotImplementedError("unsupported platform") + raise NotImplementedError(b"unsupported platform") def _CMSG_FIRSTHDR(msgh): if msgh.msg_controllen < ctypes.sizeof(_cmsghdr): diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -28,9 +28,9 @@ return x -indexformatng = ">Qiiiiii20s12x" -indexfirst = struct.calcsize("Q") -sizeint = struct.calcsize("i") +indexformatng = b">Qiiiiii20s12x" +indexfirst = struct.calcsize(b"Q") +sizeint = struct.calcsize(b"i") indexsize = struct.calcsize(indexformatng) @@ -51,7 +51,7 @@ def _check_index(self, i): if not isinstance(i, int): - raise TypeError("expecting int indexes") + raise TypeError(b"expecting int indexes") if i < 0 or i >= len(self): raise IndexError @@ -83,7 +83,7 @@ def __delitem__(self, i): if not isinstance(i, slice) or not i.stop == -1 or i.step is not None: - raise ValueError("deleting slices only supports a:-1 with step 1") + raise ValueError(b"deleting slices only supports a:-1 with step 1") i = i.start self._check_index(i) if i < self._lgt: @@ -108,19 +108,19 @@ count = 0 while off <= len(self._data) - indexsize: (s,) = struct.unpack( - ">i", self._data[off + indexfirst : off + sizeint + indexfirst] + b">i", self._data[off + indexfirst : off + sizeint + indexfirst] ) if lgt is not None: self._offsets[count] = off count += 1 off += indexsize + s if off != len(self._data): - raise ValueError("corrupted data") + raise ValueError(b"corrupted data") return count def __delitem__(self, i): if not isinstance(i, slice) or not i.stop == -1 or i.step is not None: - raise ValueError("deleting slices only supports a:-1 with step 1") + raise ValueError(b"deleting slices only supports a:-1 with step 1") i = i.start self._check_index(i) if i < self._lgt: @@ -143,7 +143,7 @@ def parse_dirstate(dmap, copymap, st): parents = [st[:20], st[20:40]] # dereference fields so they will be local in loop - format = ">cllll" + format = b">cllll" e_size = struct.calcsize(format) pos1 = 40 l = len(st) @@ -151,11 +151,11 @@ # the inner loop while pos1 < l: pos2 = pos1 + e_size - e = _unpack(">cllll", st[pos1:pos2]) # a literal here is faster + e = _unpack(b">cllll", st[pos1:pos2]) # a literal here is faster pos1 = pos2 + e[4] f = st[pos2:pos1] - if "\0" in f: - f, c = f.split("\0") + if b"\0" in f: + f, c = f.split(b"\0") copymap[f] = c dmap[f] = e[:4] return parents @@ -165,9 +165,9 @@ now = int(now) cs = stringio() write = cs.write - write("".join(pl)) + write(b"".join(pl)) for f, e in dmap.iteritems(): - if e[0] == "n" and e[3] == now: + if e[0] == b"n" and e[3] == now: # The file was last modified "simultaneously" with the current # write to dirstate (i.e. within the same second for file- # systems with a granularity of 1 sec). This commonly happens @@ -181,8 +181,8 @@ dmap[f] = e if f in copymap: - f = "%s\0%s" % (f, copymap[f]) - e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f)) + f = b"%s\0%s" % (f, copymap[f]) + e = _pack(b">cllll", e[0], e[1], e[2], e[3], len(f)) write(e) write(f) return cs.getvalue() diff --git a/mercurial/pushkey.py b/mercurial/pushkey.py --- a/mercurial/pushkey.py +++ b/mercurial/pushkey.py @@ -18,17 +18,17 @@ def _nslist(repo): n = {} for k in _namespaces: - n[k] = "" + n[k] = b"" if not obsolete.isenabled(repo, obsolete.exchangeopt): - n.pop("obsolete") + n.pop(b"obsolete") return n _namespaces = { - "namespaces": (lambda *x: False, _nslist), - "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks), - "phases": (phases.pushphase, phases.listphases), - "obsolete": (obsolete.pushmarker, obsolete.listmarkers), + b"namespaces": (lambda *x: False, _nslist), + b"bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks), + b"phases": (phases.pushphase, phases.listphases), + b"obsolete": (obsolete.pushmarker, obsolete.listmarkers), } @@ -59,13 +59,13 @@ def encodekeys(keys): """encode the content of a pushkey namespace for exchange over the wire""" - return "\n".join(["%s\t%s" % (encode(k), encode(v)) for k, v in keys]) + return b"\n".join([b"%s\t%s" % (encode(k), encode(v)) for k, v in keys]) def decodekeys(data): """decode the content of a pushkey namespace from exchange over the wire""" result = {} for l in data.splitlines(): - k, v = l.split("\t") + k, v = l.split(b"\t") result[decode(k)] = decode(v) return result diff --git a/mercurial/pvec.py b/mercurial/pvec.py --- a/mercurial/pvec.py +++ b/mercurial/pvec.py @@ -74,7 +74,7 @@ def _str(v, l): - bs = "" + bs = b"" for p in pycompat.xrange(l): bs = chr(v & 255) + bs v >>= 8 @@ -159,7 +159,7 @@ def ctxpvec(ctx): """construct a pvec for ctx while filling in the cache""" r = ctx.repo() - if not util.safehasattr(r, "_pveccache"): + if not util.safehasattr(r, b"_pveccache"): r._pveccache = {} pvc = r._pveccache if ctx.rev() not in pvc: @@ -213,7 +213,7 @@ def __sub__(self, b): if self | b: - raise ValueError("concurrent pvecs") + raise ValueError(b"concurrent pvecs") return self._depth - b._depth def distance(self, b): diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -354,7 +354,7 @@ bytesurl = identity # this can't be parsed on Python 3 - exec("def raisewithtb(exc, tb):\n" " raise exc, None, tb\n") + exec(b"def raisewithtb(exc, tb):\n" b" raise exc, None, tb\n") def fsencode(filename): """ diff --git a/mercurial/rcutil.py b/mercurial/rcutil.py --- a/mercurial/rcutil.py +++ b/mercurial/rcutil.py @@ -31,7 +31,7 @@ if os.path.isdir(p): join = os.path.join return sorted( - join(p, f) for f, k in util.listdir(p) if f.endswith(".rc") + join(p, f) for f, k in util.listdir(p) if f.endswith(b".rc") ) return [p] @@ -47,22 +47,22 @@ if env is None: env = encoding.environ checklist = [ - ("EDITOR", "ui", "editor"), - ("VISUAL", "ui", "editor"), - ("PAGER", "pager", "pager"), + (b"EDITOR", b"ui", b"editor"), + (b"VISUAL", b"ui", b"editor"), + (b"PAGER", b"pager", b"pager"), ] result = [] for envname, section, configname in checklist: if envname not in env: continue - result.append((section, configname, env[envname], "$%s" % envname)) + result.append((section, configname, env[envname], b"$%s" % envname)) return result def defaultrcpath(): """return rc paths in default.d""" path = [] - defaultpath = os.path.join(util.datapath, "default.d") + defaultpath = os.path.join(util.datapath, b"default.d") if os.path.isdir(defaultpath): path = _expandrcpath(defaultpath) return path @@ -80,18 +80,20 @@ and is the config file path. if type is 'items', obj is a list of (section, name, value, source) that should fill the config directly. """ - envrc = ("items", envrcitems()) + envrc = (b"items", envrcitems()) - if "HGRCPATH" in encoding.environ: + if b"HGRCPATH" in encoding.environ: # assume HGRCPATH is all about user configs so environments can be # overridden. _rccomponents = [envrc] - for p in encoding.environ["HGRCPATH"].split(pycompat.ospathsep): + for p in encoding.environ[b"HGRCPATH"].split(pycompat.ospathsep): if not p: continue - _rccomponents.extend(("path", p) for p in _expandrcpath(p)) + _rccomponents.extend((b"path", p) for p in _expandrcpath(p)) else: - normpaths = lambda paths: [("path", os.path.normpath(p)) for p in paths] + normpaths = lambda paths: [ + (b"path", os.path.normpath(p)) for p in paths + ] _rccomponents = normpaths(defaultrcpath() + systemrcpath()) _rccomponents.append(envrc) _rccomponents.extend(normpaths(userrcpath())) @@ -102,4 +104,4 @@ """return a dict of default environment variables and their values, intended to be set before starting a pager. """ - return {"LESS": "FRX", "LV": "-c"} + return {b"LESS": b"FRX", b"LV": b"-c"} diff --git a/mercurial/registrar.py b/mercurial/registrar.py --- a/mercurial/registrar.py +++ b/mercurial/registrar.py @@ -62,10 +62,10 @@ name = self._getname(decl) if name in self._table: - msg = 'duplicate registration for name: "%s"' % name + msg = b'duplicate registration for name: "%s"' % name raise error.ProgrammingError(msg) - if func.__doc__ and not util.safehasattr(func, "_origdoc"): + if func.__doc__ and not util.safehasattr(func, b"_origdoc"): func._origdoc = func.__doc__.strip() doc = pycompat.sysbytes(func._origdoc) func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc)) @@ -83,13 +83,13 @@ of the two registrars must match. """ if not isinstance(registrarbase, type(self)): - msg = "cannot merge different types of registrar" + msg = b"cannot merge different types of registrar" raise error.ProgrammingError(msg) dups = set(registrarbase._table).intersection(self._table) if dups: - msg = 'duplicate registration for names: "%s"' % '", "'.join(dups) + msg = b'duplicate registration for names: "%s"' % b'", "'.join(dups) raise error.ProgrammingError(msg) self._table.update(registrarbase._table) @@ -97,7 +97,7 @@ def _parsefuncdecl(self, decl): """Parse function declaration and return the name of function in it """ - i = decl.find("(") + i = decl.find(b"(") if i >= 0: return decl[:i] else: @@ -195,19 +195,19 @@ # [alias] # myalias = something # myalias:category = repo - CATEGORY_REPO_CREATION = "repo" - CATEGORY_REMOTE_REPO_MANAGEMENT = "remote" - CATEGORY_COMMITTING = "commit" - CATEGORY_CHANGE_MANAGEMENT = "management" - CATEGORY_CHANGE_ORGANIZATION = "organization" - CATEGORY_FILE_CONTENTS = "files" - CATEGORY_CHANGE_NAVIGATION = "navigation" - CATEGORY_WORKING_DIRECTORY = "wdir" - CATEGORY_IMPORT_EXPORT = "import" - CATEGORY_MAINTENANCE = "maintenance" - CATEGORY_HELP = "help" - CATEGORY_MISC = "misc" - CATEGORY_NONE = "none" + CATEGORY_REPO_CREATION = b"repo" + CATEGORY_REMOTE_REPO_MANAGEMENT = b"remote" + CATEGORY_COMMITTING = b"commit" + CATEGORY_CHANGE_MANAGEMENT = b"management" + CATEGORY_CHANGE_ORGANIZATION = b"organization" + CATEGORY_FILE_CONTENTS = b"files" + CATEGORY_CHANGE_NAVIGATION = b"navigation" + CATEGORY_WORKING_DIRECTORY = b"wdir" + CATEGORY_IMPORT_EXPORT = b"import" + CATEGORY_MAINTENANCE = b"maintenance" + CATEGORY_HELP = b"help" + CATEGORY_MISC = b"misc" + CATEGORY_NONE = b"none" def _doregister( self, @@ -280,7 +280,7 @@ """ _getname = _funcregistrarbase._parsefuncdecl - _docformat = "``%s``\n %s" + _docformat = b"``%s``\n %s" def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1): func._safe = safe @@ -331,7 +331,7 @@ """ _getname = _funcregistrarbase._parsefuncdecl - _docformat = "``%s``\n %s" + _docformat = b"``%s``\n %s" def _extrasetup(self, name, func, callstatus=False, weight=1): func._callstatus = callstatus @@ -342,7 +342,7 @@ """Base of decorator to register functions as template specific one """ - _docformat = ":%s: %s" + _docformat = b":%s: %s" class templatekeyword(_templateregistrarbase): @@ -506,12 +506,12 @@ Otherwise, explicit 'filemerge.loadinternalmerge()' is needed. """ - _docformat = "``:%s``\n %s" + _docformat = b"``:%s``\n %s" # merge type definitions: nomerge = None - mergeonly = "mergeonly" # just the full merge, no premerge - fullmerge = "fullmerge" # both premerge and merge + mergeonly = b"mergeonly" # just the full merge, no premerge + fullmerge = b"fullmerge" # both premerge and merge def _extrasetup( self, @@ -531,4 +531,4 @@ symlinkcap = symlink or mergetype == self.nomerge # actual capabilities, which this internal merge tool has - func.capabilities = {"binary": binarycap, "symlink": symlinkcap} + func.capabilities = {b"binary": binarycap, b"symlink": symlinkcap} diff --git a/mercurial/repair.py b/mercurial/repair.py --- a/mercurial/repair.py +++ b/mercurial/repair.py @@ -36,16 +36,16 @@ ): """create a bundle with the specified revisions as a backup""" - backupdir = "strip-backup" + backupdir = b"strip-backup" vfs = repo.vfs if not vfs.isdir(backupdir): vfs.mkdir(backupdir) # Include a hash of all the nodes in the filename for uniqueness - allcommits = repo.set("%ln::%ln", bases, heads) + allcommits = repo.set(b"%ln::%ln", bases, heads) allhashes = sorted(c.hex() for c in allcommits) - totalhash = hashlib.sha1("".join(allhashes)).digest() - name = "%s/%s-%s-%s.hg" % ( + totalhash = hashlib.sha1(b"".join(allhashes)).digest() + name = b"%s/%s-%s-%s.hg" % ( backupdir, short(node), hex(totalhash[:4]), @@ -54,25 +54,25 @@ cgversion = changegroup.localversion(repo) comp = None - if cgversion != "01": - bundletype = "HG20" + if cgversion != b"01": + bundletype = b"HG20" if compress: - comp = "BZ" + comp = b"BZ" elif compress: - bundletype = "HG10BZ" + bundletype = b"HG10BZ" else: - bundletype = "HG10UN" + bundletype = b"HG10UN" outgoing = discovery.outgoing(repo, missingroots=bases, missingheads=heads) contentopts = { - "cg.version": cgversion, - "obsolescence": obsolescence, - "phases": True, + b"cg.version": cgversion, + b"obsolescence": obsolescence, + b"phases": True, } return bundle2.writenewbundle( repo.ui, repo, - "strip", + b"strip", name, bundletype, outgoing, @@ -109,16 +109,16 @@ return s -def strip(ui, repo, nodelist, backup=True, topic="backup"): +def strip(ui, repo, nodelist, backup=True, topic=b"backup"): # This function requires the caller to lock the repo, but it operates # within a transaction of its own, and thus requires there to be no current # transaction when it is called. if repo.currenttransaction() is not None: - raise error.ProgrammingError("cannot strip from inside a transaction") + raise error.ProgrammingError(b"cannot strip from inside a transaction") # Simple way to maintain backwards compatibility for this # argument. - if backup in ["none", "strip"]: + if backup in [b"none", b"strip"]: backup = False repo = repo.unfiltered() @@ -165,7 +165,7 @@ stripbases = [cl.node(r) for r in tostrip] stripobsidx = obsmarkers = () - if repo.ui.configbool("devel", "strip-obsmarkers"): + if repo.ui.configbool(b"devel", b"strip-obsmarkers"): obsmarkers = obsutil.exclusivemarkers(repo, stripbases) if obsmarkers: stripobsidx = [ @@ -192,14 +192,14 @@ savebases, saveheads, node, - "temp", + b"temp", compress=False, obsolescence=False, ) with ui.uninterruptible(): try: - with repo.transaction("strip") as tr: + with repo.transaction(b"strip") as tr: # TODO this code violates the interface abstraction of the # transaction and makes assumptions that file storage is # using append-only files. We'll need some kind of storage @@ -216,7 +216,7 @@ for i in pycompat.xrange(offset, len(tr._entries)): file, troffset, ignore = tr._entries[i] - with repo.svfs(file, "a", checkambig=True) as fp: + with repo.svfs(file, b"a", checkambig=True) as fp: fp.truncate(troffset) if troffset == 0: repo.store.markremoved(file) @@ -227,25 +227,25 @@ repo._phasecache.filterunknown(repo) if tmpbundlefile: - ui.note(_("adding branch\n")) - f = vfs.open(tmpbundlefile, "rb") + ui.note(_(b"adding branch\n")) + f = vfs.open(tmpbundlefile, b"rb") gen = exchange.readbundle(ui, f, tmpbundlefile, vfs) if not repo.ui.verbose: # silence internal shuffling chatter repo.ui.pushbuffer() - tmpbundleurl = "bundle:" + vfs.join(tmpbundlefile) - txnname = "strip" + tmpbundleurl = b"bundle:" + vfs.join(tmpbundlefile) + txnname = b"strip" if not isinstance(gen, bundle2.unbundle20): - txnname = "strip\n%s" % util.hidepassword(tmpbundleurl) + txnname = b"strip\n%s" % util.hidepassword(tmpbundleurl) with repo.transaction(txnname) as tr: bundle2.applybundle( - repo, gen, tr, source="strip", url=tmpbundleurl + repo, gen, tr, source=b"strip", url=tmpbundleurl ) if not repo.ui.verbose: repo.ui.popbuffer() f.close() - with repo.transaction("repair") as tr: + with repo.transaction(b"repair") as tr: bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] repo._bookmarks.applychanges(repo, tr, bmchanges) @@ -256,7 +256,7 @@ except OSError as e: if e.errno != errno.ENOENT: ui.warn( - _("error removing %s: %s\n") + _(b"error removing %s: %s\n") % ( undovfs.join(undofile), stringutil.forcebytestr(e), @@ -266,18 +266,18 @@ except: # re-raises if backupfile: ui.warn( - _("strip failed, backup bundle stored in '%s'\n") + _(b"strip failed, backup bundle stored in '%s'\n") % vfs.join(backupfile) ) if tmpbundlefile: ui.warn( - _("strip failed, unrecovered changes stored in '%s'\n") + _(b"strip failed, unrecovered changes stored in '%s'\n") % vfs.join(tmpbundlefile) ) ui.warn( _( - "(fix the problem, then recover the changesets with " - "\"hg unbundle '%s'\")\n" + b"(fix the problem, then recover the changesets with " + b"\"hg unbundle '%s'\")\n" ) % vfs.join(tmpbundlefile) ) @@ -293,9 +293,9 @@ return backupfile -def softstrip(ui, repo, nodelist, backup=True, topic="backup"): +def softstrip(ui, repo, nodelist, backup=True, topic=b"backup"): """perform a "soft" strip using the archived phase""" - tostrip = [c.node() for c in repo.set("sort(%ln::)", nodelist)] + tostrip = [c.node() for c in repo.set(b"sort(%ln::)", nodelist)] if not tostrip: return None @@ -304,7 +304,7 @@ node = tostrip[0] backupfile = _createstripbackup(repo, tostrip, node, topic) - with repo.transaction("strip") as tr: + with repo.transaction(b"strip") as tr: phases.retractboundary(repo, tr, phases.archived, tostrip) bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] repo._bookmarks.applychanges(repo, tr, bmchanges) @@ -325,11 +325,11 @@ if updatebm: # For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), # but is much faster - newbmtarget = repo.revs("max(parents(%ld) - (%ld))", tostrip, tostrip) + newbmtarget = repo.revs(b"max(parents(%ld) - (%ld))", tostrip, tostrip) if newbmtarget: newbmtarget = repo[newbmtarget.first()].node() else: - newbmtarget = "." + newbmtarget = b"." return newbmtarget, updatebm @@ -338,9 +338,9 @@ vfs = repo.vfs cl = repo.changelog backupfile = backupbundle(repo, stripbases, cl.heads(), node, topic) - repo.ui.status(_("saved backup bundle to %s\n") % vfs.join(backupfile)) + repo.ui.status(_(b"saved backup bundle to %s\n") % vfs.join(backupfile)) repo.ui.log( - "backupbundle", "saved backup bundle to %s\n", vfs.join(backupfile) + b"backupbundle", b"saved backup bundle to %s\n", vfs.join(backupfile) ) return backupfile @@ -353,16 +353,16 @@ # orphaned = affected - wanted # affected = descendants(roots(wanted)) # wanted = revs - revset = "%ld - ( ::( (roots(%ld):: and not _phase(%s)) -%ld) )" + revset = b"%ld - ( ::( (roots(%ld):: and not _phase(%s)) -%ld) )" tostrip = set(repo.revs(revset, revs, revs, phases.internal, revs)) notstrip = revs - tostrip if notstrip: - nodestr = ", ".join(sorted(short(repo[n].node()) for n in notstrip)) + nodestr = b", ".join(sorted(short(repo[n].node()) for n in notstrip)) ui.warn( - _("warning: orphaned descendants detected, " "not stripping %s\n") + _(b"warning: orphaned descendants detected, " b"not stripping %s\n") % nodestr ) - return [c.node() for c in repo.set("roots(%ld)", tostrip)] + return [c.node() for c in repo.set(b"roots(%ld)", tostrip)] class stripcallback(object): @@ -372,7 +372,7 @@ self.ui = ui self.repo = repo self.backup = backup - self.topic = topic or "backup" + self.topic = topic or b"backup" self.nodelist = [] def addnodes(self, nodes): @@ -399,10 +399,10 @@ return strip(ui, repo, nodes, backup=backup, topic=topic) # transaction postclose callbacks are called in alphabet order. # use '\xff' as prefix so we are likely to be called last. - callback = tr.getpostclose("\xffstrip") + callback = tr.getpostclose(b"\xffstrip") if callback is None: callback = stripcallback(ui, repo, backup=backup, topic=topic) - tr.addpostclose("\xffstrip", callback) + tr.addpostclose(b"\xffstrip", callback) if topic: callback.topic = topic callback.addnodes(nodelist) @@ -415,12 +415,12 @@ def manifestrevlogs(repo): yield repo.manifestlog.getstorage(b"") - if "treemanifest" in repo.requirements: + if b"treemanifest" in repo.requirements: # This logic is safe if treemanifest isn't enabled, but also # pointless, so we skip it if treemanifest isn't enabled. for unencoded, encoded, size in repo.store.datafiles(): - if unencoded.startswith("meta/") and unencoded.endswith( - "00manifest.i" + if unencoded.startswith(b"meta/") and unencoded.endswith( + b"00manifest.i" ): dir = unencoded[5:-12] yield repo.manifestlog.getstorage(dir) @@ -433,11 +433,11 @@ """ repo = repo.unfiltered() - if "fncache" not in repo.requirements: + if b"fncache" not in repo.requirements: ui.warn( _( - "(not rebuilding fncache because repository does not " - "support fncache)\n" + b"(not rebuilding fncache because repository does not " + b"support fncache)\n" ) ) return @@ -451,7 +451,7 @@ seenfiles = set() progress = ui.makeprogress( - _("rebuilding"), unit=_("changesets"), total=len(repo) + _(b"rebuilding"), unit=_(b"changesets"), total=len(repo) ) for rev in repo: progress.update(rev) @@ -463,8 +463,8 @@ continue seenfiles.add(f) - i = "data/%s.i" % f - d = "data/%s.d" % f + i = b"data/%s.i" % f + d = b"data/%s.d" % f if repo.store._exists(i): newentries.add(i) @@ -473,12 +473,12 @@ progress.complete() - if "treemanifest" in repo.requirements: + if b"treemanifest" in repo.requirements: # This logic is safe if treemanifest isn't enabled, but also # pointless, so we skip it if treemanifest isn't enabled. for dir in util.dirs(seenfiles): - i = "meta/%s/00manifest.i" % dir - d = "meta/%s/00manifest.d" % dir + i = b"meta/%s/00manifest.i" % dir + d = b"meta/%s/00manifest.d" % dir if repo.store._exists(i): newentries.add(i) @@ -488,22 +488,22 @@ addcount = len(newentries - oldentries) removecount = len(oldentries - newentries) for p in sorted(oldentries - newentries): - ui.write(_("removing %s\n") % p) + ui.write(_(b"removing %s\n") % p) for p in sorted(newentries - oldentries): - ui.write(_("adding %s\n") % p) + ui.write(_(b"adding %s\n") % p) if addcount or removecount: ui.write( - _("%d items added, %d removed from fncache\n") + _(b"%d items added, %d removed from fncache\n") % (addcount, removecount) ) fnc.entries = newentries fnc._dirty = True - with repo.transaction("fncache") as tr: + with repo.transaction(b"fncache") as tr: fnc.write(tr) else: - ui.write(_("fncache already up to date\n")) + ui.write(_(b"fncache already up to date\n")) def deleteobsmarkers(obsstore, indices): @@ -529,7 +529,7 @@ continue left.append(m) - newobsstorefile = obsstore.svfs("obsstore", "w", atomictemp=True) + newobsstorefile = obsstore.svfs(b"obsstore", b"w", atomictemp=True) for bytes in obsolete.encodemarkers(left, True, obsstore._version): newobsstorefile.write(bytes) newobsstorefile.close() diff --git a/mercurial/repocache.py b/mercurial/repocache.py --- a/mercurial/repocache.py +++ b/mercurial/repocache.py @@ -128,12 +128,12 @@ """Copy cached attributes from srcrepo to destrepo""" destfilecache = destrepo._filecache srcfilecache = srcrepo._filecache - if "changelog" in srcfilecache: - destfilecache["changelog"] = ce = srcfilecache["changelog"] + if b"changelog" in srcfilecache: + destfilecache[b"changelog"] = ce = srcfilecache[b"changelog"] ce.obj.opener = ce.obj._realopener = destrepo.svfs - if "obsstore" in srcfilecache: - destfilecache["obsstore"] = ce = srcfilecache["obsstore"] + if b"obsstore" in srcfilecache: + destfilecache[b"obsstore"] = ce = srcfilecache[b"obsstore"] ce.obj.svfs = destrepo.svfs - if "_phasecache" in srcfilecache: - destfilecache["_phasecache"] = ce = srcfilecache["_phasecache"] + if b"_phasecache" in srcfilecache: + destfilecache[b"_phasecache"] = ce = srcfilecache[b"_phasecache"] ce.obj.opener = destrepo.svfs diff --git a/mercurial/repoview.py b/mercurial/repoview.py --- a/mercurial/repoview.py +++ b/mercurial/repoview.py @@ -31,7 +31,7 @@ branchmap (see mercurial.utils.repoviewutils.subsettable), you cannot set "public" changesets as "hideable". Doing so would break multiple code assertions and lead to crashes.""" - obsoletes = obsolete.getrevs(repo, "obsolete") + obsoletes = obsolete.getrevs(repo, b"obsolete") internals = repo._phasecache.getrevset(repo, phases.localhiddenphases) internals = frozenset(internals) return obsoletes | internals @@ -107,8 +107,8 @@ Secret and hidden changeset should not pretend to be here.""" assert not repo.changelog.filteredrevs # fast path in simple case to avoid impact of non optimised code - hiddens = filterrevs(repo, "visible") - secrets = filterrevs(repo, "served.hidden") + hiddens = filterrevs(repo, b"visible") + secrets = filterrevs(repo, b"served.hidden") if secrets: return frozenset(hiddens | secrets) else: @@ -120,7 +120,7 @@ # fast check to avoid revset call on huge repo if any(repo._phasecache.phaseroots[1:]): getphase = repo._phasecache.phase - maymutable = filterrevs(repo, "base") + maymutable = filterrevs(repo, b"base") return frozenset(r for r in maymutable if getphase(repo, r)) return frozenset() @@ -158,12 +158,12 @@ # Otherwise your filter will have to recompute all its branches cache # from scratch (very slow). filtertable = { - "visible": computehidden, - "visible-hidden": computehidden, - "served.hidden": computesecret, - "served": computeunserved, - "immutable": computemutable, - "base": computeimpactable, + b"visible": computehidden, + b"visible-hidden": computehidden, + b"served.hidden": computesecret, + b"served": computeunserved, + b"immutable": computemutable, + b"base": computeimpactable, } _basefiltername = list(filtertable) @@ -175,17 +175,17 @@ If extra filtering is configured, we make sure the associated filtered view are declared and return the associated id. """ - frevs = ui.config("experimental", "extra-filter-revs") + frevs = ui.config(b"experimental", b"extra-filter-revs") if frevs is None: return None - fid = pycompat.sysbytes(util.DIGESTS["sha1"](frevs).hexdigest())[:12] + fid = pycompat.sysbytes(util.DIGESTS[b"sha1"](frevs).hexdigest())[:12] - combine = lambda fname: fname + "%" + fid + combine = lambda fname: fname + b"%" + fid subsettable = repoviewutil.subsettable - if combine("base") not in filtertable: + if combine(b"base") not in filtertable: for name in _basefiltername: def extrafilteredrevs(repo, *args, **kwargs): diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -142,7 +142,7 @@ def offset_type(offset, type): if (type & ~flagutil.REVIDX_KNOWN_FLAGS) != 0: - raise ValueError("unknown revlog index flags") + raise ValueError(b"unknown revlog index flags") return int(int(offset) << 16 | type) @@ -197,7 +197,7 @@ # 20 bytes: parent 1 nodeid # 20 bytes: parent 2 nodeid # 20 bytes: nodeid -indexformatv0 = struct.Struct(">4l20s20s20s") +indexformatv0 = struct.Struct(b">4l20s20s20s") indexformatv0_pack = indexformatv0.pack indexformatv0_unpack = indexformatv0.unpack @@ -243,7 +243,7 @@ def packentry(self, entry, node, version, rev): if gettype(entry[0]): raise error.RevlogError( - _("index entry flags need revlog " "version 1") + _(b"index entry flags need revlog " b"version 1") ) e2 = ( getoffset(entry[0]), @@ -267,9 +267,9 @@ # 4 bytes: parent 1 rev # 4 bytes: parent 2 rev # 32 bytes: nodeid -indexformatng = struct.Struct(">Qiiiiii20s12x") +indexformatng = struct.Struct(b">Qiiiiii20s12x") indexformatng_pack = indexformatng.pack -versionformat = struct.Struct(">I") +versionformat = struct.Struct(b">I") versionformat_pack = versionformat.pack versionformat_unpack = versionformat.unpack @@ -353,7 +353,7 @@ """ self.upperboundcomp = upperboundcomp self.indexfile = indexfile - self.datafile = datafile or (indexfile[:-2] + ".d") + self.datafile = datafile or (indexfile[:-2] + b".d") self.opener = opener # When True, indexfile is opened with checkambig=True at writing, to # avoid file stat ambiguity. @@ -365,7 +365,7 @@ # Maps rev to chain base rev. self._chainbasecache = util.lrucachedict(100) # 2-tuple of (offset, data) of raw data from the revlog at an offset. - self._chunkcache = (0, "") + self._chunkcache = (0, b"") # How much data to read and cache into the raw revlog data cache. self._chunkcachesize = 65536 self._maxchainlen = None @@ -376,7 +376,7 @@ # Mapping of revision integer to full node. self._nodecache = {nullid: nullrev} self._nodepos = None - self._compengine = "zlib" + self._compengine = b"zlib" self._compengineopts = {} self._maxdeltachainspan = -1 self._withsparseread = False @@ -397,49 +397,49 @@ mmapindexthreshold = None opts = self.opener.options - if "revlogv2" in opts: + if b"revlogv2" in opts: newversionflags = REVLOGV2 | FLAG_INLINE_DATA - elif "revlogv1" in opts: + elif b"revlogv1" in opts: newversionflags = REVLOGV1 | FLAG_INLINE_DATA - if "generaldelta" in opts: + if b"generaldelta" in opts: newversionflags |= FLAG_GENERALDELTA - elif "revlogv0" in self.opener.options: + elif b"revlogv0" in self.opener.options: newversionflags = REVLOGV0 else: newversionflags = REVLOG_DEFAULT_VERSION - if "chunkcachesize" in opts: - self._chunkcachesize = opts["chunkcachesize"] - if "maxchainlen" in opts: - self._maxchainlen = opts["maxchainlen"] - if "deltabothparents" in opts: - self._deltabothparents = opts["deltabothparents"] - self._lazydelta = bool(opts.get("lazydelta", True)) + if b"chunkcachesize" in opts: + self._chunkcachesize = opts[b"chunkcachesize"] + if b"maxchainlen" in opts: + self._maxchainlen = opts[b"maxchainlen"] + if b"deltabothparents" in opts: + self._deltabothparents = opts[b"deltabothparents"] + self._lazydelta = bool(opts.get(b"lazydelta", True)) self._lazydeltabase = False if self._lazydelta: - self._lazydeltabase = bool(opts.get("lazydeltabase", False)) - if "compengine" in opts: - self._compengine = opts["compengine"] - if "zlib.level" in opts: - self._compengineopts["zlib.level"] = opts["zlib.level"] - if "zstd.level" in opts: - self._compengineopts["zstd.level"] = opts["zstd.level"] - if "maxdeltachainspan" in opts: - self._maxdeltachainspan = opts["maxdeltachainspan"] - if self._mmaplargeindex and "mmapindexthreshold" in opts: - mmapindexthreshold = opts["mmapindexthreshold"] - self.hassidedata = bool(opts.get("side-data", False)) + self._lazydeltabase = bool(opts.get(b"lazydeltabase", False)) + if b"compengine" in opts: + self._compengine = opts[b"compengine"] + if b"zlib.level" in opts: + self._compengineopts[b"zlib.level"] = opts[b"zlib.level"] + if b"zstd.level" in opts: + self._compengineopts[b"zstd.level"] = opts[b"zstd.level"] + if b"maxdeltachainspan" in opts: + self._maxdeltachainspan = opts[b"maxdeltachainspan"] + if self._mmaplargeindex and b"mmapindexthreshold" in opts: + mmapindexthreshold = opts[b"mmapindexthreshold"] + self.hassidedata = bool(opts.get(b"side-data", False)) if self.hassidedata: self._flagprocessors[REVIDX_SIDEDATA] = sidedatautil.processors - self._sparserevlog = bool(opts.get("sparse-revlog", False)) - withsparseread = bool(opts.get("with-sparse-read", False)) + self._sparserevlog = bool(opts.get(b"sparse-revlog", False)) + withsparseread = bool(opts.get(b"with-sparse-read", False)) # sparse-revlog forces sparse-read self._withsparseread = self._sparserevlog or withsparseread - if "sparse-read-density-threshold" in opts: - self._srdensitythreshold = opts["sparse-read-density-threshold"] - if "sparse-read-min-gap-size" in opts: - self._srmingapsize = opts["sparse-read-min-gap-size"] - if opts.get("enableellipsis"): + if b"sparse-read-density-threshold" in opts: + self._srdensitythreshold = opts[b"sparse-read-density-threshold"] + if b"sparse-read-min-gap-size" in opts: + self._srmingapsize = opts[b"sparse-read-min-gap-size"] + if opts.get(b"enableellipsis"): self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor # revlog v0 doesn't have flag processors @@ -448,16 +448,16 @@ if self._chunkcachesize <= 0: raise error.RevlogError( - _("revlog chunk cache size %r is not " "greater than 0") + _(b"revlog chunk cache size %r is not " b"greater than 0") % self._chunkcachesize ) elif self._chunkcachesize & (self._chunkcachesize - 1): raise error.RevlogError( - _("revlog chunk cache size %r is not a " "power of 2") + _(b"revlog chunk cache size %r is not a " b"power of 2") % self._chunkcachesize ) - indexdata = "" + indexdata = b"" self._initempty = True try: with self._indexfp() as f: @@ -489,7 +489,7 @@ if fmt == REVLOGV0: if flags: raise error.RevlogError( - _("unknown flags (%#04x) in version %d " "revlog %s") + _(b"unknown flags (%#04x) in version %d " b"revlog %s") % (flags >> 16, fmt, self.indexfile) ) @@ -499,7 +499,7 @@ elif fmt == REVLOGV1: if flags & ~REVLOGV1_FLAGS: raise error.RevlogError( - _("unknown flags (%#04x) in version %d " "revlog %s") + _(b"unknown flags (%#04x) in version %d " b"revlog %s") % (flags >> 16, fmt, self.indexfile) ) @@ -509,7 +509,7 @@ elif fmt == REVLOGV2: if flags & ~REVLOGV2_FLAGS: raise error.RevlogError( - _("unknown flags (%#04x) in version %d " "revlog %s") + _(b"unknown flags (%#04x) in version %d " b"revlog %s") % (flags >> 16, fmt, self.indexfile) ) @@ -519,7 +519,7 @@ else: raise error.RevlogError( - _("unknown version (%d) in revlog %s") % (fmt, self.indexfile) + _(b"unknown version (%d) in revlog %s") % (fmt, self.indexfile) ) # sparse-revlog can't be on without general-delta (issue6056) if not self._generaldelta: @@ -533,7 +533,9 @@ try: d = self._io.parseindex(indexdata, self._inline) except (ValueError, IndexError): - raise error.RevlogError(_("index %s is corrupted") % self.indexfile) + raise error.RevlogError( + _(b"index %s is corrupted") % self.indexfile + ) self.index, nodemap, self._chunkcache = d if nodemap is not None: self.nodemap = self._nodecache = nodemap @@ -549,16 +551,16 @@ engine = util.compengines[self._compengine] return engine.revlogcompressor(self._compengineopts) - def _indexfp(self, mode="r"): + def _indexfp(self, mode=b"r"): """file object for the revlog's index file""" args = {r"mode": mode} - if mode != "r": + if mode != b"r": args[r"checkambig"] = self._checkambig - if mode == "w": + if mode == b"w": args[r"atomictemp"] = True return self.opener(self.indexfile, **args) - def _datafp(self, mode="r"): + def _datafp(self, mode=b"r"): """file object for the revlog's data file""" return self.opener(self.datafile, mode=mode) @@ -635,7 +637,7 @@ def clearcaches(self): self._revisioncache = None self._chainbasecache.clear() - self._chunkcache = (0, "") + self._chunkcache = (0, b"") self._pcache = {} try: @@ -656,7 +658,7 @@ # parsers.c radix tree lookup failed if node == wdirid or node in wdirfilenodeids: raise error.WdirUnsupported - raise error.LookupError(node, self.indexfile, _("no node")) + raise error.LookupError(node, self.indexfile, _(b"no node")) except KeyError: # pure python cache lookup failed n = self._nodecache @@ -674,7 +676,7 @@ return r if node == wdirid or node in wdirfilenodeids: raise error.WdirUnsupported - raise error.LookupError(node, self.indexfile, _("no node")) + raise error.LookupError(node, self.indexfile, _(b"no node")) # Accessors for index entries. @@ -848,7 +850,7 @@ if rustancestor is not None: lazyancestors = rustancestor.LazyAncestors arg = self.index - elif util.safehasattr(parsers, "rustlazyancestors"): + elif util.safehasattr(parsers, b"rustlazyancestors"): lazyancestors = ancestor.rustlazyancestors arg = self.index else: @@ -1289,7 +1291,7 @@ try: # str(rev) rev = int(id) - if "%d" % rev != id: + if b"%d" % rev != id: raise ValueError if rev < 0: rev = len(self) + rev @@ -1326,7 +1328,7 @@ # fast path: for unfiltered changelog, radix tree is accurate if not getattr(self, "filteredrevs", None): raise error.AmbiguousPrefixLookupError( - id, self.indexfile, _("ambiguous identifier") + id, self.indexfile, _(b"ambiguous identifier") ) # fall through to slow path that filters hidden revisions except (AttributeError, ValueError): @@ -1352,7 +1354,7 @@ self._pcache[id] = nl[0] return nl[0] raise error.AmbiguousPrefixLookupError( - id, self.indexfile, _("ambiguous identifier") + id, self.indexfile, _(b"ambiguous identifier") ) if maybewdir: raise error.WdirUnsupported @@ -1372,7 +1374,7 @@ if n: return n - raise error.LookupError(id, self.indexfile, _("no match found")) + raise error.LookupError(id, self.indexfile, _(b"no match found")) def shortest(self, node, minlength=1): """Find the shortest unambiguous prefix that matches node.""" @@ -1386,11 +1388,11 @@ # single 'ff...' match return True if matchednode is None: - raise error.LookupError(node, self.indexfile, _("no node")) + raise error.LookupError(node, self.indexfile, _(b"no node")) return True def maybewdir(prefix): - return all(c == "f" for c in pycompat.iterbytestr(prefix)) + return all(c == b"f" for c in pycompat.iterbytestr(prefix)) hexnode = hex(node) @@ -1407,7 +1409,7 @@ return disambiguate(hexnode, length) except error.RevlogError: if node != wdirid: - raise error.LookupError(node, self.indexfile, _("no node")) + raise error.LookupError(node, self.indexfile, _(b"no node")) except AttributeError: # Fall through to pure code pass @@ -1474,8 +1476,8 @@ if len(d) - startoffset < length: raise error.RevlogError( _( - "partial read of revlog %s; expected %d bytes from " - "offset %d, got %d" + b"partial read of revlog %s; expected %d bytes from " + b"offset %d, got %d" ) % ( self.indexfile if self._inline else self.datafile, @@ -1490,8 +1492,8 @@ if len(d) < length: raise error.RevlogError( _( - "partial read of revlog %s; expected %d bytes from offset " - "%d, got %d" + b"partial read of revlog %s; expected %d bytes from offset " + b"%d, got %d" ) % ( self.indexfile if self._inline else self.datafile, @@ -1629,7 +1631,7 @@ def _chunkclear(self): """Clear the raw chunk cache.""" - self._chunkcache = (0, "") + self._chunkcache = (0, b"") def deltaparent(self, rev): """return deltaparent of the given revision""" @@ -1646,7 +1648,7 @@ """ if not self._sparserevlog: return self.deltaparent(rev) == nullrev - elif util.safehasattr(self.index, "issnapshot"): + elif util.safehasattr(self.index, b"issnapshot"): # directly assign the method to cache the testing and access self.issnapshot = self.index.issnapshot return self.issnapshot(rev) @@ -1667,7 +1669,7 @@ def snapshotdepth(self, rev): """number of snapshot in the chain before this one""" if not self.issnapshot(rev): - raise error.ProgrammingError("revision %d not a snapshot") + raise error.ProgrammingError(b"revision %d not a snapshot") return len(self._deltachain(rev)[0]) - 1 def revdiff(self, rev1, rev2): @@ -1683,11 +1685,11 @@ def _processflags(self, text, flags, operation, raw=False): """deprecated entry point to access flag processors""" - msg = "_processflag(...) use the specialized variant" - util.nouideprecwarn(msg, "5.2", stacklevel=2) + msg = b"_processflag(...) use the specialized variant" + util.nouideprecwarn(msg, b"5.2", stacklevel=2) if raw: return text, flagutil.processflagsraw(self, text, flags) - elif operation == "read": + elif operation == b"read": return flagutil.processflagsread(self, text, flags) else: # write operation return flagutil.processflagswrite(self, text, flags) @@ -1703,10 +1705,10 @@ """ if raw: msg = ( - "revlog.revision(..., raw=True) is deprecated, " - "use revlog.rawdata(...)" + b"revlog.revision(..., raw=True) is deprecated, " + b"use revlog.rawdata(...)" ) - util.nouideprecwarn(msg, "5.2", stacklevel=2) + util.nouideprecwarn(msg, b"5.2", stacklevel=2) return self._revisiondata(nodeorrev, _df, raw=raw)[0] def sidedata(self, nodeorrev, _df=None): @@ -1729,7 +1731,7 @@ # fast path the special `nullid` rev if node == nullid: - return "", {} + return b"", {} # The text as stored inside the revlog. Might be the revision or might # need to be processed to retrieve the revision. @@ -1759,7 +1761,7 @@ try: r = flagutil.processflagsread(self, rawtext, flags) except error.SidedataHashError as exc: - msg = _("integrity check failed on %s:%s sidedata key %d") + msg = _(b"integrity check failed on %s:%s sidedata key %d") msg %= (self.indexfile, pycompat.bytestr(rev), exc.sidedatakey) raise error.RevlogError(msg) text, validatehash, sidedata = r @@ -1851,7 +1853,7 @@ if revornode is None: revornode = templatefilters.short(hex(node)) raise error.RevlogError( - _("integrity check failed on %s:%s") + _(b"integrity check failed on %s:%s") % (self.indexfile, pycompat.bytestr(revornode)) ) except error.RevlogError: @@ -1876,7 +1878,7 @@ trinfo = tr.find(self.indexfile) if trinfo is None: raise error.RevlogError( - _("%s not found in the transaction") % self.indexfile + _(b"%s not found in the transaction") % self.indexfile ) trindex = trinfo[2] @@ -1896,11 +1898,11 @@ # its usage. self._writinghandles = None - with self._indexfp("r") as ifh, self._datafp("w") as dfh: + with self._indexfp(b"r") as ifh, self._datafp(b"w") as dfh: for r in self: dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) - with self._indexfp("w") as fp: + with self._indexfp(b"w") as fp: self.version &= ~FLAG_INLINE_DATA self._inline = False io = self._io @@ -1947,7 +1949,7 @@ """ if link == nullrev: raise error.RevlogError( - _("attempted to add linkrev -1 to %s") % self.indexfile + _(b"attempted to add linkrev -1 to %s") % self.indexfile ) if sidedata is None: @@ -1955,7 +1957,7 @@ flags = flags & ~REVIDX_SIDEDATA elif not self.hassidedata: raise error.ProgrammingError( - _("trying to add sidedata to a revlog who don't support them") + _(b"trying to add sidedata to a revlog who don't support them") ) else: flags |= REVIDX_SIDEDATA @@ -1974,7 +1976,9 @@ if len(rawtext) > _maxentrysize: raise error.RevlogError( - _("%s: size of %d bytes exceeds maximum revlog storage of 2GiB") + _( + b"%s: size of %d bytes exceeds maximum revlog storage of 2GiB" + ) % (self.indexfile, len(rawtext)) ) @@ -2015,8 +2019,8 @@ """ dfh = None if not self._inline: - dfh = self._datafp("a+") - ifh = self._indexfp("a+") + dfh = self._datafp(b"a+") + ifh = self._indexfp(b"a+") try: return self._addrevision( node, @@ -2039,17 +2043,17 @@ def compress(self, data): """Generate a possibly-compressed representation of data.""" if not data: - return "", data + return b"", data compressed = self._compressor.compress(data) if compressed: # The revlog compressor added the header in the returned data. - return "", compressed - - if data[0:1] == "\0": - return "", data - return "u", data + return b"", compressed + + if data[0:1] == b"\0": + return b"", data + return b"u", data def decompress(self, data): """Decompress a revlog chunk. @@ -2083,18 +2087,18 @@ # compressed chunks. And this matters for changelog and manifest reads. t = data[0:1] - if t == "x": + if t == b"x": try: return _zlibdecompress(data) except zlib.error as e: raise error.RevlogError( - _("revlog decompress error: %s") + _(b"revlog decompress error: %s") % stringutil.forcebytestr(e) ) # '\0' is more common than 'u' so it goes first. - elif t == "\0": + elif t == b"\0": return data - elif t == "u": + elif t == b"u": return util.buffer(data, 1) try: @@ -2105,7 +2109,7 @@ compressor = engine.revlogcompressor(self._compengineopts) self._decompressors[t] = compressor except KeyError: - raise error.RevlogError(_("unknown compression type %r") % t) + raise error.RevlogError(_(b"unknown compression type %r") % t) return compressor.decompress(data) @@ -2139,11 +2143,11 @@ """ if node == nullid: raise error.RevlogError( - _("%s: attempt to add null revision") % self.indexfile + _(b"%s: attempt to add null revision") % self.indexfile ) if node == wdirid or node in wdirfilenodeids: raise error.RevlogError( - _("%s: attempt to add wdir revision") % self.indexfile + _(b"%s: attempt to add wdir revision") % self.indexfile ) if self._inline: @@ -2256,7 +2260,7 @@ """ if self._writinghandles: - raise error.ProgrammingError("cannot nest addgroup() calls") + raise error.ProgrammingError(b"cannot nest addgroup() calls") nodes = [] @@ -2264,7 +2268,7 @@ end = 0 if r: end = self.end(r - 1) - ifh = self._indexfp("a+") + ifh = self._indexfp(b"a+") isize = r * self._io.size if self._inline: transaction.add(self.indexfile, end + isize, r) @@ -2272,7 +2276,7 @@ else: transaction.add(self.indexfile, isize, r) transaction.add(self.datafile, end) - dfh = self._datafp("a+") + dfh = self._datafp(b"a+") def flush(): if dfh: @@ -2299,12 +2303,12 @@ for p in (p1, p2): if p not in self.nodemap: raise error.LookupError( - p, self.indexfile, _("unknown parent") + p, self.indexfile, _(b"unknown parent") ) if deltabase not in self.nodemap: raise error.LookupError( - deltabase, self.indexfile, _("unknown delta base") + deltabase, self.indexfile, _(b"unknown delta base") ) baserev = self.rev(deltabase) @@ -2312,7 +2316,7 @@ if baserev != nullrev and self.iscensored(baserev): # if base is censored, delta must be full replacement in a # single patch operation - hlen = struct.calcsize(">lll") + hlen = struct.calcsize(b">lll") oldlen = self.rawsize(baserev) newlen = len(delta) - hlen if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): @@ -2352,8 +2356,8 @@ # addrevision switched from inline to conventional # reopen the index ifh.close() - dfh = self._datafp("a+") - ifh = self._indexfp("a+") + dfh = self._datafp(b"a+") + ifh = self._indexfp(b"a+") self._writinghandles = (ifh, dfh) finally: self._writinghandles = None @@ -2491,13 +2495,13 @@ assumehaveparentrevisions=False, deltamode=repository.CG_DELTAMODE_STD, ): - if nodesorder not in ("nodes", "storage", "linear", None): + if nodesorder not in (b"nodes", b"storage", b"linear", None): raise error.ProgrammingError( - "unhandled value for nodesorder: %s" % nodesorder + b"unhandled value for nodesorder: %s" % nodesorder ) if nodesorder is None and not self._generaldelta: - nodesorder = "storage" + nodesorder = b"storage" if ( not self._storedeltachains @@ -2520,13 +2524,13 @@ assumehaveparentrevisions=assumehaveparentrevisions, ) - DELTAREUSEALWAYS = "always" - DELTAREUSESAMEREVS = "samerevs" - DELTAREUSENEVER = "never" - - DELTAREUSEFULLADD = "fulladd" - - DELTAREUSEALL = {"always", "samerevs", "never", "fulladd"} + DELTAREUSEALWAYS = b"always" + DELTAREUSESAMEREVS = b"samerevs" + DELTAREUSENEVER = b"never" + + DELTAREUSEFULLADD = b"fulladd" + + DELTAREUSEALL = {b"always", b"samerevs", b"never", b"fulladd"} def clone( self, @@ -2578,15 +2582,17 @@ for merges. By default, the current default is used. """ if deltareuse not in self.DELTAREUSEALL: - raise ValueError(_("value for deltareuse invalid: %s") % deltareuse) + raise ValueError( + _(b"value for deltareuse invalid: %s") % deltareuse + ) if len(destrevlog): - raise ValueError(_("destination revlog is not empty")) + raise ValueError(_(b"destination revlog is not empty")) if getattr(self, "filteredrevs", None): - raise ValueError(_("source revlog has filtered revisions")) + raise ValueError(_(b"source revlog has filtered revisions")) if getattr(destrevlog, "filteredrevs", None): - raise ValueError(_("destination revlog has filtered revisions")) + raise ValueError(_(b"destination revlog has filtered revisions")) # lazydelta and lazydeltabase controls whether to reuse a cached delta, # if possible. @@ -2660,11 +2666,11 @@ rawtext = self.rawdata(rev) ifh = destrevlog.opener( - destrevlog.indexfile, "a+", checkambig=False + destrevlog.indexfile, b"a+", checkambig=False ) dfh = None if not destrevlog._inline: - dfh = destrevlog.opener(destrevlog.datafile, "a+") + dfh = destrevlog.opener(destrevlog.datafile, b"a+") try: destrevlog._addrevision( node, @@ -2690,7 +2696,7 @@ def censorrevision(self, tr, censornode, tombstone=b""): if (self.version & 0xFFFF) == REVLOGV0: raise error.RevlogError( - _("cannot censor with version %d revlogs") % self.version + _(b"cannot censor with version %d revlogs") % self.version ) censorrev = self.rev(censornode) @@ -2698,7 +2704,7 @@ if len(tombstone) > self.rawsize(censorrev): raise error.Abort( - _("censor tombstone must be no longer than " "censored data") + _(b"censor tombstone must be no longer than " b"censored data") ) # Rewriting the revlog in place is hard. Our strategy for censoring is @@ -2732,13 +2738,13 @@ if newrl.deltaparent(rev) != nullrev: raise error.Abort( _( - "censored revision stored as delta; " - "cannot censor" + b"censored revision stored as delta; " + b"cannot censor" ), hint=_( - "censoring of revlogs is not " - "fully implemented; please report " - "this bug" + b"censoring of revlogs is not " + b"fully implemented; please report " + b"this bug" ), ) continue @@ -2747,8 +2753,8 @@ if self.deltaparent(rev) != nullrev: raise error.Abort( _( - "cannot censor due to censored " - "revision having delta stored" + b"cannot censor due to censored " + b"revision having delta stored" ) ) rawtext = self._chunk(rev) @@ -2759,9 +2765,9 @@ rawtext, tr, self.linkrev(rev), p1, p2, node, self.flags(rev) ) - tr.addbackup(self.indexfile, location="store") + tr.addbackup(self.indexfile, location=b"store") if not self._inline: - tr.addbackup(self.datafile, location="store") + tr.addbackup(self.datafile, location=b"store") self.opener.rename(newrl.indexfile, self.indexfile) if not self._inline: @@ -2778,20 +2784,20 @@ """ dd, di = self.checksize() if dd: - yield revlogproblem(error=_("data length off by %d bytes") % dd) + yield revlogproblem(error=_(b"data length off by %d bytes") % dd) if di: - yield revlogproblem(error=_("index contains %d extra bytes") % di) + yield revlogproblem(error=_(b"index contains %d extra bytes") % di) version = self.version & 0xFFFF # The verifier tells us what version revlog we should be. - if version != state["expectedversion"]: + if version != state[b"expectedversion"]: yield revlogproblem( - warning=_("warning: '%s' uses revlog format %d; expected %d") - % (self.indexfile, version, state["expectedversion"]) + warning=_(b"warning: '%s' uses revlog format %d; expected %d") + % (self.indexfile, version, state[b"expectedversion"]) ) - state["skipread"] = set() + state[b"skipread"] = set() for rev in self: node = self.node(rev) @@ -2845,12 +2851,12 @@ # use either "text" (external), or "rawtext" (in revlog). try: - skipflags = state.get("skipflags", 0) + skipflags = state.get(b"skipflags", 0) if skipflags: skipflags &= self.flags(rev) if skipflags: - state["skipread"].add(node) + state[b"skipread"].add(node) else: # Side-effect: read content and verify hash. self.revision(node) @@ -2860,23 +2866,23 @@ if l1 != l2: yield revlogproblem( - error=_("unpacked size is %d, %d expected") % (l2, l1), + error=_(b"unpacked size is %d, %d expected") % (l2, l1), node=node, ) except error.CensoredNodeError: - if state["erroroncensored"]: + if state[b"erroroncensored"]: yield revlogproblem( - error=_("censored file data"), node=node + error=_(b"censored file data"), node=node ) - state["skipread"].add(node) + state[b"skipread"].add(node) except Exception as e: yield revlogproblem( - error=_("unpacking %s: %s") + error=_(b"unpacking %s: %s") % (short(node), stringutil.forcebytestr(e)), node=node, ) - state["skipread"].add(node) + state[b"skipread"].add(node) def storageinfo( self, @@ -2889,21 +2895,21 @@ d = {} if exclusivefiles: - d["exclusivefiles"] = [(self.opener, self.indexfile)] + d[b"exclusivefiles"] = [(self.opener, self.indexfile)] if not self._inline: - d["exclusivefiles"].append((self.opener, self.datafile)) + d[b"exclusivefiles"].append((self.opener, self.datafile)) if sharedfiles: - d["sharedfiles"] = [] + d[b"sharedfiles"] = [] if revisionscount: - d["revisionscount"] = len(self) + d[b"revisionscount"] = len(self) if trackedsize: - d["trackedsize"] = sum(map(self.rawsize, iter(self))) + d[b"trackedsize"] = sum(map(self.rawsize, iter(self))) if storedsize: - d["storedsize"] = sum( + d[b"storedsize"] = sum( self.opener.stat(path).st_size for path in self.files() ) diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py --- a/mercurial/revlogutils/deltas.py +++ b/mercurial/revlogutils/deltas.py @@ -514,7 +514,7 @@ # special case deltas which replace entire base; no need to decode # base revision. this neatly avoids censored bases, which throw when # they're decoded. - hlen = struct.calcsize(">lll") + hlen = struct.calcsize(b">lll") if delta[:hlen] == mdiff.replacediffheader( revlog.rawsize(baserev), len(delta) - hlen ): @@ -531,7 +531,7 @@ revlog.checkhash(fulltext, expectednode, p1=p1, p2=p2) if flags & REVIDX_ISCENSORED: raise error.StorageError( - _("node %s is not censored") % expectednode + _(b"node %s is not censored") % expectednode ) except error.CensoredNodeError: # must pass the censored index flag to add censored revisions @@ -726,7 +726,7 @@ def _findsnapshots(revlog, cache, start_rev): """find snapshot from start_rev to tip""" - if util.safehasattr(revlog.index, "findsnapshots"): + if util.safehasattr(revlog.index, b"findsnapshots"): revlog.index.findsnapshots(cache, start_rev) else: deltaparent = revlog.deltaparent diff --git a/mercurial/revlogutils/flagutil.py b/mercurial/revlogutils/flagutil.py --- a/mercurial/revlogutils/flagutil.py +++ b/mercurial/revlogutils/flagutil.py @@ -70,13 +70,13 @@ def insertflagprocessor(flag, processor, flagprocessors): if not flag & REVIDX_KNOWN_FLAGS: - msg = _("cannot register processor on unknown flag '%#x'.") % flag + msg = _(b"cannot register processor on unknown flag '%#x'.") % flag raise error.ProgrammingError(msg) if flag not in REVIDX_FLAGS_ORDER: - msg = _("flag '%#x' undefined in REVIDX_FLAGS_ORDER.") % flag + msg = _(b"flag '%#x' undefined in REVIDX_FLAGS_ORDER.") % flag raise error.ProgrammingError(msg) if flag in flagprocessors: - msg = _("cannot register multiple processors on flag '%#x'.") % flag + msg = _(b"cannot register multiple processors on flag '%#x'.") % flag raise error.Abort(msg) flagprocessors[flag] = processor @@ -97,7 +97,7 @@ processed text and ``validatehash`` is a bool indicating whether the returned text should be checked for hash integrity. """ - return _processflagsfunc(revlog, text, flags, "write", sidedata=sidedata)[ + return _processflagsfunc(revlog, text, flags, b"write", sidedata=sidedata)[ :2 ] @@ -120,7 +120,7 @@ processed text and ``validatehash`` is a bool indicating whether the returned text should be checked for hash integrity. """ - return _processflagsfunc(revlog, text, flags, "read") + return _processflagsfunc(revlog, text, flags, b"read") def processflagsraw(revlog, text, flags): @@ -139,7 +139,7 @@ processed text and ``validatehash`` is a bool indicating whether the returned text should be checked for hash integrity. """ - return _processflagsfunc(revlog, text, flags, "raw")[1] + return _processflagsfunc(revlog, text, flags, b"raw")[1] def _processflagsfunc(revlog, text, flags, operation, sidedata=None): @@ -150,19 +150,19 @@ # fast path: no flag processors will run if flags == 0: return text, True, {} - if operation not in ("read", "write", "raw"): - raise error.ProgrammingError(_("invalid '%s' operation") % operation) + if operation not in (b"read", b"write", b"raw"): + raise error.ProgrammingError(_(b"invalid '%s' operation") % operation) # Check all flags are known. if flags & ~REVIDX_KNOWN_FLAGS: raise revlog._flagserrorclass( - _("incompatible revision flag '%#x'") + _(b"incompatible revision flag '%#x'") % (flags & ~REVIDX_KNOWN_FLAGS) ) validatehash = True # Depending on the operation (read or write), the order might be # reversed due to non-commutative transforms. orderedflags = REVIDX_FLAGS_ORDER - if operation == "write": + if operation == b"write": orderedflags = reversed(orderedflags) outsidedata = {} @@ -173,16 +173,16 @@ vhash = True if flag not in revlog._flagprocessors: - message = _("missing processor for flag '%#x'") % flag + message = _(b"missing processor for flag '%#x'") % flag raise revlog._flagserrorclass(message) processor = revlog._flagprocessors[flag] if processor is not None: readtransform, writetransform, rawtransform = processor - if operation == "raw": + if operation == b"raw": vhash = rawtransform(revlog, text) - elif operation == "read": + elif operation == b"read": text, vhash, s = readtransform(revlog, text) outsidedata.update(s) else: # write operation diff --git a/mercurial/revlogutils/sidedata.py b/mercurial/revlogutils/sidedata.py --- a/mercurial/revlogutils/sidedata.py +++ b/mercurial/revlogutils/sidedata.py @@ -63,7 +63,7 @@ for key, value in sidedata: rawtext.append(value) rawtext.append(bytes(text)) - return "".join(rawtext), False + return b"".join(rawtext), False def sidedatareadprocessor(rl, text): diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -93,22 +93,22 @@ # # There are a few revsets that always redefine the order if 'define' is # specified: 'sort(X)', 'reverse(X)', 'x:y'. -anyorder = "any" # don't care the order, could be even random-shuffled -defineorder = "define" # ALWAYS redefine, or ALWAYS follow the current order -followorder = "follow" # MUST follow the current order +anyorder = b"any" # don't care the order, could be even random-shuffled +defineorder = b"define" # ALWAYS redefine, or ALWAYS follow the current order +followorder = b"follow" # MUST follow the current order # helpers def getset(repo, subset, x, order=defineorder): if not x: - raise error.ParseError(_("missing argument")) + raise error.ParseError(_(b"missing argument")) return methods[x[0]](repo, subset, *x[1:], order=order) def _getrevsource(repo, r): extra = repo[r].extra() - for label in ("source", "transplant_source", "rebase_source"): + for label in (b"source", b"transplant_source", b"rebase_source"): if label in extra: try: return repo[extra[label]].rev() @@ -126,7 +126,7 @@ def stringset(repo, subset, x, order): if not x: - raise error.ParseError(_("empty string is not a valid revision")) + raise error.ParseError(_(b"empty string is not a valid revision")) x = scmutil.intrev(scmutil.revsymbol(repo, x)) if x in subset or x in _virtualrevs and isinstance(subset, fullreposet): return baseset([x]) @@ -246,7 +246,7 @@ def relationset(repo, subset, x, y, order): - raise error.ParseError(_("can't use a relation in this context")) + raise error.ParseError(_(b"can't use a relation in this context")) def _splitrange(a, b): @@ -285,8 +285,8 @@ # descendants() predicates a, b = getintrange( z, - _("relation subscript must be an integer or a range"), - _("relation subscript bounds must be integers"), + _(b"relation subscript must be an integer or a range"), + _(b"relation subscript bounds must be integers"), deffirst=-(dagop.maxlogdepth - 1), deflast=+(dagop.maxlogdepth - 1), ) @@ -323,18 +323,18 @@ def subscriptset(repo, subset, x, y, order): - raise error.ParseError(_("can't use a subscript in this context")) + raise error.ParseError(_(b"can't use a subscript in this context")) def listset(repo, subset, *xs, **opts): raise error.ParseError( - _("can't use a list in this context"), - hint=_("see 'hg help \"revsets.x or y\"'"), + _(b"can't use a list in this context"), + hint=_(b"see 'hg help \"revsets.x or y\"'"), ) def keyvaluepair(repo, subset, k, v, order): - raise error.ParseError(_("can't use a key-value pair in this context")) + raise error.ParseError(_(b"can't use a key-value pair in this context")) def func(repo, subset, a, b, order): @@ -369,16 +369,16 @@ predicate = registrar.revsetpredicate() -@predicate("_destupdate") +@predicate(b"_destupdate") def _destupdate(repo, subset, x): # experimental revset for update destination - args = getargsdict(x, "limit", "clean") + args = getargsdict(x, b"limit", b"clean") return subset & baseset( [destutil.destupdate(repo, **pycompat.strkwargs(args))[0]] ) -@predicate("_destmerge") +@predicate(b"_destmerge") def _destmerge(repo, subset, x): # experimental revset for merge destination sourceset = None @@ -387,7 +387,7 @@ return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)]) -@predicate("adds(pattern)", safe=True, weight=30) +@predicate(b"adds(pattern)", safe=True, weight=30) def adds(repo, subset, x): """Changesets that add a file matching pattern. @@ -396,11 +396,11 @@ directory. """ # i18n: "adds" is a keyword - pat = getstring(x, _("adds requires a pattern")) + pat = getstring(x, _(b"adds requires a pattern")) return checkstatus(repo, subset, pat, 1) -@predicate("ancestor(*changeset)", safe=True, weight=0.5) +@predicate(b"ancestor(*changeset)", safe=True, weight=0.5) def ancestor(repo, subset, x): """A greatest common ancestor of the changesets. @@ -432,7 +432,7 @@ return subset & s -@predicate("ancestors(set[, depth])", safe=True) +@predicate(b"ancestors(set[, depth])", safe=True) def ancestors(repo, subset, x): """Changesets that are ancestors of changesets in set, including the given changesets themselves. @@ -441,30 +441,30 @@ the specified generation. """ # startdepth is for internal use only until we can decide the UI - args = getargsdict(x, "ancestors", "set depth startdepth") - if "set" not in args: + args = getargsdict(x, b"ancestors", b"set depth startdepth") + if b"set" not in args: # i18n: "ancestors" is a keyword - raise error.ParseError(_("ancestors takes at least 1 argument")) + raise error.ParseError(_(b"ancestors takes at least 1 argument")) startdepth = stopdepth = None - if "startdepth" in args: + if b"startdepth" in args: n = getinteger( - args["startdepth"], "ancestors expects an integer startdepth" + args[b"startdepth"], b"ancestors expects an integer startdepth" ) if n < 0: - raise error.ParseError("negative startdepth") + raise error.ParseError(b"negative startdepth") startdepth = n - if "depth" in args: + if b"depth" in args: # i18n: "ancestors" is a keyword - n = getinteger(args["depth"], _("ancestors expects an integer depth")) + n = getinteger(args[b"depth"], _(b"ancestors expects an integer depth")) if n < 0: - raise error.ParseError(_("negative depth")) + raise error.ParseError(_(b"negative depth")) stopdepth = n + 1 return _ancestors( - repo, subset, args["set"], startdepth=startdepth, stopdepth=stopdepth + repo, subset, args[b"set"], startdepth=startdepth, stopdepth=stopdepth ) -@predicate("_firstancestors", safe=True) +@predicate(b"_firstancestors", safe=True) def _firstancestors(repo, subset, x): # ``_firstancestors(set)`` # Like ``ancestors(set)`` but follows only the first parents. @@ -483,7 +483,7 @@ break if len(c) > 1: raise error.RepoLookupError( - _("revision in set has more than one child") + _(b"revision in set has more than one child") ) r = c[0].rev() else: @@ -496,7 +496,7 @@ Changesets that are the Nth ancestor (first parents only) of a changeset in set. """ - n = getinteger(n, _("~ expects a number")) + n = getinteger(n, _(b"~ expects a number")) if n < 0: # children lookup return _childrenspec(repo, subset, x, -n, order) @@ -512,19 +512,19 @@ return subset & ps -@predicate("author(string)", safe=True, weight=10) +@predicate(b"author(string)", safe=True, weight=10) def author(repo, subset, x): """Alias for ``user(string)``. """ # i18n: "author" is a keyword - n = getstring(x, _("author requires a string")) + n = getstring(x, _(b"author requires a string")) kind, pattern, matcher = _substringmatcher(n, casesensitive=False) return subset.filter( - lambda x: matcher(repo[x].user()), condrepr=("", n) + lambda x: matcher(repo[x].user()), condrepr=(b"", n) ) -@predicate("bisect(string)", safe=True) +@predicate(b"bisect(string)", safe=True) def bisect(repo, subset, x): """Changesets marked in the specified bisect status: @@ -537,41 +537,41 @@ - ``current`` : the cset currently being bisected """ # i18n: "bisect" is a keyword - status = getstring(x, _("bisect requires a string")).lower() + status = getstring(x, _(b"bisect requires a string")).lower() state = set(hbisect.get(repo, status)) return subset & state # Backward-compatibility # - no help entry so that we do not advertise it any more -@predicate("bisected", safe=True) +@predicate(b"bisected", safe=True) def bisected(repo, subset, x): return bisect(repo, subset, x) -@predicate("bookmark([name])", safe=True) +@predicate(b"bookmark([name])", safe=True) def bookmark(repo, subset, x): """The named bookmark or all bookmarks. Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. """ # i18n: "bookmark" is a keyword - args = getargs(x, 0, 1, _("bookmark takes one or no arguments")) + args = getargs(x, 0, 1, _(b"bookmark takes one or no arguments")) if args: bm = getstring( args[0], # i18n: "bookmark" is a keyword - _("the argument to bookmark must be a string"), + _(b"the argument to bookmark must be a string"), ) kind, pattern, matcher = stringutil.stringmatcher(bm) bms = set() - if kind == "literal": + if kind == b"literal": if bm == pattern: pattern = repo._bookmarks.expandname(pattern) bmrev = repo._bookmarks.get(pattern, None) if not bmrev: raise error.RepoLookupError( - _("bookmark '%s' does not exist") % pattern + _(b"bookmark '%s' does not exist") % pattern ) bms.add(repo[bmrev].rev()) else: @@ -587,7 +587,7 @@ return subset & bms -@predicate("branch(string or set)", safe=True, weight=10) +@predicate(b"branch(string or set)", safe=True, weight=10) def branch(repo, subset, x): """ All changesets belonging to the given branch or the branches of the given @@ -605,26 +605,27 @@ return repo[r].branch() try: - b = getstring(x, "") + b = getstring(x, b"") except error.ParseError: # not a string, but another revspec, e.g. tip() pass else: kind, pattern, matcher = stringutil.stringmatcher(b) - if kind == "literal": + if kind == b"literal": # note: falls through to the revspec case if no branch with # this name exists and pattern kind is not specified explicitly if repo.branchmap().hasbranch(pattern): return subset.filter( - lambda r: matcher(getbranch(r)), condrepr=("", b) + lambda r: matcher(getbranch(r)), + condrepr=(b"", b), ) - if b.startswith("literal:"): + if b.startswith(b"literal:"): raise error.RepoLookupError( - _("branch '%s' does not exist") % pattern + _(b"branch '%s' does not exist") % pattern ) else: return subset.filter( - lambda r: matcher(getbranch(r)), condrepr=("", b) + lambda r: matcher(getbranch(r)), condrepr=(b"", b) ) s = getset(repo, fullreposet(repo), x) @@ -634,11 +635,11 @@ c = s.__contains__ return subset.filter( lambda r: c(r) or getbranch(r) in b, - condrepr=lambda: "" % _sortedb(b), + condrepr=lambda: b"" % _sortedb(b), ) -@predicate("phasedivergent()", safe=True) +@predicate(b"phasedivergent()", safe=True) def phasedivergent(repo, subset, x): """Mutable changesets marked as successors of public changesets. @@ -646,12 +647,12 @@ (EXPERIMENTAL) """ # i18n: "phasedivergent" is a keyword - getargs(x, 0, 0, _("phasedivergent takes no arguments")) - phasedivergent = obsmod.getrevs(repo, "phasedivergent") + getargs(x, 0, 0, _(b"phasedivergent takes no arguments")) + phasedivergent = obsmod.getrevs(repo, b"phasedivergent") return subset & phasedivergent -@predicate("bundle()", safe=True) +@predicate(b"bundle()", safe=True) def bundle(repo, subset, x): """Changesets in the bundle. @@ -660,7 +661,7 @@ try: bundlerevs = repo.changelog.bundlerevs except AttributeError: - raise error.Abort(_("no bundle provided - specify with -R")) + raise error.Abort(_(b"no bundle provided - specify with -R")) return subset & bundlerevs @@ -671,7 +672,7 @@ 1: added 2: removed """ - hasset = matchmod.patkind(pat) == "set" + hasset = matchmod.patkind(pat) == b"set" mcache = [None] @@ -701,7 +702,7 @@ if m(f): return True - return subset.filter(matches, condrepr=("", field, pat)) + return subset.filter(matches, condrepr=(b"", field, pat)) def _children(repo, subset, parentset): @@ -722,7 +723,7 @@ return baseset(cs) -@predicate("children(set)", safe=True) +@predicate(b"children(set)", safe=True) def children(repo, subset, x): """Child changesets of changesets in set. """ @@ -731,19 +732,19 @@ return subset & cs -@predicate("closed()", safe=True, weight=10) +@predicate(b"closed()", safe=True, weight=10) def closed(repo, subset, x): """Changeset is closed. """ # i18n: "closed" is a keyword - getargs(x, 0, 0, _("closed takes no arguments")) + getargs(x, 0, 0, _(b"closed takes no arguments")) return subset.filter( - lambda r: repo[r].closesbranch(), condrepr="" + lambda r: repo[r].closesbranch(), condrepr=b"" ) # for internal use -@predicate("_commonancestorheads(set)", safe=True) +@predicate(b"_commonancestorheads(set)", safe=True) def _commonancestorheads(repo, subset, x): # This is an internal method is for quickly calculating "heads(::x and # ::y)" @@ -756,7 +757,7 @@ return subset & baseset(ancs) -@predicate("commonancestors(set)", safe=True) +@predicate(b"commonancestors(set)", safe=True) def commonancestors(repo, subset, x): """Changesets that are ancestors of every changeset in set. """ @@ -768,7 +769,7 @@ return subset -@predicate("contains(pattern)", weight=100) +@predicate(b"contains(pattern)", weight=100) def contains(repo, subset, x): """The revision's manifest contains a file matching pattern (but might not modify it). See :hg:`help patterns` for information about file patterns. @@ -778,7 +779,7 @@ for efficiency. """ # i18n: "contains" is a keyword - pat = getstring(x, _("contains requires a pattern")) + pat = getstring(x, _(b"contains requires a pattern")) def matches(x): if not matchmod.patkind(pat): @@ -793,10 +794,10 @@ return True return False - return subset.filter(matches, condrepr=("", pat)) - - -@predicate("converted([id])", safe=True) + return subset.filter(matches, condrepr=(b"", pat)) + + +@predicate(b"converted([id])", safe=True) def converted(repo, subset, x): """Changesets converted from the given identifier in the old repository if present, or all converted changesets if no identifier is specified. @@ -807,33 +808,33 @@ rev = None # i18n: "converted" is a keyword - l = getargs(x, 0, 1, _("converted takes one or no arguments")) + l = getargs(x, 0, 1, _(b"converted takes one or no arguments")) if l: # i18n: "converted" is a keyword - rev = getstring(l[0], _("converted requires a revision")) + rev = getstring(l[0], _(b"converted requires a revision")) def _matchvalue(r): - source = repo[r].extra().get("convert_revision", None) + source = repo[r].extra().get(b"convert_revision", None) return source is not None and (rev is None or source.startswith(rev)) return subset.filter( - lambda r: _matchvalue(r), condrepr=("", rev) + lambda r: _matchvalue(r), condrepr=(b"", rev) ) -@predicate("date(interval)", safe=True, weight=10) +@predicate(b"date(interval)", safe=True, weight=10) def date(repo, subset, x): """Changesets within the interval, see :hg:`help dates`. """ # i18n: "date" is a keyword - ds = getstring(x, _("date requires a string")) + ds = getstring(x, _(b"date requires a string")) dm = dateutil.matchdate(ds) return subset.filter( - lambda x: dm(repo[x].date()[0]), condrepr=("", ds) + lambda x: dm(repo[x].date()[0]), condrepr=(b"", ds) ) -@predicate("desc(string)", safe=True, weight=10) +@predicate(b"desc(string)", safe=True, weight=10) def desc(repo, subset, x): """Search commit message for string. The match is case-insensitive. @@ -841,12 +842,12 @@ :hg:`help revisions.patterns`. """ # i18n: "desc" is a keyword - ds = getstring(x, _("desc requires a string")) + ds = getstring(x, _(b"desc requires a string")) kind, pattern, matcher = _substringmatcher(ds, casesensitive=False) return subset.filter( - lambda r: matcher(repo[r].description()), condrepr=("", ds) + lambda r: matcher(repo[r].description()), condrepr=(b"", ds) ) @@ -860,7 +861,7 @@ return subset & s -@predicate("descendants(set[, depth])", safe=True) +@predicate(b"descendants(set[, depth])", safe=True) def descendants(repo, subset, x): """Changesets which are descendants of changesets in set, including the given changesets themselves. @@ -869,37 +870,39 @@ the specified generation. """ # startdepth is for internal use only until we can decide the UI - args = getargsdict(x, "descendants", "set depth startdepth") - if "set" not in args: + args = getargsdict(x, b"descendants", b"set depth startdepth") + if b"set" not in args: # i18n: "descendants" is a keyword - raise error.ParseError(_("descendants takes at least 1 argument")) + raise error.ParseError(_(b"descendants takes at least 1 argument")) startdepth = stopdepth = None - if "startdepth" in args: + if b"startdepth" in args: n = getinteger( - args["startdepth"], "descendants expects an integer startdepth" + args[b"startdepth"], b"descendants expects an integer startdepth" ) if n < 0: - raise error.ParseError("negative startdepth") + raise error.ParseError(b"negative startdepth") startdepth = n - if "depth" in args: + if b"depth" in args: # i18n: "descendants" is a keyword - n = getinteger(args["depth"], _("descendants expects an integer depth")) + n = getinteger( + args[b"depth"], _(b"descendants expects an integer depth") + ) if n < 0: - raise error.ParseError(_("negative depth")) + raise error.ParseError(_(b"negative depth")) stopdepth = n + 1 return _descendants( - repo, subset, args["set"], startdepth=startdepth, stopdepth=stopdepth + repo, subset, args[b"set"], startdepth=startdepth, stopdepth=stopdepth ) -@predicate("_firstdescendants", safe=True) +@predicate(b"_firstdescendants", safe=True) def _firstdescendants(repo, subset, x): # ``_firstdescendants(set)`` # Like ``descendants(set)`` but follows only the first parents. return _descendants(repo, subset, x, followfirst=True) -@predicate("destination([set])", safe=True, weight=10) +@predicate(b"destination([set])", safe=True, weight=10) def destination(repo, subset, x): """Changesets that were created by a graft, transplant or rebase operation, with the given revisions specified as the source. Omitting the optional set @@ -943,23 +946,23 @@ return subset.filter( dests.__contains__, - condrepr=lambda: "" % _sortedb(dests), + condrepr=lambda: b"" % _sortedb(dests), ) -@predicate("contentdivergent()", safe=True) +@predicate(b"contentdivergent()", safe=True) def contentdivergent(repo, subset, x): """ Final successors of changesets with an alternative set of final successors. (EXPERIMENTAL) """ # i18n: "contentdivergent" is a keyword - getargs(x, 0, 0, _("contentdivergent takes no arguments")) - contentdivergent = obsmod.getrevs(repo, "contentdivergent") + getargs(x, 0, 0, _(b"contentdivergent takes no arguments")) + contentdivergent = obsmod.getrevs(repo, b"contentdivergent") return subset & contentdivergent -@predicate("expectsize(set[, size])", safe=True, takeorder=True) +@predicate(b"expectsize(set[, size])", safe=True, takeorder=True) def expectsize(repo, subset, x, order): """Return the given revset if size matches the revset size. Abort if the revset doesn't expect given size. @@ -968,28 +971,28 @@ For example, ``expectsize(0:1, 3:5)`` will abort as revset size is 2 and 2 is not between 3 and 5 inclusive.""" - args = getargsdict(x, "expectsize", "set size") + args = getargsdict(x, b"expectsize", b"set size") minsize = 0 maxsize = len(repo) + 1 - err = "" - if "size" not in args or "set" not in args: - raise error.ParseError(_("invalid set of arguments")) + err = b"" + if b"size" not in args or b"set" not in args: + raise error.ParseError(_(b"invalid set of arguments")) minsize, maxsize = getintrange( - args["size"], - _("expectsize requires a size range" " or a positive integer"), - _("size range bounds must be integers"), + args[b"size"], + _(b"expectsize requires a size range" b" or a positive integer"), + _(b"size range bounds must be integers"), minsize, maxsize, ) if minsize < 0 or maxsize < 0: - raise error.ParseError(_("negative size")) - rev = getset(repo, fullreposet(repo), args["set"], order=order) + raise error.ParseError(_(b"negative size")) + rev = getset(repo, fullreposet(repo), args[b"set"], order=order) if minsize != maxsize and (len(rev) < minsize or len(rev) > maxsize): err = _( - "revset size mismatch." " expected between %d and %d, got %d" + b"revset size mismatch." b" expected between %d and %d, got %d" ) % (minsize, maxsize, len(rev)) elif minsize == maxsize and len(rev) != minsize: - err = _("revset size mismatch." " expected %d, got %d") % ( + err = _(b"revset size mismatch." b" expected %d, got %d") % ( minsize, len(rev), ) @@ -1001,31 +1004,31 @@ return rev & subset -@predicate("extdata(source)", safe=False, weight=100) +@predicate(b"extdata(source)", safe=False, weight=100) def extdata(repo, subset, x): """Changesets in the specified extdata source. (EXPERIMENTAL)""" # i18n: "extdata" is a keyword - args = getargsdict(x, "extdata", "source") + args = getargsdict(x, b"extdata", b"source") source = getstring( - args.get("source"), + args.get(b"source"), # i18n: "extdata" is a keyword - _("extdata takes at least 1 string argument"), + _(b"extdata takes at least 1 string argument"), ) data = scmutil.extdatasource(repo, source) return subset & baseset(data) -@predicate("extinct()", safe=True) +@predicate(b"extinct()", safe=True) def extinct(repo, subset, x): """Obsolete changesets with obsolete descendants only. """ # i18n: "extinct" is a keyword - getargs(x, 0, 0, _("extinct takes no arguments")) - extincts = obsmod.getrevs(repo, "extinct") + getargs(x, 0, 0, _(b"extinct takes no arguments")) + extincts = obsmod.getrevs(repo, b"extinct") return subset & extincts -@predicate("extra(label, [value])", safe=True) +@predicate(b"extra(label, [value])", safe=True) def extra(repo, subset, x): """Changesets with the given label in the extra metadata, with the given optional value. @@ -1033,20 +1036,20 @@ Pattern matching is supported for `value`. See :hg:`help revisions.patterns`. """ - args = getargsdict(x, "extra", "label value") - if "label" not in args: + args = getargsdict(x, b"extra", b"label value") + if b"label" not in args: # i18n: "extra" is a keyword - raise error.ParseError(_("extra takes at least 1 argument")) + raise error.ParseError(_(b"extra takes at least 1 argument")) # i18n: "extra" is a keyword label = getstring( - args["label"], _("first argument to extra must be " "a string") + args[b"label"], _(b"first argument to extra must be " b"a string") ) value = None - if "value" in args: + if b"value" in args: # i18n: "extra" is a keyword value = getstring( - args["value"], _("second argument to extra must be " "a string") + args[b"value"], _(b"second argument to extra must be " b"a string") ) kind, value, matcher = stringutil.stringmatcher(value) @@ -1055,11 +1058,11 @@ return label in extra and (value is None or matcher(extra[label])) return subset.filter( - lambda r: _matchvalue(r), condrepr=("", label, value) + lambda r: _matchvalue(r), condrepr=(b"", label, value) ) -@predicate("filelog(pattern)", safe=True) +@predicate(b"filelog(pattern)", safe=True) def filelog(repo, subset, x): """Changesets connected to the specified filelog. @@ -1074,7 +1077,7 @@ """ # i18n: "filelog" is a keyword - pat = getstring(x, _("filelog requires a pattern")) + pat = getstring(x, _(b"filelog requires a pattern")) s = set() cl = repo.changelog @@ -1123,7 +1126,7 @@ return subset & s -@predicate("first(set, [n])", safe=True, takeorder=True, weight=0) +@predicate(b"first(set, [n])", safe=True, takeorder=True, weight=0) def first(repo, subset, x, order): """An alias for limit(). """ @@ -1131,52 +1134,53 @@ def _follow(repo, subset, x, name, followfirst=False): - args = getargsdict(x, name, "file startrev") + args = getargsdict(x, name, b"file startrev") revs = None - if "startrev" in args: - revs = getset(repo, fullreposet(repo), args["startrev"]) - if "file" in args: - x = getstring(args["file"], _("%s expected a pattern") % name) + if b"startrev" in args: + revs = getset(repo, fullreposet(repo), args[b"startrev"]) + if b"file" in args: + x = getstring(args[b"file"], _(b"%s expected a pattern") % name) if revs is None: revs = [None] fctxs = [] for r in revs: ctx = mctx = repo[r] if r is None: - ctx = repo["."] + ctx = repo[b"."] m = matchmod.match( - repo.root, repo.getcwd(), [x], ctx=mctx, default="path" + repo.root, repo.getcwd(), [x], ctx=mctx, default=b"path" ) fctxs.extend(ctx[f].introfilectx() for f in ctx.manifest().walk(m)) s = dagop.filerevancestors(fctxs, followfirst) else: if revs is None: - revs = baseset([repo["."].rev()]) + revs = baseset([repo[b"."].rev()]) s = dagop.revancestors(repo, revs, followfirst) return subset & s -@predicate("follow([file[, startrev]])", safe=True) +@predicate(b"follow([file[, startrev]])", safe=True) def follow(repo, subset, x): """ An alias for ``::.`` (ancestors of the working directory's first parent). If file pattern is specified, the histories of files matching given pattern in the revision given by startrev are followed, including copies. """ - return _follow(repo, subset, x, "follow") - - -@predicate("_followfirst", safe=True) + return _follow(repo, subset, x, b"follow") + + +@predicate(b"_followfirst", safe=True) def _followfirst(repo, subset, x): # ``followfirst([file[, startrev]])`` # Like ``follow([file[, startrev]])`` but follows only the first parent # of every revisions or files revisions. - return _follow(repo, subset, x, "_followfirst", followfirst=True) + return _follow(repo, subset, x, b"_followfirst", followfirst=True) @predicate( - "followlines(file, fromline:toline[, startrev=., descend=False])", safe=True + b"followlines(file, fromline:toline[, startrev=., descend=False])", + safe=True, ) def followlines(repo, subset, x): """Changesets modifying `file` in line range ('fromline', 'toline'). @@ -1189,40 +1193,40 @@ descendants of 'startrev' are returned though renames are (currently) not followed in this direction. """ - args = getargsdict(x, "followlines", "file *lines startrev descend") - if len(args["lines"]) != 1: - raise error.ParseError(_("followlines requires a line range")) - - rev = "." - if "startrev" in args: - revs = getset(repo, fullreposet(repo), args["startrev"]) + args = getargsdict(x, b"followlines", b"file *lines startrev descend") + if len(args[b"lines"]) != 1: + raise error.ParseError(_(b"followlines requires a line range")) + + rev = b"." + if b"startrev" in args: + revs = getset(repo, fullreposet(repo), args[b"startrev"]) if len(revs) != 1: raise error.ParseError( # i18n: "followlines" is a keyword - _("followlines expects exactly one revision") + _(b"followlines expects exactly one revision") ) rev = revs.last() - pat = getstring(args["file"], _("followlines requires a pattern")) + pat = getstring(args[b"file"], _(b"followlines requires a pattern")) # i18n: "followlines" is a keyword - msg = _("followlines expects exactly one file") + msg = _(b"followlines expects exactly one file") fname = scmutil.parsefollowlinespattern(repo, rev, pat, msg) fromline, toline = util.processlinerange( *getintrange( - args["lines"][0], + args[b"lines"][0], # i18n: "followlines" is a keyword - _("followlines expects a line number or a range"), - _("line range bounds must be integers"), + _(b"followlines expects a line number or a range"), + _(b"line range bounds must be integers"), ) ) fctx = repo[rev].filectx(fname) descend = False - if "descend" in args: + if b"descend" in args: descend = getboolean( - args["descend"], + args[b"descend"], # i18n: "descend" is a keyword - _("descend argument must be a boolean"), + _(b"descend argument must be a boolean"), ) if descend: rs = generatorset( @@ -1247,16 +1251,16 @@ return subset & rs -@predicate("all()", safe=True) +@predicate(b"all()", safe=True) def getall(repo, subset, x): """All changesets, the same as ``0:tip``. """ # i18n: "all" is a keyword - getargs(x, 0, 0, _("all takes no arguments")) + getargs(x, 0, 0, _(b"all takes no arguments")) return subset & spanset(repo) # drop "null" if any -@predicate("grep(regex)", weight=10) +@predicate(b"grep(regex)", weight=10) def grep(repo, subset, x): """Like ``keyword(string)`` but accepts a regex. Use ``grep(r'...')`` to ensure special escape characters are handled correctly. Unlike @@ -1264,10 +1268,10 @@ """ try: # i18n: "grep" is a keyword - gr = re.compile(getstring(x, _("grep requires a string"))) + gr = re.compile(getstring(x, _(b"grep requires a string"))) except re.error as e: raise error.ParseError( - _("invalid match pattern: %s") % stringutil.forcebytestr(e) + _(b"invalid match pattern: %s") % stringutil.forcebytestr(e) ) def matches(x): @@ -1277,10 +1281,10 @@ return True return False - return subset.filter(matches, condrepr=("", gr.pattern)) - - -@predicate("_matchfiles", safe=True) + return subset.filter(matches, condrepr=(b"", gr.pattern)) + + +@predicate(b"_matchfiles", safe=True) def _matchfiles(repo, subset, x): # _matchfiles takes a revset list of prefixed arguments: # @@ -1294,38 +1298,38 @@ # initialized. Use 'd:' to set the default matching mode, default # to 'glob'. At most one 'r:' and 'd:' argument can be passed. - l = getargs(x, 1, -1, "_matchfiles requires at least one argument") + l = getargs(x, 1, -1, b"_matchfiles requires at least one argument") pats, inc, exc = [], [], [] rev, default = None, None for arg in l: - s = getstring(arg, "_matchfiles requires string arguments") + s = getstring(arg, b"_matchfiles requires string arguments") prefix, value = s[:2], s[2:] - if prefix == "p:": + if prefix == b"p:": pats.append(value) - elif prefix == "i:": + elif prefix == b"i:": inc.append(value) - elif prefix == "x:": + elif prefix == b"x:": exc.append(value) - elif prefix == "r:": + elif prefix == b"r:": if rev is not None: raise error.ParseError( - "_matchfiles expected at most one " "revision" + b"_matchfiles expected at most one " b"revision" ) - if value == "": # empty means working directory + if value == b"": # empty means working directory rev = node.wdirrev else: rev = value - elif prefix == "d:": + elif prefix == b"d:": if default is not None: raise error.ParseError( - "_matchfiles expected at most one " "default mode" + b"_matchfiles expected at most one " b"default mode" ) default = value else: - raise error.ParseError("invalid _matchfiles prefix: %s" % prefix) + raise error.ParseError(b"invalid _matchfiles prefix: %s" % prefix) if not default: - default = "glob" - hasset = any(matchmod.patkind(p) == "set" for p in pats + inc + exc) + default = b"glob" + hasset = any(matchmod.patkind(p) == b"set" for p in pats + inc + exc) mcache = [None] @@ -1361,8 +1365,8 @@ return subset.filter( matches, condrepr=( - "", + b"", pats, inc, exc, @@ -1372,7 +1376,7 @@ ) -@predicate("file(pattern)", safe=True, weight=10) +@predicate(b"file(pattern)", safe=True, weight=10) def hasfile(repo, subset, x): """Changesets affecting files matched by pattern. @@ -1382,16 +1386,16 @@ This predicate uses ``glob:`` as the default kind of pattern. """ # i18n: "file" is a keyword - pat = getstring(x, _("file requires a pattern")) - return _matchfiles(repo, subset, ("string", "p:" + pat)) - - -@predicate("head()", safe=True) + pat = getstring(x, _(b"file requires a pattern")) + return _matchfiles(repo, subset, (b"string", b"p:" + pat)) + + +@predicate(b"head()", safe=True) def head(repo, subset, x): """Changeset is a named branch head. """ # i18n: "head" is a keyword - getargs(x, 0, 0, _("head takes no arguments")) + getargs(x, 0, 0, _(b"head takes no arguments")) hs = set() cl = repo.changelog for ls in repo.branchmap().iterheads(): @@ -1399,7 +1403,7 @@ return subset & baseset(hs) -@predicate("heads(set)", safe=True, takeorder=True) +@predicate(b"heads(set)", safe=True, takeorder=True) def heads(repo, subset, x, order): """Members of set with no children in set. """ @@ -1421,17 +1425,17 @@ return subset & heads -@predicate("hidden()", safe=True) +@predicate(b"hidden()", safe=True) def hidden(repo, subset, x): """Hidden changesets. """ # i18n: "hidden" is a keyword - getargs(x, 0, 0, _("hidden takes no arguments")) - hiddenrevs = repoview.filterrevs(repo, "visible") + getargs(x, 0, 0, _(b"hidden takes no arguments")) + hiddenrevs = repoview.filterrevs(repo, b"visible") return subset & hiddenrevs -@predicate("keyword(string)", safe=True, weight=10) +@predicate(b"keyword(string)", safe=True, weight=10) def keyword(repo, subset, x): """Search commit message, user name, and names of changed files for string. The match is case-insensitive. @@ -1440,7 +1444,7 @@ ``grep(regex)``. """ # i18n: "keyword" is a keyword - kw = encoding.lower(getstring(x, _("keyword requires a string"))) + kw = encoding.lower(getstring(x, _(b"keyword requires a string"))) def matches(r): c = repo[r] @@ -1449,44 +1453,46 @@ for t in c.files() + [c.user(), c.description()] ) - return subset.filter(matches, condrepr=("", kw)) - - -@predicate("limit(set[, n[, offset]])", safe=True, takeorder=True, weight=0) + return subset.filter(matches, condrepr=(b"", kw)) + + +@predicate(b"limit(set[, n[, offset]])", safe=True, takeorder=True, weight=0) def limit(repo, subset, x, order): """First n members of set, defaulting to 1, starting from offset. """ - args = getargsdict(x, "limit", "set n offset") - if "set" not in args: + args = getargsdict(x, b"limit", b"set n offset") + if b"set" not in args: # i18n: "limit" is a keyword - raise error.ParseError(_("limit requires one to three arguments")) + raise error.ParseError(_(b"limit requires one to three arguments")) # i18n: "limit" is a keyword - lim = getinteger(args.get("n"), _("limit expects a number"), default=1) + lim = getinteger(args.get(b"n"), _(b"limit expects a number"), default=1) if lim < 0: - raise error.ParseError(_("negative number to select")) + raise error.ParseError(_(b"negative number to select")) # i18n: "limit" is a keyword - ofs = getinteger(args.get("offset"), _("limit expects a number"), default=0) + ofs = getinteger( + args.get(b"offset"), _(b"limit expects a number"), default=0 + ) if ofs < 0: - raise error.ParseError(_("negative offset")) - os = getset(repo, fullreposet(repo), args["set"]) + raise error.ParseError(_(b"negative offset")) + os = getset(repo, fullreposet(repo), args[b"set"]) ls = os.slice(ofs, ofs + lim) if order == followorder and lim > 1: return subset & ls return ls & subset -@predicate("last(set, [n])", safe=True, takeorder=True) +@predicate(b"last(set, [n])", safe=True, takeorder=True) def last(repo, subset, x, order): """Last n members of set, defaulting to 1. """ # i18n: "last" is a keyword - l = getargs(x, 1, 2, _("last requires one or two arguments")) + l = getargs(x, 1, 2, _(b"last requires one or two arguments")) lim = 1 if len(l) == 2: # i18n: "last" is a keyword - lim = getinteger(l[1], _("last expects a number")) + lim = getinteger(l[1], _(b"last expects a number")) if lim < 0: - raise error.ParseError(_("negative number to select")) + raise error.ParseError(_(b"negative number to select")) os = getset(repo, fullreposet(repo), l[0]) os.reverse() ls = os.slice(0, lim) @@ -1496,7 +1502,7 @@ return ls & subset -@predicate("max(set)", safe=True) +@predicate(b"max(set)", safe=True) def maxrev(repo, subset, x): """Changeset with highest revision number in set. """ @@ -1504,20 +1510,20 @@ try: m = os.max() if m in subset: - return baseset([m], datarepr=("", subset, os)) + return baseset([m], datarepr=(b"", subset, os)) except ValueError: # os.max() throws a ValueError when the collection is empty. # Same as python's max(). pass - return baseset(datarepr=("", subset, os)) - - -@predicate("merge()", safe=True) + return baseset(datarepr=(b"", subset, os)) + + +@predicate(b"merge()", safe=True) def merge(repo, subset, x): """Changeset is a merge changeset. """ # i18n: "merge" is a keyword - getargs(x, 0, 0, _("merge takes no arguments")) + getargs(x, 0, 0, _(b"merge takes no arguments")) cl = repo.changelog nullrev = node.nullrev @@ -1527,15 +1533,15 @@ except error.WdirUnsupported: return bool(repo[r].p2()) - return subset.filter(ismerge, condrepr="") - - -@predicate("branchpoint()", safe=True) + return subset.filter(ismerge, condrepr=b"") + + +@predicate(b"branchpoint()", safe=True) def branchpoint(repo, subset, x): """Changesets with more than one child. """ # i18n: "branchpoint" is a keyword - getargs(x, 0, 0, _("branchpoint takes no arguments")) + getargs(x, 0, 0, _(b"branchpoint takes no arguments")) cl = repo.changelog if not subset: return baseset() @@ -1548,11 +1554,11 @@ if p >= baserev: parentscount[p - baserev] += 1 return subset.filter( - lambda r: parentscount[r - baserev] > 1, condrepr="" + lambda r: parentscount[r - baserev] > 1, condrepr=b"" ) -@predicate("min(set)", safe=True) +@predicate(b"min(set)", safe=True) def minrev(repo, subset, x): """Changeset with lowest revision number in set. """ @@ -1560,15 +1566,15 @@ try: m = os.min() if m in subset: - return baseset([m], datarepr=("", subset, os)) + return baseset([m], datarepr=(b"", subset, os)) except ValueError: # os.min() throws a ValueError when the collection is empty. # Same as python's min(). pass - return baseset(datarepr=("", subset, os)) - - -@predicate("modifies(pattern)", safe=True, weight=30) + return baseset(datarepr=(b"", subset, os)) + + +@predicate(b"modifies(pattern)", safe=True, weight=30) def modifies(repo, subset, x): """Changesets modifying files matched by pattern. @@ -1577,11 +1583,11 @@ directory. """ # i18n: "modifies" is a keyword - pat = getstring(x, _("modifies requires a pattern")) + pat = getstring(x, _(b"modifies requires a pattern")) return checkstatus(repo, subset, pat, 0) -@predicate("named(namespace)") +@predicate(b"named(namespace)") def named(repo, subset, x): """The changesets in a given namespace. @@ -1589,18 +1595,20 @@ :hg:`help revisions.patterns`. """ # i18n: "named" is a keyword - args = getargs(x, 1, 1, _("named requires a namespace argument")) + args = getargs(x, 1, 1, _(b"named requires a namespace argument")) ns = getstring( args[0], # i18n: "named" is a keyword - _("the argument to named must be a string"), + _(b"the argument to named must be a string"), ) kind, pattern, matcher = stringutil.stringmatcher(ns) namespaces = set() - if kind == "literal": + if kind == b"literal": if pattern not in repo.names: - raise error.RepoLookupError(_("namespace '%s' does not exist") % ns) + raise error.RepoLookupError( + _(b"namespace '%s' does not exist") % ns + ) namespaces.add(repo.names[pattern]) else: for name, ns in repo.names.iteritems(): @@ -1617,14 +1625,14 @@ return subset & names -@predicate("id(string)", safe=True) +@predicate(b"id(string)", safe=True) def node_(repo, subset, x): """Revision non-ambiguously specified by the given hex string prefix. """ # i18n: "id" is a keyword - l = getargs(x, 1, 1, _("id requires one argument")) + l = getargs(x, 1, 1, _(b"id requires one argument")) # i18n: "id" is a keyword - n = getstring(l[0], _("id requires a string")) + n = getstring(l[0], _(b"id requires a string")) if len(n) == 40: try: rn = repo.changelog.rev(node.bin(n)) @@ -1649,25 +1657,25 @@ return result & subset -@predicate("none()", safe=True) +@predicate(b"none()", safe=True) def none(repo, subset, x): """No changesets. """ # i18n: "none" is a keyword - getargs(x, 0, 0, _("none takes no arguments")) + getargs(x, 0, 0, _(b"none takes no arguments")) return baseset() -@predicate("obsolete()", safe=True) +@predicate(b"obsolete()", safe=True) def obsolete(repo, subset, x): """Mutable changeset with a newer version.""" # i18n: "obsolete" is a keyword - getargs(x, 0, 0, _("obsolete takes no arguments")) - obsoletes = obsmod.getrevs(repo, "obsolete") + getargs(x, 0, 0, _(b"obsolete takes no arguments")) + obsoletes = obsmod.getrevs(repo, b"obsolete") return subset & obsoletes -@predicate("only(set, [set])", safe=True) +@predicate(b"only(set, [set])", safe=True) def only(repo, subset, x): """Changesets that are ancestors of the first set that are not ancestors of any other head in the repo. If a second set is specified, the result @@ -1676,7 +1684,7 @@ """ cl = repo.changelog # i18n: "only" is a keyword - args = getargs(x, 1, 2, _("only takes one or two arguments")) + args = getargs(x, 1, 2, _(b"only takes one or two arguments")) include = getset(repo, fullreposet(repo), args[0]) if len(args) == 1: if not include: @@ -1697,7 +1705,7 @@ return subset & results -@predicate("origin([set])", safe=True) +@predicate(b"origin([set])", safe=True) def origin(repo, subset, x): """ Changesets that were specified as a source for the grafts, transplants or @@ -1730,7 +1738,7 @@ return subset & o -@predicate("outgoing([path])", safe=False, weight=10) +@predicate(b"outgoing([path])", safe=False, weight=10) def outgoing(repo, subset, x): """Changesets not found in the specified destination repository, or the default push location. @@ -1742,17 +1750,19 @@ ) # i18n: "outgoing" is a keyword - l = getargs(x, 0, 1, _("outgoing takes one or no arguments")) + l = getargs(x, 0, 1, _(b"outgoing takes one or no arguments")) # i18n: "outgoing" is a keyword - dest = l and getstring(l[0], _("outgoing requires a repository path")) or "" + dest = ( + l and getstring(l[0], _(b"outgoing requires a repository path")) or b"" + ) if not dest: # ui.paths.getpath() explicitly tests for None, not just a boolean dest = None - path = repo.ui.paths.getpath(dest, default=("default-push", "default")) + path = repo.ui.paths.getpath(dest, default=(b"default-push", b"default")) if not path: raise error.Abort( - _("default repository not configured!"), - hint=_("see 'hg help config.paths'"), + _(b"default repository not configured!"), + hint=_(b"see 'hg help config.paths'"), ) dest = path.pushloc or path.loc branches = path.branch, [] @@ -1769,7 +1779,7 @@ return subset & o -@predicate("p1([set])", safe=True) +@predicate(b"p1([set])", safe=True) def p1(repo, subset, x): """First parent of changesets in set, or the working directory. """ @@ -1792,7 +1802,7 @@ return subset & ps -@predicate("p2([set])", safe=True) +@predicate(b"p2([set])", safe=True) def p2(repo, subset, x): """Second parent of changesets in set, or the working directory. """ @@ -1825,7 +1835,7 @@ return p1(repo, subset, x) -@predicate("parents([set])", safe=True) +@predicate(b"parents([set])", safe=True) def parents(repo, subset, x): """ The set of all parents for all changesets in set, or the working directory. @@ -1851,32 +1861,32 @@ return repo._phasecache.getrevset(repo, targets, subset) -@predicate("_phase(idx)", safe=True) +@predicate(b"_phase(idx)", safe=True) def phase(repo, subset, x): - l = getargs(x, 1, 1, "_phase requires one argument") - target = getinteger(l[0], "_phase expects a number") + l = getargs(x, 1, 1, b"_phase requires one argument") + target = getinteger(l[0], b"_phase expects a number") return _phase(repo, subset, target) -@predicate("draft()", safe=True) +@predicate(b"draft()", safe=True) def draft(repo, subset, x): """Changeset in draft phase.""" # i18n: "draft" is a keyword - getargs(x, 0, 0, _("draft takes no arguments")) + getargs(x, 0, 0, _(b"draft takes no arguments")) target = phases.draft return _phase(repo, subset, target) -@predicate("secret()", safe=True) +@predicate(b"secret()", safe=True) def secret(repo, subset, x): """Changeset in secret phase.""" # i18n: "secret" is a keyword - getargs(x, 0, 0, _("secret takes no arguments")) + getargs(x, 0, 0, _(b"secret takes no arguments")) target = phases.secret return _phase(repo, subset, target) -@predicate("stack([revs])", safe=True) +@predicate(b"stack([revs])", safe=True) def stack(repo, subset, x): """Experimental revset for the stack of changesets or working directory parent. (EXPERIMENTAL) @@ -1903,7 +1913,7 @@ if n not in (0, 1, 2): raise ValueError except (TypeError, ValueError): - raise error.ParseError(_("^ expects a number 0, 1, or 2")) + raise error.ParseError(_(b"^ expects a number 0, 1, or 2")) ps = set() cl = repo.changelog for r in getset(repo, fullreposet(repo), x): @@ -1926,7 +1936,7 @@ return subset & ps -@predicate("present(set)", safe=True, takeorder=True) +@predicate(b"present(set)", safe=True, takeorder=True) def present(repo, subset, x, order): """An empty set, if any revision in set isn't found; otherwise, all revisions in set. @@ -1942,30 +1952,30 @@ # for internal use -@predicate("_notpublic", safe=True) +@predicate(b"_notpublic", safe=True) def _notpublic(repo, subset, x): - getargs(x, 0, 0, "_notpublic takes no arguments") + getargs(x, 0, 0, b"_notpublic takes no arguments") return _phase(repo, subset, phases.draft, phases.secret) # for internal use -@predicate("_phaseandancestors(phasename, set)", safe=True) +@predicate(b"_phaseandancestors(phasename, set)", safe=True) def _phaseandancestors(repo, subset, x): # equivalent to (phasename() & ancestors(set)) but more efficient # phasename could be one of 'draft', 'secret', or '_notpublic' - args = getargs(x, 2, 2, "_phaseandancestors requires two arguments") + args = getargs(x, 2, 2, b"_phaseandancestors requires two arguments") phasename = getsymbol(args[0]) s = getset(repo, fullreposet(repo), args[1]) draft = phases.draft secret = phases.secret phasenamemap = { - "_notpublic": draft, - "draft": draft, # follow secret's ancestors - "secret": secret, + b"_notpublic": draft, + b"draft": draft, # follow secret's ancestors + b"secret": secret, } if phasename not in phasenamemap: - raise error.ParseError("%r is not a valid phasename" % phasename) + raise error.ParseError(b"%r is not a valid phasename" % phasename) minimalphase = phasenamemap[phasename] getphase = repo._phasecache.phase @@ -1975,20 +1985,20 @@ revs = dagop.revancestors(repo, s, cutfunc=cutfunc) - if phasename == "draft": # need to remove secret changesets + if phasename == b"draft": # need to remove secret changesets revs = revs.filter(lambda r: getphase(repo, r) == draft) return subset & revs -@predicate("public()", safe=True) +@predicate(b"public()", safe=True) def public(repo, subset, x): """Changeset in public phase.""" # i18n: "public" is a keyword - getargs(x, 0, 0, _("public takes no arguments")) + getargs(x, 0, 0, _(b"public takes no arguments")) return _phase(repo, subset, phases.public) -@predicate("remote([id [,path]])", safe=False) +@predicate(b"remote([id [,path]])", safe=False) def remote(repo, subset, x): """Local revision that corresponds to the given identifier in a remote repository, if present. Here, the '.' identifier is a @@ -1998,20 +2008,20 @@ from . import hg # avoid start-up nasties # i18n: "remote" is a keyword - l = getargs(x, 0, 2, _("remote takes zero, one, or two arguments")) - - q = "." + l = getargs(x, 0, 2, _(b"remote takes zero, one, or two arguments")) + + q = b"." if len(l) > 0: # i18n: "remote" is a keyword - q = getstring(l[0], _("remote requires a string id")) - if q == ".": - q = repo["."].branch() - - dest = "" + q = getstring(l[0], _(b"remote requires a string id")) + if q == b".": + q = repo[b"."].branch() + + dest = b"" if len(l) > 1: # i18n: "remote" is a keyword - dest = getstring(l[1], _("remote requires a repository path")) - dest = repo.ui.expandpath(dest or "default") + dest = getstring(l[1], _(b"remote requires a repository path")) + dest = repo.ui.expandpath(dest or b"default") dest, branches = hg.parseurl(dest) revs, checkout = hg.addbranchrevs(repo, repo, branches, []) if revs: @@ -2025,7 +2035,7 @@ return baseset() -@predicate("removes(pattern)", safe=True, weight=30) +@predicate(b"removes(pattern)", safe=True, weight=30) def removes(repo, subset, x): """Changesets which remove files matching pattern. @@ -2034,43 +2044,43 @@ directory. """ # i18n: "removes" is a keyword - pat = getstring(x, _("removes requires a pattern")) + pat = getstring(x, _(b"removes requires a pattern")) return checkstatus(repo, subset, pat, 2) -@predicate("rev(number)", safe=True) +@predicate(b"rev(number)", safe=True) def rev(repo, subset, x): """Revision with the given numeric identifier. """ # i18n: "rev" is a keyword - l = getargs(x, 1, 1, _("rev requires one argument")) + l = getargs(x, 1, 1, _(b"rev requires one argument")) try: # i18n: "rev" is a keyword - l = int(getstring(l[0], _("rev requires a number"))) + l = int(getstring(l[0], _(b"rev requires a number"))) except (TypeError, ValueError): # i18n: "rev" is a keyword - raise error.ParseError(_("rev expects a number")) + raise error.ParseError(_(b"rev expects a number")) if l not in repo.changelog and l not in _virtualrevs: return baseset() return subset & baseset([l]) -@predicate("_rev(number)", safe=True) +@predicate(b"_rev(number)", safe=True) def _rev(repo, subset, x): # internal version of "rev(x)" that raise error if "x" is invalid # i18n: "rev" is a keyword - l = getargs(x, 1, 1, _("rev requires one argument")) + l = getargs(x, 1, 1, _(b"rev requires one argument")) try: # i18n: "rev" is a keyword - l = int(getstring(l[0], _("rev requires a number"))) + l = int(getstring(l[0], _(b"rev requires a number"))) except (TypeError, ValueError): # i18n: "rev" is a keyword - raise error.ParseError(_("rev expects a number")) + raise error.ParseError(_(b"rev expects a number")) repo.changelog.node(l) # check that the rev exists return subset & baseset([l]) -@predicate("revset(set)", safe=True, takeorder=True) +@predicate(b"revset(set)", safe=True, takeorder=True) def revsetpredicate(repo, subset, x, order): """Strictly interpret the content as a revset. @@ -2081,7 +2091,7 @@ return getset(repo, subset, x, order) -@predicate("matching(revision [, field])", safe=True) +@predicate(b"matching(revision [, field])", safe=True) def matching(repo, subset, x): """Changesets in which a given set of fields match the set of fields in the selected revision or set. @@ -2107,16 +2117,16 @@ specified. You can match more than one field at a time. """ # i18n: "matching" is a keyword - l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments")) + l = getargs(x, 1, 2, _(b"matching takes 1 or 2 arguments")) revs = getset(repo, fullreposet(repo), l[0]) - fieldlist = ["metadata"] + fieldlist = [b"metadata"] if len(l) > 1: fieldlist = getstring( l[1], # i18n: "matching" is a keyword - _("matching requires a string " "as its second argument"), + _(b"matching requires a string " b"as its second argument"), ).split() # Make sure that there are no repeated fields, @@ -2124,36 +2134,36 @@ # and check the 'files' whenever we check the 'diff' fields = [] for field in fieldlist: - if field == "metadata": - fields += ["user", "description", "date"] - elif field == "diff": + if field == b"metadata": + fields += [b"user", b"description", b"date"] + elif field == b"diff": # a revision matching the diff must also match the files # since matching the diff is very costly, make sure to # also match the files first - fields += ["files", "diff"] + fields += [b"files", b"diff"] else: - if field == "author": - field = "user" + if field == b"author": + field = b"user" fields.append(field) fields = set(fields) - if "summary" in fields and "description" in fields: + if b"summary" in fields and b"description" in fields: # If a revision matches its description it also matches its summary - fields.discard("summary") + fields.discard(b"summary") # We may want to match more than one field # Not all fields take the same amount of time to be matched # Sort the selected fields in order of increasing matching cost fieldorder = [ - "phase", - "parents", - "user", - "date", - "branch", - "summary", - "files", - "description", - "substate", - "diff", + b"phase", + b"parents", + b"user", + b"date", + b"branch", + b"summary", + b"files", + b"description", + b"substate", + b"diff", ] def fieldkeyfunc(f): @@ -2170,17 +2180,17 @@ # which will be added to the getfieldfuncs array of functions getfieldfuncs = [] _funcs = { - "user": lambda r: repo[r].user(), - "branch": lambda r: repo[r].branch(), - "date": lambda r: repo[r].date(), - "description": lambda r: repo[r].description(), - "files": lambda r: repo[r].files(), - "parents": lambda r: repo[r].parents(), - "phase": lambda r: repo[r].phase(), - "substate": lambda r: repo[r].substate, - "summary": lambda r: repo[r].description().splitlines()[0], - "diff": lambda r: list( - repo[r].diff(opts=diffutil.diffallopts(repo.ui, {"git": True})) + b"user": lambda r: repo[r].user(), + b"branch": lambda r: repo[r].branch(), + b"date": lambda r: repo[r].date(), + b"description": lambda r: repo[r].description(), + b"files": lambda r: repo[r].files(), + b"parents": lambda r: repo[r].parents(), + b"phase": lambda r: repo[r].phase(), + b"substate": lambda r: repo[r].substate, + b"summary": lambda r: repo[r].description().splitlines()[0], + b"diff": lambda r: list( + repo[r].diff(opts=diffutil.diffallopts(repo.ui, {b"git": True})) ), } for info in fields: @@ -2188,7 +2198,7 @@ if getfield is None: raise error.ParseError( # i18n: "matching" is a keyword - _("unexpected field name passed to matching: %s") + _(b"unexpected field name passed to matching: %s") % info ) getfieldfuncs.append(getfield) @@ -2208,10 +2218,10 @@ return True return False - return subset.filter(matches, condrepr=("", fields, revs)) - - -@predicate("reverse(set)", safe=True, takeorder=True, weight=0) + return subset.filter(matches, condrepr=(b"", fields, revs)) + + +@predicate(b"reverse(set)", safe=True, takeorder=True, weight=0) def reverse(repo, subset, x, order): """Reverse order of set. """ @@ -2221,7 +2231,7 @@ return l -@predicate("roots(set)", safe=True) +@predicate(b"roots(set)", safe=True) def roots(repo, subset, x): """Changesets in set with no parent changeset in set. """ @@ -2234,66 +2244,66 @@ return False return True - return subset & s.filter(filter, condrepr="") + return subset & s.filter(filter, condrepr=b"") _sortkeyfuncs = { - "rev": lambda c: c.rev(), - "branch": lambda c: c.branch(), - "desc": lambda c: c.description(), - "user": lambda c: c.user(), - "author": lambda c: c.user(), - "date": lambda c: c.date()[0], + b"rev": lambda c: c.rev(), + b"branch": lambda c: c.branch(), + b"desc": lambda c: c.description(), + b"user": lambda c: c.user(), + b"author": lambda c: c.user(), + b"date": lambda c: c.date()[0], } def _getsortargs(x): """Parse sort options into (set, [(key, reverse)], opts)""" - args = getargsdict(x, "sort", "set keys topo.firstbranch") - if "set" not in args: + args = getargsdict(x, b"sort", b"set keys topo.firstbranch") + if b"set" not in args: # i18n: "sort" is a keyword - raise error.ParseError(_("sort requires one or two arguments")) - keys = "rev" - if "keys" in args: + raise error.ParseError(_(b"sort requires one or two arguments")) + keys = b"rev" + if b"keys" in args: # i18n: "sort" is a keyword - keys = getstring(args["keys"], _("sort spec must be a string")) + keys = getstring(args[b"keys"], _(b"sort spec must be a string")) keyflags = [] for k in keys.split(): fk = k - reverse = k.startswith("-") + reverse = k.startswith(b"-") if reverse: k = k[1:] - if k not in _sortkeyfuncs and k != "topo": + if k not in _sortkeyfuncs and k != b"topo": raise error.ParseError( - _("unknown sort key %r") % pycompat.bytestr(fk) + _(b"unknown sort key %r") % pycompat.bytestr(fk) ) keyflags.append((k, reverse)) - if len(keyflags) > 1 and any(k == "topo" for k, reverse in keyflags): + if len(keyflags) > 1 and any(k == b"topo" for k, reverse in keyflags): # i18n: "topo" is a keyword raise error.ParseError( - _("topo sort order cannot be combined " "with other sort keys") + _(b"topo sort order cannot be combined " b"with other sort keys") ) opts = {} - if "topo.firstbranch" in args: - if any(k == "topo" for k, reverse in keyflags): - opts["topo.firstbranch"] = args["topo.firstbranch"] + if b"topo.firstbranch" in args: + if any(k == b"topo" for k, reverse in keyflags): + opts[b"topo.firstbranch"] = args[b"topo.firstbranch"] else: # i18n: "topo" and "topo.firstbranch" are keywords raise error.ParseError( _( - "topo.firstbranch can only be used " - "when using the topo sort key" + b"topo.firstbranch can only be used " + b"when using the topo sort key" ) ) - return args["set"], keyflags, opts + return args[b"set"], keyflags, opts @predicate( - "sort(set[, [-]key... [, ...]])", safe=True, takeorder=True, weight=10 + b"sort(set[, [-]key... [, ...]])", safe=True, takeorder=True, weight=10 ) def sort(repo, subset, x, order): """Sort set by keys. The default sort order is ascending, specify a key @@ -2318,13 +2328,13 @@ if not keyflags or order != defineorder: return revs - if len(keyflags) == 1 and keyflags[0][0] == "rev": + if len(keyflags) == 1 and keyflags[0][0] == b"rev": revs.sort(reverse=keyflags[0][1]) return revs - elif keyflags[0][0] == "topo": + elif keyflags[0][0] == b"topo": firstbranch = () - if "topo.firstbranch" in opts: - firstbranch = getset(repo, subset, opts["topo.firstbranch"]) + if b"topo.firstbranch" in opts: + firstbranch = getset(repo, subset, opts[b"topo.firstbranch"]) revs = baseset( dagop.toposort(revs, repo.changelog.parentrevs, firstbranch), istopo=True, @@ -2340,18 +2350,18 @@ return baseset([c.rev() for c in ctxs]) -@predicate("subrepo([pattern])") +@predicate(b"subrepo([pattern])") def subrepo(repo, subset, x): """Changesets that add, modify or remove the given subrepo. If no subrepo pattern is named, any subrepo changes are returned. """ # i18n: "subrepo" is a keyword - args = getargs(x, 0, 1, _("subrepo takes at most one argument")) + args = getargs(x, 0, 1, _(b"subrepo takes at most one argument")) pat = None if len(args) != 0: - pat = getstring(args[0], _("subrepo requires a pattern")) - - m = matchmod.exact([".hgsubstate"]) + pat = getstring(args[0], _(b"subrepo requires a pattern")) + + m = matchmod.exact([b".hgsubstate"]) def submatches(names): k, p, m = stringutil.stringmatcher(pat) @@ -2382,7 +2392,7 @@ return False - return subset.filter(matches, condrepr=("", pat)) + return subset.filter(matches, condrepr=(b"", pat)) def _mapbynodefunc(repo, s, f): @@ -2400,7 +2410,7 @@ return smartset.baseset(result - repo.changelog.filteredrevs) -@predicate("successors(set)", safe=True) +@predicate(b"successors(set)", safe=True) def successors(repo, subset, x): """All successors for set, including the given set themselves""" s = getset(repo, fullreposet(repo), x) @@ -2413,7 +2423,7 @@ kind, pattern, matcher = stringutil.stringmatcher( pattern, casesensitive=casesensitive ) - if kind == "literal": + if kind == b"literal": if not casesensitive: pattern = encoding.lower(pattern) matcher = lambda s: pattern in encoding.lower(s) @@ -2422,7 +2432,7 @@ return kind, pattern, matcher -@predicate("tag([name])", safe=True) +@predicate(b"tag([name])", safe=True) def tag(repo, subset, x): """The specified tag by name, or all tagged revisions if no name is given. @@ -2430,46 +2440,46 @@ :hg:`help revisions.patterns`. """ # i18n: "tag" is a keyword - args = getargs(x, 0, 1, _("tag takes one or no arguments")) + args = getargs(x, 0, 1, _(b"tag takes one or no arguments")) cl = repo.changelog if args: pattern = getstring( args[0], # i18n: "tag" is a keyword - _("the argument to tag must be a string"), + _(b"the argument to tag must be a string"), ) kind, pattern, matcher = stringutil.stringmatcher(pattern) - if kind == "literal": + if kind == b"literal": # avoid resolving all tags tn = repo._tagscache.tags.get(pattern, None) if tn is None: raise error.RepoLookupError( - _("tag '%s' does not exist") % pattern + _(b"tag '%s' does not exist") % pattern ) s = {repo[tn].rev()} else: s = {cl.rev(n) for t, n in repo.tagslist() if matcher(t)} else: - s = {cl.rev(n) for t, n in repo.tagslist() if t != "tip"} + s = {cl.rev(n) for t, n in repo.tagslist() if t != b"tip"} return subset & s -@predicate("tagged", safe=True) +@predicate(b"tagged", safe=True) def tagged(repo, subset, x): return tag(repo, subset, x) -@predicate("orphan()", safe=True) +@predicate(b"orphan()", safe=True) def orphan(repo, subset, x): """Non-obsolete changesets with obsolete ancestors. (EXPERIMENTAL) """ # i18n: "orphan" is a keyword - getargs(x, 0, 0, _("orphan takes no arguments")) - orphan = obsmod.getrevs(repo, "orphan") + getargs(x, 0, 0, _(b"orphan takes no arguments")) + orphan = obsmod.getrevs(repo, b"orphan") return subset & orphan -@predicate("user(string)", safe=True, weight=10) +@predicate(b"user(string)", safe=True, weight=10) def user(repo, subset, x): """User name contains string. The match is case-insensitive. @@ -2479,18 +2489,18 @@ return author(repo, subset, x) -@predicate("wdir()", safe=True, weight=0) +@predicate(b"wdir()", safe=True, weight=0) def wdir(repo, subset, x): """Working directory. (EXPERIMENTAL)""" # i18n: "wdir" is a keyword - getargs(x, 0, 0, _("wdir takes no arguments")) + getargs(x, 0, 0, _(b"wdir takes no arguments")) if node.wdirrev in subset or isinstance(subset, fullreposet): return baseset([node.wdirrev]) return baseset() def _orderedlist(repo, subset, x): - s = getstring(x, "internal error") + s = getstring(x, b"internal error") if not s: return baseset() # remove duplicates here. it's difficult for caller to deduplicate sets @@ -2498,11 +2508,11 @@ cl = repo.changelog ls = [] seen = set() - for t in s.split("\0"): + for t in s.split(b"\0"): try: # fast path for integer revision r = int(t) - if ("%d" % r) != t or r not in cl: + if (b"%d" % r) != t or r not in cl: raise ValueError revs = [r] except ValueError: @@ -2522,7 +2532,7 @@ # for internal use -@predicate("_list", safe=True, takeorder=True) +@predicate(b"_list", safe=True, takeorder=True) def _list(repo, subset, x, order): if order == followorder: # slow path to take the subset order @@ -2532,16 +2542,16 @@ def _orderedintlist(repo, subset, x): - s = getstring(x, "internal error") + s = getstring(x, b"internal error") if not s: return baseset() - ls = [int(r) for r in s.split("\0")] + ls = [int(r) for r in s.split(b"\0")] s = subset return baseset([r for r in ls if r in s]) # for internal use -@predicate("_intlist", safe=True, takeorder=True, weight=0) +@predicate(b"_intlist", safe=True, takeorder=True, weight=0) def _intlist(repo, subset, x, order): if order == followorder: # slow path to take the subset order @@ -2551,17 +2561,17 @@ def _orderedhexlist(repo, subset, x): - s = getstring(x, "internal error") + s = getstring(x, b"internal error") if not s: return baseset() cl = repo.changelog - ls = [cl.rev(node.bin(r)) for r in s.split("\0")] + ls = [cl.rev(node.bin(r)) for r in s.split(b"\0")] s = subset return baseset([r for r in ls if r in s]) # for internal use -@predicate("_hexlist", safe=True, takeorder=True) +@predicate(b"_hexlist", safe=True, takeorder=True) def _hexlist(repo, subset, x, order): if order == followorder: # slow path to take the subset order @@ -2571,33 +2581,33 @@ methods = { - "range": rangeset, - "rangeall": rangeall, - "rangepre": rangepre, - "rangepost": rangepost, - "dagrange": dagrange, - "string": stringset, - "symbol": stringset, - "and": andset, - "andsmally": andsmallyset, - "or": orset, - "not": notset, - "difference": differenceset, - "relation": relationset, - "relsubscript": relsubscriptset, - "subscript": subscriptset, - "list": listset, - "keyvalue": keyvaluepair, - "func": func, - "ancestor": ancestorspec, - "parent": parentspec, - "parentpost": parentpost, - "smartset": rawsmartset, + b"range": rangeset, + b"rangeall": rangeall, + b"rangepre": rangepre, + b"rangepost": rangepost, + b"dagrange": dagrange, + b"string": stringset, + b"symbol": stringset, + b"and": andset, + b"andsmally": andsmallyset, + b"or": orset, + b"not": notset, + b"difference": differenceset, + b"relation": relationset, + b"relsubscript": relsubscriptset, + b"subscript": subscriptset, + b"list": listset, + b"keyvalue": keyvaluepair, + b"func": func, + b"ancestor": ancestorspec, + b"parent": parentspec, + b"parentpost": parentpost, + b"smartset": rawsmartset, } subscriptrelations = { - "g": generationsrel, - "generations": generationsrel, + b"g": generationsrel, + b"generations": generationsrel, } @@ -2627,19 +2637,19 @@ return mfunc if not all(specs): - raise error.ParseError(_("empty query")) + raise error.ParseError(_(b"empty query")) if len(specs) == 1: tree = revsetlang.parse(specs[0], lookup) else: tree = ( - "or", - ("list",) + tuple(revsetlang.parse(s, lookup) for s in specs), + b"or", + (b"list",) + tuple(revsetlang.parse(s, lookup) for s in specs), ) aliases = [] warn = None if ui: - aliases.extend(ui.configitems("revsetalias")) + aliases.extend(ui.configitems(b"revsetalias")) warn = ui.warn if localalias: aliases.extend(localalias.items()) diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py --- a/mercurial/revsetlang.py +++ b/mercurial/revsetlang.py @@ -22,63 +22,63 @@ elements = { # token-type: binding-strength, primary, prefix, infix, suffix - "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None), - "[": (21, None, None, ("subscript", 1, "]"), None), - "#": (21, None, None, ("relation", 21), None), - "##": (20, None, None, ("_concat", 20), None), - "~": (18, None, None, ("ancestor", 18), None), - "^": (18, None, None, ("parent", 18), "parentpost"), - "-": (5, None, ("negate", 19), ("minus", 5), None), - "::": ( + b"(": (21, None, (b"group", 1, b")"), (b"func", 1, b")"), None), + b"[": (21, None, None, (b"subscript", 1, b"]"), None), + b"#": (21, None, None, (b"relation", 21), None), + b"##": (20, None, None, (b"_concat", 20), None), + b"~": (18, None, None, (b"ancestor", 18), None), + b"^": (18, None, None, (b"parent", 18), b"parentpost"), + b"-": (5, None, (b"negate", 19), (b"minus", 5), None), + b"::": ( 17, - "dagrangeall", - ("dagrangepre", 17), - ("dagrange", 17), - "dagrangepost", + b"dagrangeall", + (b"dagrangepre", 17), + (b"dagrange", 17), + b"dagrangepost", ), - "..": ( + b"..": ( 17, - "dagrangeall", - ("dagrangepre", 17), - ("dagrange", 17), - "dagrangepost", + b"dagrangeall", + (b"dagrangepre", 17), + (b"dagrange", 17), + b"dagrangepost", ), - ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"), - "not": (10, None, ("not", 10), None, None), - "!": (10, None, ("not", 10), None, None), - "and": (5, None, None, ("and", 5), None), - "&": (5, None, None, ("and", 5), None), - "%": (5, None, None, ("only", 5), "onlypost"), - "or": (4, None, None, ("or", 4), None), - "|": (4, None, None, ("or", 4), None), - "+": (4, None, None, ("or", 4), None), - "=": (3, None, None, ("keyvalue", 3), None), - ",": (2, None, None, ("list", 2), None), - ")": (0, None, None, None, None), - "]": (0, None, None, None, None), - "symbol": (0, "symbol", None, None, None), - "string": (0, "string", None, None, None), - "end": (0, None, None, None, None), + b":": (15, b"rangeall", (b"rangepre", 15), (b"range", 15), b"rangepost"), + b"not": (10, None, (b"not", 10), None, None), + b"!": (10, None, (b"not", 10), None, None), + b"and": (5, None, None, (b"and", 5), None), + b"&": (5, None, None, (b"and", 5), None), + b"%": (5, None, None, (b"only", 5), b"onlypost"), + b"or": (4, None, None, (b"or", 4), None), + b"|": (4, None, None, (b"or", 4), None), + b"+": (4, None, None, (b"or", 4), None), + b"=": (3, None, None, (b"keyvalue", 3), None), + b",": (2, None, None, (b"list", 2), None), + b")": (0, None, None, None, None), + b"]": (0, None, None, None, None), + b"symbol": (0, b"symbol", None, None, None), + b"string": (0, b"string", None, None, None), + b"end": (0, None, None, None, None), } -keywords = {"and", "or", "not"} +keywords = {b"and", b"or", b"not"} symbols = {} -_quoteletters = {'"', "'"} -_simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%")) +_quoteletters = {b'"', b"'"} +_simpleopletters = set(pycompat.iterbytestr(b"()[]#:=,-|&+!~^%")) # default set of valid characters for the initial letter of symbols _syminitletters = set( pycompat.iterbytestr( pycompat.sysbytes(string.ascii_letters) + pycompat.sysbytes(string.digits) - + "._@" + + b"._@" ) ) | set(map(pycompat.bytechr, pycompat.xrange(128, 256))) # default set of valid characters for non-initial letters of symbols -_symletters = _syminitletters | set(pycompat.iterbytestr("-/")) +_symletters = _syminitletters | set(pycompat.iterbytestr(b"-/")) def tokenize(program, lookup=None, syminitletters=None, symletters=None): @@ -104,7 +104,7 @@ """ if not isinstance(program, bytes): raise error.ProgrammingError( - "revset statement must be bytes, got %r" % program + b"revset statement must be bytes, got %r" % program ) program = pycompat.bytestr(program) if syminitletters is None: @@ -115,16 +115,16 @@ if program and lookup: # attempt to parse old-style ranges first to deal with # things like old-tag which contain query metacharacters - parts = program.split(":", 1) + parts = program.split(b":", 1) if all(lookup(sym) for sym in parts if sym): if parts[0]: - yield ("symbol", parts[0], 0) + yield (b"symbol", parts[0], 0) if len(parts) > 1: s = len(parts[0]) - yield (":", None, s) + yield (b":", None, s) if parts[1]: - yield ("symbol", parts[1], s + 1) - yield ("end", None, len(program)) + yield (b"symbol", parts[1], s + 1) + yield (b"end", None, len(program)) return pos, l = 0, len(program) @@ -133,28 +133,28 @@ if c.isspace(): # skip inter-token whitespace pass elif ( - c == ":" and program[pos : pos + 2] == "::" + c == b":" and program[pos : pos + 2] == b"::" ): # look ahead carefully - yield ("::", None, pos) + yield (b"::", None, pos) pos += 1 # skip ahead elif ( - c == "." and program[pos : pos + 2] == ".." + c == b"." and program[pos : pos + 2] == b".." ): # look ahead carefully - yield ("..", None, pos) + yield (b"..", None, pos) pos += 1 # skip ahead elif ( - c == "#" and program[pos : pos + 2] == "##" + c == b"#" and program[pos : pos + 2] == b"##" ): # look ahead carefully - yield ("##", None, pos) + yield (b"##", None, pos) pos += 1 # skip ahead elif c in _simpleopletters: # handle simple operators yield (c, None, pos) elif ( c in _quoteletters - or c == "r" - and program[pos : pos + 2] in ("r'", 'r"') + or c == b"r" + and program[pos : pos + 2] in (b"r'", b'r"') ): # handle quoted strings - if c == "r": + if c == b"r": pos += 1 c = program[pos] decode = lambda x: x @@ -164,15 +164,15 @@ s = pos while pos < l: # find closing quote d = program[pos] - if d == "\\": # skip over escaped characters + if d == b"\\": # skip over escaped characters pos += 2 continue if d == c: - yield ("string", decode(program[s:pos]), s) + yield (b"string", decode(program[s:pos]), s) break pos += 1 else: - raise error.ParseError(_("unterminated string"), s) + raise error.ParseError(_(b"unterminated string"), s) # gather up a symbol/keyword elif c in syminitletters: s = pos @@ -181,38 +181,40 @@ d = program[pos] if d not in symletters: break - if d == "." and program[pos - 1] == ".": # special case for .. + if ( + d == b"." and program[pos - 1] == b"." + ): # special case for .. pos -= 1 break pos += 1 sym = program[s:pos] if sym in keywords: # operator keywords yield (sym, None, s) - elif "-" in sym: + elif b"-" in sym: # some jerk gave us foo-bar-baz, try to check if it's a symbol if lookup and lookup(sym): # looks like a real symbol - yield ("symbol", sym, s) + yield (b"symbol", sym, s) else: # looks like an expression - parts = sym.split("-") + parts = sym.split(b"-") for p in parts[:-1]: if p: # possible consecutive - - yield ("symbol", p, s) + yield (b"symbol", p, s) s += len(p) - yield ("-", None, s) + yield (b"-", None, s) s += 1 if parts[-1]: # possible trailing - - yield ("symbol", parts[-1], s) + yield (b"symbol", parts[-1], s) else: - yield ("symbol", sym, s) + yield (b"symbol", sym, s) pos -= 1 else: raise error.ParseError( - _("syntax error in revset '%s'") % program, pos + _(b"syntax error in revset '%s'") % program, pos ) pos += 1 - yield ("end", None, pos) + yield (b"end", None, pos) # helpers @@ -221,13 +223,13 @@ def getsymbol(x): - if x and x[0] == "symbol": + if x and x[0] == b"symbol": return x[1] - raise error.ParseError(_("not a symbol")) + raise error.ParseError(_(b"not a symbol")) def getstring(x, err): - if x and (x[0] == "string" or x[0] == "symbol"): + if x and (x[0] == b"string" or x[0] == b"symbol"): return x[1] raise error.ParseError(err) @@ -251,7 +253,7 @@ def getlist(x): if not x: return [] - if x[0] == "list": + if x[0] == b"list": return list(x[1:]) return [x] @@ -260,13 +262,13 @@ if not x: raise error.ParseError(err) op = x[0] - if op == "range": + if op == b"range": return x[1], x[2] - elif op == "rangepre": + elif op == b"rangepre": return None, x[1] - elif op == "rangepost": + elif op == b"rangepost": return x[1], None - elif op == "rangeall": + elif op == b"rangeall": return None, None raise error.ParseError(err) @@ -277,7 +279,7 @@ If any of the sides omitted, and if no default provided, ParseError will be raised. """ - if x and (x[0] == "string" or x[0] == "symbol"): + if x and (x[0] == b"string" or x[0] == b"symbol"): n = getinteger(x, err1) return n, n a, b = getrange(x, err1) @@ -296,8 +298,8 @@ getlist(x), funcname, parser.splitargspec(keys), - keyvaluenode="keyvalue", - keynode="symbol", + keyvaluenode=b"keyvalue", + keynode=b"symbol", ) @@ -320,7 +322,7 @@ ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2')) """ template = _cachedtree(tmplspec) - return parser.buildtree(template, ("symbol", "_"), *repls) + return parser.buildtree(template, (b"symbol", b"_"), *repls) def _match(patspec, tree): @@ -333,12 +335,12 @@ """ pattern = _cachedtree(patspec) return parser.matchtree( - pattern, tree, ("symbol", "_"), {"keyvalue", "list"} + pattern, tree, (b"symbol", b"_"), {b"keyvalue", b"list"} ) def _matchonly(revs, bases): - return _match("ancestors(_) and not ancestors(_)", ("and", revs, bases)) + return _match(b"ancestors(_) and not ancestors(_)", (b"and", revs, bases)) def _fixops(x): @@ -348,25 +350,25 @@ return x op = x[0] - if op == "parent": + if op == b"parent": # x^:y means (x^) : y, not x ^ (:y) # x^: means (x^) :, not x ^ (:) - post = ("parentpost", x[1]) - if x[2][0] == "dagrangepre": - return _fixops(("dagrange", post, x[2][1])) - elif x[2][0] == "dagrangeall": - return _fixops(("dagrangepost", post)) - elif x[2][0] == "rangepre": - return _fixops(("range", post, x[2][1])) - elif x[2][0] == "rangeall": - return _fixops(("rangepost", post)) - elif op == "or": + post = (b"parentpost", x[1]) + if x[2][0] == b"dagrangepre": + return _fixops((b"dagrange", post, x[2][1])) + elif x[2][0] == b"dagrangeall": + return _fixops((b"dagrangepost", post)) + elif x[2][0] == b"rangepre": + return _fixops((b"range", post, x[2][1])) + elif x[2][0] == b"rangeall": + return _fixops((b"rangepost", post)) + elif op == b"or": # make number of arguments deterministic: # x + y + z -> (or x y z) -> (or (list x y z)) - return (op, _fixops(("list",) + x[1:])) - elif op == "subscript" and x[1][0] == "relation": + return (op, _fixops((b"list",) + x[1:])) + elif op == b"subscript" and x[1][0] == b"relation": # x#y[z] ternary - return _fixops(("relsubscript", x[1][1], x[1][2], x[2])) + return _fixops((b"relsubscript", x[1][1], x[1][2], x[2])) return (op,) + tuple(_fixops(y) for y in x[1:]) @@ -376,53 +378,53 @@ return x op = x[0] - if op == "minus": - return _analyze(_build("_ and not _", *x[1:])) - elif op == "only": - return _analyze(_build("only(_, _)", *x[1:])) - elif op == "onlypost": - return _analyze(_build("only(_)", x[1])) - elif op == "dagrangeall": - raise error.ParseError(_("can't use '::' in this context")) - elif op == "dagrangepre": - return _analyze(_build("ancestors(_)", x[1])) - elif op == "dagrangepost": - return _analyze(_build("descendants(_)", x[1])) - elif op == "negate": - s = getstring(x[1], _("can't negate that")) - return _analyze(("string", "-" + s)) - elif op in ("string", "symbol", "smartset"): + if op == b"minus": + return _analyze(_build(b"_ and not _", *x[1:])) + elif op == b"only": + return _analyze(_build(b"only(_, _)", *x[1:])) + elif op == b"onlypost": + return _analyze(_build(b"only(_)", x[1])) + elif op == b"dagrangeall": + raise error.ParseError(_(b"can't use '::' in this context")) + elif op == b"dagrangepre": + return _analyze(_build(b"ancestors(_)", x[1])) + elif op == b"dagrangepost": + return _analyze(_build(b"descendants(_)", x[1])) + elif op == b"negate": + s = getstring(x[1], _(b"can't negate that")) + return _analyze((b"string", b"-" + s)) + elif op in (b"string", b"symbol", b"smartset"): return x - elif op == "rangeall": + elif op == b"rangeall": return (op, None) - elif op in {"or", "not", "rangepre", "rangepost", "parentpost"}: + elif op in {b"or", b"not", b"rangepre", b"rangepost", b"parentpost"}: return (op, _analyze(x[1])) - elif op == "group": + elif op == b"group": return _analyze(x[1]) elif op in { - "and", - "dagrange", - "range", - "parent", - "ancestor", - "relation", - "subscript", + b"and", + b"dagrange", + b"range", + b"parent", + b"ancestor", + b"relation", + b"subscript", }: ta = _analyze(x[1]) tb = _analyze(x[2]) return (op, ta, tb) - elif op == "relsubscript": + elif op == b"relsubscript": ta = _analyze(x[1]) tb = _analyze(x[2]) tc = _analyze(x[3]) return (op, ta, tb, tc) - elif op == "list": + elif op == b"list": return (op,) + tuple(_analyze(y) for y in x[1:]) - elif op == "keyvalue": + elif op == b"keyvalue": return (op, x[1], _analyze(x[2])) - elif op == "func": + elif op == b"func": return (op, x[1], _analyze(x[2])) - raise ValueError("invalid operator %r" % op) + raise ValueError(b"invalid operator %r" % op) def analyze(x): @@ -440,30 +442,30 @@ return 0, x op = x[0] - if op in ("string", "symbol", "smartset"): + if op in (b"string", b"symbol", b"smartset"): return 0.5, x # single revisions are small - elif op == "and": + elif op == b"and": wa, ta = _optimize(x[1]) wb, tb = _optimize(x[2]) w = min(wa, wb) # (draft/secret/_notpublic() & ::x) have a fast path - m = _match("_() & ancestors(_)", ("and", ta, tb)) - if m and getsymbol(m[1]) in {"draft", "secret", "_notpublic"}: - return w, _build("_phaseandancestors(_, _)", m[1], m[2]) + m = _match(b"_() & ancestors(_)", (b"and", ta, tb)) + if m and getsymbol(m[1]) in {b"draft", b"secret", b"_notpublic"}: + return w, _build(b"_phaseandancestors(_, _)", m[1], m[2]) # (::x and not ::y)/(not ::y and ::x) have a fast path m = _matchonly(ta, tb) or _matchonly(tb, ta) if m: - return w, _build("only(_, _)", *m[1:]) + return w, _build(b"only(_, _)", *m[1:]) - m = _match("not _", tb) + m = _match(b"not _", tb) if m: - return wa, ("difference", ta, m[1]) + return wa, (b"difference", ta, m[1]) if wa > wb: - op = "andsmally" + op = b"andsmally" return w, (op, ta, tb) - elif op == "or": + elif op == b"or": # fast path for machine-generated expression, that is likely to have # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()' ws, ts, ss = [], [], [] @@ -474,8 +476,8 @@ if len(ss) == 1: w, t = ss[0] else: - s = "\0".join(t[1] for w, t in ss) - y = _build("_list(_)", ("string", s)) + s = b"\0".join(t[1] for w, t in ss) + y = _build(b"_list(_)", (b"string", s)) w, t = _optimize(y) ws.append(w) ts.append(t) @@ -483,7 +485,7 @@ for y in getlist(x[1]): w, t = _optimize(y) - if t is not None and (t[0] == "string" or t[0] == "symbol"): + if t is not None and (t[0] == b"string" or t[0] == b"symbol"): ss.append((w, t)) continue flushss() @@ -492,48 +494,48 @@ flushss() if len(ts) == 1: return ws[0], ts[0] # 'or' operation is fully optimized out - return max(ws), (op, ("list",) + tuple(ts)) - elif op == "not": + return max(ws), (op, (b"list",) + tuple(ts)) + elif op == b"not": # Optimize not public() to _notpublic() because we have a fast version - if _match("public()", x[1]): - o = _optimize(_build("_notpublic()")) + if _match(b"public()", x[1]): + o = _optimize(_build(b"_notpublic()")) return o[0], o[1] else: o = _optimize(x[1]) return o[0], (op, o[1]) - elif op == "rangeall": + elif op == b"rangeall": return 1, x - elif op in ("rangepre", "rangepost", "parentpost"): + elif op in (b"rangepre", b"rangepost", b"parentpost"): o = _optimize(x[1]) return o[0], (op, o[1]) - elif op in ("dagrange", "range"): + elif op in (b"dagrange", b"range"): wa, ta = _optimize(x[1]) wb, tb = _optimize(x[2]) return wa + wb, (op, ta, tb) - elif op in ("parent", "ancestor", "relation", "subscript"): + elif op in (b"parent", b"ancestor", b"relation", b"subscript"): w, t = _optimize(x[1]) return w, (op, t, x[2]) - elif op == "relsubscript": + elif op == b"relsubscript": w, t = _optimize(x[1]) return w, (op, t, x[2], x[3]) - elif op == "list": + elif op == b"list": ws, ts = zip(*(_optimize(y) for y in x[1:])) return sum(ws), (op,) + ts - elif op == "keyvalue": + elif op == b"keyvalue": w, t = _optimize(x[2]) return w, (op, x[1], t) - elif op == "func": + elif op == b"func": f = getsymbol(x[1]) wa, ta = _optimize(x[2]) w = getattr(symbols.get(f), "_weight", 1) - m = _match("commonancestors(_)", ta) + m = _match(b"commonancestors(_)", ta) # Optimize heads(commonancestors(_)) because we have a fast version - if f == "heads" and m: - return w + wa, _build("_commonancestorheads(_)", m[1]) + if f == b"heads" and m: + return w + wa, _build(b"_commonancestorheads(_)", m[1]) return w + wa, (op, x[1], ta) - raise ValueError("invalid operator %r" % op) + raise ValueError(b"invalid operator %r" % op) def optimize(tree): @@ -547,7 +549,7 @@ # the set of valid characters for the initial letter of symbols in # alias declarations and definitions -_aliassyminitletters = _syminitletters | {"$"} +_aliassyminitletters = _syminitletters | {b"$"} def _parsewith(spec, lookup=None, syminitletters=None): @@ -564,21 +566,21 @@ ... ParseError: ('invalid token', 4) """ - if lookup and spec.startswith("revset(") and spec.endswith(")"): + if lookup and spec.startswith(b"revset(") and spec.endswith(b")"): lookup = None p = parser.parser(elements) tree, pos = p.parse( tokenize(spec, lookup=lookup, syminitletters=syminitletters) ) if pos != len(spec): - raise error.ParseError(_("invalid token"), pos) - return _fixops(parser.simplifyinfixops(tree, ("list", "or"))) + raise error.ParseError(_(b"invalid token"), pos) + return _fixops(parser.simplifyinfixops(tree, (b"list", b"or"))) class _aliasrules(parser.basealiasrules): """Parsing and expansion rule set of revset aliases""" - _section = _("revset alias") + _section = _(b"revset alias") @staticmethod def _parse(spec): @@ -592,7 +594,7 @@ @staticmethod def _trygetfunc(tree): - if tree[0] == "func" and tree[1][0] == "symbol": + if tree[0] == b"func" and tree[1][0] == b"symbol": return tree[1][1], getlist(tree[2]) @@ -604,7 +606,7 @@ if warn is not None: for name, alias in sorted(aliases.iteritems()): if alias.error and not alias.warned: - warn(_("warning: %s\n") % (alias.error)) + warn(_(b"warning: %s\n") % (alias.error)) alias.warned = True return tree @@ -613,24 +615,24 @@ """Fold elements to be concatenated by `##` """ if not isinstance(tree, tuple) or tree[0] in ( - "string", - "symbol", - "smartset", + b"string", + b"symbol", + b"smartset", ): return tree - if tree[0] == "_concat": + if tree[0] == b"_concat": pending = [tree] l = [] while pending: e = pending.pop() - if e[0] == "_concat": + if e[0] == b"_concat": pending.extend(reversed(e[1:])) - elif e[0] in ("string", "symbol"): + elif e[0] in (b"string", b"symbol"): l.append(e[1]) else: - msg = _('"##" can\'t concatenate "%s" element') % (e[0]) + msg = _(b'"##" can\'t concatenate "%s" element') % (e[0]) raise error.ParseError(msg) - return ("string", "".join(l)) + return (b"string", b"".join(l)) else: return tuple(foldconcat(t) for t in tree) @@ -642,12 +644,12 @@ if len(inst.args) > 1: # has location loc = inst.args[1] # Remove newlines -- spaces are equivalent whitespace. - spec = spec.replace("\n", " ") + spec = spec.replace(b"\n", b" ") # We want the caret to point to the place in the template that # failed to parse, but in a hint we get a open paren at the # start. Therefore, we print "loc + 1" spaces (instead of "loc") # to line up the caret with the location of the error. - inst.hint = spec + "\n" + " " * (loc + 1) + "^ " + _("here") + inst.hint = spec + b"\n" + b" " * (loc + 1) + b"^ " + _(b"here") raise @@ -663,70 +665,70 @@ >>> _quote(1) "'1'" """ - return "'%s'" % stringutil.escapestr(pycompat.bytestr(s)) + return b"'%s'" % stringutil.escapestr(pycompat.bytestr(s)) def _formatargtype(c, arg): - if c == "d": - return "_rev(%d)" % int(arg) - elif c == "s": + if c == b"d": + return b"_rev(%d)" % int(arg) + elif c == b"s": return _quote(arg) - elif c == "r": + elif c == b"r": if not isinstance(arg, bytes): raise TypeError parse(arg) # make sure syntax errors are confined - return "(%s)" % arg - elif c == "n": + return b"(%s)" % arg + elif c == b"n": return _quote(node.hex(arg)) - elif c == "b": + elif c == b"b": try: return _quote(arg.branch()) except AttributeError: raise TypeError - raise error.ParseError(_("unexpected revspec format character %s") % c) + raise error.ParseError(_(b"unexpected revspec format character %s") % c) def _formatlistexp(s, t): l = len(s) if l == 0: - return "_list('')" + return b"_list('')" elif l == 1: return _formatargtype(t, s[0]) - elif t == "d": + elif t == b"d": return _formatintlist(s) - elif t == "s": - return "_list(%s)" % _quote("\0".join(s)) - elif t == "n": - return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s) - elif t == "b": + elif t == b"s": + return b"_list(%s)" % _quote(b"\0".join(s)) + elif t == b"n": + return b"_hexlist('%s')" % b"\0".join(node.hex(a) for a in s) + elif t == b"b": try: - return "_list('%s')" % "\0".join(a.branch() for a in s) + return b"_list('%s')" % b"\0".join(a.branch() for a in s) except AttributeError: raise TypeError m = l // 2 - return "(%s or %s)" % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t)) + return b"(%s or %s)" % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t)) def _formatintlist(data): try: l = len(data) if l == 0: - return "_list('')" + return b"_list('')" elif l == 1: - return _formatargtype("d", data[0]) - return "_intlist('%s')" % "\0".join("%d" % int(a) for a in data) + return _formatargtype(b"d", data[0]) + return b"_intlist('%s')" % b"\0".join(b"%d" % int(a) for a in data) except (TypeError, ValueError): - raise error.ParseError(_("invalid argument for revspec")) + raise error.ParseError(_(b"invalid argument for revspec")) def _formatparamexp(args, t): - return ", ".join(_formatargtype(t, a) for a in args) + return b", ".join(_formatargtype(t, a) for a in args) _formatlistfuncs = { - "l": _formatlistexp, - "p": _formatparamexp, + b"l": _formatlistexp, + b"p": _formatparamexp, } @@ -772,12 +774,12 @@ for t, arg in parsed: if t is None: ret.append(arg) - elif t == "baseset": + elif t == b"baseset": if isinstance(arg, set): arg = sorted(arg) ret.append(_formatintlist(list(arg))) else: - raise error.ProgrammingError("unknown revspec item type: %r" % t) + raise error.ProgrammingError(b"unknown revspec item type: %r" % t) return b"".join(ret) @@ -789,15 +791,15 @@ for t, arg in parsed: if t is None: ret.append(arg) - elif t == "baseset": - newtree = ("smartset", smartset.baseset(arg)) + elif t == b"baseset": + newtree = (b"smartset", smartset.baseset(arg)) inputs.append(newtree) - ret.append("$") + ret.append(b"$") else: - raise error.ProgrammingError("unknown revspec item type: %r" % t) + raise error.ProgrammingError(b"unknown revspec item type: %r" % t) expr = b"".join(ret) tree = _parsewith(expr, syminitletters=_aliassyminitletters) - tree = parser.buildtree(tree, ("symbol", "$"), *inputs) + tree = parser.buildtree(tree, (b"symbol", b"$"), *inputs) tree = foldconcat(tree) tree = analyze(tree) tree = optimize(tree) @@ -818,7 +820,7 @@ ret = [] pos = 0 while pos < len(expr): - q = expr.find("%", pos) + q = expr.find(b"%", pos) if q < 0: ret.append((None, expr[pos:])) break @@ -827,8 +829,8 @@ try: d = expr[pos] except IndexError: - raise error.ParseError(_("incomplete revspec format character")) - if d == "%": + raise error.ParseError(_(b"incomplete revspec format character")) + if d == b"%": ret.append((None, d)) pos += 1 continue @@ -836,45 +838,47 @@ try: arg = next(argiter) except StopIteration: - raise error.ParseError(_("missing argument for revspec")) + raise error.ParseError(_(b"missing argument for revspec")) f = _formatlistfuncs.get(d) if f: # a list of some type, might be expensive, do not replace pos += 1 - islist = d == "l" + islist = d == b"l" try: d = expr[pos] except IndexError: - raise error.ParseError(_("incomplete revspec format character")) - if islist and d == "d" and arg: + raise error.ParseError( + _(b"incomplete revspec format character") + ) + if islist and d == b"d" and arg: # we don't create a baseset yet, because it come with an # extra cost. If we are going to serialize it we better # skip it. - ret.append(("baseset", arg)) + ret.append((b"baseset", arg)) pos += 1 continue try: ret.append((None, f(list(arg), d))) except (TypeError, ValueError): - raise error.ParseError(_("invalid argument for revspec")) + raise error.ParseError(_(b"invalid argument for revspec")) else: # a single entry, not expensive, replace try: ret.append((None, _formatargtype(d, arg))) except (TypeError, ValueError): - raise error.ParseError(_("invalid argument for revspec")) + raise error.ParseError(_(b"invalid argument for revspec")) pos += 1 try: next(argiter) - raise error.ParseError(_("too many revspec arguments specified")) + raise error.ParseError(_(b"too many revspec arguments specified")) except StopIteration: pass return ret def prettyformat(tree): - return parser.prettyformat(tree, ("string", "symbol")) + return parser.prettyformat(tree, (b"string", b"symbol")) def depth(tree): @@ -885,18 +889,18 @@ def funcsused(tree): - if not isinstance(tree, tuple) or tree[0] in ("string", "symbol"): + if not isinstance(tree, tuple) or tree[0] in (b"string", b"symbol"): return set() else: funcs = set() for s in tree[1:]: funcs |= funcsused(s) - if tree[0] == "func": + if tree[0] == b"func": funcs.add(tree[1][1]) return funcs -_hashre = util.re.compile("[0-9a-fA-F]{1,40}$") +_hashre = util.re.compile(b"[0-9a-fA-F]{1,40}$") def _ishashlikesymbol(symbol): @@ -919,7 +923,7 @@ if not tree: return [] - if tree[0] == "symbol": + if tree[0] == b"symbol": if _ishashlikesymbol(tree[1]): return [tree[1]] elif len(tree) >= 3: diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py --- a/mercurial/rewriteutil.py +++ b/mercurial/rewriteutil.py @@ -17,29 +17,29 @@ ) -def precheck(repo, revs, action="rewrite"): +def precheck(repo, revs, action=b"rewrite"): """check if revs can be rewritten action is used to control the error message. Make sure this function is called after taking the lock. """ if node.nullrev in revs: - msg = _("cannot %s null changeset") % action - hint = _("no changeset checked out") + msg = _(b"cannot %s null changeset") % action + hint = _(b"no changeset checked out") raise error.Abort(msg, hint=hint) if len(repo[None].parents()) > 1: - raise error.Abort(_("cannot %s while merging") % action) + raise error.Abort(_(b"cannot %s while merging") % action) - publicrevs = repo.revs("%ld and public()", revs) + publicrevs = repo.revs(b"%ld and public()", revs) if publicrevs: - msg = _("cannot %s public changesets") % action - hint = _("see 'hg help phases' for details") + msg = _(b"cannot %s public changesets") % action + hint = _(b"see 'hg help phases' for details") raise error.Abort(msg, hint=hint) newunstable = disallowednewunstable(repo, revs) if newunstable: - raise error.Abort(_("cannot %s changeset with children") % action) + raise error.Abort(_(b"cannot %s changeset with children") % action) def disallowednewunstable(repo, revs): @@ -52,4 +52,4 @@ allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt) if allowunstable: return revset.baseset() - return repo.revs("(%ld::) - %ld", revs, revs) + return repo.revs(b"(%ld::) - %ld", revs, revs) diff --git a/mercurial/scmposix.py b/mercurial/scmposix.py --- a/mercurial/scmposix.py +++ b/mercurial/scmposix.py @@ -16,18 +16,18 @@ # $MORE variable, but there's no compatible option with Linux 'more'. Given # OS X is widely used and most modern Unix systems would have 'less', setting # 'less' as the default seems reasonable. -fallbackpager = "less" +fallbackpager = b"less" def _rcfiles(path): - rcs = [os.path.join(path, "hgrc")] - rcdir = os.path.join(path, "hgrc.d") + rcs = [os.path.join(path, b"hgrc")] + rcdir = os.path.join(path, b"hgrc.d") try: rcs.extend( [ os.path.join(rcdir, f) for f, kind in util.listdir(rcdir) - if f.endswith(".rc") + if f.endswith(b".rc") ] ) except OSError: @@ -37,32 +37,32 @@ def systemrcpath(): path = [] - if pycompat.sysplatform == "plan9": - root = "lib/mercurial" + if pycompat.sysplatform == b"plan9": + root = b"lib/mercurial" else: - root = "etc/mercurial" + root = b"etc/mercurial" # old mod_python does not set sys.argv if len(getattr(sys, "argv", [])) > 0: p = os.path.dirname(os.path.dirname(pycompat.sysargv[0])) - if p != "/": + if p != b"/": path.extend(_rcfiles(os.path.join(p, root))) - path.extend(_rcfiles("/" + root)) + path.extend(_rcfiles(b"/" + root)) return path def userrcpath(): - if pycompat.sysplatform == "plan9": - return [encoding.environ["home"] + "/lib/hgrc"] + if pycompat.sysplatform == b"plan9": + return [encoding.environ[b"home"] + b"/lib/hgrc"] elif pycompat.isdarwin: - return [os.path.expanduser("~/.hgrc")] + return [os.path.expanduser(b"~/.hgrc")] else: - confighome = encoding.environ.get("XDG_CONFIG_HOME") + confighome = encoding.environ.get(b"XDG_CONFIG_HOME") if confighome is None or not os.path.isabs(confighome): - confighome = os.path.expanduser("~/.config") + confighome = os.path.expanduser(b"~/.config") return [ - os.path.expanduser("~/.hgrc"), - os.path.join(confighome, "hg", "hgrc"), + os.path.expanduser(b"~/.hgrc"), + os.path.join(confighome, b"hg", b"hgrc"), ] @@ -82,7 +82,7 @@ continue if not os.isatty(fd): continue - arri = fcntl.ioctl(fd, TIOCGWINSZ, "\0" * 8) + arri = fcntl.ioctl(fd, TIOCGWINSZ, b"\0" * 8) height, width = array.array(r"h", arri)[:2] if width > 0 and height > 0: return width, height diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -158,11 +158,11 @@ if secretlist: ui.status( - _("no changes found (ignored %d secret changesets)\n") + _(b"no changes found (ignored %d secret changesets)\n") % len(secretlist) ) else: - ui.status(_("no changes found\n")) + ui.status(_(b"no changes found\n")) def callcatch(ui, func): @@ -181,20 +181,20 @@ # Mercurial-specific first, followed by built-in and library exceptions except error.LockHeld as inst: if inst.errno == errno.ETIMEDOUT: - reason = _("timed out waiting for lock held by %r") % ( + reason = _(b"timed out waiting for lock held by %r") % ( pycompat.bytestr(inst.locker) ) else: - reason = _("lock held by %r") % inst.locker + reason = _(b"lock held by %r") % inst.locker ui.error( - _("abort: %s: %s\n") + _(b"abort: %s: %s\n") % (inst.desc or stringutil.forcebytestr(inst.filename), reason) ) if not inst.locker: - ui.error(_("(lock might be very busy)\n")) + ui.error(_(b"(lock might be very busy)\n")) except error.LockUnavailable as inst: ui.error( - _("abort: could not lock %s: %s\n") + _(b"abort: could not lock %s: %s\n") % ( inst.desc or stringutil.forcebytestr(inst.filename), encoding.strtolocal(inst.strerror), @@ -202,57 +202,57 @@ ) except error.OutOfBandError as inst: if inst.args: - msg = _("abort: remote error:\n") + msg = _(b"abort: remote error:\n") else: - msg = _("abort: remote error\n") + msg = _(b"abort: remote error\n") ui.error(msg) if inst.args: - ui.error("".join(inst.args)) + ui.error(b"".join(inst.args)) if inst.hint: - ui.error("(%s)\n" % inst.hint) + ui.error(b"(%s)\n" % inst.hint) except error.RepoError as inst: - ui.error(_("abort: %s!\n") % inst) + ui.error(_(b"abort: %s!\n") % inst) if inst.hint: - ui.error(_("(%s)\n") % inst.hint) + ui.error(_(b"(%s)\n") % inst.hint) except error.ResponseError as inst: - ui.error(_("abort: %s") % inst.args[0]) + ui.error(_(b"abort: %s") % inst.args[0]) msg = inst.args[1] if isinstance(msg, type(u"")): msg = pycompat.sysbytes(msg) if not isinstance(msg, bytes): - ui.error(" %r\n" % (msg,)) + ui.error(b" %r\n" % (msg,)) elif not msg: - ui.error(_(" empty string\n")) + ui.error(_(b" empty string\n")) else: - ui.error("\n%r\n" % pycompat.bytestr(stringutil.ellipsis(msg))) + ui.error(b"\n%r\n" % pycompat.bytestr(stringutil.ellipsis(msg))) except error.CensoredNodeError as inst: - ui.error(_("abort: file censored %s!\n") % inst) + ui.error(_(b"abort: file censored %s!\n") % inst) except error.StorageError as inst: - ui.error(_("abort: %s!\n") % inst) + ui.error(_(b"abort: %s!\n") % inst) if inst.hint: - ui.error(_("(%s)\n") % inst.hint) + ui.error(_(b"(%s)\n") % inst.hint) except error.InterventionRequired as inst: - ui.error("%s\n" % inst) + ui.error(b"%s\n" % inst) if inst.hint: - ui.error(_("(%s)\n") % inst.hint) + ui.error(_(b"(%s)\n") % inst.hint) return 1 except error.WdirUnsupported: - ui.error(_("abort: working directory revision cannot be specified\n")) + ui.error(_(b"abort: working directory revision cannot be specified\n")) except error.Abort as inst: - ui.error(_("abort: %s\n") % inst) + ui.error(_(b"abort: %s\n") % inst) if inst.hint: - ui.error(_("(%s)\n") % inst.hint) + ui.error(_(b"(%s)\n") % inst.hint) except ImportError as inst: - ui.error(_("abort: %s!\n") % stringutil.forcebytestr(inst)) + ui.error(_(b"abort: %s!\n") % stringutil.forcebytestr(inst)) m = stringutil.forcebytestr(inst).split()[-1] - if m in "mpatch bdiff".split(): - ui.error(_("(did you forget to compile extensions?)\n")) - elif m in "zlib".split(): - ui.error(_("(is your Python install correct?)\n")) + if m in b"mpatch bdiff".split(): + ui.error(_(b"(did you forget to compile extensions?)\n")) + elif m in b"zlib".split(): + ui.error(_(b"(is your Python install correct?)\n")) except (IOError, OSError) as inst: - if util.safehasattr(inst, "code"): # HTTPError - ui.error(_("abort: %s\n") % stringutil.forcebytestr(inst)) - elif util.safehasattr(inst, "reason"): # URLError or SSLError + if util.safehasattr(inst, b"code"): # HTTPError + ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst)) + elif util.safehasattr(inst, b"reason"): # URLError or SSLError try: # usually it is in the form (errno, strerror) reason = inst.reason.args[1] except (AttributeError, IndexError): @@ -261,9 +261,9 @@ if isinstance(reason, pycompat.unicode): # SSLError of Python 2.7.9 contains a unicode reason = encoding.unitolocal(reason) - ui.error(_("abort: error: %s\n") % reason) + ui.error(_(b"abort: error: %s\n") % reason) elif ( - util.safehasattr(inst, "args") + util.safehasattr(inst, b"args") and inst.args and inst.args[0] == errno.EPIPE ): @@ -271,18 +271,18 @@ elif getattr(inst, "strerror", None): # common IOError or OSError if getattr(inst, "filename", None) is not None: ui.error( - _("abort: %s: '%s'\n") + _(b"abort: %s: '%s'\n") % ( encoding.strtolocal(inst.strerror), stringutil.forcebytestr(inst.filename), ) ) else: - ui.error(_("abort: %s\n") % encoding.strtolocal(inst.strerror)) + ui.error(_(b"abort: %s\n") % encoding.strtolocal(inst.strerror)) else: # suspicious IOError raise except MemoryError: - ui.error(_("abort: out of memory\n")) + ui.error(_(b"abort: out of memory\n")) except SystemExit as inst: # Commands shouldn't sys.exit directly, but give a return code. # Just in case catch this and and pass exit code to caller. @@ -294,27 +294,27 @@ def checknewlabel(repo, lbl, kind): # Do not use the "kind" parameter in ui output. # It makes strings difficult to translate. - if lbl in ["tip", ".", "null"]: - raise error.Abort(_("the name '%s' is reserved") % lbl) - for c in (":", "\0", "\n", "\r"): + if lbl in [b"tip", b".", b"null"]: + raise error.Abort(_(b"the name '%s' is reserved") % lbl) + for c in (b":", b"\0", b"\n", b"\r"): if c in lbl: raise error.Abort( - _("%r cannot be used in a name") % pycompat.bytestr(c) + _(b"%r cannot be used in a name") % pycompat.bytestr(c) ) try: int(lbl) - raise error.Abort(_("cannot use an integer as a name")) + raise error.Abort(_(b"cannot use an integer as a name")) except ValueError: pass if lbl.strip() != lbl: - raise error.Abort(_("leading or trailing whitespace in name %r") % lbl) + raise error.Abort(_(b"leading or trailing whitespace in name %r") % lbl) def checkfilename(f): """Check that the filename f is an acceptable filename for a tracked file""" - if "\r" in f or "\n" in f: + if b"\r" in f or b"\n" in f: raise error.Abort( - _("'\\n' and '\\r' disallowed in filenames: %r") + _(b"'\\n' and '\\r' disallowed in filenames: %r") % pycompat.bytestr(f) ) @@ -326,23 +326,23 @@ if abort or warn: msg = util.checkwinfilename(f) if msg: - msg = "%s: %s" % (msg, procutil.shellquote(f)) + msg = b"%s: %s" % (msg, procutil.shellquote(f)) if abort: raise error.Abort(msg) - ui.warn(_("warning: %s\n") % msg) + ui.warn(_(b"warning: %s\n") % msg) def checkportabilityalert(ui): """check if the user's config requests nothing, a warning, or abort for non-portable filenames""" - val = ui.config("ui", "portablefilenames") + val = ui.config(b"ui", b"portablefilenames") lval = val.lower() bval = stringutil.parsebool(val) - abort = pycompat.iswindows or lval == "abort" - warn = bval or lval == "warn" - if bval is None and not (warn or abort or lval == "ignore"): + abort = pycompat.iswindows or lval == b"abort" + warn = bval or lval == b"warn" + if bval is None and not (warn or abort or lval == b"ignore"): raise error.ConfigError( - _("ui.portablefilenames value is invalid ('%s')") % val + _(b"ui.portablefilenames value is invalid ('%s')") % val ) return abort, warn @@ -351,8 +351,8 @@ def __init__(self, ui, abort, dirstate): self._ui = ui self._abort = abort - allfiles = "\0".join(dirstate) - self._loweredfiles = set(encoding.lower(allfiles).split("\0")) + allfiles = b"\0".join(dirstate) + self._loweredfiles = set(encoding.lower(allfiles).split(b"\0")) self._dirstate = dirstate # The purpose of _newfiles is so that we don't complain about # case collisions if someone were to call this object with the @@ -364,10 +364,10 @@ return fl = encoding.lower(f) if fl in self._loweredfiles and f not in self._dirstate: - msg = _("possible case-folding collision for %s") % f + msg = _(b"possible case-folding collision for %s") % f if self._abort: raise error.Abort(msg) - self._ui.warn(_("warning: %s\n") % msg) + self._ui.warn(_(b"warning: %s\n") % msg) self._loweredfiles.add(fl) self._newfiles.add(f) @@ -392,7 +392,7 @@ if revs: s = hashlib.sha1() for rev in revs: - s.update("%d;" % rev) + s.update(b"%d;" % rev) key = s.digest() return key @@ -423,14 +423,14 @@ adddir(seen_dirs, path) for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler): dirs.sort() - if ".hg" in dirs: + if b".hg" in dirs: yield root # found a repository - qroot = os.path.join(root, ".hg", "patches") - if os.path.isdir(os.path.join(qroot, ".hg")): + qroot = os.path.join(root, b".hg", b"patches") + if os.path.isdir(os.path.join(qroot, b".hg")): yield qroot # we have a patch queue repo here if recurse: # avoid recursing inside the .hg directory - dirs.remove(".hg") + dirs.remove(b".hg") else: dirs[:] = [] # don't descend further elif followsym: @@ -476,12 +476,12 @@ hexfunc = hex else: hexfunc = short - return "%d:%s" % (rev, hexfunc(node)) + return b"%d:%s" % (rev, hexfunc(node)) def resolvehexnodeidprefix(repo, prefix): - if prefix.startswith("x") and repo.ui.configbool( - "experimental", "revisions.prefixhexnode" + if prefix.startswith(b"x") and repo.ui.configbool( + b"experimental", b"revisions.prefixhexnode" ): prefix = prefix[1:] try: @@ -489,11 +489,13 @@ # This matches the shortesthexnodeidprefix() function below. node = repo.unfiltered().changelog._partialmatch(prefix) except error.AmbiguousPrefixLookupError: - revset = repo.ui.config("experimental", "revisions.disambiguatewithin") + revset = repo.ui.config( + b"experimental", b"revisions.disambiguatewithin" + ) if revset: # Clear config to avoid infinite recursion configoverrides = { - ("experimental", "revisions.disambiguatewithin"): None + (b"experimental", b"revisions.disambiguatewithin"): None } with repo.ui.configoverride(configoverrides): revs = repo.anyrevs([revset], user=True) @@ -540,9 +542,9 @@ def disambiguate(prefix): """Disambiguate against revnums.""" - if repo.ui.configbool("experimental", "revisions.prefixhexnode"): + if repo.ui.configbool(b"experimental", b"revisions.prefixhexnode"): if mayberevnum(repo, prefix): - return "x" + prefix + return b"x" + prefix else: return prefix @@ -553,20 +555,20 @@ return prefix cl = repo.unfiltered().changelog - revset = repo.ui.config("experimental", "revisions.disambiguatewithin") + revset = repo.ui.config(b"experimental", b"revisions.disambiguatewithin") if revset: revs = None if cache is not None: - revs = cache.get("disambiguationrevset") + revs = cache.get(b"disambiguationrevset") if revs is None: revs = repo.anyrevs([revset], user=True) if cache is not None: - cache["disambiguationrevset"] = revs + cache[b"disambiguationrevset"] = revs if cl.rev(node) in revs: hexnode = hex(node) nodetree = None if cache is not None: - nodetree = cache.get("disambiguationnodetree") + nodetree = cache.get(b"disambiguationnodetree") if not nodetree: try: nodetree = parsers.nodetree(cl.index, len(revs)) @@ -577,7 +579,7 @@ for r in revs: nodetree.insert(r) if cache is not None: - cache["disambiguationnodetree"] = nodetree + cache[b"disambiguationnodetree"] = nodetree if nodetree is not None: length = max(nodetree.shortest(node), minlength) prefix = hexnode[:length] @@ -620,17 +622,17 @@ """ if not isinstance(symbol, bytes): msg = ( - "symbol (%s of type %s) was not a string, did you mean " - "repo[symbol]?" % (symbol, type(symbol)) + b"symbol (%s of type %s) was not a string, did you mean " + b"repo[symbol]?" % (symbol, type(symbol)) ) raise error.ProgrammingError(msg) try: - if symbol in (".", "tip", "null"): + if symbol in (b".", b"tip", b"null"): return repo[symbol] try: r = int(symbol) - if "%d" % r != symbol: + if b"%d" % r != symbol: raise ValueError l = len(repo.changelog) if r < 0: @@ -666,7 +668,7 @@ rev = repo.changelog.rev(node) return repo[rev] - raise error.RepoLookupError(_("unknown revision '%s'") % symbol) + raise error.RepoLookupError(_(b"unknown revision '%s'") % symbol) except error.WdirUnsupported: return repo[None] @@ -683,7 +685,7 @@ This is extracted in a function to help extensions (eg: evolve) to experiment with various message variants.""" - if repo.filtername.startswith("visible"): + if repo.filtername.startswith(b"visible"): # Check if the changeset is obsolete unfilteredrepo = repo.unfiltered() @@ -694,39 +696,44 @@ if ctx.obsolete(): msg = obsutil._getfilteredreason(repo, changeid, ctx) else: - msg = _("hidden revision '%s'") % changeid + msg = _(b"hidden revision '%s'") % changeid - hint = _("use --hidden to access hidden revisions") + hint = _(b"use --hidden to access hidden revisions") return error.FilteredRepoLookupError(msg, hint=hint) - msg = _("filtered revision '%s' (not in '%s' subset)") + msg = _(b"filtered revision '%s' (not in '%s' subset)") msg %= (changeid, repo.filtername) return error.FilteredRepoLookupError(msg) -def revsingle(repo, revspec, default=".", localalias=None): +def revsingle(repo, revspec, default=b".", localalias=None): if not revspec and revspec != 0: return repo[default] l = revrange(repo, [revspec], localalias=localalias) if not l: - raise error.Abort(_("empty revision set")) + raise error.Abort(_(b"empty revision set")) return repo[l.last()] def _pairspec(revspec): tree = revsetlang.parse(revspec) - return tree and tree[0] in ("range", "rangepre", "rangepost", "rangeall") + return tree and tree[0] in ( + b"range", + b"rangepre", + b"rangepost", + b"rangeall", + ) def revpair(repo, revs): if not revs: - return repo["."], repo[None] + return repo[b"."], repo[None] l = revrange(repo, revs) if not l: - raise error.Abort(_("empty revision range")) + raise error.Abort(_(b"empty revision range")) first = l.first() second = l.last() @@ -736,7 +743,7 @@ and len(revs) >= 2 and not all(revrange(repo, [r]) for r in revs) ): - raise error.Abort(_("empty revision on one side of range")) + raise error.Abort(_(b"empty revision on one side of range")) # if top-level is range expression, the result must always be a pair if first == second and len(revs) == 1 and not _pairspec(revs[0]): @@ -769,7 +776,7 @@ allspecs = [] for spec in specs: if isinstance(spec, int): - spec = revsetlang.formatspec("%d", spec) + spec = revsetlang.formatspec(b"%d", spec) allspecs.append(spec) return repo.anyrevs(allspecs, user=True, localalias=localalias) @@ -808,21 +815,21 @@ if forcerelativevalue is not None: relative = forcerelativevalue else: - config = repo.ui.config("ui", "relative-paths") - if config == "legacy": + config = repo.ui.config(b"ui", b"relative-paths") + if config == b"legacy": relative = legacyrelativevalue else: relative = stringutil.parsebool(config) if relative is None: raise error.ConfigError( - _("ui.relative-paths is not a boolean ('%s')") % config + _(b"ui.relative-paths is not a boolean ('%s')") % config ) if relative: cwd = repo.getcwd() pathto = repo.pathto return lambda f: pathto(f, cwd) - elif repo.ui.configbool("ui", "slash"): + elif repo.ui.configbool(b"ui", b"slash"): return lambda f: f else: return util.localpath @@ -839,7 +846,7 @@ Some commands (e.g. addremove) use this condition for deciding whether to print absolute or relative paths. """ - return bool(pats or opts.get("include") or opts.get("exclude")) + return bool(pats or opts.get(b"include") or opts.get(b"exclude")) def expandpats(pats): @@ -863,30 +870,30 @@ def matchandpats( - ctx, pats=(), opts=None, globbed=False, default="relpath", badfn=None + ctx, pats=(), opts=None, globbed=False, default=b"relpath", badfn=None ): """Return a matcher and the patterns that were used. The matcher will warn about bad matches, unless an alternate badfn callback is provided.""" if opts is None: opts = {} - if not globbed and default == "relpath": + if not globbed and default == b"relpath": pats = expandpats(pats or []) uipathfn = getuipathfn(ctx.repo(), legacyrelativevalue=True) def bad(f, msg): - ctx.repo().ui.warn("%s: %s\n" % (uipathfn(f), msg)) + ctx.repo().ui.warn(b"%s: %s\n" % (uipathfn(f), msg)) if badfn is None: badfn = bad m = ctx.match( pats, - opts.get("include"), - opts.get("exclude"), + opts.get(b"include"), + opts.get(b"exclude"), default, - listsubrepos=opts.get("subrepos"), + listsubrepos=opts.get(b"subrepos"), badfn=badfn, ) @@ -896,7 +903,7 @@ def match( - ctx, pats=(), opts=None, globbed=False, default="relpath", badfn=None + ctx, pats=(), opts=None, globbed=False, default=b"relpath", badfn=None ): """Return a matcher that will warn about bad matches.""" return matchandpats(ctx, pats, opts, globbed, default, badfn=badfn)[0] @@ -931,7 +938,7 @@ """return a vfs suitable to save 'orig' file return None if no special directory is configured""" - origbackuppath = ui.config("ui", "origbackuppath") + origbackuppath = ui.config(b"ui", b"origbackuppath") if not origbackuppath: return None return vfs.vfs(repo.wvfs.join(origbackuppath)) @@ -949,16 +956,16 @@ """ origvfs = getorigvfs(ui, repo) if origvfs is None: - return repo.wjoin(filepath + ".orig") + return repo.wjoin(filepath + b".orig") origbackupdir = origvfs.dirname(filepath) if not origvfs.isdir(origbackupdir) or origvfs.islink(origbackupdir): - ui.note(_("creating directory: %s\n") % origvfs.join(origbackupdir)) + ui.note(_(b"creating directory: %s\n") % origvfs.join(origbackupdir)) # Remove any files that conflict with the backup file's path for f in reversed(list(util.finddirs(filepath))): if origvfs.isfileorlink(f): - ui.note(_("removing conflicting file: %s\n") % origvfs.join(f)) + ui.note(_(b"removing conflicting file: %s\n") % origvfs.join(f)) origvfs.unlink(f) break @@ -966,7 +973,7 @@ if origvfs.isdir(filepath) and not origvfs.islink(filepath): ui.note( - _("removing conflicting directory: %s\n") % origvfs.join(filepath) + _(b"removing conflicting directory: %s\n") % origvfs.join(filepath) ) origvfs.rmtree(filepath, forcibly=True) @@ -1014,7 +1021,7 @@ return # translate mapping's other forms - if not util.safehasattr(replacements, "items"): + if not util.safehasattr(replacements, b"items"): replacements = {(n,): () for n in replacements} else: # upgrading non tuple "source" to tuple ones for BC @@ -1037,14 +1044,14 @@ continue if len(newnodes) > 1: # usually a split, take the one with biggest rev number - newnode = next(unfi.set("max(%ln)", newnodes)).node() + newnode = next(unfi.set(b"max(%ln)", newnodes)).node() elif len(newnodes) == 0: # move bookmark backwards allreplaced = [] for rep in replacements: allreplaced.extend(rep) roots = list( - unfi.set("max((::%n) - %ln)", oldnode, allreplaced) + unfi.set(b"max((::%n) - %ln)", oldnode, allreplaced) ) if roots: newnode = roots[0].node() @@ -1086,7 +1093,7 @@ elif newphase < ctx.phase(): toadvance.setdefault(newphase, []).append(newnode) - with repo.transaction("cleanup") as tr: + with repo.transaction(b"cleanup") as tr: # Move bookmarks bmarks = repo._bookmarks bmarkchanges = [] @@ -1097,7 +1104,7 @@ from . import bookmarks # avoid import cycle repo.ui.debug( - "moving bookmarks %r from %s to %s\n" + b"moving bookmarks %r from %s to %s\n" % ( pycompat.rapply(pycompat.maybebytestr, oldbmarks), hex(oldnode), @@ -1106,7 +1113,7 @@ ) # Delete divergent bookmarks being parents of related newnodes deleterevs = repo.revs( - "parents(roots(%ln & (::%n))) - parents(%n)", + b"parents(roots(%ln & (::%n))) - parents(%n)", allnewnodes, newnode, oldnode, @@ -1125,7 +1132,7 @@ for phase, nodes in toadvance.items(): phases.advanceboundary(repo, tr, phase, nodes) - mayusearchived = repo.ui.config("experimental", "cleanup-as-archived") + mayusearchived = repo.ui.config(b"experimental", b"cleanup-as-archived") # Obsolete or strip nodes if obsolete.isenabled(repo, obsolete.createmarkersopt): # If a node is already obsoleted, and we want to obsolete it @@ -1171,13 +1178,13 @@ if opts is None: opts = {} m = matcher - dry_run = opts.get("dry_run") + dry_run = opts.get(b"dry_run") try: - similarity = float(opts.get("similarity") or 0) + similarity = float(opts.get(b"similarity") or 0) except ValueError: - raise error.Abort(_("similarity must be a number")) + raise error.Abort(_(b"similarity must be a number")) if similarity < 0 or similarity > 100: - raise error.Abort(_("similarity must be between 0 and 100")) + raise error.Abort(_(b"similarity must be between 0 and 100")) similarity /= 100.0 ret = 0 @@ -1185,7 +1192,7 @@ wctx = repo[None] for subpath in sorted(wctx.substate): submatch = matchmod.subdirmatcher(subpath, m) - if opts.get("subrepos") or m.exact(subpath) or any(submatch.files()): + if opts.get(b"subrepos") or m.exact(subpath) or any(submatch.files()): sub = wctx.sub(subpath) subprefix = repo.wvfs.reljoin(prefix, subpath) subuipathfn = subdiruipathfn(subpath, uipathfn) @@ -1194,7 +1201,7 @@ ret = 1 except error.LookupError: repo.ui.status( - _("skipping missing subrepository: %s\n") + _(b"skipping missing subrepository: %s\n") % uipathfn(subpath) ) @@ -1216,11 +1223,11 @@ for abs in sorted(toprint): if repo.ui.verbose or not m.exact(abs): if abs in unknownset: - status = _("adding %s\n") % uipathfn(abs) - label = "ui.addremove.added" + status = _(b"adding %s\n") % uipathfn(abs) + label = b"ui.addremove.added" else: - status = _("removing %s\n") % uipathfn(abs) - label = "ui.addremove.removed" + status = _(b"removing %s\n") % uipathfn(abs) + label = b"ui.addremove.removed" repo.ui.status(status, label=label) renames = _findrenames( @@ -1250,9 +1257,9 @@ toprint.update(deleted) for abs in sorted(toprint): if abs in unknownset: - status = _("adding %s\n") % abs + status = _(b"adding %s\n") % abs else: - status = _("removing %s\n") % abs + status = _(b"removing %s\n") % abs repo.ui.status(status) # TODO: We should probably have the caller pass in uipathfn and apply it to @@ -1292,16 +1299,16 @@ ) for abs, st in walkresults.iteritems(): dstate = dirstate[abs] - if dstate == "?" and audit_path.check(abs): + if dstate == b"?" and audit_path.check(abs): unknown.append(abs) - elif dstate != "r" and not st: + elif dstate != b"r" and not st: deleted.append(abs) - elif dstate == "r" and st: + elif dstate == b"r" and st: forgotten.append(abs) # for finding renames - elif dstate == "r" and not st: + elif dstate == b"r" and not st: removed.append(abs) - elif dstate == "a": + elif dstate == b"a": added.append(abs) return added, unknown, deleted, removed, forgotten @@ -1321,8 +1328,8 @@ ): repo.ui.status( _( - "recording removal of %s as rename to %s " - "(%d%% similar)\n" + b"recording removal of %s as rename to %s " + b"(%d%% similar)\n" ) % (uipathfn(old), uipathfn(new), score * 100) ) @@ -1419,19 +1426,19 @@ """ origsrc = repo.dirstate.copied(src) or src if dst == origsrc: # copying back a copy? - if repo.dirstate[dst] not in "mn" and not dryrun: + if repo.dirstate[dst] not in b"mn" and not dryrun: repo.dirstate.normallookup(dst) else: - if repo.dirstate[origsrc] == "a" and origsrc == src: + if repo.dirstate[origsrc] == b"a" and origsrc == src: if not ui.quiet: ui.warn( _( - "%s has not been committed yet, so no copy " - "data will be stored for %s.\n" + b"%s has not been committed yet, so no copy " + b"data will be stored for %s.\n" ) % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd)) ) - if repo.dirstate[dst] in "?r" and not dryrun: + if repo.dirstate[dst] in b"?r" and not dryrun: wctx.add([dst]) elif not dryrun: wctx.copy(origsrc, dst) @@ -1444,29 +1451,29 @@ a matcher that doesn't match all the differences between the parent of the working copy and newctx. """ - oldctx = repo["."] + oldctx = repo[b"."] ds = repo.dirstate ds.setparents(newctx.node(), nullid) copies = dict(ds.copies()) s = newctx.status(oldctx, match=match) for f in s.modified: - if ds[f] == "r": + if ds[f] == b"r": # modified + removed -> removed continue ds.normallookup(f) for f in s.added: - if ds[f] == "r": + if ds[f] == b"r": # added + removed -> unknown ds.drop(f) - elif ds[f] != "a": + elif ds[f] != b"a": ds.add(f) for f in s.removed: - if ds[f] == "a": + if ds[f] == b"a": # removed + added -> normal ds.normallookup(f) - elif ds[f] != "r": + elif ds[f] != b"r": ds.remove(f) # Merge old parent and old working dir copies @@ -1477,15 +1484,15 @@ ) # Adjust the dirstate copies for dst, src in copies.iteritems(): - if src not in newctx or dst in newctx or ds[dst] != "a": + if src not in newctx or dst in newctx or ds[dst] != b"a": src = None ds.copy(src, dst) def writerequires(opener, requirements): - with opener("requires", "w", atomictemp=True) as fp: + with opener(b"requires", b"w", atomictemp=True) as fp: for r in sorted(requirements): - fp.write("%s\n" % r) + fp.write(b"%s\n" % r) class filecachesubentry(object): @@ -1664,14 +1671,14 @@ remote data sources. """ - spec = repo.ui.config("extdata", source) + spec = repo.ui.config(b"extdata", source) if not spec: - raise error.Abort(_("unknown extdata source '%s'") % source) + raise error.Abort(_(b"unknown extdata source '%s'") % source) data = {} src = proc = None try: - if spec.startswith("shell:"): + if spec.startswith(b"shell:"): # external commands should be run relative to the repo root cmd = spec[6:] proc = subprocess.Popen( @@ -1687,10 +1694,10 @@ # treat as a URL or file src = url.open(repo.ui, spec) for l in src: - if " " in l: - k, v = l.strip().split(" ", 1) + if b" " in l: + k, v = l.strip().split(b" ", 1) else: - k, v = l.strip(), "" + k, v = l.strip(), b"" k = encoding.tolocal(k) try: @@ -1709,7 +1716,7 @@ src.close() if proc and proc.returncode != 0: raise error.Abort( - _("extdata command '%s' failed: %s") + _(b"extdata command '%s' failed: %s") % (cmd, procutil.explainexit(proc.returncode)) ) @@ -1719,7 +1726,7 @@ def _locksub(repo, lock, envvar, cmd, environ=None, *args, **kwargs): if lock is None: raise error.LockInheritanceContractViolation( - "lock can only be inherited while held" + b"lock can only be inherited while held" ) if environ is None: environ = {} @@ -1735,18 +1742,18 @@ arguments that ui.system does, and returns the exit code of the subprocess.""" return _locksub( - repo, repo.currentwlock(), "HG_WLOCK_LOCKER", cmd, *args, **kwargs + repo, repo.currentwlock(), b"HG_WLOCK_LOCKER", cmd, *args, **kwargs ) class progress(object): - def __init__(self, ui, updatebar, topic, unit="", total=None): + def __init__(self, ui, updatebar, topic, unit=b"", total=None): self.ui = ui self.pos = 0 self.topic = topic self.unit = unit self.total = total - self.debug = ui.configbool("progress", "debug") + self.debug = ui.configbool(b"progress", b"debug") self._updatebar = updatebar def __enter__(self): @@ -1755,7 +1762,7 @@ def __exit__(self, exc_type, exc_value, exc_tb): self.complete() - def update(self, pos, item="", total=None): + def update(self, pos, item=b"", total=None): assert pos is not None if total: self.total = total @@ -1764,37 +1771,37 @@ if self.debug: self._printdebug(item) - def increment(self, step=1, item="", total=None): + def increment(self, step=1, item=b"", total=None): self.update(self.pos + step, item, total) def complete(self): self.pos = None - self.unit = "" + self.unit = b"" self.total = None - self._updatebar(self.topic, self.pos, "", self.unit, self.total) + self._updatebar(self.topic, self.pos, b"", self.unit, self.total) def _printdebug(self, item): if self.unit: - unit = " " + self.unit + unit = b" " + self.unit if item: - item = " " + item + item = b" " + item if self.total: pct = 100.0 * self.pos / self.total self.ui.debug( - "%s:%s %d/%d%s (%4.2f%%)\n" + b"%s:%s %d/%d%s (%4.2f%%)\n" % (self.topic, item, self.pos, self.total, unit, pct) ) else: - self.ui.debug("%s:%s %d%s\n" % (self.topic, item, self.pos, unit)) + self.ui.debug(b"%s:%s %d%s\n" % (self.topic, item, self.pos, unit)) def gdinitconfig(ui): """helper function to know if a repo should be created as general delta """ # experimental config: format.generaldelta - return ui.configbool("format", "generaldelta") or ui.configbool( - "format", "usegeneraldelta" + return ui.configbool(b"format", b"generaldelta") or ui.configbool( + b"format", b"usegeneraldelta" ) @@ -1802,7 +1809,7 @@ """helper function to know if incoming delta should be optimised """ # experimental config: format.generaldelta - return ui.configbool("format", "generaldelta") + return ui.configbool(b"format", b"generaldelta") class simplekeyvaluefile(object): @@ -1811,7 +1818,7 @@ Keys must be alphanumerics and start with a letter, values must not contain '\n' characters""" - firstlinekey = "__firstline" + firstlinekey = b"__firstline" def __init__(self, vfs, path, keys=None): self.vfs = vfs @@ -1827,7 +1834,7 @@ d = {} if firstlinenonkeyval: if not lines: - e = _("empty simplekeyvalue file") + e = _(b"empty simplekeyvalue file") raise error.CorruptedState(e) # we don't want to include '\n' in the __firstline d[self.firstlinekey] = lines[0][:-1] @@ -1838,10 +1845,10 @@ # lines which only contain '\n' therefore are not skipped # by 'if line' updatedict = dict( - line[:-1].split("=", 1) for line in lines if line.strip() + line[:-1].split(b"=", 1) for line in lines if line.strip() ) if self.firstlinekey in updatedict: - e = _("%r can't be used as a key") + e = _(b"%r can't be used as a key") raise error.CorruptedState(e % self.firstlinekey) d.update(updatedict) except ValueError as e: @@ -1857,37 +1864,37 @@ everything else, as it is, not in a key=value form""" lines = [] if firstline is not None: - lines.append("%s\n" % firstline) + lines.append(b"%s\n" % firstline) for k, v in data.items(): if k == self.firstlinekey: - e = "key name '%s' is reserved" % self.firstlinekey + e = b"key name '%s' is reserved" % self.firstlinekey raise error.ProgrammingError(e) if not k[0:1].isalpha(): - e = "keys must start with a letter in a key-value file" + e = b"keys must start with a letter in a key-value file" raise error.ProgrammingError(e) if not k.isalnum(): - e = "invalid key name in a simple key-value file" + e = b"invalid key name in a simple key-value file" raise error.ProgrammingError(e) - if "\n" in v: - e = "invalid value in a simple key-value file" + if b"\n" in v: + e = b"invalid value in a simple key-value file" raise error.ProgrammingError(e) - lines.append("%s=%s\n" % (k, v)) - with self.vfs(self.path, mode="wb", atomictemp=True) as fp: - fp.write("".join(lines)) + lines.append(b"%s=%s\n" % (k, v)) + with self.vfs(self.path, mode=b"wb", atomictemp=True) as fp: + fp.write(b"".join(lines)) _reportobsoletedsource = [ - "debugobsolete", - "pull", - "push", - "serve", - "unbundle", + b"debugobsolete", + b"pull", + b"push", + b"serve", + b"unbundle", ] _reportnewcssource = [ - "pull", - "unbundle", + b"pull", + b"unbundle", ] @@ -1912,7 +1919,7 @@ _reportstroubledchangesets = True -def registersummarycallback(repo, otr, txnname=""): +def registersummarycallback(repo, otr, txnname=b""): """register a callback to issue a summary after the transaction is closed """ @@ -1937,22 +1944,22 @@ repo = repo.filtered(filtername) func(repo, tr) - newcat = "%02i-txnreport" % len(categories) + newcat = b"%02i-txnreport" % len(categories) otr.addpostclose(newcat, wrapped) categories.append(newcat) return wrapped @reportsummary def reportchangegroup(repo, tr): - cgchangesets = tr.changes.get("changegroup-count-changesets", 0) - cgrevisions = tr.changes.get("changegroup-count-revisions", 0) - cgfiles = tr.changes.get("changegroup-count-files", 0) - cgheads = tr.changes.get("changegroup-count-heads", 0) + cgchangesets = tr.changes.get(b"changegroup-count-changesets", 0) + cgrevisions = tr.changes.get(b"changegroup-count-revisions", 0) + cgfiles = tr.changes.get(b"changegroup-count-files", 0) + cgheads = tr.changes.get(b"changegroup-count-heads", 0) if cgchangesets or cgrevisions or cgfiles: - htext = "" + htext = b"" if cgheads: - htext = _(" (%+d heads)") % cgheads - msg = _("added %d changesets with %d changes to %d files%s\n") + htext = _(b" (%+d heads)") % cgheads + msg = _(b"added %d changesets with %d changes to %d files%s\n") repo.ui.status(msg % (cgchangesets, cgrevisions, cgfiles, htext)) if txmatch(_reportobsoletedsource): @@ -1960,19 +1967,21 @@ @reportsummary def reportobsoleted(repo, tr): obsoleted = obsutil.getobsoleted(repo, tr) - newmarkers = len(tr.changes.get("obsmarkers", ())) + newmarkers = len(tr.changes.get(b"obsmarkers", ())) if newmarkers: - repo.ui.status(_("%i new obsolescence markers\n") % newmarkers) + repo.ui.status(_(b"%i new obsolescence markers\n") % newmarkers) if obsoleted: - repo.ui.status(_("obsoleted %i changesets\n") % len(obsoleted)) + repo.ui.status(_(b"obsoleted %i changesets\n") % len(obsoleted)) if obsolete.isenabled( repo, obsolete.createmarkersopt - ) and repo.ui.configbool("experimental", "evolution.report-instabilities"): + ) and repo.ui.configbool( + b"experimental", b"evolution.report-instabilities" + ): instabilitytypes = [ - ("orphan", "orphan"), - ("phase-divergent", "phasedivergent"), - ("content-divergent", "contentdivergent"), + (b"orphan", b"orphan"), + (b"phase-divergent", b"phasedivergent"), + (b"content-divergent", b"contentdivergent"), ] def getinstabilitycounts(repo): @@ -2003,7 +2012,7 @@ @reportsummary def reportnewcs(repo, tr): """Report the range of new revisions pulled/unbundled.""" - origrepolen = tr.changes.get("origrepolen", len(repo)) + origrepolen = tr.changes.get(b"origrepolen", len(repo)) unfi = repo.unfiltered() if origrepolen >= len(unfi): return @@ -2016,29 +2025,29 @@ if minrev == maxrev: revrange = minrev else: - revrange = "%s:%s" % (minrev, maxrev) - draft = len(repo.revs("%ld and draft()", revs)) - secret = len(repo.revs("%ld and secret()", revs)) + revrange = b"%s:%s" % (minrev, maxrev) + draft = len(repo.revs(b"%ld and draft()", revs)) + secret = len(repo.revs(b"%ld and secret()", revs)) if not (draft or secret): - msg = _("new changesets %s\n") % revrange + msg = _(b"new changesets %s\n") % revrange elif draft and secret: - msg = _("new changesets %s (%d drafts, %d secrets)\n") + msg = _(b"new changesets %s (%d drafts, %d secrets)\n") msg %= (revrange, draft, secret) elif draft: - msg = _("new changesets %s (%d drafts)\n") + msg = _(b"new changesets %s (%d drafts)\n") msg %= (revrange, draft) elif secret: - msg = _("new changesets %s (%d secrets)\n") + msg = _(b"new changesets %s (%d secrets)\n") msg %= (revrange, secret) else: - errormsg = "entered unreachable condition" + errormsg = b"entered unreachable condition" raise error.ProgrammingError(errormsg) repo.ui.status(msg) # search new changesets directly pulled as obsolete - duplicates = tr.changes.get("revduplicates", ()) + duplicates = tr.changes.get(b"revduplicates", ()) obsadded = unfi.revs( - "(%d: + %ld) and obsolete()", origrepolen, duplicates + b"(%d: + %ld) and obsolete()", origrepolen, duplicates ) cl = repo.changelog extinctadded = [r for r in obsadded if r not in cl] @@ -2046,7 +2055,7 @@ # They are not just obsolete, but obsolete and invisible # we call them "extinct" internally but the terms have not been # exposed to users. - msg = "(%d other changesets obsolete on arrival)\n" + msg = b"(%d other changesets obsolete on arrival)\n" repo.ui.status(msg % len(extinctadded)) @reportsummary @@ -2054,8 +2063,8 @@ """Report statistics of phase changes for changesets pre-existing pull/unbundle. """ - origrepolen = tr.changes.get("origrepolen", len(repo)) - phasetracking = tr.changes.get("phases", {}) + origrepolen = tr.changes.get(b"origrepolen", len(repo)) + phasetracking = tr.changes.get(b"phases", {}) if not phasetracking: return published = [ @@ -2066,7 +2075,7 @@ if not published: return repo.ui.status( - _("%d local changesets published\n") % len(published) + _(b"%d local changesets published\n") % len(published) ) @@ -2076,30 +2085,30 @@ exists as a separate function so that extension can wrap to show more information like how to fix instabilities""" if delta > 0: - return _("%i new %s changesets\n") % (delta, instability) + return _(b"%i new %s changesets\n") % (delta, instability) def nodesummaries(repo, nodes, maxnumnodes=4): if len(nodes) <= maxnumnodes or repo.ui.verbose: - return " ".join(short(h) for h in nodes) - first = " ".join(short(h) for h in nodes[:maxnumnodes]) - return _("%s and %d others") % (first, len(nodes) - maxnumnodes) + return b" ".join(short(h) for h in nodes) + first = b" ".join(short(h) for h in nodes[:maxnumnodes]) + return _(b"%s and %d others") % (first, len(nodes) - maxnumnodes) def enforcesinglehead(repo, tr, desc, accountclosed=False): """check that no named branch has multiple heads""" - if desc in ("strip", "repair"): + if desc in (b"strip", b"repair"): # skip the logic during strip return - visible = repo.filtered("visible") + visible = repo.filtered(b"visible") # possible improvement: we could restrict the check to affected branch bm = visible.branchmap() for name in bm: heads = bm.branchheads(name, closed=accountclosed) if len(heads) > 1: - msg = _('rejecting multiple heads on branch "%s"') + msg = _(b'rejecting multiple heads on branch "%s"') msg %= name - hint = _("%d heads: %s") + hint = _(b"%d heads: %s") hint %= (len(heads), nodesummaries(repo, heads)) raise error.Abort(msg, hint=hint) @@ -2121,11 +2130,11 @@ returns a repo object with the required changesets unhidden """ if not repo.filtername or not repo.ui.configbool( - "experimental", "directaccess" + b"experimental", b"directaccess" ): return repo - if repo.filtername not in ("visible", "visible-hidden"): + if repo.filtername not in (b"visible", b"visible-hidden"): return repo symbols = set() @@ -2145,20 +2154,20 @@ if not revs: return repo - if hiddentype == "warn": + if hiddentype == b"warn": unfi = repo.unfiltered() - revstr = ", ".join([pycompat.bytestr(unfi[l]) for l in revs]) + revstr = b", ".join([pycompat.bytestr(unfi[l]) for l in revs]) repo.ui.warn( _( - "warning: accessing hidden changesets for write " - "operation: %s\n" + b"warning: accessing hidden changesets for write " + b"operation: %s\n" ) % revstr ) # we have to use new filtername to separate branch/tags cache until we can # disbale these cache when revisions are dynamically pinned. - return repo.filtered("visible-hidden", revs) + return repo.filtered(b"visible-hidden", revs) def _getrevsfromsymbols(repo, symbols): @@ -2169,7 +2178,7 @@ unficl = unfi.changelog cl = repo.changelog tiprev = len(unficl) - allowrevnums = repo.ui.configbool("experimental", "directaccess.revnums") + allowrevnums = repo.ui.configbool(b"experimental", b"directaccess.revnums") for s in symbols: try: n = int(s) @@ -2201,9 +2210,9 @@ Select revisions reachable by a given bookmark """ return repo.revs( - "ancestors(bookmark(%s)) - " - "ancestors(head() and not bookmark(%s)) - " - "ancestors(bookmark() and not bookmark(%s))", + b"ancestors(bookmark(%s)) - " + b"ancestors(head() and not bookmark(%s)) - " + b"ancestors(bookmark() and not bookmark(%s))", mark, mark, mark, diff --git a/mercurial/scmwindows.py b/mercurial/scmwindows.py --- a/mercurial/scmwindows.py +++ b/mercurial/scmwindows.py @@ -17,7 +17,7 @@ import winreg # MS-DOS 'more' is the only pager available by default on Windows. -fallbackpager = "more" +fallbackpager = b"more" def systemrcpath(): @@ -25,39 +25,39 @@ rcpath = [] filename = win32.executablepath() # Use mercurial.ini found in directory with hg.exe - progrc = os.path.join(os.path.dirname(filename), "mercurial.ini") + progrc = os.path.join(os.path.dirname(filename), b"mercurial.ini") rcpath.append(progrc) # Use hgrc.d found in directory with hg.exe - progrcd = os.path.join(os.path.dirname(filename), "hgrc.d") + progrcd = os.path.join(os.path.dirname(filename), b"hgrc.d") if os.path.isdir(progrcd): for f, kind in util.listdir(progrcd): - if f.endswith(".rc"): + if f.endswith(b".rc"): rcpath.append(os.path.join(progrcd, f)) # else look for a system rcpath in the registry value = util.lookupreg( - "SOFTWARE\\Mercurial", None, winreg.HKEY_LOCAL_MACHINE + b"SOFTWARE\\Mercurial", None, winreg.HKEY_LOCAL_MACHINE ) if not isinstance(value, str) or not value: return rcpath value = util.localpath(value) for p in value.split(pycompat.ospathsep): - if p.lower().endswith("mercurial.ini"): + if p.lower().endswith(b"mercurial.ini"): rcpath.append(p) elif os.path.isdir(p): for f, kind in util.listdir(p): - if f.endswith(".rc"): + if f.endswith(b".rc"): rcpath.append(os.path.join(p, f)) return rcpath def userrcpath(): """return os-specific hgrc search path to the user dir""" - home = os.path.expanduser("~") - path = [os.path.join(home, "mercurial.ini"), os.path.join(home, ".hgrc")] - userprofile = encoding.environ.get("USERPROFILE") + home = os.path.expanduser(b"~") + path = [os.path.join(home, b"mercurial.ini"), os.path.join(home, b".hgrc")] + userprofile = encoding.environ.get(b"USERPROFILE") if userprofile and userprofile != home: - path.append(os.path.join(userprofile, "mercurial.ini")) - path.append(os.path.join(userprofile, ".hgrc")) + path.append(os.path.join(userprofile, b"mercurial.ini")) + path.append(os.path.join(userprofile, b".hgrc")) return path diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -37,15 +37,15 @@ postexecargs = {} - if opts["daemon_postexec"]: - for inst in opts["daemon_postexec"]: - if inst.startswith("unlink:"): - postexecargs["unlink"] = inst[7:] - elif inst.startswith("chdir:"): - postexecargs["chdir"] = inst[6:] - elif inst != "none": + if opts[b"daemon_postexec"]: + for inst in opts[b"daemon_postexec"]: + if inst.startswith(b"unlink:"): + postexecargs[b"unlink"] = inst[7:] + elif inst.startswith(b"chdir:"): + postexecargs[b"chdir"] = inst[6:] + elif inst != b"none": raise error.Abort( - _("invalid value for --daemon-postexec: %s") % inst + _(b"invalid value for --daemon-postexec: %s") % inst ) # When daemonized on Windows, redirect stdout/stderr to the lockfile (which @@ -53,13 +53,15 @@ # read and print the error if this child dies early. See 594dd384803c. On # other platforms, the child can write to the parent's stdio directly, until # it is redirected prior to runfn(). - if pycompat.iswindows and opts["daemon_postexec"]: - if "unlink" in postexecargs and os.path.exists(postexecargs["unlink"]): + if pycompat.iswindows and opts[b"daemon_postexec"]: + if b"unlink" in postexecargs and os.path.exists( + postexecargs[b"unlink"] + ): procutil.stdout.flush() procutil.stderr.flush() fd = os.open( - postexecargs["unlink"], os.O_WRONLY | os.O_APPEND | os.O_BINARY + postexecargs[b"unlink"], os.O_WRONLY | os.O_APPEND | os.O_BINARY ) try: os.dup2(fd, procutil.stdout.fileno()) @@ -68,30 +70,30 @@ os.close(fd) def writepid(pid): - if opts["pid_file"]: + if opts[b"pid_file"]: if appendpid: - mode = "ab" + mode = b"ab" else: - mode = "wb" - fp = open(opts["pid_file"], mode) - fp.write("%d\n" % pid) + mode = b"wb" + fp = open(opts[b"pid_file"], mode) + fp.write(b"%d\n" % pid) fp.close() - if opts["daemon"] and not opts["daemon_postexec"]: + if opts[b"daemon"] and not opts[b"daemon_postexec"]: # Signal child process startup with file removal - lockfd, lockpath = pycompat.mkstemp(prefix="hg-service-") + lockfd, lockpath = pycompat.mkstemp(prefix=b"hg-service-") os.close(lockfd) try: if not runargs: runargs = procutil.hgcmd() + pycompat.sysargv[1:] - runargs.append("--daemon-postexec=unlink:%s" % lockpath) + runargs.append(b"--daemon-postexec=unlink:%s" % lockpath) # Don't pass --cwd to the child process, because we've already # changed directory. for i in pycompat.xrange(1, len(runargs)): - if runargs[i].startswith("--cwd="): + if runargs[i].startswith(b"--cwd="): del runargs[i] break - elif runargs[i].startswith("--cwd"): + elif runargs[i].startswith(b"--cwd"): del runargs[i : i + 2] break @@ -103,10 +105,10 @@ # If the daemonized process managed to write out an error msg, # report it. if pycompat.iswindows and os.path.exists(lockpath): - with open(lockpath, "rb") as log: + with open(lockpath, b"rb") as log: for line in log: procutil.stderr.write(line) - raise error.Abort(_("child process failed to start")) + raise error.Abort(_(b"child process failed to start")) writepid(pid) finally: util.tryunlink(lockpath) @@ -118,17 +120,17 @@ if initfn: initfn() - if not opts["daemon"]: + if not opts[b"daemon"]: writepid(procutil.getpid()) - if opts["daemon_postexec"]: + if opts[b"daemon_postexec"]: try: os.setsid() except AttributeError: pass - if "chdir" in postexecargs: - os.chdir(postexecargs["chdir"]) + if b"chdir" in postexecargs: + os.chdir(postexecargs[b"chdir"]) procutil.hidewindow() procutil.stdout.flush() procutil.stderr.flush() @@ -154,34 +156,34 @@ # Only unlink after redirecting stdout/stderr, so Windows doesn't # complain about a sharing violation. - if "unlink" in postexecargs: - os.unlink(postexecargs["unlink"]) + if b"unlink" in postexecargs: + os.unlink(postexecargs[b"unlink"]) if runfn: return runfn() _cmdservicemap = { - "chgunix": chgserver.chgunixservice, - "pipe": commandserver.pipeservice, - "unix": commandserver.unixforkingservice, + b"chgunix": chgserver.chgunixservice, + b"pipe": commandserver.pipeservice, + b"unix": commandserver.unixforkingservice, } def _createcmdservice(ui, repo, opts): - mode = opts["cmdserver"] + mode = opts[b"cmdserver"] try: servicefn = _cmdservicemap[mode] except KeyError: - raise error.Abort(_("unknown mode %s") % mode) + raise error.Abort(_(b"unknown mode %s") % mode) commandserver.setuplogging(ui, repo) return servicefn(ui, repo, opts) def _createhgwebservice(ui, repo, opts): # this way we can check if something was given in the command-line - if opts.get("port"): - opts["port"] = util.getport(opts.get("port")) + if opts.get(b"port"): + opts[b"port"] = util.getport(opts.get(b"port")) alluis = {ui} if repo: @@ -189,44 +191,44 @@ alluis.update([repo.baseui, repo.ui]) else: baseui = ui - webconf = opts.get("web_conf") or opts.get("webdir_conf") + webconf = opts.get(b"web_conf") or opts.get(b"webdir_conf") if webconf: - if opts.get("subrepos"): - raise error.Abort(_("--web-conf cannot be used with --subrepos")) + if opts.get(b"subrepos"): + raise error.Abort(_(b"--web-conf cannot be used with --subrepos")) # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() - servui.readconfig(webconf, sections=["web"]) + servui.readconfig(webconf, sections=[b"web"]) alluis.add(servui) - elif opts.get("subrepos"): + elif opts.get(b"subrepos"): servui = ui # If repo is None, hgweb.createapp() already raises a proper abort # message as long as webconf is None. if repo: webconf = dict() - cmdutil.addwebdirpath(repo, "", webconf) + cmdutil.addwebdirpath(repo, b"", webconf) else: servui = ui optlist = ( - "name templates style address port prefix ipv6" - " accesslog errorlog certificate encoding" + b"name templates style address port prefix ipv6" + b" accesslog errorlog certificate encoding" ) for o in optlist.split(): - val = opts.get(o, "") - if val in (None, ""): # should check against default options instead + val = opts.get(o, b"") + if val in (None, b""): # should check against default options instead continue for u in alluis: - u.setconfig("web", o, val, "serve") + u.setconfig(b"web", o, val, b"serve") app = hgweb.createapp(baseui, repo, webconf) return hgweb.httpservice(servui, app, opts) def createservice(ui, repo, opts): - if opts["cmdserver"]: + if opts[b"cmdserver"]: return _createcmdservice(ui, repo, opts) else: return _createhgwebservice(ui, repo, opts) diff --git a/mercurial/setdiscovery.py b/mercurial/setdiscovery.py --- a/mercurial/setdiscovery.py +++ b/mercurial/setdiscovery.py @@ -140,7 +140,7 @@ def addmissings(self, missings): """register some nodes as missing""" - newmissing = self._repo.revs("%ld::%ld", missings, self.undecided) + newmissing = self._repo.revs(b"%ld::%ld", missings, self.undecided) if newmissing: self.missing.update(newmissing) self.undecided.difference_update(newmissing) @@ -176,7 +176,7 @@ def stats(self): return { - "undecided": len(self.undecided), + b"undecided": len(self.undecided), } def commonheads(self): @@ -234,7 +234,7 @@ revs = self.undecided if len(revs) <= size: return list(revs) - sample = set(self._repo.revs("heads(%ld)", revs)) + sample = set(self._repo.revs(b"heads(%ld)", revs)) if len(sample) >= size: return _limitsample(sample, size, randomize=self.randomize) @@ -249,7 +249,7 @@ if len(revs) <= size: return list(revs) repo = self._repo - sample = set(repo.revs("heads(%ld)", revs)) + sample = set(repo.revs(b"heads(%ld)", revs)) parentrevs = self._parentsgetter() # update from heads @@ -257,7 +257,7 @@ _updatesample(revs, revsheads, sample, parentrevs) # update from roots - revsroots = set(repo.revs("roots(%ld)", revs)) + revsroots = set(repo.revs(b"roots(%ld)", revs)) childrenrevs = self._childrengetter() _updatesample(revs, revsroots, sample, childrenrevs) assert sample @@ -308,7 +308,7 @@ ownheads = [rev for rev in cl.headrevs() if rev != nullrev] # early exit if we know all the specified remote heads already - ui.debug("query 1; heads\n") + ui.debug(b"query 1; heads\n") roundtrips += 1 # We also ask remote about all the local heads. That set can be arbitrarily # large, so we used to limit it size to `initialsamplesize`. We no longer @@ -369,8 +369,10 @@ sample = ownheads with remote.commandexecutor() as e: - fheads = e.callcommand("heads", {}) - fknown = e.callcommand("known", {"nodes": [clnode(r) for r in sample],}) + fheads = e.callcommand(b"heads", {}) + fknown = e.callcommand( + b"known", {b"nodes": [clnode(r) for r in sample],} + ) srvheadhashes, yesno = fheads.result(), fknown.result() @@ -381,7 +383,7 @@ # start actual discovery (we note this before the next "if" for # compatibility reasons) - ui.status(_("searching for changes\n")) + ui.status(_(b"searching for changes\n")) knownsrvheads = [] # revnos of remote heads that are known locally for node in srvheadhashes: @@ -395,17 +397,17 @@ continue if len(knownsrvheads) == len(srvheadhashes): - ui.debug("all remote heads known locally\n") + ui.debug(b"all remote heads known locally\n") return srvheadhashes, False, srvheadhashes if len(sample) == len(ownheads) and all(yesno): - ui.note(_("all local changesets known remotely\n")) + ui.note(_(b"all local changesets known remotely\n")) ownheadhashes = [clnode(r) for r in ownheads] return ownheadhashes, True, srvheadhashes # full blown discovery - randomize = ui.configbool("devel", "discovery.randomize") + randomize = ui.configbool(b"devel", b"discovery.randomize") disco = partialdiscovery( local, ownheads, remote.limitedarguments, randomize=randomize ) @@ -415,21 +417,21 @@ disco.addinfo(zip(sample, yesno)) full = False - progress = ui.makeprogress(_("searching"), unit=_("queries")) + progress = ui.makeprogress(_(b"searching"), unit=_(b"queries")) while not disco.iscomplete(): if full or disco.hasinfo(): if full: - ui.note(_("sampling from both directions\n")) + ui.note(_(b"sampling from both directions\n")) else: - ui.debug("taking initial sample\n") + ui.debug(b"taking initial sample\n") samplefunc = disco.takefullsample targetsize = fullsamplesize if not remote.limitedarguments: fullsamplesize = int(fullsamplesize * samplegrowth) else: # use even cheaper initial sample - ui.debug("taking quick initial sample\n") + ui.debug(b"taking quick initial sample\n") samplefunc = disco.takequicksample targetsize = initialsamplesize sample = samplefunc(ownheads, targetsize) @@ -438,8 +440,8 @@ progress.update(roundtrips) stats = disco.stats() ui.debug( - "query %i; still undecided: %i, sample size is: %i\n" - % (roundtrips, stats["undecided"], len(sample)) + b"query %i; still undecided: %i, sample size is: %i\n" + % (roundtrips, stats[b"undecided"], len(sample)) ) # indices between sample and externalized version must match @@ -447,7 +449,7 @@ with remote.commandexecutor() as e: yesno = e.callcommand( - "known", {"nodes": [clnode(r) for r in sample],} + b"known", {b"nodes": [clnode(r) for r in sample],} ).result() full = True @@ -457,19 +459,19 @@ result = disco.commonheads() elapsed = util.timer() - start progress.complete() - ui.debug("%d total queries in %.4fs\n" % (roundtrips, elapsed)) + ui.debug(b"%d total queries in %.4fs\n" % (roundtrips, elapsed)) msg = ( - "found %d common and %d unknown server heads," - " %d roundtrips in %.4fs\n" + b"found %d common and %d unknown server heads," + b" %d roundtrips in %.4fs\n" ) missing = set(result) - set(knownsrvheads) - ui.log("discovery", msg, len(result), len(missing), roundtrips, elapsed) + ui.log(b"discovery", msg, len(result), len(missing), roundtrips, elapsed) if not result and srvheadhashes != [nullid]: if abortwhenunrelated: - raise error.Abort(_("repository is unrelated")) + raise error.Abort(_(b"repository is unrelated")) else: - ui.warn(_("warning: repository is unrelated\n")) + ui.warn(_(b"warning: repository is unrelated\n")) return ( {nullid}, True, diff --git a/mercurial/shelve.py b/mercurial/shelve.py --- a/mercurial/shelve.py +++ b/mercurial/shelve.py @@ -56,15 +56,15 @@ stringutil, ) -backupdir = "shelve-backup" -shelvedir = "shelved" -shelvefileextensions = ["hg", "patch", "shelve"] +backupdir = b"shelve-backup" +shelvedir = b"shelved" +shelvefileextensions = [b"hg", b"patch", b"shelve"] # universal extension is present in all types of shelves -patchextension = "patch" +patchextension = b"patch" # we never need the user, so we use a # generic user for all shelve operations -shelveuser = "shelve@localhost" +shelveuser = b"shelve@localhost" class shelvedfile(object): @@ -80,7 +80,7 @@ self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir)) self.ui = self.repo.ui if filetype: - self.fname = name + "." + filetype + self.fname = name + b"." + filetype else: self.fname = name @@ -93,9 +93,9 @@ def backupfilename(self): def gennames(base): yield base - base, ext = base.rsplit(".", 1) + base, ext = base.rsplit(b".", 1) for i in itertools.count(1): - yield "%s-%d.%s" % (base, i, ext) + yield b"%s-%d.%s" % (base, i, ext) name = self.backupvfs.join(self.fname) for n in gennames(name): @@ -110,13 +110,13 @@ def stat(self): return self.vfs.stat(self.fname) - def opener(self, mode="rb"): + def opener(self, mode=b"rb"): try: return self.vfs(self.fname, mode) except IOError as err: if err.errno != errno.ENOENT: raise - raise error.Abort(_("shelved change '%s' not found") % self.name) + raise error.Abort(_(b"shelved change '%s' not found") % self.name) def applybundle(self, tr): fp = self.opener() @@ -125,18 +125,18 @@ if not phases.supportinternal(self.repo): targetphase = phases.secret gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs) - pretip = self.repo["tip"] + pretip = self.repo[b"tip"] bundle2.applybundle( self.repo, gen, tr, - source="unshelve", - url="bundle:" + self.vfs.join(self.fname), + source=b"unshelve", + url=b"bundle:" + self.vfs.join(self.fname), targetphase=targetphase, ) - shelvectx = self.repo["tip"] + shelvectx = self.repo[b"tip"] if pretip == shelvectx: - shelverev = tr.changes["revduplicates"][-1] + shelverev = tr.changes[b"revduplicates"][-1] shelvectx = self.repo[shelverev] return shelvectx finally: @@ -145,24 +145,24 @@ def bundlerepo(self): path = self.vfs.join(self.fname) return bundlerepo.instance( - self.repo.baseui, "bundle://%s+%s" % (self.repo.root, path) + self.repo.baseui, b"bundle://%s+%s" % (self.repo.root, path) ) def writebundle(self, bases, node): cgversion = changegroup.safeversion(self.repo) - if cgversion == "01": - btype = "HG10BZ" + if cgversion == b"01": + btype = b"HG10BZ" compression = None else: - btype = "HG20" - compression = "BZ" + btype = b"HG20" + compression = b"BZ" repo = self.repo.unfiltered() outgoing = discovery.outgoing( repo, missingroots=bases, missingheads=[node] ) - cg = changegroup.makechangegroup(repo, outgoing, cgversion, "shelve") + cg = changegroup.makechangegroup(repo, outgoing, cgversion, b"shelve") bundle2.writebundle( self.ui, cg, self.fname, btype, self.vfs, compression=compression @@ -183,22 +183,22 @@ """ _version = 2 - _filename = "shelvedstate" - _keep = "keep" - _nokeep = "nokeep" + _filename = b"shelvedstate" + _keep = b"keep" + _nokeep = b"nokeep" # colon is essential to differentiate from a real bookmark name - _noactivebook = ":no-active-bookmark" - _interactive = "interactive" + _noactivebook = b":no-active-bookmark" + _interactive = b"interactive" @classmethod def _verifyandtransform(cls, d): """Some basic shelvestate syntactic verification and transformation""" try: - d["originalwctx"] = nodemod.bin(d["originalwctx"]) - d["pendingctx"] = nodemod.bin(d["pendingctx"]) - d["parents"] = [nodemod.bin(h) for h in d["parents"].split(" ")] - d["nodestoremove"] = [ - nodemod.bin(h) for h in d["nodestoremove"].split(" ") + d[b"originalwctx"] = nodemod.bin(d[b"originalwctx"]) + d[b"pendingctx"] = nodemod.bin(d[b"pendingctx"]) + d[b"parents"] = [nodemod.bin(h) for h in d[b"parents"].split(b" ")] + d[b"nodestoremove"] = [ + nodemod.bin(h) for h in d[b"nodestoremove"].split(b" ") ] except (ValueError, TypeError, KeyError) as err: raise error.CorruptedState(pycompat.bytestr(err)) @@ -222,15 +222,15 @@ # to detemine values of fields (i.g. name is on the second line, # originalwctx is on the third and so forth). Please do not change. keys = [ - "version", - "name", - "originalwctx", - "pendingctx", - "parents", - "nodestoremove", - "branchtorestore", - "keep", - "activebook", + b"version", + b"name", + b"originalwctx", + b"pendingctx", + b"parents", + b"nodestoremove", + b"branchtorestore", + b"keep", + b"activebook", ] # this is executed only seldomly, so it is not a big deal # that we open this file twice @@ -255,25 +255,25 @@ else: raise error.Abort( _( - "this version of shelve is incompatible " - "with the version used in this repo" + b"this version of shelve is incompatible " + b"with the version used in this repo" ) ) cls._verifyandtransform(d) try: obj = cls() - obj.name = d["name"] - obj.wctx = repo[d["originalwctx"]] - obj.pendingctx = repo[d["pendingctx"]] - obj.parents = d["parents"] - obj.nodestoremove = d["nodestoremove"] - obj.branchtorestore = d.get("branchtorestore", "") - obj.keep = d.get("keep") == cls._keep - obj.activebookmark = "" - if d.get("activebook", "") != cls._noactivebook: - obj.activebookmark = d.get("activebook", "") - obj.interactive = d.get("interactive") == cls._interactive + obj.name = d[b"name"] + obj.wctx = repo[d[b"originalwctx"]] + obj.pendingctx = repo[d[b"pendingctx"]] + obj.parents = d[b"parents"] + obj.nodestoremove = d[b"nodestoremove"] + obj.branchtorestore = d.get(b"branchtorestore", b"") + obj.keep = d.get(b"keep") == cls._keep + obj.activebookmark = b"" + if d.get(b"activebook", b"") != cls._noactivebook: + obj.activebookmark = d.get(b"activebook", b"") + obj.interactive = d.get(b"interactive") == cls._interactive except (error.RepoLookupError, KeyError) as err: raise error.CorruptedState(pycompat.bytestr(err)) @@ -289,25 +289,27 @@ nodestoremove, branchtorestore, keep=False, - activebook="", + activebook=b"", interactive=False, ): info = { - "name": name, - "originalwctx": nodemod.hex(originalwctx.node()), - "pendingctx": nodemod.hex(pendingctx.node()), - "parents": " ".join( + b"name": name, + b"originalwctx": nodemod.hex(originalwctx.node()), + b"pendingctx": nodemod.hex(pendingctx.node()), + b"parents": b" ".join( [nodemod.hex(p) for p in repo.dirstate.parents()] ), - "nodestoremove": " ".join([nodemod.hex(n) for n in nodestoremove]), - "branchtorestore": branchtorestore, - "keep": cls._keep if keep else cls._nokeep, - "activebook": activebook or cls._noactivebook, + b"nodestoremove": b" ".join( + [nodemod.hex(n) for n in nodestoremove] + ), + b"branchtorestore": branchtorestore, + b"keep": cls._keep if keep else cls._nokeep, + b"activebook": activebook or cls._noactivebook, } if interactive: - info["interactive"] = cls._interactive + info[b"interactive"] = cls._interactive scmutil.simplekeyvaluefile(repo.vfs, cls._filename).write( - info, firstline=("%d" % cls._version) + info, firstline=(b"%d" % cls._version) ) @classmethod @@ -317,8 +319,8 @@ def cleanupoldbackups(repo): vfs = vfsmod.vfs(repo.vfs.join(backupdir)) - maxbackups = repo.ui.configint("shelve", "maxbackups") - hgfiles = [f for f in vfs.listdir() if f.endswith("." + patchextension)] + maxbackups = repo.ui.configint(b"shelve", b"maxbackups") + hgfiles = [f for f in vfs.listdir() if f.endswith(b"." + patchextension)] hgfiles = sorted([(vfs.stat(f)[stat.ST_MTIME], f) for f in hgfiles]) if maxbackups > 0 and maxbackups < len(hgfiles): bordermtime = hgfiles[-maxbackups][0] @@ -330,7 +332,7 @@ continue base = f[: -(1 + len(patchextension))] for ext in shelvefileextensions: - vfs.tryunlink(base + "." + ext) + vfs.tryunlink(base + b"." + ext) def _backupactivebookmark(repo): @@ -348,7 +350,7 @@ def _aborttransaction(repo, tr): """Abort current transaction for shelve/unshelve, but keep dirstate """ - dirstatebackupname = "dirstate.shelve" + dirstatebackupname = b"dirstate.shelve" repo.dirstate.savebackup(tr, dirstatebackupname) tr.abort() repo.dirstate.restorebackup(None, dirstatebackupname) @@ -360,27 +362,29 @@ def gennames(): yield label for i in itertools.count(1): - yield "%s-%02d" % (label, i) + yield b"%s-%02d" % (label, i) - name = opts.get("name") - label = repo._activebookmark or parent.branch() or "default" + name = opts.get(b"name") + label = repo._activebookmark or parent.branch() or b"default" # slashes aren't allowed in filenames, therefore we rename it - label = label.replace("/", "_") - label = label.replace("\\", "_") + label = label.replace(b"/", b"_") + label = label.replace(b"\\", b"_") # filenames must not start with '.' as it should not be hidden - if label.startswith("."): - label = label.replace(".", "_", 1) + if label.startswith(b"."): + label = label.replace(b".", b"_", 1) if name: if shelvedfile(repo, name, patchextension).exists(): - e = _("a shelved change named '%s' already exists") % name + e = _(b"a shelved change named '%s' already exists") % name raise error.Abort(e) # ensure we are not creating a subdirectory or a hidden file - if "/" in name or "\\" in name: - raise error.Abort(_("shelved change names can not contain slashes")) - if name.startswith("."): - raise error.Abort(_("shelved change names can not start with '.'")) + if b"/" in name or b"\\" in name: + raise error.Abort( + _(b"shelved change names can not contain slashes") + ) + if name.startswith(b"."): + raise error.Abort(_(b"shelved change names can not start with '.'")) else: for n in gennames(): @@ -411,25 +415,25 @@ def getcommitfunc(extra, interactive, editor=False): def commitfunc(ui, repo, message, match, opts): - hasmq = util.safehasattr(repo, "mq") + hasmq = util.safehasattr(repo, b"mq") if hasmq: saved, repo.mq.checkapplied = repo.mq.checkapplied, False targetphase = phases.internal if not phases.supportinternal(repo): targetphase = phases.secret - overrides = {("phases", "new-commit"): targetphase} + overrides = {(b"phases", b"new-commit"): targetphase} try: editor_ = False if editor: editor_ = cmdutil.getcommiteditor( - editform="shelve.shelve", **pycompat.strkwargs(opts) + editform=b"shelve.shelve", **pycompat.strkwargs(opts) ) with repo.ui.configoverride(overrides): return repo.commit( message, shelveuser, - opts.get("date"), + opts.get(b"date"), match, editor=editor_, extra=extra, @@ -440,8 +444,8 @@ def interactivecommitfunc(ui, repo, *pats, **opts): opts = pycompat.byteskwargs(opts) - match = scmutil.match(repo["."], pats, {}) - message = opts["message"] + match = scmutil.match(repo[b"."], pats, {}) + message = opts[b"message"] return commitfunc(ui, repo, message, match, opts) return interactivecommitfunc if interactive else commitfunc @@ -451,19 +455,19 @@ stat = repo.status(match=scmutil.match(repo[None], pats, opts)) if stat.deleted: ui.status( - _("nothing changed (%d missing files, see " "'hg status')\n") + _(b"nothing changed (%d missing files, see " b"'hg status')\n") % len(stat.deleted) ) else: - ui.status(_("nothing changed\n")) + ui.status(_(b"nothing changed\n")) def _shelvecreatedcommit(repo, node, name, match): - info = {"node": nodemod.hex(node)} - shelvedfile(repo, name, "shelve").writeinfo(info) + info = {b"node": nodemod.hex(node)} + shelvedfile(repo, name, b"shelve").writeinfo(info) bases = list(mutableancestors(repo[node])) - shelvedfile(repo, name, "hg").writebundle(bases, node) - with shelvedfile(repo, name, patchextension).opener("wb") as fp: + shelvedfile(repo, name, b"hg").writebundle(bases, node) + with shelvedfile(repo, name, patchextension).opener(b"wb") as fp: cmdutil.exportfile( repo, [node], fp, opts=mdiff.diffopts(git=True), match=match ) @@ -472,7 +476,7 @@ def _includeunknownfiles(repo, pats, opts, extra): s = repo.status(match=scmutil.match(repo[None], pats, opts), unknown=True) if s.unknown: - extra["shelve_unknown"] = "\0".join(s.unknown) + extra[b"shelve_unknown"] = b"\0".join(s.unknown) repo[None].add(s.unknown) @@ -497,12 +501,12 @@ origbranch = wctx.branch() if parent.node() != nodemod.nullid: - desc = "changes to: %s" % parent.description().split("\n", 1)[0] + desc = b"changes to: %s" % parent.description().split(b"\n", 1)[0] else: - desc = "(changes in empty repository)" + desc = b"(changes in empty repository)" - if not opts.get("message"): - opts["message"] = desc + if not opts.get(b"message"): + opts[b"message"] = desc lock = tr = activebookmark = None try: @@ -510,23 +514,23 @@ # use an uncommitted transaction to generate the bundle to avoid # pull races. ensure we don't print the abort message to stderr. - tr = repo.transaction("shelve", report=lambda x: None) + tr = repo.transaction(b"shelve", report=lambda x: None) - interactive = opts.get("interactive", False) - includeunknown = opts.get("unknown", False) and not opts.get( - "addremove", False + interactive = opts.get(b"interactive", False) + includeunknown = opts.get(b"unknown", False) and not opts.get( + b"addremove", False ) name = getshelvename(repo, parent, opts) activebookmark = _backupactivebookmark(repo) - extra = {"internal": "shelve"} + extra = {b"internal": b"shelve"} if includeunknown: _includeunknownfiles(repo, pats, opts, extra) if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts): # In non-bare shelve we don't store newly created branch # at bundled commit - repo.dirstate.setbranch(repo["."].branch()) + repo.dirstate.setbranch(repo[b"."].branch()) commitfunc = getcommitfunc(extra, interactive, editor=True) if not interactive: @@ -554,13 +558,13 @@ if ui.formatted(): desc = stringutil.ellipsis(desc, ui.termwidth()) - ui.status(_("shelved as %s\n") % name) - if opts["keep"]: + ui.status(_(b"shelved as %s\n") % name) + if opts[b"keep"]: with repo.dirstate.parentchange(): scmutil.movedirstate(repo, parent, match) else: hg.update(repo, parent.node()) - if origbranch != repo["."].branch() and not _isbareshelve(pats, opts): + if origbranch != repo[b"."].branch() and not _isbareshelve(pats, opts): repo.dirstate.setbranch(origbranch) _finishshelve(repo, tr) @@ -572,14 +576,14 @@ def _isbareshelve(pats, opts): return ( not pats - and not opts.get("interactive", False) - and not opts.get("include", False) - and not opts.get("exclude", False) + and not opts.get(b"interactive", False) + and not opts.get(b"include", False) + and not opts.get(b"exclude", False) ) def _iswctxonnewbranch(repo): - return repo[None].branch() != repo["."].branch() + return repo[None].branch() != repo[b"."].branch() def cleanupcmd(ui, repo): @@ -587,7 +591,7 @@ with repo.wlock(): for (name, _type) in repo.vfs.readdir(shelvedir): - suffix = name.rsplit(".", 1)[-1] + suffix = name.rsplit(b".", 1)[-1] if suffix in shelvefileextensions: shelvedfile(repo, name).movetobackup() cleanupoldbackups(repo) @@ -596,7 +600,7 @@ def deletecmd(ui, repo, pats): """subcommand that deletes a specific shelve""" if not pats: - raise error.Abort(_("no shelved changes specified!")) + raise error.Abort(_(b"no shelved changes specified!")) with repo.wlock(): try: for name in pats: @@ -613,7 +617,7 @@ except OSError as err: if err.errno != errno.ENOENT: raise - raise error.Abort(_("shelved change '%s' not found") % name) + raise error.Abort(_(b"shelved change '%s' not found") % name) def listshelves(repo): @@ -626,7 +630,7 @@ return [] info = [] for (name, _type) in names: - pfx, sfx = name.rsplit(".", 1) + pfx, sfx = name.rsplit(b".", 1) if not pfx or sfx != patchextension: continue st = shelvedfile(repo, name).stat() @@ -640,43 +644,43 @@ width = 80 if not ui.plain(): width = ui.termwidth() - namelabel = "shelve.newest" - ui.pager("shelve") + namelabel = b"shelve.newest" + ui.pager(b"shelve") for mtime, name in listshelves(repo): sname = util.split(name)[1] if pats and sname not in pats: continue ui.write(sname, label=namelabel) - namelabel = "shelve.name" + namelabel = b"shelve.name" if ui.quiet: - ui.write("\n") + ui.write(b"\n") continue - ui.write(" " * (16 - len(sname))) + ui.write(b" " * (16 - len(sname))) used = 16 date = dateutil.makedate(mtime) - age = "(%s)" % templatefilters.age(date, abbrev=True) - ui.write(age, label="shelve.age") - ui.write(" " * (12 - len(age))) + age = b"(%s)" % templatefilters.age(date, abbrev=True) + ui.write(age, label=b"shelve.age") + ui.write(b" " * (12 - len(age))) used += 12 - with open(name + "." + patchextension, "rb") as fp: + with open(name + b"." + patchextension, b"rb") as fp: while True: line = fp.readline() if not line: break - if not line.startswith("#"): + if not line.startswith(b"#"): desc = line.rstrip() if ui.formatted(): desc = stringutil.ellipsis(desc, width - used) ui.write(desc) break - ui.write("\n") - if not (opts["patch"] or opts["stat"]): + ui.write(b"\n") + if not (opts[b"patch"] or opts[b"stat"]): continue difflines = fp.readlines() - if opts["patch"]: + if opts[b"patch"]: for chunk, label in patch.difflabel(iter, difflines): ui.write(chunk, label=label) - if opts["stat"]: + if opts[b"stat"]: for chunk, label in patch.diffstatui(difflines, width=width): ui.write(chunk, label=label) @@ -686,14 +690,14 @@ if len(pats) == 0: shelves = listshelves(repo) if not shelves: - raise error.Abort(_("there are no shelves to show")) + raise error.Abort(_(b"there are no shelves to show")) mtime, name = shelves[0] sname = util.split(name)[1] pats = [sname] for shelfname in pats: if not shelvedfile(repo, shelfname, patchextension).exists(): - raise error.Abort(_("cannot find shelf %s") % shelfname) + raise error.Abort(_(b"cannot find shelf %s") % shelfname) listcmd(ui, repo, pats, opts) @@ -702,34 +706,35 @@ """check parent while resuming an unshelve""" if state.parents != repo.dirstate.parents(): raise error.Abort( - _("working directory parents do not match unshelve " "state") + _(b"working directory parents do not match unshelve " b"state") ) def _loadshelvedstate(ui, repo, opts): try: state = shelvedstate.load(repo) - if opts.get("keep") is None: - opts["keep"] = state.keep + if opts.get(b"keep") is None: + opts[b"keep"] = state.keep except IOError as err: if err.errno != errno.ENOENT: raise - cmdutil.wrongtooltocontinue(repo, _("unshelve")) + cmdutil.wrongtooltocontinue(repo, _(b"unshelve")) except error.CorruptedState as err: - ui.debug(pycompat.bytestr(err) + "\n") - if opts.get("continue"): - msg = _("corrupted shelved state file") + ui.debug(pycompat.bytestr(err) + b"\n") + if opts.get(b"continue"): + msg = _(b"corrupted shelved state file") hint = _( - "please run hg unshelve --abort to abort unshelve " "operation" + b"please run hg unshelve --abort to abort unshelve " + b"operation" ) raise error.Abort(msg, hint=hint) - elif opts.get("abort"): + elif opts.get(b"abort"): shelvedstate.clear(repo) raise error.Abort( _( - "could not read shelved state file, your " - "working copy may be in an unexpected state\n" - "please update to some commit\n" + b"could not read shelved state file, your " + b"working copy may be in an unexpected state\n" + b"please update to some commit\n" ) ) return state @@ -747,24 +752,24 @@ mergefiles(ui, repo, state.wctx, state.pendingctx) if not phases.supportinternal(repo): repair.strip( - ui, repo, state.nodestoremove, backup=False, topic="shelve" + ui, repo, state.nodestoremove, backup=False, topic=b"shelve" ) finally: shelvedstate.clear(repo) - ui.warn(_("unshelve of '%s' aborted\n") % state.name) + ui.warn(_(b"unshelve of '%s' aborted\n") % state.name) def hgabortunshelve(ui, repo): """logic to abort unshelve using 'hg abort""" with repo.wlock(): - state = _loadshelvedstate(ui, repo, {"abort": True}) + state = _loadshelvedstate(ui, repo, {b"abort": True}) return unshelveabort(ui, repo, state) def mergefiles(ui, repo, wctx, shelvectx): """updates to wctx and merges the changes from shelvectx into the dirstate.""" - with ui.configoverride({("ui", "quiet"): True}): + with ui.configoverride({(b"ui", b"quiet"): True}): hg.update(repo, wctx.node()) ui.pushbuffer(True) cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents()) @@ -775,13 +780,13 @@ if branchtorestore and branchtorestore != repo.dirstate.branch(): repo.dirstate.setbranch(branchtorestore) ui.status( - _("marked working directory as branch %s\n") % branchtorestore + _(b"marked working directory as branch %s\n") % branchtorestore ) def unshelvecleanup(ui, repo, name, opts): """remove related files after an unshelve""" - if not opts.get("keep"): + if not opts.get(b"keep"): for filetype in shelvefileextensions: shfile = shelvedfile(repo, name, filetype) if shfile.exists(): @@ -800,8 +805,8 @@ ms = merge.mergestate.read(repo) if list(ms.unresolved()): raise error.Abort( - _("unresolved conflicts, can't continue"), - hint=_("see 'hg resolve', then 'hg unshelve --continue'"), + _(b"unresolved conflicts, can't continue"), + hint=_(b"see 'hg resolve', then 'hg unshelve --continue'"), ) shelvectx = repo[state.parents[1]] @@ -814,8 +819,8 @@ targetphase = phases.internal if not phases.supportinternal(repo): targetphase = phases.secret - overrides = {("phases", "new-commit"): targetphase} - with repo.ui.configoverride(overrides, "unshelve"): + overrides = {(b"phases", b"new-commit"): targetphase} + with repo.ui.configoverride(overrides, b"unshelve"): with repo.dirstate.parentchange(): repo.setparents(state.parents[0], nodemod.nullid) newnode, ispartialunshelve = _createunshelvectx( @@ -829,8 +834,8 @@ merge.mergestate.clean(repo) shelvectx = state.pendingctx msg = _( - "note: unshelved changes already existed " - "in the working copy\n" + b"note: unshelved changes already existed " + b"in the working copy\n" ) ui.status(msg) else: @@ -844,20 +849,20 @@ if not phases.supportinternal(repo): repair.strip( - ui, repo, state.nodestoremove, backup=False, topic="shelve" + ui, repo, state.nodestoremove, backup=False, topic=b"shelve" ) shelvedstate.clear(repo) if not ispartialunshelve: unshelvecleanup(ui, repo, state.name, opts) _restoreactivebookmark(repo, state.activebookmark) - ui.status(_("unshelve of '%s' complete\n") % state.name) + ui.status(_(b"unshelve of '%s' complete\n") % state.name) def hgcontinueunshelve(ui, repo): """logic to resume unshelve using 'hg continue'""" with repo.wlock(): - state = _loadshelvedstate(ui, repo, {"continue": True}) - return unshelvecontinue(ui, repo, state, {"keep": state.keep}) + state = _loadshelvedstate(ui, repo, {b"continue": True}) + return unshelvecontinue(ui, repo, state, {b"keep": state.keep}) def _commitworkingcopychanges(ui, repo, opts, tmpwctx): @@ -870,16 +875,16 @@ return tmpwctx, addedbefore ui.status( _( - "temporarily committing pending changes " - "(restore with 'hg unshelve --abort')\n" + b"temporarily committing pending changes " + b"(restore with 'hg unshelve --abort')\n" ) ) - extra = {"internal": "shelve"} + extra = {b"internal": b"shelve"} commitfunc = getcommitfunc(extra=extra, interactive=False, editor=False) tempopts = {} - tempopts["message"] = "pending changes temporary commit" - tempopts["date"] = opts.get("date") - with ui.configoverride({("ui", "quiet"): True}): + tempopts[b"message"] = b"pending changes temporary commit" + tempopts[b"date"] = opts.get(b"date") + with ui.configoverride({(b"ui", b"quiet"): True}): node = cmdutil.commit(ui, repo, commitfunc, [], tempopts) tmpwctx = repo[node] return tmpwctx, addedbefore @@ -889,16 +894,16 @@ """Recreate commit in the repository during the unshelve""" repo = repo.unfiltered() node = None - if shelvedfile(repo, basename, "shelve").exists(): - node = shelvedfile(repo, basename, "shelve").readinfo()["node"] + if shelvedfile(repo, basename, b"shelve").exists(): + node = shelvedfile(repo, basename, b"shelve").readinfo()[b"node"] if node is None or node not in repo: - with ui.configoverride({("ui", "quiet"): True}): - shelvectx = shelvedfile(repo, basename, "hg").applybundle(tr) + with ui.configoverride({(b"ui", b"quiet"): True}): + shelvectx = shelvedfile(repo, basename, b"hg").applybundle(tr) # We might not strip the unbundled changeset, so we should keep track of # the unshelve node in case we need to reuse it (eg: unshelve --keep) if node is None: - info = {"node": nodemod.hex(shelvectx.node())} - shelvedfile(repo, basename, "shelve").writeinfo(info) + info = {b"node": nodemod.hex(shelvectx.node())} + shelvedfile(repo, basename, b"shelve").writeinfo(info) else: shelvectx = repo[node] @@ -926,8 +931,8 @@ Here, we return both the newnode which is created interactively and a bool to know whether the shelve is partly done or completely done. """ - opts["message"] = shelvectx.description() - opts["interactive-unshelve"] = True + opts[b"message"] = shelvectx.description() + opts[b"interactive-unshelve"] = True pats = [] if not interactive: newnode = repo.commit( @@ -977,23 +982,23 @@ """Rebase restored commit from its original location to a destination""" # If the shelve is not immediately on top of the commit # we'll be merging with, rebase it to be on top. - interactive = opts.get("interactive") + interactive = opts.get(b"interactive") if tmpwctx.node() == shelvectx.p1().node() and not interactive: # We won't skip on interactive mode because, the user might want to # unshelve certain changes only. return shelvectx, False overrides = { - ("ui", "forcemerge"): opts.get("tool", ""), - ("phases", "new-commit"): phases.secret, + (b"ui", b"forcemerge"): opts.get(b"tool", b""), + (b"phases", b"new-commit"): phases.secret, } - with repo.ui.configoverride(overrides, "unshelve"): - ui.status(_("rebasing shelved changes\n")) + with repo.ui.configoverride(overrides, b"unshelve"): + ui.status(_(b"rebasing shelved changes\n")) stats = merge.graft( repo, shelvectx, shelvectx.p1(), - labels=["shelve", "working-copy"], + labels=[b"shelve", b"working-copy"], keepconflictparent=True, ) if stats.unresolvedcount: @@ -1010,14 +1015,14 @@ tmpwctx, nodestoremove, branchtorestore, - opts.get("keep"), + opts.get(b"keep"), activebookmark, interactive, ) raise error.InterventionRequired( _( - "unresolved conflicts (see 'hg resolve', then " - "'hg unshelve --continue')" + b"unresolved conflicts (see 'hg resolve', then " + b"'hg unshelve --continue')" ) ) @@ -1034,8 +1039,8 @@ merge.mergestate.clean(repo) shelvectx = tmpwctx msg = _( - "note: unshelved changes already existed " - "in the working copy\n" + b"note: unshelved changes already existed " + b"in the working copy\n" ) ui.status(msg) else: @@ -1048,10 +1053,10 @@ def _forgetunknownfiles(repo, shelvectx, addedbefore): # Forget any files that were unknown before the shelve, unknown before # unshelve started, but are now added. - shelveunknown = shelvectx.extra().get("shelve_unknown") + shelveunknown = shelvectx.extra().get(b"shelve_unknown") if not shelveunknown: return - shelveunknown = frozenset(shelveunknown.split("\0")) + shelveunknown = frozenset(shelveunknown.split(b"\0")) addedafter = frozenset(repo.status().added) toforget = (addedafter & shelveunknown) - addedbefore repo[None].forget(toforget) @@ -1074,66 +1079,66 @@ shelvetouched = set(shelvectx.files()) intersection = wcdeleted.intersection(shelvetouched) if intersection: - m = _("shelved change touches missing files") - hint = _("run hg status to see which files are missing") + m = _(b"shelved change touches missing files") + hint = _(b"run hg status to see which files are missing") raise error.Abort(m, hint=hint) def dounshelve(ui, repo, *shelved, **opts): opts = pycompat.byteskwargs(opts) - abortf = opts.get("abort") - continuef = opts.get("continue") - interactive = opts.get("interactive") + abortf = opts.get(b"abort") + continuef = opts.get(b"continue") + interactive = opts.get(b"interactive") if not abortf and not continuef: cmdutil.checkunfinished(repo) shelved = list(shelved) - if opts.get("name"): - shelved.append(opts["name"]) + if opts.get(b"name"): + shelved.append(opts[b"name"]) - if interactive and opts.get("keep"): - raise error.Abort(_("--keep on --interactive is not yet supported")) + if interactive and opts.get(b"keep"): + raise error.Abort(_(b"--keep on --interactive is not yet supported")) if abortf or continuef: if abortf and continuef: - raise error.Abort(_("cannot use both abort and continue")) + raise error.Abort(_(b"cannot use both abort and continue")) if shelved: raise error.Abort( _( - "cannot combine abort/continue with " - "naming a shelved change" + b"cannot combine abort/continue with " + b"naming a shelved change" ) ) - if abortf and opts.get("tool", False): - ui.warn(_("tool option will be ignored\n")) + if abortf and opts.get(b"tool", False): + ui.warn(_(b"tool option will be ignored\n")) state = _loadshelvedstate(ui, repo, opts) if abortf: return unshelveabort(ui, repo, state) elif continuef and interactive: - raise error.Abort(_("cannot use both continue and interactive")) + raise error.Abort(_(b"cannot use both continue and interactive")) elif continuef: return unshelvecontinue(ui, repo, state, opts) elif len(shelved) > 1: - raise error.Abort(_("can only unshelve one change at a time")) + raise error.Abort(_(b"can only unshelve one change at a time")) elif not shelved: shelved = listshelves(repo) if not shelved: - raise error.Abort(_("no shelved changes to apply!")) + raise error.Abort(_(b"no shelved changes to apply!")) basename = util.split(shelved[0][1])[1] - ui.status(_("unshelving change '%s'\n") % basename) + ui.status(_(b"unshelving change '%s'\n") % basename) else: basename = shelved[0] if not shelvedfile(repo, basename, patchextension).exists(): - raise error.Abort(_("shelved change '%s' not found") % basename) + raise error.Abort(_(b"shelved change '%s' not found") % basename) repo = repo.unfiltered() lock = tr = None try: lock = repo.lock() - tr = repo.transaction("unshelve", report=lambda x: None) + tr = repo.transaction(b"unshelve", report=lambda x: None) oldtiprev = len(repo) - pctx = repo["."] + pctx = repo[b"."] tmpwctx = pctx # The goal is to have a commit structure like so: # ...-> pctx -> tmpwctx -> shelvectx @@ -1147,7 +1152,7 @@ ) repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename) _checkunshelveuntrackedproblems(ui, repo, shelvectx) - branchtorestore = "" + branchtorestore = b"" if shelvectx.branch() != shelvectx.p1().branch(): branchtorestore = shelvectx.branch() @@ -1164,8 +1169,8 @@ branchtorestore, activebookmark, ) - overrides = {("ui", "forcemerge"): opts.get("tool", "")} - with ui.configoverride(overrides, "unshelve"): + overrides = {(b"ui", b"forcemerge"): opts.get(b"tool", b"")} + with ui.configoverride(overrides, b"unshelve"): mergefiles(ui, repo, pctx, shelvectx) restorebranch(ui, repo, branchtorestore) shelvedstate.clear(repo) diff --git a/mercurial/similar.py b/mercurial/similar.py --- a/mercurial/similar.py +++ b/mercurial/similar.py @@ -21,9 +21,9 @@ # We use hash() to discard fctx.data() from memory. hashes = {} progress = repo.ui.makeprogress( - _("searching for exact renames"), + _(b"searching for exact renames"), total=(len(added) + len(removed)), - unit=_("files"), + unit=_(b"files"), ) for fctx in removed: progress.increment() @@ -81,7 +81,7 @@ """ copies = {} progress = repo.ui.makeprogress( - _("searching for similar files"), unit=_("files"), total=len(removed) + _(b"searching for similar files"), unit=_(b"files"), total=len(removed) ) for r in removed: progress.increment() diff --git a/mercurial/simplemerge.py b/mercurial/simplemerge.py --- a/mercurial/simplemerge.py +++ b/mercurial/simplemerge.py @@ -93,9 +93,9 @@ name_a=None, name_b=None, name_base=None, - start_marker="<<<<<<<", - mid_marker="=======", - end_marker=">>>>>>>", + start_marker=b"<<<<<<<", + mid_marker=b"=======", + end_marker=b">>>>>>>", base_marker=None, localorother=None, minimize=False, @@ -103,37 +103,37 @@ """Return merge in cvs-like form. """ self.conflicts = False - newline = "\n" + newline = b"\n" if len(self.a) > 0: - if self.a[0].endswith("\r\n"): - newline = "\r\n" - elif self.a[0].endswith("\r"): - newline = "\r" + if self.a[0].endswith(b"\r\n"): + newline = b"\r\n" + elif self.a[0].endswith(b"\r"): + newline = b"\r" if name_a and start_marker: - start_marker = start_marker + " " + name_a + start_marker = start_marker + b" " + name_a if name_b and end_marker: - end_marker = end_marker + " " + name_b + end_marker = end_marker + b" " + name_b if name_base and base_marker: - base_marker = base_marker + " " + name_base + base_marker = base_marker + b" " + name_base merge_regions = self.merge_regions() if minimize: merge_regions = self.minimize(merge_regions) for t in merge_regions: what = t[0] - if what == "unchanged": + if what == b"unchanged": for i in range(t[1], t[2]): yield self.base[i] - elif what == "a" or what == "same": + elif what == b"a" or what == b"same": for i in range(t[1], t[2]): yield self.a[i] - elif what == "b": + elif what == b"b": for i in range(t[1], t[2]): yield self.b[i] - elif what == "conflict": - if localorother == "local": + elif what == b"conflict": + if localorother == b"local": for i in range(t[3], t[4]): yield self.a[i] - elif localorother == "other": + elif localorother == b"other": for i in range(t[5], t[6]): yield self.b[i] else: @@ -175,13 +175,13 @@ """ for t in self.merge_regions(): what = t[0] - if what == "unchanged": + if what == b"unchanged": yield what, self.base[t[1] : t[2]] - elif what == "a" or what == "same": + elif what == b"a" or what == b"same": yield what, self.a[t[1] : t[2]] - elif what == "b": + elif what == b"b": yield what, self.b[t[1] : t[2]] - elif what == "conflict": + elif what == b"conflict": yield ( what, self.base[t[1] : t[2]], @@ -253,15 +253,15 @@ same = compare_range(self.a, ia, amatch, self.b, ib, bmatch) if same: - yield "same", ia, amatch + yield b"same", ia, amatch elif equal_a and not equal_b: - yield "b", ib, bmatch + yield b"b", ib, bmatch elif equal_b and not equal_a: - yield "a", ia, amatch + yield b"a", ia, amatch elif not equal_a and not equal_b: - yield "conflict", iz, zmatch, ia, amatch, ib, bmatch + yield b"conflict", iz, zmatch, ia, amatch, ib, bmatch else: - raise AssertionError("can't handle a=b=base but unmatched") + raise AssertionError(b"can't handle a=b=base but unmatched") ia = amatch ib = bmatch @@ -275,7 +275,7 @@ assert ib == bmatch assert iz == zmatch - yield "unchanged", zmatch, zend + yield b"unchanged", zmatch, zend iz = zend ia = aend ib = bend @@ -288,7 +288,7 @@ region and are instead considered the same. """ for region in merge_regions: - if region[0] != "conflict": + if region[0] != b"conflict": yield region continue issue, z1, z2, a1, a2, b1, b2 = region @@ -314,10 +314,10 @@ endmatches = ii if startmatches > 0: - yield "same", a1, a1 + startmatches + yield b"same", a1, a1 + startmatches yield ( - "conflict", + b"conflict", z1, z2, a1 + startmatches, @@ -327,7 +327,7 @@ ) if endmatches > 0: - yield "same", a2 - endmatches, a2 + yield b"same", a2 - endmatches, a2 def find_sync_regions(self): """Return a list of sync regions, where both descendants match the base. @@ -420,17 +420,17 @@ """verifies that text is non-binary (unless opts[text] is passed, then we just warn)""" if stringutil.binary(text): - msg = _("%s looks like a binary file.") % path - if not opts.get("quiet"): - ui.warn(_("warning: %s\n") % msg) - if not opts.get("text"): + msg = _(b"%s looks like a binary file.") % path + if not opts.get(b"quiet"): + ui.warn(_(b"warning: %s\n") % msg) + if not opts.get(b"text"): raise error.Abort(msg) return text def _picklabels(defaults, overrides): if len(overrides) > 3: - raise error.Abort(_("can only specify three labels.")) + raise error.Abort(_(b"can only specify three labels.")) result = defaults[:] for i, override in enumerate(overrides): result[i] = override @@ -454,11 +454,11 @@ # repository usually sees) might be more useful. return _verifytext(ctx.decodeddata(), ctx.path(), ui, opts) - mode = opts.get("mode", "merge") + mode = opts.get(b"mode", b"merge") name_a, name_b, name_base = None, None, None - if mode != "union": + if mode != b"union": name_a, name_b, name_base = _picklabels( - [localctx.path(), otherctx.path(), None], opts.get("label", []) + [localctx.path(), otherctx.path(), None], opts.get(b"label", []) ) try: @@ -470,29 +470,29 @@ m3 = Merge3Text(basetext, localtext, othertext) extrakwargs = { - "localorother": opts.get("localorother", None), - "minimize": True, + b"localorother": opts.get(b"localorother", None), + b"minimize": True, } - if mode == "union": - extrakwargs["start_marker"] = None - extrakwargs["mid_marker"] = None - extrakwargs["end_marker"] = None + if mode == b"union": + extrakwargs[b"start_marker"] = None + extrakwargs[b"mid_marker"] = None + extrakwargs[b"end_marker"] = None elif name_base is not None: - extrakwargs["base_marker"] = "|||||||" - extrakwargs["name_base"] = name_base - extrakwargs["minimize"] = False + extrakwargs[b"base_marker"] = b"|||||||" + extrakwargs[b"name_base"] = name_base + extrakwargs[b"minimize"] = False - mergedtext = "" + mergedtext = b"" for line in m3.merge_lines( name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs) ): - if opts.get("print"): + if opts.get(b"print"): ui.fout.write(line) else: mergedtext += line - if not opts.get("print"): + if not opts.get(b"print"): localctx.write(mergedtext, localctx.flags()) - if m3.conflicts and not mode == "union": + if m3.conflicts and not mode == b"union": return 1 diff --git a/mercurial/smartset.py b/mercurial/smartset.py --- a/mercurial/smartset.py +++ b/mercurial/smartset.py @@ -17,7 +17,7 @@ def _typename(o): - return pycompat.sysbytes(type(o).__name__).lstrip("_") + return pycompat.sysbytes(type(o).__name__).lstrip(b"_") class abstractsmartset(object): @@ -63,7 +63,7 @@ for v in self.fastasc(): break else: - raise ValueError("arg is an empty sequence") + raise ValueError(b"arg is an empty sequence") self.min = lambda: v return v @@ -75,7 +75,7 @@ for v in self.fastdesc(): break else: - raise ValueError("arg is an empty sequence") + raise ValueError(b"arg is an empty sequence") self.max = lambda: v return v @@ -125,7 +125,7 @@ This is part of the mandatory API for smartset.""" c = other.__contains__ return self.filter( - lambda r: not c(r), condrepr=("", other), cache=False + lambda r: not c(r), condrepr=(b"", other), cache=False ) def filter(self, condition, condrepr=None, cache=True): @@ -137,14 +137,14 @@ This is part of the mandatory API for smartset.""" # builtin cannot be cached. but do not needs to - if cache and util.safehasattr(condition, "__code__"): + if cache and util.safehasattr(condition, b"__code__"): condition = util.cachefunc(condition) return filteredset(self, condition, condrepr) def slice(self, start, stop): """Return new smartset that contains selected elements from this set""" if start < 0 or stop < 0: - raise error.ProgrammingError("negative index not allowed") + raise error.ProgrammingError(b"negative index not allowed") return self._slice(start, stop) def _slice(self, start, stop): @@ -161,7 +161,7 @@ if y is None: break ys.append(y) - return baseset(ys, datarepr=("slice=%d:%d %r", start, stop, self)) + return baseset(ys, datarepr=(b"slice=%d:%d %r", start, stop, self)) class baseset(abstractsmartset): @@ -359,10 +359,10 @@ return s def __and__(self, other): - return self._fastsetop(other, "__and__") + return self._fastsetop(other, b"__and__") def __sub__(self, other): - return self._fastsetop(other, "__sub__") + return self._fastsetop(other, b"__sub__") def _slice(self, start, stop): # creating new list should be generally cheaper than iterating items @@ -378,7 +378,7 @@ @encoding.strmethod def __repr__(self): - d = {None: "", False: "-", True: "+"}[self._ascending] + d = {None: b"", False: b"-", True: b"+"}[self._ascending] s = stringutil.buildrepr(self._datarepr) if not s: l = self._list @@ -388,7 +388,7 @@ if self._ascending is not None: l = self._asclist s = pycompat.byterepr(l) - return "<%s%s %s>" % (_typename(self), d, s) + return b"<%s%s %s>" % (_typename(self), d, s) class filteredset(abstractsmartset): @@ -508,7 +508,7 @@ s = stringutil.buildrepr(self._condrepr) if s: xs.append(s) - return "<%s %s>" % (_typename(self), ", ".join(xs)) + return b"<%s %s>" % (_typename(self), b", ".join(xs)) def _iterordered(ascending, iter1, iter2): @@ -668,9 +668,9 @@ # try to use our own fast iterator if it exists self._trysetasclist() if self._ascending: - attr = "fastasc" + attr = b"fastasc" else: - attr = "fastdesc" + attr = b"fastdesc" it = getattr(self, attr) if it is not None: return it() @@ -760,8 +760,8 @@ @encoding.strmethod def __repr__(self): - d = {None: "", False: "-", True: "+"}[self._ascending] - return "<%s%s %r, %r>" % (_typename(self), d, self._r1, self._r2) + d = {None: b"", False: b"-", True: b"+"}[self._ascending] + return b"<%s%s %r, %r>" % (_typename(self), d, self._r1, self._r2) class generatorset(abstractsmartset): @@ -928,8 +928,8 @@ @encoding.strmethod def __repr__(self): - d = {False: "-", True: "+"}[self._ascending] - return "<%s%s>" % (_typename(self), d) + d = {False: b"-", True: b"+"}[self._ascending] + return b"<%s%s>" % (_typename(self), d) class _generatorsetasc(generatorset): @@ -1104,8 +1104,8 @@ @encoding.strmethod def __repr__(self): - d = {False: "-", True: "+"}[self._ascending] - return "<%s%s %d:%d>" % (_typename(self), d, self._start, self._end) + d = {False: b"-", True: b"+"}[self._ascending] + return b"<%s%s %d:%d>" % (_typename(self), d, self._start, self._end) class fullreposet(_spanset): @@ -1127,7 +1127,7 @@ This boldly assumes the other contains valid revs only. """ # other not a smartset, make is so - if not util.safehasattr(other, "isascending"): + if not util.safehasattr(other, b"isascending"): # filter out hidden revision # (this boldly assumes all smartset are pure) # diff --git a/mercurial/sparse.py b/mercurial/sparse.py --- a/mercurial/sparse.py +++ b/mercurial/sparse.py @@ -44,49 +44,52 @@ current = None havesection = False - for line in raw.split("\n"): + for line in raw.split(b"\n"): line = line.strip() - if not line or line.startswith("#"): + if not line or line.startswith(b"#"): # empty or comment line, skip continue - elif line.startswith("%include "): + elif line.startswith(b"%include "): line = line[9:].strip() if line: profiles.add(line) - elif line == "[include]": + elif line == b"[include]": if havesection and current != includes: # TODO pass filename into this API so we can report it. raise error.Abort( _( - "%(action)s config cannot have includes " - "after excludes" + b"%(action)s config cannot have includes " + b"after excludes" ) - % {"action": action} + % {b"action": action} ) havesection = True current = includes continue - elif line == "[exclude]": + elif line == b"[exclude]": havesection = True current = excludes elif line: if current is None: raise error.Abort( - _("%(action)s config entry outside of " "section: %(line)s") - % {"action": action, "line": line}, + _( + b"%(action)s config entry outside of " + b"section: %(line)s" + ) + % {b"action": action, b"line": line}, hint=_( - "add an [include] or [exclude] line " - "to declare the entry type" + b"add an [include] or [exclude] line " + b"to declare the entry type" ), ) - if line.strip().startswith("/"): + if line.strip().startswith(b"/"): ui.warn( _( - "warning: %(action)s profile cannot use" - " paths starting with /, ignoring %(line)s\n" + b"warning: %(action)s profile cannot use" + b" paths starting with /, ignoring %(line)s\n" ) - % {"action": action, "line": line} + % {b"action": action, b"line": line} ) continue current.add(line) @@ -112,16 +115,16 @@ if not enabled: return set(), set(), set() - raw = repo.vfs.tryread("sparse") + raw = repo.vfs.tryread(b"sparse") if not raw: return set(), set(), set() if rev is None: raise error.Abort( - _("cannot parse sparse patterns from working " "directory") + _(b"cannot parse sparse patterns from working " b"directory") ) - includes, excludes, profiles = parseconfig(repo.ui, raw, "sparse") + includes, excludes, profiles = parseconfig(repo.ui, raw, b"sparse") ctx = repo[rev] if profiles: @@ -137,17 +140,19 @@ raw = readprofile(repo, profile, rev) except error.ManifestLookupError: msg = ( - "warning: sparse profile '%s' not found " - "in rev %s - ignoring it\n" % (profile, ctx) + b"warning: sparse profile '%s' not found " + b"in rev %s - ignoring it\n" % (profile, ctx) ) # experimental config: sparse.missingwarning - if repo.ui.configbool("sparse", "missingwarning"): + if repo.ui.configbool(b"sparse", b"missingwarning"): repo.ui.warn(msg) else: repo.ui.debug(msg) continue - pincludes, pexcludes, subprofs = parseconfig(repo.ui, raw, "sparse") + pincludes, pexcludes, subprofs = parseconfig( + repo.ui, raw, b"sparse" + ) includes.update(pincludes) excludes.update(pexcludes) profiles.update(subprofs) @@ -155,7 +160,7 @@ profiles = visited if includes: - includes.add(".hg*") + includes.add(b".hg*") return includes, excludes, profiles @@ -192,56 +197,56 @@ """ cache = repo._sparsesignaturecache - signature = cache.get("signature") + signature = cache.get(b"signature") if includetemp: - tempsignature = cache.get("tempsignature") + tempsignature = cache.get(b"tempsignature") else: - tempsignature = "0" + tempsignature = b"0" if signature is None or (includetemp and tempsignature is None): - signature = hex(hashlib.sha1(repo.vfs.tryread("sparse")).digest()) - cache["signature"] = signature + signature = hex(hashlib.sha1(repo.vfs.tryread(b"sparse")).digest()) + cache[b"signature"] = signature if includetemp: - raw = repo.vfs.tryread("tempsparse") + raw = repo.vfs.tryread(b"tempsparse") tempsignature = hex(hashlib.sha1(raw).digest()) - cache["tempsignature"] = tempsignature + cache[b"tempsignature"] = tempsignature - return "%s %s" % (signature, tempsignature) + return b"%s %s" % (signature, tempsignature) def writeconfig(repo, includes, excludes, profiles): """Write the sparse config file given a sparse configuration.""" - with repo.vfs("sparse", "wb") as fh: + with repo.vfs(b"sparse", b"wb") as fh: for p in sorted(profiles): - fh.write("%%include %s\n" % p) + fh.write(b"%%include %s\n" % p) if includes: - fh.write("[include]\n") + fh.write(b"[include]\n") for i in sorted(includes): fh.write(i) - fh.write("\n") + fh.write(b"\n") if excludes: - fh.write("[exclude]\n") + fh.write(b"[exclude]\n") for e in sorted(excludes): fh.write(e) - fh.write("\n") + fh.write(b"\n") repo._sparsesignaturecache.clear() def readtemporaryincludes(repo): - raw = repo.vfs.tryread("tempsparse") + raw = repo.vfs.tryread(b"tempsparse") if not raw: return set() - return set(raw.split("\n")) + return set(raw.split(b"\n")) def writetemporaryincludes(repo, includes): - repo.vfs.write("tempsparse", "\n".join(sorted(includes))) + repo.vfs.write(b"tempsparse", b"\n".join(sorted(includes))) repo._sparsesignaturecache.clear() @@ -253,7 +258,7 @@ def prunetemporaryincludes(repo): - if not enabled or not repo.vfs.exists("tempsparse"): + if not enabled or not repo.vfs.exists(b"tempsparse"): return s = repo.status() @@ -268,24 +273,25 @@ tempincludes = readtemporaryincludes(repo) for file in tempincludes: if file in dirstate and not sparsematch(file): - message = _("dropping temporarily included sparse files") + message = _(b"dropping temporarily included sparse files") actions.append((file, None, message)) dropped.append(file) typeactions = mergemod.emptyactions() - typeactions["r"] = actions + typeactions[b"r"] = actions mergemod.applyupdates( - repo, typeactions, repo[None], repo["."], False, wantfiledata=False + repo, typeactions, repo[None], repo[b"."], False, wantfiledata=False ) # Fix dirstate for file in dropped: dirstate.drop(file) - repo.vfs.unlink("tempsparse") + repo.vfs.unlink(b"tempsparse") repo._sparsesignaturecache.clear() msg = _( - "cleaned up %d temporarily added file(s) from the " "sparse checkout\n" + b"cleaned up %d temporarily added file(s) from the " + b"sparse checkout\n" ) repo.ui.status(msg % len(tempincludes)) @@ -293,8 +299,8 @@ def forceincludematcher(matcher, includes): """Returns a matcher that returns true for any of the forced includes before testing against the actual matcher.""" - kindpats = [("path", include, "") for include in includes] - includematcher = matchmod.includematcher("", kindpats) + kindpats = [(b"path", include, b"") for include in includes] + includematcher = matchmod.includematcher(b"", kindpats) return matchmod.unionmatcher([includematcher, matcher]) @@ -319,7 +325,7 @@ signature = configsignature(repo, includetemp=includetemp) - key = "%s %s" % (signature, " ".join(map(pycompat.bytestr, revs))) + key = b"%s %s" % (signature, b" ".join(map(pycompat.bytestr, revs))) result = repo._sparsematchercache.get(key) if result: @@ -333,11 +339,11 @@ if includes or excludes: matcher = matchmod.match( repo.root, - "", + b"", [], include=includes, exclude=excludes, - default="relpath", + default=b"relpath", ) matchers.append(matcher) except IOError: @@ -388,17 +394,17 @@ files.add(file) if sparsematch(file): prunedactions[file] = action - elif type == "m": + elif type == b"m": temporaryfiles.append(file) prunedactions[file] = action elif branchmerge: - if type != "k": + if type != b"k": temporaryfiles.append(file) prunedactions[file] = action - elif type == "f": + elif type == b"f": prunedactions[file] = action elif file in wctx: - prunedactions[file] = ("r", args, msg) + prunedactions[file] = (b"r", args, msg) if branchmerge and type == mergemod.ACTION_MERGE: f1, f2, fa, move, anc = args @@ -408,8 +414,8 @@ if len(temporaryfiles) > 0: repo.ui.status( _( - "temporarily included %d file(s) in the sparse " - "checkout for merging\n" + b"temporarily included %d file(s) in the sparse " + b"checkout for merging\n" ) % len(temporaryfiles) ) @@ -417,7 +423,7 @@ # Add the new files to the working copy so they can be merged, etc actions = [] - message = "temporarily adding to sparse checkout" + message = b"temporarily adding to sparse checkout" wctxmanifest = repo[None].manifest() for file in temporaryfiles: if file in wctxmanifest: @@ -425,9 +431,9 @@ actions.append((file, (fctx.flags(), False), message)) typeactions = mergemod.emptyactions() - typeactions["g"] = actions + typeactions[b"g"] = actions mergemod.applyupdates( - repo, typeactions, repo[None], repo["."], False, wantfiledata=False + repo, typeactions, repo[None], repo[b"."], False, wantfiledata=False ) dirstate = repo.dirstate @@ -446,9 +452,9 @@ new = sparsematch(file) if not old and new: flags = mf.flags(file) - prunedactions[file] = ("g", (flags, False), "") + prunedactions[file] = (b"g", (flags, False), b"") elif old and not new: - prunedactions[file] = ("r", [], "") + prunedactions[file] = (b"r", [], b"") return prunedactions @@ -472,17 +478,17 @@ for f in pending: if not sparsematch(f): - repo.ui.warn(_("pending changes to '%s'\n") % f) + repo.ui.warn(_(b"pending changes to '%s'\n") % f) abort = not force if abort: raise error.Abort( - _("could not update sparseness due to pending " "changes") + _(b"could not update sparseness due to pending " b"changes") ) # Calculate actions dirstate = repo.dirstate - ctx = repo["."] + ctx = repo[b"."] added = [] lookup = [] dropped = [] @@ -499,29 +505,29 @@ if (new and not old) or (old and new and not file in dirstate): fl = mf.flags(file) if repo.wvfs.exists(file): - actions[file] = ("e", (fl,), "") + actions[file] = (b"e", (fl,), b"") lookup.append(file) else: - actions[file] = ("g", (fl, False), "") + actions[file] = (b"g", (fl, False), b"") added.append(file) # Drop files that are newly excluded, or that still exist in # the dirstate. elif (old and not new) or (not old and not new and file in dirstate): dropped.append(file) if file not in pending: - actions[file] = ("r", [], "") + actions[file] = (b"r", [], b"") # Verify there are no pending changes in newly included files abort = False for file in lookup: - repo.ui.warn(_("pending changes to '%s'\n") % file) + repo.ui.warn(_(b"pending changes to '%s'\n") % file) abort = not force if abort: raise error.Abort( _( - "cannot change sparseness due to pending " - "changes (delete the files or use " - "--force to bring them back dirty)" + b"cannot change sparseness due to pending " + b"changes (delete the files or use " + b"--force to bring them back dirty)" ) ) @@ -539,7 +545,7 @@ typeactions[m].append((f, args, msg)) mergemod.applyupdates( - repo, typeactions, repo[None], repo["."], False, wantfiledata=False + repo, typeactions, repo[None], repo[b"."], False, wantfiledata=False ) # Fix dirstate @@ -577,8 +583,8 @@ repo, includes, excludes, profiles, force=False, removing=False ): """Update the sparse config and working directory state.""" - raw = repo.vfs.tryread("sparse") - oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, "sparse") + raw = repo.vfs.tryread(b"sparse") + oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, b"sparse") oldstatus = repo.status() oldmatch = matcher(repo) @@ -592,11 +598,11 @@ # updated. But this requires massive rework to matcher() and its # consumers. - if "exp-sparse" in oldrequires and removing: - repo.requirements.discard("exp-sparse") + if b"exp-sparse" in oldrequires and removing: + repo.requirements.discard(b"exp-sparse") scmutil.writerequires(repo.vfs, repo.requirements) - elif "exp-sparse" not in oldrequires: - repo.requirements.add("exp-sparse") + elif b"exp-sparse" not in oldrequires: + repo.requirements.add(b"exp-sparse") scmutil.writerequires(repo.vfs, repo.requirements) try: @@ -618,8 +624,8 @@ directory is refreshed, as needed. """ with repo.wlock(): - raw = repo.vfs.tryread("sparse") - includes, excludes, profiles = parseconfig(repo.ui, raw, "sparse") + raw = repo.vfs.tryread(b"sparse") + includes, excludes, profiles = parseconfig(repo.ui, raw, b"sparse") if not includes and not excludes: return @@ -635,19 +641,19 @@ """ with repo.wlock(): # read current configuration - raw = repo.vfs.tryread("sparse") - includes, excludes, profiles = parseconfig(repo.ui, raw, "sparse") + raw = repo.vfs.tryread(b"sparse") + includes, excludes, profiles = parseconfig(repo.ui, raw, b"sparse") aincludes, aexcludes, aprofiles = activeconfig(repo) # Import rules on top; only take in rules that are not yet # part of the active rules. changed = False for p in paths: - with util.posixfile(util.expandpath(p), mode="rb") as fh: + with util.posixfile(util.expandpath(p), mode=b"rb") as fh: raw = fh.read() iincludes, iexcludes, iprofiles = parseconfig( - repo.ui, raw, "sparse" + repo.ui, raw, b"sparse" ) oldsize = len(includes) + len(excludes) + len(profiles) includes.update(iincludes - aincludes) @@ -696,9 +702,9 @@ The new config is written out and a working directory refresh is performed. """ with repo.wlock(): - raw = repo.vfs.tryread("sparse") + raw = repo.vfs.tryread(b"sparse") oldinclude, oldexclude, oldprofiles = parseconfig( - repo.ui, raw, "sparse" + repo.ui, raw, b"sparse" ) if reset: @@ -711,7 +717,7 @@ newprofiles = set(oldprofiles) if any(os.path.isabs(pat) for pat in pats): - raise error.Abort(_("paths cannot be absolute")) + raise error.Abort(_(b"paths cannot be absolute")) if not usereporootpaths: # let's treat paths as relative to cwd @@ -720,7 +726,7 @@ for kindpat in pats: kind, pat = matchmod._patsplit(kindpat, None) if kind in matchmod.cwdrelativepatternkinds or kind is None: - ap = (kind + ":" if kind else "") + pathutil.canonpath( + ap = (kind + b":" if kind else b"") + pathutil.canonpath( root, cwd, pat ) abspats.append(ap) @@ -778,24 +784,24 @@ conflicting=0, ): """Print output summarizing sparse config changes.""" - with ui.formatter("sparse", opts) as fm: + with ui.formatter(b"sparse", opts) as fm: fm.startitem() fm.condwrite( ui.verbose, - "profiles_added", - _("Profiles changed: %d\n"), + b"profiles_added", + _(b"Profiles changed: %d\n"), profilecount, ) fm.condwrite( ui.verbose, - "include_rules_added", - _("Include rules changed: %d\n"), + b"include_rules_added", + _(b"Include rules changed: %d\n"), includecount, ) fm.condwrite( ui.verbose, - "exclude_rules_added", - _("Exclude rules changed: %d\n"), + b"exclude_rules_added", + _(b"Exclude rules changed: %d\n"), excludecount, ) @@ -804,14 +810,14 @@ # framework. No point in repeating ourselves in that case. if not fm.isplain(): fm.condwrite( - ui.verbose, "files_added", _("Files added: %d\n"), added + ui.verbose, b"files_added", _(b"Files added: %d\n"), added ) fm.condwrite( - ui.verbose, "files_dropped", _("Files dropped: %d\n"), dropped + ui.verbose, b"files_dropped", _(b"Files dropped: %d\n"), dropped ) fm.condwrite( ui.verbose, - "files_conflicting", - _("Files conflicting: %d\n"), + b"files_conflicting", + _(b"Files conflicting: %d\n"), conflicting, ) diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -30,9 +30,9 @@ """quote a string for the remote shell ... which we assume is sh""" if not s: return s - if re.match("[a-zA-Z0-9@%_+=:,./-]*$", s): + if re.match(b"[a-zA-Z0-9@%_+=:,./-]*$", s): return s - return "'%s'" % s.replace("'", "'\\''") + return b"'%s'" % s.replace(b"'", b"'\\''") def _forwardoutput(ui, pipe): @@ -43,7 +43,7 @@ s = procutil.readpipe(pipe) if s: for l in s.splitlines(): - ui.status(_("remote: "), l, "\n") + ui.status(_(b"remote: "), l, b"\n") class doublepipe(object): @@ -91,10 +91,10 @@ return (self._main.fileno() in act, self._side.fileno() in act) def write(self, data): - return self._call("write", data) + return self._call(b"write", data) def read(self, size): - r = self._call("read", size) + r = self._call(b"read", size) if size != 0 and not r: # We've observed a condition that indicates the # stdout closed unexpectedly. Check stderr one @@ -105,7 +105,7 @@ return r def unbufferedread(self, size): - r = self._call("unbufferedread", size) + r = self._call(b"unbufferedread", size) if size != 0 and not r: # We've observed a condition that indicates the # stdout closed unexpectedly. Check stderr one @@ -116,7 +116,7 @@ return r def readline(self): - return self._call("readline") + return self._call(b"readline") def _call(self, methname, data=None): """call on "main", forward output of "side" while blocking @@ -124,7 +124,7 @@ # data can be '' or 0 if (data is not None and not data) or self._main.closed: _forwardoutput(self._ui, self._side) - return "" + return b"" while True: mainready, sideready = self._wait() if sideready: @@ -154,7 +154,7 @@ # Try to read from the err descriptor until EOF. try: for l in pipee: - ui.status(_("remote: "), l) + ui.status(_(b"remote: "), l) except (IOError, ValueError): pass @@ -167,16 +167,16 @@ Returns a tuple of (process, stdin, stdout, stderr) for the spawned process. """ - cmd = "%s %s %s" % ( + cmd = b"%s %s %s" % ( sshcmd, args, procutil.shellquote( - "%s -R %s serve --stdio" + b"%s -R %s serve --stdio" % (_serverquote(remotecmd), _serverquote(path)) ), ) - ui.debug("running %s\n" % cmd) + ui.debug(b"running %s\n" % cmd) cmd = procutil.quotecommand(cmd) # no buffer allow the use of 'select' @@ -192,12 +192,12 @@ Returns a list of capabilities that are supported by this client. """ - protoparams = {"partial-pull"} + protoparams = {b"partial-pull"} comps = [ e.wireprotosupport().name for e in util.compengines.supportedwireengines(util.CLIENTROLE) ] - protoparams.add("comp=%s" % ",".join(comps)) + protoparams.add(b"comp=%s" % b",".join(comps)) return protoparams @@ -206,8 +206,8 @@ # Flush any output on stderr. _forwardoutput(ui, stderr) - msg = _("no suitable response from remote hg") - hint = ui.config("ui", "ssherrorhint") + msg = _(b"no suitable response from remote hg") + hint = ui.config(b"ui", b"ssherrorhint") raise error.RepoError(msg, hint=hint) # The handshake consists of sending wire protocol commands in reverse @@ -262,37 +262,37 @@ # for output to our well-known ``between`` command. Of course, if # the banner contains ``1\n\n``, this will throw off our detection. - requestlog = ui.configbool("devel", "debug.peer-request") + requestlog = ui.configbool(b"devel", b"debug.peer-request") # Generate a random token to help identify responses to version 2 # upgrade request. token = pycompat.sysbytes(str(uuid.uuid4())) upgradecaps = [ - ("proto", wireprotoserver.SSHV2), + (b"proto", wireprotoserver.SSHV2), ] upgradecaps = util.urlreq.urlencode(upgradecaps) try: - pairsarg = "%s-%s" % ("0" * 40, "0" * 40) + pairsarg = b"%s-%s" % (b"0" * 40, b"0" * 40) handshake = [ - "hello\n", - "between\n", - "pairs %d\n" % len(pairsarg), + b"hello\n", + b"between\n", + b"pairs %d\n" % len(pairsarg), pairsarg, ] # Request upgrade to version 2 if configured. - if ui.configbool("experimental", "sshpeer.advertise-v2"): - ui.debug("sending upgrade request: %s %s\n" % (token, upgradecaps)) - handshake.insert(0, "upgrade %s %s\n" % (token, upgradecaps)) + if ui.configbool(b"experimental", b"sshpeer.advertise-v2"): + ui.debug(b"sending upgrade request: %s %s\n" % (token, upgradecaps)) + handshake.insert(0, b"upgrade %s %s\n" % (token, upgradecaps)) if requestlog: - ui.debug("devel-peer-request: hello+between\n") - ui.debug("devel-peer-request: pairs: %d bytes\n" % len(pairsarg)) - ui.debug("sending hello command\n") - ui.debug("sending between command\n") + ui.debug(b"devel-peer-request: hello+between\n") + ui.debug(b"devel-peer-request: pairs: %d bytes\n" % len(pairsarg)) + ui.debug(b"sending hello command\n") + ui.debug(b"sending between command\n") - stdin.write("".join(handshake)) + stdin.write(b"".join(handshake)) stdin.flush() except IOError: badresponse() @@ -301,7 +301,7 @@ protoname = wireprototypes.SSHV1 reupgraded = re.compile(b"^upgraded %s (.*)$" % stringutil.reescape(token)) - lines = ["", "dummy"] + lines = [b"", b"dummy"] max_noise = 500 while lines[-1] and max_noise: try: @@ -313,7 +313,7 @@ m = reupgraded.match(l) if m: protoname = m.group(1) - ui.debug("protocol upgraded to %s\n" % protoname) + ui.debug(b"protocol upgraded to %s\n" % protoname) # If an upgrade was handled, the ``hello`` and ``between`` # requests are ignored. The next output belongs to the # protocol, so stop scanning lines. @@ -322,10 +322,10 @@ # Otherwise it could be a banner, ``0\n`` response if server # doesn't support upgrade. - if lines[-1] == "1\n" and l == "\n": + if lines[-1] == b"1\n" and l == b"\n": break if l: - ui.debug("remote: ", l) + ui.debug(b"remote: ", l) lines.append(l) max_noise -= 1 except IOError: @@ -341,8 +341,8 @@ for l in reversed(lines): # Look for response to ``hello`` command. Scan from the back so # we don't misinterpret banner output as the command reply. - if l.startswith("capabilities:"): - caps.update(l[:-1].split(":")[1].split()) + if l.startswith(b"capabilities:"): + caps.update(l[:-1].split(b":")[1].split()) break elif protoname == wireprotoserver.SSHV2: # We see a line with number of bytes to follow and then a value @@ -354,12 +354,12 @@ badresponse() capsline = stdout.read(valuelen) - if not capsline.startswith("capabilities: "): + if not capsline.startswith(b"capabilities: "): badresponse() - ui.debug("remote: %s\n" % capsline) + ui.debug(b"remote: %s\n" % capsline) - caps.update(capsline.split(":")[1].split()) + caps.update(capsline.split(b":")[1].split()) # Trailing newline. stdout.read(1) @@ -412,7 +412,7 @@ # Commands that have a "framed" response where the first line of the # response contains the length of that response. _FRAMED_COMMANDS = { - "batch", + b"batch", } # Begin of ipeerconnection interface. @@ -455,34 +455,34 @@ def _sendrequest(self, cmd, args, framed=False): if self.ui.debugflag and self.ui.configbool( - "devel", "debug.peer-request" + b"devel", b"debug.peer-request" ): dbg = self.ui.debug - line = "devel-peer-request: %s\n" + line = b"devel-peer-request: %s\n" dbg(line % cmd) for key, value in sorted(args.items()): if not isinstance(value, dict): - dbg(line % " %s: %d bytes" % (key, len(value))) + dbg(line % b" %s: %d bytes" % (key, len(value))) else: for dk, dv in sorted(value.items()): - dbg(line % " %s-%s: %d" % (key, dk, len(dv))) - self.ui.debug("sending %s command\n" % cmd) - self._pipeo.write("%s\n" % cmd) + dbg(line % b" %s-%s: %d" % (key, dk, len(dv))) + self.ui.debug(b"sending %s command\n" % cmd) + self._pipeo.write(b"%s\n" % cmd) _func, names = wireprotov1server.commands[cmd] keys = names.split() wireargs = {} for k in keys: - if k == "*": - wireargs["*"] = args + if k == b"*": + wireargs[b"*"] = args break else: wireargs[k] = args[k] del args[k] for k, v in sorted(wireargs.iteritems()): - self._pipeo.write("%s %d\n" % (k, len(v))) + self._pipeo.write(b"%s %d\n" % (k, len(v))) if isinstance(v, dict): for dk, dv in v.iteritems(): - self._pipeo.write("%s %d\n" % (dk, len(dv))) + self._pipeo.write(b"%s %d\n" % (dk, len(dv))) self._pipeo.write(dv) else: self._pipeo.write(v) @@ -515,21 +515,21 @@ # continue submitting the payload. r = self._call(cmd, **args) if r: - return "", r + return b"", r # The payload consists of frames with content followed by an empty # frame. - for d in iter(lambda: fp.read(4096), ""): + for d in iter(lambda: fp.read(4096), b""): self._writeframed(d) - self._writeframed("", flush=True) + self._writeframed(b"", flush=True) # In case of success, there is an empty frame and a frame containing # the integer result (as a string). # In case of error, there is a non-empty frame containing the error. r = self._readframed() if r: - return "", r - return self._readframed(), "" + return b"", r + return self._readframed(), b"" def _calltwowaystream(self, cmd, fp, **args): # The server responds with an empty frame if the client should @@ -537,29 +537,29 @@ r = self._call(cmd, **args) if r: # XXX needs to be made better - raise error.Abort(_("unexpected remote reply: %s") % r) + raise error.Abort(_(b"unexpected remote reply: %s") % r) # The payload consists of frames with content followed by an empty # frame. - for d in iter(lambda: fp.read(4096), ""): + for d in iter(lambda: fp.read(4096), b""): self._writeframed(d) - self._writeframed("", flush=True) + self._writeframed(b"", flush=True) return self._pipei def _getamount(self): l = self._pipei.readline() - if l == "\n": + if l == b"\n": if self._autoreadstderr: self._readerr() - msg = _("check previous remote output") + msg = _(b"check previous remote output") self._abort(error.OutOfBandError(hint=msg)) if self._autoreadstderr: self._readerr() try: return int(l) except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), l)) + self._abort(error.ResponseError(_(b"unexpected response:"), l)) def _readframed(self): size = self._getamount() @@ -569,7 +569,7 @@ return self._pipei.read(size) def _writeframed(self, data, flush=False): - self._pipeo.write("%d\n" % len(data)) + self._pipeo.write(b"%d\n" % len(data)) if data: self._pipeo.write(data) if flush: @@ -631,7 +631,7 @@ else: _cleanuppipes(ui, stdout, stdin, stderr) raise error.RepoError( - _("unknown version of SSH protocol: %s") % protoname + _(b"unknown version of SSH protocol: %s") % protoname ) @@ -641,19 +641,19 @@ The returned object conforms to the ``wireprotov1peer.wirepeer`` interface. """ u = util.url(path, parsequery=False, parsefragment=False) - if u.scheme != "ssh" or not u.host or u.path is None: - raise error.RepoError(_("couldn't parse location %s") % path) + if u.scheme != b"ssh" or not u.host or u.path is None: + raise error.RepoError(_(b"couldn't parse location %s") % path) util.checksafessh(path) if u.passwd is not None: - raise error.RepoError(_("password in URL not supported")) + raise error.RepoError(_(b"password in URL not supported")) - sshcmd = ui.config("ui", "ssh") - remotecmd = ui.config("ui", "remotecmd") - sshaddenv = dict(ui.configitems("sshenv")) + sshcmd = ui.config(b"ui", b"ssh") + remotecmd = ui.config(b"ui", b"remotecmd") + sshaddenv = dict(ui.configitems(b"sshenv")) sshenv = procutil.shellenviron(sshaddenv) - remotepath = u.path or "." + remotepath = u.path or b"." args = procutil.sshargs(sshcmd, u.host, u.user, u.port) @@ -664,21 +664,24 @@ # supports said requested feature. if createopts: raise error.RepoError( - _("cannot create remote SSH repositories " "with extra options") + _( + b"cannot create remote SSH repositories " + b"with extra options" + ) ) - cmd = "%s %s %s" % ( + cmd = b"%s %s %s" % ( sshcmd, args, procutil.shellquote( - "%s init %s" + b"%s init %s" % (_serverquote(remotecmd), _serverquote(remotepath)) ), ) - ui.debug("running %s\n" % cmd) - res = ui.system(cmd, blockedtag="sshpeer", environ=sshenv) + ui.debug(b"running %s\n" % cmd) + res = ui.system(cmd, blockedtag=b"sshpeer", environ=sshenv) if res != 0: - raise error.RepoError(_("could not create remote repo")) + raise error.RepoError(_(b"could not create remote repo")) proc, stdin, stdout, stderr = _makeconnection( ui, sshcmd, args, remotecmd, remotepath, sshenv @@ -688,13 +691,13 @@ # Finally, if supported by the server, notify it about our own # capabilities. - if "protocaps" in peer.capabilities(): + if b"protocaps" in peer.capabilities(): try: peer._call( - "protocaps", caps=" ".join(sorted(_clientcapabilities())) + b"protocaps", caps=b" ".join(sorted(_clientcapabilities())) ) except IOError: peer._cleanup() - raise error.RepoError(_("capability exchange failed")) + raise error.RepoError(_(b"capability exchange failed")) return peer diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py --- a/mercurial/sslutil.py +++ b/mercurial/sslutil.py @@ -36,27 +36,27 @@ # separate code paths depending on support in Python. configprotocols = { - "tls1.0", - "tls1.1", - "tls1.2", + b"tls1.0", + b"tls1.1", + b"tls1.2", } hassni = getattr(ssl, "HAS_SNI", False) # TLS 1.1 and 1.2 may not be supported if the OpenSSL Python is compiled # against doesn't support them. -supportedprotocols = {"tls1.0"} -if util.safehasattr(ssl, "PROTOCOL_TLSv1_1"): - supportedprotocols.add("tls1.1") -if util.safehasattr(ssl, "PROTOCOL_TLSv1_2"): - supportedprotocols.add("tls1.2") +supportedprotocols = {b"tls1.0"} +if util.safehasattr(ssl, b"PROTOCOL_TLSv1_1"): + supportedprotocols.add(b"tls1.1") +if util.safehasattr(ssl, b"PROTOCOL_TLSv1_2"): + supportedprotocols.add(b"tls1.2") try: # ssl.SSLContext was added in 2.7.9 and presence indicates modern # SSL/TLS features are available. SSLContext = ssl.SSLContext modernssl = True - _canloaddefaultcerts = util.safehasattr(SSLContext, "load_default_certs") + _canloaddefaultcerts = util.safehasattr(SSLContext, b"load_default_certs") except AttributeError: modernssl = False _canloaddefaultcerts = False @@ -87,9 +87,9 @@ def load_verify_locations(self, cafile=None, capath=None, cadata=None): if capath: - raise error.Abort(_("capath not supported")) + raise error.Abort(_(b"capath not supported")) if cadata: - raise error.Abort(_("cadata not supported")) + raise error.Abort(_(b"cadata not supported")) self._cacerts = cafile @@ -123,175 +123,182 @@ s = { # Whether we should attempt to load default/available CA certs # if an explicit ``cafile`` is not defined. - "allowloaddefaultcerts": True, + b"allowloaddefaultcerts": True, # List of 2-tuple of (hash algorithm, hash). - "certfingerprints": [], + b"certfingerprints": [], # Path to file containing concatenated CA certs. Used by # SSLContext.load_verify_locations(). - "cafile": None, + b"cafile": None, # Whether certificate verification should be disabled. - "disablecertverification": False, + b"disablecertverification": False, # Whether the legacy [hostfingerprints] section has data for this host. - "legacyfingerprint": False, + b"legacyfingerprint": False, # PROTOCOL_* constant to use for SSLContext.__init__. - "protocol": None, + b"protocol": None, # String representation of minimum protocol to be used for UI # presentation. - "protocolui": None, + b"protocolui": None, # ssl.CERT_* constant used by SSLContext.verify_mode. - "verifymode": None, + b"verifymode": None, # Defines extra ssl.OP* bitwise options to set. - "ctxoptions": None, + b"ctxoptions": None, # OpenSSL Cipher List to use (instead of default). - "ciphers": None, + b"ciphers": None, } # Allow minimum TLS protocol to be specified in the config. def validateprotocol(protocol, key): if protocol not in configprotocols: raise error.Abort( - _("unsupported protocol from hostsecurity.%s: %s") + _(b"unsupported protocol from hostsecurity.%s: %s") % (key, protocol), - hint=_("valid protocols: %s") - % " ".join(sorted(configprotocols)), + hint=_(b"valid protocols: %s") + % b" ".join(sorted(configprotocols)), ) # We default to TLS 1.1+ where we can because TLS 1.0 has known # vulnerabilities (like BEAST and POODLE). We allow users to downgrade to # TLS 1.0+ via config options in case a legacy server is encountered. - if "tls1.1" in supportedprotocols: - defaultprotocol = "tls1.1" + if b"tls1.1" in supportedprotocols: + defaultprotocol = b"tls1.1" else: # Let people know they are borderline secure. # We don't document this config option because we want people to see # the bold warnings on the web site. # internal config: hostsecurity.disabletls10warning - if not ui.configbool("hostsecurity", "disabletls10warning"): + if not ui.configbool(b"hostsecurity", b"disabletls10warning"): ui.warn( _( - "warning: connecting to %s using legacy security " - "technology (TLS 1.0); see " - "https://mercurial-scm.org/wiki/SecureConnections for " - "more info\n" + b"warning: connecting to %s using legacy security " + b"technology (TLS 1.0); see " + b"https://mercurial-scm.org/wiki/SecureConnections for " + b"more info\n" ) % bhostname ) - defaultprotocol = "tls1.0" + defaultprotocol = b"tls1.0" - key = "minimumprotocol" - protocol = ui.config("hostsecurity", key, defaultprotocol) + key = b"minimumprotocol" + protocol = ui.config(b"hostsecurity", key, defaultprotocol) validateprotocol(protocol, key) - key = "%s:minimumprotocol" % bhostname - protocol = ui.config("hostsecurity", key, protocol) + key = b"%s:minimumprotocol" % bhostname + protocol = ui.config(b"hostsecurity", key, protocol) validateprotocol(protocol, key) # If --insecure is used, we allow the use of TLS 1.0 despite config options. # We always print a "connection security to %s is disabled..." message when # --insecure is used. So no need to print anything more here. if ui.insecureconnections: - protocol = "tls1.0" - - s["protocol"], s["ctxoptions"], s["protocolui"] = protocolsettings(protocol) + protocol = b"tls1.0" - ciphers = ui.config("hostsecurity", "ciphers") - ciphers = ui.config("hostsecurity", "%s:ciphers" % bhostname, ciphers) - s["ciphers"] = ciphers + s[b"protocol"], s[b"ctxoptions"], s[b"protocolui"] = protocolsettings( + protocol + ) + + ciphers = ui.config(b"hostsecurity", b"ciphers") + ciphers = ui.config(b"hostsecurity", b"%s:ciphers" % bhostname, ciphers) + s[b"ciphers"] = ciphers # Look for fingerprints in [hostsecurity] section. Value is a list # of : strings. - fingerprints = ui.configlist("hostsecurity", "%s:fingerprints" % bhostname) + fingerprints = ui.configlist( + b"hostsecurity", b"%s:fingerprints" % bhostname + ) for fingerprint in fingerprints: - if not (fingerprint.startswith(("sha1:", "sha256:", "sha512:"))): + if not (fingerprint.startswith((b"sha1:", b"sha256:", b"sha512:"))): raise error.Abort( - _("invalid fingerprint for %s: %s") % (bhostname, fingerprint), - hint=_('must begin with "sha1:", "sha256:", ' 'or "sha512:"'), + _(b"invalid fingerprint for %s: %s") % (bhostname, fingerprint), + hint=_(b'must begin with "sha1:", "sha256:", ' b'or "sha512:"'), ) - alg, fingerprint = fingerprint.split(":", 1) - fingerprint = fingerprint.replace(":", "").lower() - s["certfingerprints"].append((alg, fingerprint)) + alg, fingerprint = fingerprint.split(b":", 1) + fingerprint = fingerprint.replace(b":", b"").lower() + s[b"certfingerprints"].append((alg, fingerprint)) # Fingerprints from [hostfingerprints] are always SHA-1. - for fingerprint in ui.configlist("hostfingerprints", bhostname): - fingerprint = fingerprint.replace(":", "").lower() - s["certfingerprints"].append(("sha1", fingerprint)) - s["legacyfingerprint"] = True + for fingerprint in ui.configlist(b"hostfingerprints", bhostname): + fingerprint = fingerprint.replace(b":", b"").lower() + s[b"certfingerprints"].append((b"sha1", fingerprint)) + s[b"legacyfingerprint"] = True # If a host cert fingerprint is defined, it is the only thing that # matters. No need to validate CA certs. - if s["certfingerprints"]: - s["verifymode"] = ssl.CERT_NONE - s["allowloaddefaultcerts"] = False + if s[b"certfingerprints"]: + s[b"verifymode"] = ssl.CERT_NONE + s[b"allowloaddefaultcerts"] = False # If --insecure is used, don't take CAs into consideration. elif ui.insecureconnections: - s["disablecertverification"] = True - s["verifymode"] = ssl.CERT_NONE - s["allowloaddefaultcerts"] = False + s[b"disablecertverification"] = True + s[b"verifymode"] = ssl.CERT_NONE + s[b"allowloaddefaultcerts"] = False - if ui.configbool("devel", "disableloaddefaultcerts"): - s["allowloaddefaultcerts"] = False + if ui.configbool(b"devel", b"disableloaddefaultcerts"): + s[b"allowloaddefaultcerts"] = False # If both fingerprints and a per-host ca file are specified, issue a warning # because users should not be surprised about what security is or isn't # being performed. - cafile = ui.config("hostsecurity", "%s:verifycertsfile" % bhostname) - if s["certfingerprints"] and cafile: + cafile = ui.config(b"hostsecurity", b"%s:verifycertsfile" % bhostname) + if s[b"certfingerprints"] and cafile: ui.warn( _( - "(hostsecurity.%s:verifycertsfile ignored when host " - "fingerprints defined; using host fingerprints for " - "verification)\n" + b"(hostsecurity.%s:verifycertsfile ignored when host " + b"fingerprints defined; using host fingerprints for " + b"verification)\n" ) % bhostname ) # Try to hook up CA certificate validation unless something above # makes it not necessary. - if s["verifymode"] is None: + if s[b"verifymode"] is None: # Look at per-host ca file first. if cafile: cafile = util.expandpath(cafile) if not os.path.exists(cafile): raise error.Abort( - _("path specified by %s does not exist: %s") - % ("hostsecurity.%s:verifycertsfile" % (bhostname,), cafile) + _(b"path specified by %s does not exist: %s") + % ( + b"hostsecurity.%s:verifycertsfile" % (bhostname,), + cafile, + ) ) - s["cafile"] = cafile + s[b"cafile"] = cafile else: # Find global certificates file in config. - cafile = ui.config("web", "cacerts") + cafile = ui.config(b"web", b"cacerts") if cafile: cafile = util.expandpath(cafile) if not os.path.exists(cafile): raise error.Abort( - _("could not find web.cacerts: %s") % cafile + _(b"could not find web.cacerts: %s") % cafile ) - elif s["allowloaddefaultcerts"]: + elif s[b"allowloaddefaultcerts"]: # CAs not defined in config. Try to find system bundles. cafile = _defaultcacerts(ui) if cafile: - ui.debug("using %s for CA file\n" % cafile) + ui.debug(b"using %s for CA file\n" % cafile) - s["cafile"] = cafile + s[b"cafile"] = cafile # Require certificate validation if CA certs are being loaded and # verification hasn't been disabled above. - if cafile or (_canloaddefaultcerts and s["allowloaddefaultcerts"]): - s["verifymode"] = ssl.CERT_REQUIRED + if cafile or (_canloaddefaultcerts and s[b"allowloaddefaultcerts"]): + s[b"verifymode"] = ssl.CERT_REQUIRED else: # At this point we don't have a fingerprint, aren't being # explicitly insecure, and can't load CA certs. Connecting # is insecure. We allow the connection and abort during # validation (once we have the fingerprint to print to the # user). - s["verifymode"] = ssl.CERT_NONE + s[b"verifymode"] = ssl.CERT_NONE - assert s["protocol"] is not None - assert s["ctxoptions"] is not None - assert s["verifymode"] is not None + assert s[b"protocol"] is not None + assert s[b"ctxoptions"] is not None + assert s[b"verifymode"] is not None return s @@ -304,7 +311,7 @@ of the ``minimumprotocol`` config option equivalent. """ if protocol not in configprotocols: - raise ValueError("protocol value not supported: %s" % protocol) + raise ValueError(b"protocol value not supported: %s" % protocol) # Despite its name, PROTOCOL_SSLv23 selects the highest protocol # that both ends support, including TLS protocols. On legacy stacks, @@ -317,18 +324,18 @@ # disable protocols via SSLContext.options and OP_NO_* constants. # However, SSLContext.options doesn't work unless we have the # full/real SSLContext available to us. - if supportedprotocols == {"tls1.0"}: - if protocol != "tls1.0": + if supportedprotocols == {b"tls1.0"}: + if protocol != b"tls1.0": raise error.Abort( - _("current Python does not support protocol " "setting %s") + _(b"current Python does not support protocol " b"setting %s") % protocol, hint=_( - "upgrade Python or disable setting since " - "only TLS 1.0 is supported" + b"upgrade Python or disable setting since " + b"only TLS 1.0 is supported" ), ) - return ssl.PROTOCOL_TLSv1, 0, "tls1.0" + return ssl.PROTOCOL_TLSv1, 0, b"tls1.0" # WARNING: returned options don't work unless the modern ssl module # is available. Be careful when adding options here. @@ -336,15 +343,15 @@ # SSLv2 and SSLv3 are broken. We ban them outright. options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 - if protocol == "tls1.0": + if protocol == b"tls1.0": # Defaults above are to use TLS 1.0+ pass - elif protocol == "tls1.1": + elif protocol == b"tls1.1": options |= ssl.OP_NO_TLSv1 - elif protocol == "tls1.2": + elif protocol == b"tls1.2": options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 else: - raise error.Abort(_("this should not happen")) + raise error.Abort(_(b"this should not happen")) # Prevent CRIME. # There is no guarantee this attribute is defined on the module. @@ -367,7 +374,7 @@ to use. """ if not serverhostname: - raise error.Abort(_("serverhostname argument is required")) + raise error.Abort(_(b"serverhostname argument is required")) if b"SSLKEYLOGFILE" in encoding.environ: try: @@ -388,11 +395,11 @@ for f in (keyfile, certfile): if f and not os.path.exists(f): raise error.Abort( - _("certificate file (%s) does not exist; cannot connect to %s") + _(b"certificate file (%s) does not exist; cannot connect to %s") % (f, pycompat.bytesurl(serverhostname)), hint=_( - "restore missing file or fix references " - "in Mercurial config" + b"restore missing file or fix references " + b"in Mercurial config" ), ) @@ -405,48 +412,48 @@ # bundle with a specific CA cert removed. If the system/default CA bundle # is loaded and contains that removed CA, you've just undone the user's # choice. - sslcontext = SSLContext(settings["protocol"]) + sslcontext = SSLContext(settings[b"protocol"]) # This is a no-op unless using modern ssl. - sslcontext.options |= settings["ctxoptions"] + sslcontext.options |= settings[b"ctxoptions"] # This still works on our fake SSLContext. - sslcontext.verify_mode = settings["verifymode"] + sslcontext.verify_mode = settings[b"verifymode"] - if settings["ciphers"]: + if settings[b"ciphers"]: try: - sslcontext.set_ciphers(pycompat.sysstr(settings["ciphers"])) + sslcontext.set_ciphers(pycompat.sysstr(settings[b"ciphers"])) except ssl.SSLError as e: raise error.Abort( - _("could not set ciphers: %s") + _(b"could not set ciphers: %s") % stringutil.forcebytestr(e.args[0]), - hint=_("change cipher string (%s) in config") - % settings["ciphers"], + hint=_(b"change cipher string (%s) in config") + % settings[b"ciphers"], ) if certfile is not None: def password(): f = keyfile or certfile - return ui.getpass(_("passphrase for %s: ") % f, "") + return ui.getpass(_(b"passphrase for %s: ") % f, b"") sslcontext.load_cert_chain(certfile, keyfile, password) - if settings["cafile"] is not None: + if settings[b"cafile"] is not None: try: - sslcontext.load_verify_locations(cafile=settings["cafile"]) + sslcontext.load_verify_locations(cafile=settings[b"cafile"]) except ssl.SSLError as e: if len(e.args) == 1: # pypy has different SSLError args msg = e.args[0] else: msg = e.args[1] raise error.Abort( - _("error loading CA file %s: %s") - % (settings["cafile"], stringutil.forcebytestr(msg)), - hint=_("file is empty or malformed?"), + _(b"error loading CA file %s: %s") + % (settings[b"cafile"], stringutil.forcebytestr(msg)), + hint=_(b"file is empty or malformed?"), ) caloaded = True - elif settings["allowloaddefaultcerts"]: + elif settings[b"allowloaddefaultcerts"]: # This is a no-op on old Python. sslcontext.load_default_certs() caloaded = True @@ -468,24 +475,24 @@ try: if ( caloaded - and settings["verifymode"] == ssl.CERT_REQUIRED + and settings[b"verifymode"] == ssl.CERT_REQUIRED and modernssl and not sslcontext.get_ca_certs() ): ui.warn( _( - "(an attempt was made to load CA certificates but " - "none were loaded; see " - "https://mercurial-scm.org/wiki/SecureConnections " - "for how to configure Mercurial to avoid this " - "error)\n" + b"(an attempt was made to load CA certificates but " + b"none were loaded; see " + b"https://mercurial-scm.org/wiki/SecureConnections " + b"for how to configure Mercurial to avoid this " + b"error)\n" ) ) except ssl.SSLError: pass # Try to print more helpful error messages for known failures. - if util.safehasattr(e, "reason"): + if util.safehasattr(e, b"reason"): # This error occurs when the client and server don't share a # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3 # outright. Hopefully the reason for this error is that we require @@ -493,36 +500,36 @@ # reason, try to emit an actionable warning. if e.reason == r"UNSUPPORTED_PROTOCOL": # We attempted TLS 1.0+. - if settings["protocolui"] == "tls1.0": + if settings[b"protocolui"] == b"tls1.0": # We support more than just TLS 1.0+. If this happens, # the likely scenario is either the client or the server # is really old. (e.g. server doesn't support TLS 1.0+ or # client doesn't support modern TLS versions introduced # several years from when this comment was written). - if supportedprotocols != {"tls1.0"}: + if supportedprotocols != {b"tls1.0"}: ui.warn( _( - "(could not communicate with %s using security " - "protocols %s; if you are using a modern Mercurial " - "version, consider contacting the operator of this " - "server; see " - "https://mercurial-scm.org/wiki/SecureConnections " - "for more info)\n" + b"(could not communicate with %s using security " + b"protocols %s; if you are using a modern Mercurial " + b"version, consider contacting the operator of this " + b"server; see " + b"https://mercurial-scm.org/wiki/SecureConnections " + b"for more info)\n" ) % ( pycompat.bytesurl(serverhostname), - ", ".join(sorted(supportedprotocols)), + b", ".join(sorted(supportedprotocols)), ) ) else: ui.warn( _( - "(could not communicate with %s using TLS 1.0; the " - "likely cause of this is the server no longer " - "supports TLS 1.0 because it has known security " - "vulnerabilities; see " - "https://mercurial-scm.org/wiki/SecureConnections " - "for more info)\n" + b"(could not communicate with %s using TLS 1.0; the " + b"likely cause of this is the server no longer " + b"supports TLS 1.0 because it has known security " + b"vulnerabilities; see " + b"https://mercurial-scm.org/wiki/SecureConnections " + b"for more info)\n" ) % pycompat.bytesurl(serverhostname) ) @@ -533,30 +540,30 @@ # offer. ui.warn( _( - "(could not negotiate a common security protocol (%s+) " - "with %s; the likely cause is Mercurial is configured " - "to be more secure than the server can support)\n" + b"(could not negotiate a common security protocol (%s+) " + b"with %s; the likely cause is Mercurial is configured " + b"to be more secure than the server can support)\n" ) % ( - settings["protocolui"], + settings[b"protocolui"], pycompat.bytesurl(serverhostname), ) ) ui.warn( _( - "(consider contacting the operator of this " - "server and ask them to support modern TLS " - "protocol versions; or, set " - "hostsecurity.%s:minimumprotocol=tls1.0 to allow " - "use of legacy, less secure protocols when " - "communicating with this server)\n" + b"(consider contacting the operator of this " + b"server and ask them to support modern TLS " + b"protocol versions; or, set " + b"hostsecurity.%s:minimumprotocol=tls1.0 to allow " + b"use of legacy, less secure protocols when " + b"communicating with this server)\n" ) % pycompat.bytesurl(serverhostname) ) ui.warn( _( - "(see https://mercurial-scm.org/wiki/SecureConnections " - "for more info)\n" + b"(see https://mercurial-scm.org/wiki/SecureConnections " + b"for more info)\n" ) ) @@ -566,8 +573,8 @@ ui.warn( _( - "(the full certificate chain may not be available " - 'locally; see "hg help debugssl")\n' + b"(the full certificate chain may not be available " + b'locally; see "hg help debugssl")\n' ) ) raise @@ -576,13 +583,13 @@ # closed # - see http://bugs.python.org/issue13721 if not sslsocket.cipher(): - raise error.Abort(_("ssl connection failed")) + raise error.Abort(_(b"ssl connection failed")) sslsocket._hgstate = { - "caloaded": caloaded, - "hostname": serverhostname, - "settings": settings, - "ui": ui, + b"caloaded": caloaded, + b"hostname": serverhostname, + b"settings": settings, + b"ui": ui, } return sslsocket @@ -608,27 +615,27 @@ for f in (certfile, keyfile, cafile): if f and not os.path.exists(f): raise error.Abort( - _("referenced certificate file (%s) does not " "exist") % f + _(b"referenced certificate file (%s) does not " b"exist") % f ) - protocol, options, _protocolui = protocolsettings("tls1.0") + protocol, options, _protocolui = protocolsettings(b"tls1.0") # This config option is intended for use in tests only. It is a giant # footgun to kill security. Don't define it. - exactprotocol = ui.config("devel", "serverexactprotocol") - if exactprotocol == "tls1.0": + exactprotocol = ui.config(b"devel", b"serverexactprotocol") + if exactprotocol == b"tls1.0": protocol = ssl.PROTOCOL_TLSv1 - elif exactprotocol == "tls1.1": - if "tls1.1" not in supportedprotocols: - raise error.Abort(_("TLS 1.1 not supported by this Python")) + elif exactprotocol == b"tls1.1": + if b"tls1.1" not in supportedprotocols: + raise error.Abort(_(b"TLS 1.1 not supported by this Python")) protocol = ssl.PROTOCOL_TLSv1_1 - elif exactprotocol == "tls1.2": - if "tls1.2" not in supportedprotocols: - raise error.Abort(_("TLS 1.2 not supported by this Python")) + elif exactprotocol == b"tls1.2": + if b"tls1.2" not in supportedprotocols: + raise error.Abort(_(b"TLS 1.2 not supported by this Python")) protocol = ssl.PROTOCOL_TLSv1_2 elif exactprotocol: raise error.Abort( - _("invalid value for serverexactprotocol: %s") % exactprotocol + _(b"invalid value for serverexactprotocol: %s") % exactprotocol ) if modernssl: @@ -643,7 +650,7 @@ sslcontext.options |= getattr(ssl, "OP_SINGLE_ECDH_USE", 0) # Use the list of more secure ciphers if found in the ssl module. - if util.safehasattr(ssl, "_RESTRICTED_SERVER_CIPHERS"): + if util.safehasattr(ssl, b"_RESTRICTED_SERVER_CIPHERS"): sslcontext.options |= getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) else: @@ -681,13 +688,13 @@ dn = pycompat.bytesurl(dn) hostname = pycompat.bytesurl(hostname) - pieces = dn.split(".") + pieces = dn.split(b".") leftmost = pieces[0] remainder = pieces[1:] - wildcards = leftmost.count("*") + wildcards = leftmost.count(b"*") if wildcards > maxwildcards: raise wildcarderror( - _("too many wildcards in certificate DNS name: %s") % dn + _(b"too many wildcards in certificate DNS name: %s") % dn ) # speed up common case w/o wildcards @@ -697,11 +704,11 @@ # RFC 6125, section 6.4.3, subitem 1. # The client SHOULD NOT attempt to match a presented identifier in which # the wildcard character comprises a label other than the left-most label. - if leftmost == "*": + if leftmost == b"*": # When '*' is a fragment by itself, it matches a non-empty dotless # fragment. - pats.append("[^.]+") - elif leftmost.startswith("xn--") or hostname.startswith("xn--"): + pats.append(b"[^.]+") + elif leftmost.startswith(b"xn--") or hostname.startswith(b"xn--"): # RFC 6125, section 6.4.3, subitem 3. # The client SHOULD NOT attempt to match a presented identifier # where the wildcard character is embedded within an A-label or @@ -709,7 +716,7 @@ pats.append(stringutil.reescape(leftmost)) else: # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(stringutil.reescape(leftmost).replace(br"\*", "[^.]*")) + pats.append(stringutil.reescape(leftmost).replace(br"\*", b"[^.]*")) # add the remaining fragments, ignore any wildcards for frag in remainder: @@ -726,7 +733,7 @@ Returns error message if any problems are found and None on success. """ if not cert: - return _("no certificate received") + return _(b"no certificate received") dnsnames = [] san = cert.get(r"subjectAltName", []) @@ -751,7 +758,7 @@ try: value = value.encode("ascii") except UnicodeEncodeError: - return _("IDN in certificate not supported") + return _(b"IDN in certificate not supported") try: if _dnsnamematch(value, hostname): @@ -763,11 +770,11 @@ dnsnames = [pycompat.bytesurl(d) for d in dnsnames] if len(dnsnames) > 1: - return _("certificate is for %s") % ", ".join(dnsnames) + return _(b"certificate is for %s") % b", ".join(dnsnames) elif len(dnsnames) == 1: - return _("certificate is for %s") % dnsnames[0] + return _(b"certificate is for %s") % dnsnames[0] else: - return _("no commonName or subjectAltName found in certificate") + return _(b"no commonName or subjectAltName found in certificate") def _plainapplepython(): @@ -785,16 +792,16 @@ ): return False exe = os.path.realpath(pycompat.sysexecutable).lower() - return exe.startswith("/usr/bin/python") or exe.startswith( - "/system/library/frameworks/python.framework/" + return exe.startswith(b"/usr/bin/python") or exe.startswith( + b"/system/library/frameworks/python.framework/" ) _systemcacertpaths = [ # RHEL, CentOS, and Fedora - "/etc/pki/tls/certs/ca-bundle.trust.crt", + b"/etc/pki/tls/certs/ca-bundle.trust.crt", # Debian, Ubuntu, Gentoo - "/etc/ssl/certs/ca-certificates.crt", + b"/etc/ssl/certs/ca-certificates.crt", ] @@ -815,7 +822,7 @@ certs = certifi.where() if os.path.exists(certs): - ui.debug("using ca certificates from certifi\n") + ui.debug(b"using ca certificates from certifi\n") return pycompat.fsencode(certs) except (ImportError, AttributeError): pass @@ -829,9 +836,9 @@ if not _canloaddefaultcerts: ui.warn( _( - "(unable to load Windows CA certificates; see " - "https://mercurial-scm.org/wiki/SecureConnections for " - "how to configure Mercurial to avoid this message)\n" + b"(unable to load Windows CA certificates; see " + b"https://mercurial-scm.org/wiki/SecureConnections for " + b"how to configure Mercurial to avoid this message)\n" ) ) @@ -842,7 +849,7 @@ # trick. if _plainapplepython(): dummycert = os.path.join( - os.path.dirname(pycompat.fsencode(__file__)), "dummycert.pem" + os.path.dirname(pycompat.fsencode(__file__)), b"dummycert.pem" ) if os.path.exists(dummycert): return dummycert @@ -856,9 +863,9 @@ if not _canloaddefaultcerts: ui.warn( _( - "(unable to load CA certificates; see " - "https://mercurial-scm.org/wiki/SecureConnections for " - "how to configure Mercurial to avoid this message)\n" + b"(unable to load CA certificates; see " + b"https://mercurial-scm.org/wiki/SecureConnections for " + b"how to configure Mercurial to avoid this message)\n" ) ) return None @@ -880,12 +887,12 @@ if os.path.isfile(path): ui.warn( _( - "(using CA certificates from %s; if you see this " - "message, your Mercurial install is not properly " - "configured; see " - "https://mercurial-scm.org/wiki/SecureConnections " - "for how to configure Mercurial to avoid this " - "message)\n" + b"(using CA certificates from %s; if you see this " + b"message, your Mercurial install is not properly " + b"configured; see " + b"https://mercurial-scm.org/wiki/SecureConnections " + b"for how to configure Mercurial to avoid this " + b"message)\n" ) % path ) @@ -893,9 +900,9 @@ ui.warn( _( - "(unable to load CA certificates; see " - "https://mercurial-scm.org/wiki/SecureConnections for " - "how to configure Mercurial to avoid this message)\n" + b"(unable to load CA certificates; see " + b"https://mercurial-scm.org/wiki/SecureConnections for " + b"how to configure Mercurial to avoid this message)\n" ) ) @@ -907,23 +914,23 @@ The passed socket must have been created with ``wrapsocket()``. """ - shost = sock._hgstate["hostname"] + shost = sock._hgstate[b"hostname"] host = pycompat.bytesurl(shost) - ui = sock._hgstate["ui"] - settings = sock._hgstate["settings"] + ui = sock._hgstate[b"ui"] + settings = sock._hgstate[b"settings"] try: peercert = sock.getpeercert(True) peercert2 = sock.getpeercert() except AttributeError: - raise error.Abort(_("%s ssl connection error") % host) + raise error.Abort(_(b"%s ssl connection error") % host) if not peercert: raise error.Abort( - _("%s certificate error: " "no certificate received") % host + _(b"%s certificate error: " b"no certificate received") % host ) - if settings["disablecertverification"]: + if settings[b"disablecertverification"]: # We don't print the certificate fingerprint because it shouldn't # be necessary: if the user requested certificate verification be # disabled, they presumably already saw a message about the inability @@ -932,9 +939,9 @@ # value. ui.warn( _( - "warning: connection security to %s is disabled per current " - "settings; communication is susceptible to eavesdropping " - "and tampering\n" + b"warning: connection security to %s is disabled per current " + b"settings; communication is susceptible to eavesdropping " + b"and tampering\n" ) % host ) @@ -943,63 +950,63 @@ # If a certificate fingerprint is pinned, use it and only it to # validate the remote cert. peerfingerprints = { - "sha1": node.hex(hashlib.sha1(peercert).digest()), - "sha256": node.hex(hashlib.sha256(peercert).digest()), - "sha512": node.hex(hashlib.sha512(peercert).digest()), + b"sha1": node.hex(hashlib.sha1(peercert).digest()), + b"sha256": node.hex(hashlib.sha256(peercert).digest()), + b"sha512": node.hex(hashlib.sha512(peercert).digest()), } def fmtfingerprint(s): - return ":".join([s[x : x + 2] for x in range(0, len(s), 2)]) + return b":".join([s[x : x + 2] for x in range(0, len(s), 2)]) - nicefingerprint = "sha256:%s" % fmtfingerprint(peerfingerprints["sha256"]) + nicefingerprint = b"sha256:%s" % fmtfingerprint(peerfingerprints[b"sha256"]) - if settings["certfingerprints"]: - for hash, fingerprint in settings["certfingerprints"]: + if settings[b"certfingerprints"]: + for hash, fingerprint in settings[b"certfingerprints"]: if peerfingerprints[hash].lower() == fingerprint: ui.debug( - "%s certificate matched fingerprint %s:%s\n" + b"%s certificate matched fingerprint %s:%s\n" % (host, hash, fmtfingerprint(fingerprint)) ) - if settings["legacyfingerprint"]: + if settings[b"legacyfingerprint"]: ui.warn( _( - "(SHA-1 fingerprint for %s found in legacy " - "[hostfingerprints] section; " - "if you trust this fingerprint, remove the old " - "SHA-1 fingerprint from [hostfingerprints] and " - "add the following entry to the new " - "[hostsecurity] section: %s:fingerprints=%s)\n" + b"(SHA-1 fingerprint for %s found in legacy " + b"[hostfingerprints] section; " + b"if you trust this fingerprint, remove the old " + b"SHA-1 fingerprint from [hostfingerprints] and " + b"add the following entry to the new " + b"[hostsecurity] section: %s:fingerprints=%s)\n" ) % (host, host, nicefingerprint) ) return # Pinned fingerprint didn't match. This is a fatal error. - if settings["legacyfingerprint"]: - section = "hostfingerprint" - nice = fmtfingerprint(peerfingerprints["sha1"]) + if settings[b"legacyfingerprint"]: + section = b"hostfingerprint" + nice = fmtfingerprint(peerfingerprints[b"sha1"]) else: - section = "hostsecurity" - nice = "%s:%s" % (hash, fmtfingerprint(peerfingerprints[hash])) + section = b"hostsecurity" + nice = b"%s:%s" % (hash, fmtfingerprint(peerfingerprints[hash])) raise error.Abort( - _("certificate for %s has unexpected " "fingerprint %s") + _(b"certificate for %s has unexpected " b"fingerprint %s") % (host, nice), - hint=_("check %s configuration") % section, + hint=_(b"check %s configuration") % section, ) # Security is enabled but no CAs are loaded. We can't establish trust # for the cert so abort. - if not sock._hgstate["caloaded"]: + if not sock._hgstate[b"caloaded"]: raise error.Abort( _( - "unable to verify security of %s (no loaded CA certificates); " - "refusing to connect" + b"unable to verify security of %s (no loaded CA certificates); " + b"refusing to connect" ) % host, hint=_( - "see https://mercurial-scm.org/wiki/SecureConnections for " - "how to configure Mercurial to avoid this error or set " - "hostsecurity.%s:fingerprints=%s to trust this server" + b"see https://mercurial-scm.org/wiki/SecureConnections for " + b"how to configure Mercurial to avoid this error or set " + b"hostsecurity.%s:fingerprints=%s to trust this server" ) % (host, nicefingerprint), ) @@ -1007,11 +1014,11 @@ msg = _verifycert(peercert2, shost) if msg: raise error.Abort( - _("%s certificate error: %s") % (host, msg), + _(b"%s certificate error: %s") % (host, msg), hint=_( - "set hostsecurity.%s:certfingerprints=%s " - "config setting or use --insecure to connect " - "insecurely" + b"set hostsecurity.%s:certfingerprints=%s " + b"config setting or use --insecure to connect " + b"insecurely" ) % (host, nicefingerprint), ) diff --git a/mercurial/stack.py b/mercurial/stack.py --- a/mercurial/stack.py +++ b/mercurial/stack.py @@ -16,9 +16,9 @@ the revision and are not merges. """ if rev is None: - rev = "." + rev = b"." - revspec = "only(%s) and not public() and not ::merge()" + revspec = b"only(%s) and not public() and not ::merge()" revisions = repo.revs(revspec, rev) revisions.sort() return revisions diff --git a/mercurial/state.py b/mercurial/state.py --- a/mercurial/state.py +++ b/mercurial/state.py @@ -60,23 +60,23 @@ """ if not isinstance(version, int): raise error.ProgrammingError( - "version of state file should be" " an integer" + b"version of state file should be" b" an integer" ) - with self._repo.vfs(self.fname, "wb", atomictemp=True) as fp: - fp.write("%d\n" % version) + with self._repo.vfs(self.fname, b"wb", atomictemp=True) as fp: + fp.write(b"%d\n" % version) for chunk in cborutil.streamencode(data): fp.write(chunk) def _read(self): """reads the state file and returns a dictionary which contain data in the same format as it was before storing""" - with self._repo.vfs(self.fname, "rb") as fp: + with self._repo.vfs(self.fname, b"rb") as fp: try: int(fp.readline()) except ValueError: raise error.CorruptedState( - "unknown version of state file" " found" + b"unknown version of state file" b" found" ) return cborutil.decodeall(fp.read())[0] @@ -133,12 +133,12 @@ """ if not self._statushint: hint = _( - "To continue: hg %s --continue\n" - "To abort: hg %s --abort" + b"To continue: hg %s --continue\n" + b"To abort: hg %s --abort" ) % (self._opname, self._opname) if self._stopflag: hint = hint + ( - _("\nTo stop: hg %s --stop") % (self._opname) + _(b"\nTo stop: hg %s --stop") % (self._opname) ) return hint return self._statushint @@ -148,7 +148,7 @@ operation """ if not self._cmdhint: - return _("use 'hg %s --continue' or 'hg %s --abort'") % ( + return _(b"use 'hg %s --continue' or 'hg %s --abort'") % ( self._opname, self._opname, ) @@ -157,18 +157,18 @@ def msg(self): """returns the status message corresponding to the command""" if not self._cmdmsg: - return _("%s in progress") % (self._opname) + return _(b"%s in progress") % (self._opname) return self._cmdmsg def continuemsg(self): """ returns appropriate continue message corresponding to command""" - return _("hg %s --continue") % (self._opname) + return _(b"hg %s --continue") % (self._opname) def isunfinished(self, repo): """determines whether a multi-step operation is in progress or not """ - if self._opname == "merge": + if self._opname == b"merge": return len(repo[None].parents()) > 1 else: return repo.vfs.exists(self._fname) @@ -186,9 +186,9 @@ reportonly=False, continueflag=False, stopflag=False, - cmdmsg="", - cmdhint="", - statushint="", + cmdmsg=b"", + cmdhint=b"", + statushint=b"", abortfunc=None, continuefunc=None, ): @@ -233,36 +233,36 @@ abortfunc, continuefunc, ) - if opname == "merge": + if opname == b"merge": _unfinishedstates.append(statecheckobj) else: _unfinishedstates.insert(0, statecheckobj) addunfinished( - "update", - fname="updatestate", + b"update", + fname=b"updatestate", clearable=True, - cmdmsg=_("last update was interrupted"), - cmdhint=_("use 'hg update' to get a consistent checkout"), - statushint=_("To continue: hg update ."), + cmdmsg=_(b"last update was interrupted"), + cmdhint=_(b"use 'hg update' to get a consistent checkout"), + statushint=_(b"To continue: hg update ."), ) addunfinished( - "bisect", - fname="bisect.state", + b"bisect", + fname=b"bisect.state", allowcommit=True, reportonly=True, statushint=_( - "To mark the changeset good: hg bisect --good\n" - "To mark the changeset bad: hg bisect --bad\n" - "To abort: hg bisect --reset\n" + b"To mark the changeset good: hg bisect --good\n" + b"To mark the changeset bad: hg bisect --bad\n" + b"To abort: hg bisect --reset\n" ), ) def getrepostate(repo): # experimental config: commands.status.skipstates - skip = set(repo.ui.configlist("commands", "status.skipstates")) + skip = set(repo.ui.configlist(b"commands", b"status.skipstates")) for state in _unfinishedstates: if state._opname in skip: continue diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py +++ b/mercurial/statichttprepo.py @@ -49,7 +49,7 @@ def read(self, bytes=None): req = urlreq.request(pycompat.strurl(self.url)) - end = "" + end = b"" if bytes: end = self.pos + bytes - 1 if self.pos or end: @@ -112,7 +112,7 @@ def http_error_416(self, req, fp, code, msg, hdrs): # HTTP's Range Not Satisfiable error - raise _RangeError("Requested Range Not Satisfiable") + raise _RangeError(b"Requested Range Not Satisfiable") def build_opener(ui, authinfo): @@ -125,10 +125,10 @@ self.base = base self.options = {} - def __call__(self, path, mode="r", *args, **kw): - if mode not in ("r", "rb"): - raise IOError("Permission denied") - f = "/".join((self.base, urlreq.quote(path))) + def __call__(self, path, mode=b"r", *args, **kw): + if mode not in (b"r", b"rb"): + raise IOError(b"Permission denied") + f = b"/".join((self.base, urlreq.quote(path))) return httprangereader(f, urlopener) def join(self, path): @@ -158,12 +158,12 @@ self.ui = ui self.root = path - u = util.url(path.rstrip("/") + "/.hg") + u = util.url(path.rstrip(b"/") + b"/.hg") self.path, authinfo = u.authinfo() vfsclass = build_opener(ui, authinfo) self.vfs = vfsclass(self.path) - self.cachevfs = vfsclass(self.vfs.join("cache")) + self.cachevfs = vfsclass(self.vfs.join(b"cache")) self._phasedefaults = [] self.names = namespaces.namespaces() @@ -179,14 +179,14 @@ # check if it is a non-empty old-style repository try: - fp = self.vfs("00changelog.i") + fp = self.vfs(b"00changelog.i") fp.read(1) fp.close() except IOError as inst: if inst.errno != errno.ENOENT: raise # we do not care about empty old-style repositories here - msg = _("'%s' does not appear to be an hg repository") % path + msg = _(b"'%s' does not appear to be an hg repository") % path raise error.RepoError(msg) supportedrequirements = localrepo.gathersupportedrequirements(ui) @@ -218,7 +218,7 @@ def _restrictcapabilities(self, caps): caps = super(statichttprepository, self)._restrictcapabilities(caps) - return caps.difference(["pushkey"]) + return caps.difference([b"pushkey"]) def url(self): return self._url @@ -232,13 +232,13 @@ def wlock(self, wait=True): raise error.LockUnavailable( 0, - _("lock not available"), - "lock", - _("cannot lock static-http repository"), + _(b"lock not available"), + b"lock", + _(b"cannot lock static-http repository"), ) def lock(self, wait=True): - raise error.Abort(_("cannot lock static-http repository")) + raise error.Abort(_(b"cannot lock static-http repository")) def _writecaches(self): pass # statichttprepository are read only @@ -246,5 +246,5 @@ def instance(ui, path, create, intents=None, createopts=None): if create: - raise error.Abort(_("cannot create new static-http repository")) + raise error.Abort(_(b"cannot create new static-http repository")) return statichttprepository(ui, path[7:]) diff --git a/mercurial/statprof.py b/mercurial/statprof.py old mode 100755 new mode 100644 --- a/mercurial/statprof.py +++ b/mercurial/statprof.py @@ -123,7 +123,7 @@ defaultdict = collections.defaultdict contextmanager = contextlib.contextmanager -__all__ = ["start", "stop", "reset", "display", "profile"] +__all__ = [b"start", b"stop", b"reset", b"display", b"profile"] skips = { r"util.py:check", @@ -158,7 +158,7 @@ class ProfileState(object): def __init__(self, frequency=None): self.reset(frequency) - self.track = "cpu" + self.track = b"cpu" def reset(self, frequency=None): # total so far @@ -195,7 +195,7 @@ @property def timeidx(self): - if self.track == "real": + if self.track == b"real": return 1 return 0 @@ -239,7 +239,7 @@ if self.source is None: lineno = self.lineno - 1 try: - with open(self.path, "rb") as fp: + with open(self.path, b"rb") as fp: for i, line in enumerate(fp): if i == lineno: self.source = line.strip() @@ -247,11 +247,11 @@ except: pass if self.source is None: - self.source = "" + self.source = b"" source = self.source if len(source) > length: - source = source[: (length - 3)] + "..." + source = source[: (length - 3)] + b"..." return source def filename(self): @@ -331,7 +331,7 @@ lastmechanism = None -def start(mechanism="thread", track="cpu"): +def start(mechanism=b"thread", track=b"cpu"): """Install the profiling signal handler, and start profiling.""" state.track = track # note: nesting different mode won't work state.profile_level += 1 @@ -343,16 +343,16 @@ global lastmechanism lastmechanism = mechanism - if mechanism == "signal": + if mechanism == b"signal": signal.signal(signal.SIGPROF, profile_signal_handler) signal.setitimer( signal.ITIMER_PROF, rpt or state.sample_interval, 0.0 ) - elif mechanism == "thread": + elif mechanism == b"thread": frame = inspect.currentframe() tid = [k for k, f in sys._current_frames().items() if f == frame][0] state.thread = threading.Thread( - target=samplerthread, args=(tid,), name="samplerthread" + target=samplerthread, args=(tid,), name=b"samplerthread" ) state.thread.start() @@ -361,17 +361,17 @@ """Stop profiling, and uninstall the profiling signal handler.""" state.profile_level -= 1 if state.profile_level == 0: - if lastmechanism == "signal": + if lastmechanism == b"signal": rpt = signal.setitimer(signal.ITIMER_PROF, 0.0, 0.0) signal.signal(signal.SIGPROF, signal.SIG_IGN) state.remaining_prof_time = rpt[0] - elif lastmechanism == "thread": + elif lastmechanism == b"thread": stopthread.set() state.thread.join() state.accumulate_time(clock()) state.last_start_time = None - statprofpath = encoding.environ.get("STATPROF_DEST") + statprofpath = encoding.environ.get(b"STATPROF_DEST") if statprofpath: save_data(statprofpath) @@ -379,29 +379,30 @@ def save_data(path): - with open(path, "w+") as file: - file.write("%f %f\n" % state.accumulated_time) + with open(path, b"w+") as file: + file.write(b"%f %f\n" % state.accumulated_time) for sample in state.samples: time = sample.time stack = sample.stack sites = [ - "\1".join([s.path, b"%d" % s.lineno, s.function]) for s in stack + b"\1".join([s.path, b"%d" % s.lineno, s.function]) + for s in stack ] - file.write("%d\0%s\n" % (time, "\0".join(sites))) + file.write(b"%d\0%s\n" % (time, b"\0".join(sites))) def load_data(path): - lines = open(path, "rb").read().splitlines() + lines = open(path, b"rb").read().splitlines() state.accumulated_time = [float(value) for value in lines[0].split()] state.samples = [] for line in lines[1:]: - parts = line.split("\0") + parts = line.split(b"\0") time = float(parts[0]) rawsites = parts[1:] sites = [] for rawsite in rawsites: - siteparts = rawsite.split("\1") + siteparts = rawsite.split(b"\1") sites.append( CodeSite.get(siteparts[0], int(siteparts[1]), siteparts[2]) ) @@ -415,7 +416,7 @@ The optional frequency argument specifies the number of samples to collect per second.""" - assert state.profile_level == 0, "Can't reset() while statprof is running" + assert state.profile_level == 0, b"Can't reset() while statprof is running" CodeSite.cache.clear() state.reset(frequency) @@ -515,7 +516,7 @@ elif format == DisplayFormats.Chrome: write_to_chrome(data, fp, **kwargs) else: - raise Exception("Invalid display format") + raise Exception(b"Invalid display format") if format not in (DisplayFormats.Json, DisplayFormats.Chrome): fp.write(b"---\n") @@ -540,7 +541,7 @@ for stat in stats: site = stat.site - sitelabel = "%s:%d:%s" % (site.filename(), site.lineno, site.function) + sitelabel = b"%s:%d:%s" % (site.filename(), site.lineno, site.function) fp.write( b"%6.2f %9.2f %9.2f %s\n" % ( @@ -557,11 +558,12 @@ as one row in a table. Important lines within that function are output as nested rows. Sorted by self-time per line.""" fp.write( - b"%5.5s %10.10s %7.7s %-8.8s\n" % ("% ", "cumulative", "self", "") + b"%5.5s %10.10s %7.7s %-8.8s\n" + % (b"% ", b"cumulative", b"self", b"") ) fp.write( b"%5.5s %9.9s %8.8s %-8.8s\n" - % ("time", "seconds", "seconds", "name") + % (b"time", b"seconds", b"seconds", b"name") ) stats = SiteStats.buildstats(data.samples) @@ -623,11 +625,11 @@ def display_about_method(data, fp, function=None, **kwargs): if function is None: - raise Exception("Invalid function") + raise Exception(b"Invalid function") filename = None - if ":" in function: - filename, function = function.split(":") + if b":" in function: + filename, function = function.split(b":") relevant_samples = 0 parents = {} @@ -686,7 +688,7 @@ fp.write( b"\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n\n" % ( - pycompat.sysbytes(filename or "___"), + pycompat.sysbytes(filename or b"___"), pycompat.sysbytes(function), total_cum_sec, total_cum_percent, @@ -747,37 +749,41 @@ ] if site: indent = depth * 2 - 1 - filename = "" - function = "" + filename = b"" + function = b"" if len(node.children) > 0: childsite = list(node.children.itervalues())[0].site - filename = (childsite.filename() + ":").ljust(15) + filename = (childsite.filename() + b":").ljust(15) function = childsite.function # lots of string formatting listpattern = ( - "".ljust(indent) - + ("\\" if multiple_siblings else "|") - + " %4.1f%%" - + (" %5.2fs" % node.count if showtime else "") - + " %s %s" + b"".ljust(indent) + + (b"\\" if multiple_siblings else b"|") + + b" %4.1f%%" + + (b" %5.2fs" % node.count if showtime else b"") + + b" %s %s" ) liststring = listpattern % ( node.count / root.count * 100, filename, function, ) - codepattern = "%" + ("%d" % (55 - len(liststring))) + "s %d: %s" - codestring = codepattern % ("line", site.lineno, site.getsource(30)) + codepattern = b"%" + (b"%d" % (55 - len(liststring))) + b"s %d: %s" + codestring = codepattern % ( + b"line", + site.lineno, + site.getsource(30), + ) finalstring = liststring + codestring childrensamples = sum([c.count for c in node.children.itervalues()]) # Make frames that performed more than 10% of the operation red if node.count - childrensamples > (0.1 * root.count): - finalstring = "\033[91m" + finalstring + "\033[0m" + finalstring = b"\033[91m" + finalstring + b"\033[0m" # Make frames that didn't actually perform work dark grey elif node.count - childrensamples == 0: - finalstring = "\033[90m" + finalstring + "\033[0m" + finalstring = b"\033[90m" + finalstring + b"\033[0m" fp.write(finalstring + b"\n") newdepth = depth @@ -794,7 +800,7 @@ def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs): if scriptpath is None: - scriptpath = encoding.environ["HOME"] + "/flamegraph.pl" + scriptpath = encoding.environ[b"HOME"] + b"/flamegraph.pl" if not os.path.exists(scriptpath): fp.write(b"error: missing %s\n" % scriptpath) fp.write(b"get it here: https://github.com/brendangregg/FlameGraph\n") @@ -804,7 +810,7 @@ for sample in data.samples: sites = [s.function for s in sample.stack] sites.reverse() - line = ";".join(sites) + line = b";".join(sites) if line in lines: lines[line] = lines[line] + 1 else: @@ -812,14 +818,14 @@ fd, path = pycompat.mkstemp() - with open(path, "w+") as file: + with open(path, b"w+") as file: for line, count in lines.iteritems(): - file.write("%s %d\n" % (line, count)) + file.write(b"%s %d\n" % (line, count)) if outputfile is None: - outputfile = "~/flamegraph.svg" + outputfile = b"~/flamegraph.svg" - os.system("perl ~/flamegraph.pl %s > %s" % (path, outputfile)) + os.system(b"perl ~/flamegraph.pl %s > %s" % (path, outputfile)) fp.write(b"Written to %s\n" % outputfile) @@ -984,7 +990,7 @@ if not isinstance(data, bytes): data = data.encode("utf-8") fp.write(data) - fp.write("\n") + fp.write(b"\n") def printusage(): @@ -1021,19 +1027,19 @@ displayargs = {} optstart = 2 - displayargs["function"] = None + displayargs[b"function"] = None if argv[1] == r"hotpath": - displayargs["format"] = DisplayFormats.Hotpath + displayargs[b"format"] = DisplayFormats.Hotpath elif argv[1] == r"lines": - displayargs["format"] = DisplayFormats.ByLine + displayargs[b"format"] = DisplayFormats.ByLine elif argv[1] == r"functions": - displayargs["format"] = DisplayFormats.ByMethod + displayargs[b"format"] = DisplayFormats.ByMethod elif argv[1] == r"function": - displayargs["format"] = DisplayFormats.AboutMethod - displayargs["function"] = argv[2] + displayargs[b"format"] = DisplayFormats.AboutMethod + displayargs[b"function"] = argv[2] optstart = 3 elif argv[1] == r"flame": - displayargs["format"] = DisplayFormats.FlameGraph + displayargs[b"format"] = DisplayFormats.FlameGraph else: printusage() return 0 @@ -1042,30 +1048,30 @@ try: opts, args = pycompat.getoptb( sys.argv[optstart:], - "hl:f:o:p:", - ["help", "limit=", "file=", "output-file=", "script-path="], + b"hl:f:o:p:", + [b"help", b"limit=", b"file=", b"output-file=", b"script-path="], ) except getopt.error as msg: print(msg) printusage() return 2 - displayargs["limit"] = 0.05 + displayargs[b"limit"] = 0.05 path = None for o, value in opts: if o in (r"-l", r"--limit"): - displayargs["limit"] = float(value) + displayargs[b"limit"] = float(value) elif o in (r"-f", r"--file"): path = value elif o in (r"-o", r"--output-file"): - displayargs["outputfile"] = value + displayargs[b"outputfile"] = value elif o in (r"-p", r"--script-path"): - displayargs["scriptpath"] = value + displayargs[b"scriptpath"] = value elif o in (r"-h", r"help"): printusage() return 0 else: - assert False, "unhandled option %s" % o + assert False, b"unhandled option %s" % o if not path: print(r"must specify --file to load") diff --git a/mercurial/store.py b/mercurial/store.py --- a/mercurial/store.py +++ b/mercurial/store.py @@ -40,12 +40,12 @@ if matcher is None: return True path = decodedir(path) - if path.startswith("data/"): - return matcher(path[len("data/") : -len(".i")]) - elif path.startswith("meta/"): - return matcher.visitdir(path[len("meta/") : -len("/00manifest.i")]) + if path.startswith(b"data/"): + return matcher(path[len(b"data/") : -len(b".i")]) + elif path.startswith(b"meta/"): + return matcher.visitdir(path[len(b"meta/") : -len(b"/00manifest.i")]) - raise error.ProgrammingError("cannot decode path %s" % path) + raise error.ProgrammingError(b"cannot decode path %s" % path) # This avoids a collision between a file named foo and a dir named @@ -62,9 +62,9 @@ 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n' """ return ( - path.replace(".hg/", ".hg.hg/") - .replace(".i/", ".i.hg/") - .replace(".d/", ".d.hg/") + path.replace(b".hg/", b".hg.hg/") + .replace(b".i/", b".i.hg/") + .replace(b".d/", b".d.hg/") ) @@ -80,12 +80,12 @@ >>> decodedir(b'data/foo.i.hg.hg/bla.i') 'data/foo.i.hg/bla.i' """ - if ".hg/" not in path: + if b".hg/" not in path: return path return ( - path.replace(".d.hg/", ".d/") - .replace(".i.hg/", ".i/") - .replace(".hg.hg/", ".hg/") + path.replace(b".d.hg/", b".d/") + .replace(b".i.hg/", b".i/") + .replace(b".hg.hg/", b".hg/") ) @@ -131,14 +131,14 @@ >>> dec(b'the~07quick~adshot') 'the\\x07quick\\xadshot' """ - e = "_" + e = b"_" xchr = pycompat.bytechr asciistr = list(map(xchr, range(127))) - capitals = list(range(ord("A"), ord("Z") + 1)) + capitals = list(range(ord(b"A"), ord(b"Z") + 1)) cmap = dict((x, x) for x in asciistr) for x in _reserved(): - cmap[xchr(x)] = "~%02x" % x + cmap[xchr(x)] = b"~%02x" % x for x in capitals + [ord(e)]: cmap[xchr(x)] = e + xchr(x).lower() @@ -160,10 +160,10 @@ raise KeyError return ( - lambda s: "".join( + lambda s: b"".join( [cmap[s[c : c + 1]] for c in pycompat.xrange(len(s))] ), - lambda s: "".join(list(decode(s))), + lambda s: b"".join(list(decode(s))), ) @@ -201,12 +201,12 @@ xchr = pycompat.bytechr cmap = dict([(xchr(x), xchr(x)) for x in pycompat.xrange(127)]) for x in _reserved(): - cmap[xchr(x)] = "~%02x" % x - for x in range(ord("A"), ord("Z") + 1): + cmap[xchr(x)] = b"~%02x" % x + for x in range(ord(b"A"), ord(b"Z") + 1): cmap[xchr(x)] = xchr(x).lower() def lowerencode(s): - return "".join([cmap[c] for c in pycompat.iterbytestr(s)]) + return b"".join([cmap[c] for c in pycompat.iterbytestr(s)]) return lowerencode @@ -214,8 +214,8 @@ lowerencode = getattr(parsers, "lowerencode", None) or _buildlowerencodefun() # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9 -_winres3 = ("aux", "con", "prn", "nul") # length 3 -_winres4 = ("com", "lpt") # length 4 (with trailing 1..9) +_winres3 = (b"aux", b"con", b"prn", b"nul") # length 3 +_winres4 = (b"com", b"lpt") # length 4 (with trailing 1..9) def _auxencode(path, dotencode): @@ -243,23 +243,26 @@ for i, n in enumerate(path): if not n: continue - if dotencode and n[0] in ". ": - n = "~%02x" % ord(n[0:1]) + n[1:] + if dotencode and n[0] in b". ": + n = b"~%02x" % ord(n[0:1]) + n[1:] path[i] = n else: - l = n.find(".") + l = n.find(b".") if l == -1: l = len(n) if (l == 3 and n[:3] in _winres3) or ( - l == 4 and n[3:4] <= "9" and n[3:4] >= "1" and n[:3] in _winres4 + l == 4 + and n[3:4] <= b"9" + and n[3:4] >= b"1" + and n[:3] in _winres4 ): # encode third letter ('aux' -> 'au~78') - ec = "~%02x" % ord(n[2:3]) + ec = b"~%02x" % ord(n[2:3]) n = n[0:2] + ec + n[3:] path[i] = n - if n[-1] in ". ": + if n[-1] in b". ": # encode last period or space ('foo...' -> 'foo..~2e') - path[i] = n[:-1] + "~%02x" % ord(n[-1:]) + path[i] = n[:-1] + b"~%02x" % ord(n[-1:]) return path @@ -270,7 +273,7 @@ def _hashencode(path, dotencode): digest = node.hex(hashlib.sha1(path).digest()) - le = lowerencode(path[5:]).split("/") # skips prefix 'data/' or 'meta/' + le = lowerencode(path[5:]).split(b"/") # skips prefix 'data/' or 'meta/' parts = _auxencode(le, dotencode) basename = parts[-1] _root, ext = os.path.splitext(basename) @@ -278,9 +281,9 @@ sdirslen = 0 for p in parts[:-1]: d = p[:_dirprefixlen] - if d[-1] in ". ": + if d[-1] in b". ": # Windows can't access dirs ending in period or space - d = d[:-1] + "_" + d = d[:-1] + b"_" if sdirslen == 0: t = len(d) else: @@ -289,14 +292,14 @@ break sdirs.append(d) sdirslen = t - dirs = "/".join(sdirs) + dirs = b"/".join(sdirs) if len(dirs) > 0: - dirs += "/" - res = "dh/" + dirs + digest + ext + dirs += b"/" + res = b"dh/" + dirs + digest + ext spaceleft = _maxstorepathlen - len(res) if spaceleft > 0: filler = basename[:spaceleft] - res = "dh/" + dirs + filler + digest + ext + res = b"dh/" + dirs + filler + digest + ext return res @@ -332,8 +335,8 @@ encoding was used. """ path = encodedir(path) - ef = _encodefname(path).split("/") - res = "/".join(_auxencode(ef, dotencode)) + ef = _encodefname(path).split(b"/") + res = b"/".join(_auxencode(ef, dotencode)) if len(res) > _maxstorepathlen: res = _hashencode(path, dotencode) return res @@ -343,8 +346,8 @@ de = encodedir(path) if len(path) > _maxstorepathlen: return _hashencode(de, True) - ef = _encodefname(de).split("/") - res = "/".join(_auxencode(ef, True)) + ef = _encodefname(de).split(b"/") + res = b"/".join(_auxencode(ef, True)) if len(res) > _maxstorepathlen: return _hashencode(de, True) return res @@ -370,13 +373,13 @@ _data = ( - "bookmarks narrowspec data meta 00manifest.d 00manifest.i" - " 00changelog.d 00changelog.i phaseroots obsstore" + b"bookmarks narrowspec data meta 00manifest.d 00manifest.i" + b" 00changelog.d 00changelog.i phaseroots obsstore" ) def isrevlog(f, kind, st): - return kind == stat.S_IFREG and f[-2:] in (".i", ".d") + return kind == stat.S_IFREG and f[-2:] in (b".i", b".d") class basicstore(object): @@ -392,13 +395,13 @@ self.opener = self.vfs def join(self, f): - return self.path + "/" + encodedir(f) + return self.path + b"/" + encodedir(f) def _walk(self, relpath, recurse, filefilter=isrevlog): """yields (unencoded, encoded, size)""" path = self.path if relpath: - path += "/" + relpath + path += b"/" + relpath striplen = len(self.path) + 1 l = [] if self.rawvfs.isdir(path): @@ -407,7 +410,7 @@ while visit: p = visit.pop() for f, kind, st in readdir(p, stat=True): - fp = p + "/" + f + fp = p + b"/" + f if filefilter(f, kind, st): n = util.pconvert(fp[striplen:]) l.append((decodedir(n), n, st.st_size)) @@ -424,11 +427,11 @@ return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) def datafiles(self, matcher=None): - return self._walk("data", True) + self._walk("meta", True) + return self._walk(b"data", True) + self._walk(b"meta", True) def topfiles(self): # yield manifest before changelog - return reversed(self._walk("", False)) + return reversed(self._walk(b"", False)) def walk(self, matcher=None): """yields (unencoded, encoded, size) @@ -443,7 +446,7 @@ yield x def copylist(self): - return ["requires"] + _data.split() + return [b"requires"] + _data.split() def write(self, tr): pass @@ -456,19 +459,19 @@ def __contains__(self, path): """Checks if the store contains path""" - path = "/".join(("data", path)) + path = b"/".join((b"data", path)) # file? - if self.vfs.exists(path + ".i"): + if self.vfs.exists(path + b".i"): return True # dir? - if not path.endswith("/"): - path = path + "/" + if not path.endswith(b"/"): + path = path + b"/" return self.vfs.exists(path) class encodedstore(basicstore): def __init__(self, path, vfstype): - vfs = vfstype(path + "/store") + vfs = vfstype(path + b"/store") self.path = vfs.base self.createmode = _calcmode(vfs) vfs.createmode = self.createmode @@ -487,11 +490,11 @@ yield a, b, size def join(self, f): - return self.path + "/" + encodefilename(f) + return self.path + b"/" + encodefilename(f) def copylist(self): - return ["requires", "00changelog.i"] + [ - "store/" + f for f in _data.split() + return [b"requires", b"00changelog.i"] + [ + b"store/" + f for f in _data.split() ] @@ -517,7 +520,7 @@ """fill the entries from the fncache file""" self._dirty = False try: - fp = self.vfs("fncache", mode="rb") + fp = self.vfs(b"fncache", mode=b"rb") except IOError: # skip nonexistent file self.entries = set() @@ -537,14 +540,15 @@ pass if chunk: - msg = _("fncache does not ends with a newline") + msg = _(b"fncache does not ends with a newline") if warn: - warn(msg + "\n") + warn(msg + b"\n") else: raise error.Abort( msg, hint=_( - "use 'hg debugrebuildfncache' to " "rebuild the fncache" + b"use 'hg debugrebuildfncache' to " + b"rebuild the fncache" ), ) self._checkentries(fp, warn) @@ -552,13 +556,13 @@ def _checkentries(self, fp, warn): """ make sure there is no empty string in entries """ - if "" in self.entries: + if b"" in self.entries: fp.seek(0) for n, line in enumerate(util.iterfile(fp)): - if not line.rstrip("\n"): - t = _("invalid entry in fncache, line %d") % (n + 1) + if not line.rstrip(b"\n"): + t = _(b"invalid entry in fncache, line %d") % (n + 1) if warn: - warn(t + "\n") + warn(t + b"\n") else: raise error.Abort(t) @@ -567,18 +571,18 @@ assert self.entries is not None self.entries = self.entries | self.addls self.addls = set() - tr.addbackup("fncache") - fp = self.vfs("fncache", mode="wb", atomictemp=True) + tr.addbackup(b"fncache") + fp = self.vfs(b"fncache", mode=b"wb", atomictemp=True) if self.entries: - fp.write(encodedir("\n".join(self.entries) + "\n")) + fp.write(encodedir(b"\n".join(self.entries) + b"\n")) fp.close() self._dirty = False if self.addls: # if we have just new entries, let's append them to the fncache - tr.addbackup("fncache") - fp = self.vfs("fncache", mode="ab", atomictemp=True) + tr.addbackup(b"fncache") + fp = self.vfs(b"fncache", mode=b"ab", atomictemp=True) if self.addls: - fp.write(encodedir("\n".join(self.addls) + "\n")) + fp.write(encodedir(b"\n".join(self.addls) + b"\n")) fp.close() self.entries = None self.addls = set() @@ -620,15 +624,15 @@ self.fncache = fnc self.encode = encode - def __call__(self, path, mode="r", *args, **kw): + def __call__(self, path, mode=b"r", *args, **kw): encoded = self.encode(path) - if mode not in ("r", "rb") and ( - path.startswith("data/") or path.startswith("meta/") + if mode not in (b"r", b"rb") and ( + path.startswith(b"data/") or path.startswith(b"meta/") ): # do not trigger a fncache load when adding a file that already is # known to exist. notload = self.fncache.entries is None and self.vfs.exists(encoded) - if notload and "a" in mode and not self.vfs.stat(encoded).st_size: + if notload and b"a" in mode and not self.vfs.stat(encoded).st_size: # when appending to an existing file, if the file has size zero, # it should be considered as missing. Such zero-size files are # the result of truncation when a transaction is aborted. @@ -651,9 +655,9 @@ else: encode = _plainhybridencode self.encode = encode - vfs = vfstype(path + "/store") + vfs = vfstype(path + b"/store") self.path = vfs.base - self.pathsep = self.path + "/" + self.pathsep = self.path + b"/" self.createmode = _calcmode(vfs) vfs.createmode = self.createmode self.rawvfs = vfs @@ -681,10 +685,12 @@ def copylist(self): d = ( - "bookmarks narrowspec data meta dh fncache phaseroots obsstore" - " 00manifest.d 00manifest.i 00changelog.d 00changelog.i" + b"bookmarks narrowspec data meta dh fncache phaseroots obsstore" + b" 00manifest.d 00manifest.i 00changelog.d 00changelog.i" ) - return ["requires", "00changelog.i"] + ["store/" + f for f in d.split()] + return [b"requires", b"00changelog.i"] + [ + b"store/" + f for f in d.split() + ] def write(self, tr): self.fncache.write(tr) @@ -709,14 +715,14 @@ def __contains__(self, path): """Checks if the store contains path""" - path = "/".join(("data", path)) + path = b"/".join((b"data", path)) # check for files (exact match) - e = path + ".i" + e = path + b".i" if e in self.fncache and self._exists(e): return True # now check for directories (prefix match) - if not path.endswith("/"): - path += "/" + if not path.endswith(b"/"): + path += b"/" for e in self.fncache: if e.startswith(path) and self._exists(e): return True diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py --- a/mercurial/streamclone.py +++ b/mercurial/streamclone.py @@ -40,7 +40,7 @@ bundle2supported = False if pullop.canusebundle2: - if "v2" in pullop.remotebundle2caps.get("stream", []): + if b"v2" in pullop.remotebundle2caps.get(b"stream", []): bundle2supported = True # else # Server doesn't support bundle2 stream clone or doesn't support @@ -67,7 +67,7 @@ # likely only comes into play in LANs. if streamrequested is None: # The server can advertise whether to prefer streaming clone. - streamrequested = remote.capable("stream-preferred") + streamrequested = remote.capable(b"stream-preferred") if not streamrequested: return False, None @@ -80,35 +80,35 @@ # if the only requirement is "revlogv1." Else, the "streamreqs" capability # is advertised and contains a comma-delimited list of requirements. requirements = set() - if remote.capable("stream"): - requirements.add("revlogv1") + if remote.capable(b"stream"): + requirements.add(b"revlogv1") else: - streamreqs = remote.capable("streamreqs") + streamreqs = remote.capable(b"streamreqs") # This is weird and shouldn't happen with modern servers. if not streamreqs: pullop.repo.ui.warn( _( - "warning: stream clone requested but server has them " - "disabled\n" + b"warning: stream clone requested but server has them " + b"disabled\n" ) ) return False, None - streamreqs = set(streamreqs.split(",")) + streamreqs = set(streamreqs.split(b",")) # Server requires something we don't support. Bail. missingreqs = streamreqs - repo.supportedformats if missingreqs: pullop.repo.ui.warn( _( - "warning: stream clone requested but client is missing " - "requirements: %s\n" + b"warning: stream clone requested but client is missing " + b"requirements: %s\n" ) - % ", ".join(sorted(missingreqs)) + % b", ".join(sorted(missingreqs)) ) pullop.repo.ui.warn( _( - "(see https://www.mercurial-scm.org/wiki/MissingRequirement " - "for more information)\n" + b"(see https://www.mercurial-scm.org/wiki/MissingRequirement " + b"for more information)\n" ) ) return False, None @@ -139,14 +139,14 @@ # Save remote branchmap. We will use it later to speed up branchcache # creation. rbranchmap = None - if remote.capable("branchmap"): + if remote.capable(b"branchmap"): with remote.commandexecutor() as e: - rbranchmap = e.callcommand("branchmap", {}).result() + rbranchmap = e.callcommand(b"branchmap", {}).result() - repo.ui.status(_("streaming all changes\n")) + repo.ui.status(_(b"streaming all changes\n")) with remote.commandexecutor() as e: - fp = e.callcommand("stream_out", {}).result() + fp = e.callcommand(b"stream_out", {}).result() # TODO strictly speaking, this code should all be inside the context # manager because the context manager is supposed to ensure all wire state @@ -157,21 +157,21 @@ resp = int(l) except ValueError: raise error.ResponseError( - _("unexpected response from remote server:"), l + _(b"unexpected response from remote server:"), l ) if resp == 1: - raise error.Abort(_("operation forbidden by server")) + raise error.Abort(_(b"operation forbidden by server")) elif resp == 2: - raise error.Abort(_("locking the remote repository failed")) + raise error.Abort(_(b"locking the remote repository failed")) elif resp != 0: - raise error.Abort(_("the server sent an unknown error code")) + raise error.Abort(_(b"the server sent an unknown error code")) l = fp.readline() try: - filecount, bytecount = map(int, l.split(" ", 1)) + filecount, bytecount = map(int, l.split(b" ", 1)) except (ValueError, TypeError): raise error.ResponseError( - _("unexpected response from remote server:"), l + _(b"unexpected response from remote server:"), l ) with repo.lock(): @@ -199,14 +199,14 @@ if repository.REPO_FEATURE_STREAM_CLONE not in repo.features: return False - if not repo.ui.configbool("server", "uncompressed", untrusted=True): + if not repo.ui.configbool(b"server", b"uncompressed", untrusted=True): return False # The way stream clone works makes it impossible to hide secret changesets. # So don't allow this by default. secret = phases.hassecret(repo) if secret: - return repo.ui.configbool("server", "uncompressedallowsecret") + return repo.ui.configbool(b"server", b"uncompressedallowsecret") return True @@ -239,14 +239,14 @@ total_bytes = 0 # Get consistent snapshot of repo, lock during scan. with repo.lock(): - repo.ui.debug("scanning\n") + repo.ui.debug(b"scanning\n") for name, ename, size in _walkstreamfiles(repo): if size: entries.append((name, size)) total_bytes += size repo.ui.debug( - "%d files, %d bytes to transfer\n" % (len(entries), total_bytes) + b"%d files, %d bytes to transfer\n" % (len(entries), total_bytes) ) svfs = repo.svfs @@ -255,12 +255,12 @@ def emitrevlogdata(): for name, size in entries: if debugflag: - repo.ui.debug("sending %s (%d bytes)\n" % (name, size)) + repo.ui.debug(b"sending %s (%d bytes)\n" % (name, size)) # partially encode name over the wire for backwards compat - yield "%s\0%d\n" % (store.encodedir(name), size) + yield b"%s\0%d\n" % (store.encodedir(name), size) # auditing at this stage is both pointless (paths are already # trusted by the local repo) and expensive - with svfs(name, "rb", auditpath=False) as fp: + with svfs(name, b"rb", auditpath=False) as fp: if size <= 65536: yield fp.read(size) else: @@ -282,23 +282,23 @@ a permissions error for the server process). """ if not allowservergeneration(repo): - yield "1\n" + yield b"1\n" return try: filecount, bytecount, it = generatev1(repo) except error.LockError: - yield "2\n" + yield b"2\n" return # Indicates successful response. - yield "0\n" - yield "%d %d\n" % (filecount, bytecount) + yield b"0\n" + yield b"%d %d\n" % (filecount, bytecount) for chunk in it: yield chunk -def generatebundlev1(repo, compression="UN"): +def generatebundlev1(repo, compression=b"UN"): """Emit content for version 1 of a stream clone bundle. The first 4 bytes of the output ("HGS1") denote this as stream clone @@ -320,30 +320,30 @@ Returns a tuple of (requirements, data generator). """ - if compression != "UN": - raise ValueError("we do not support the compression argument yet") + if compression != b"UN": + raise ValueError(b"we do not support the compression argument yet") requirements = repo.requirements & repo.supportedformats - requires = ",".join(sorted(requirements)) + requires = b",".join(sorted(requirements)) def gen(): - yield "HGS1" + yield b"HGS1" yield compression filecount, bytecount, it = generatev1(repo) repo.ui.status( - _("writing %d bytes for %d files\n") % (bytecount, filecount) + _(b"writing %d bytes for %d files\n") % (bytecount, filecount) ) - yield struct.pack(">QQ", filecount, bytecount) - yield struct.pack(">H", len(requires) + 1) - yield requires + "\0" + yield struct.pack(b">QQ", filecount, bytecount) + yield struct.pack(b">H", len(requires) + 1) + yield requires + b"\0" # This is where we'll add compression in the future. - assert compression == "UN" + assert compression == b"UN" progress = repo.ui.makeprogress( - _("bundle"), total=bytecount, unit=_("bytes") + _(b"bundle"), total=bytecount, unit=_(b"bytes") ) progress.update(0) @@ -367,11 +367,11 @@ """ with repo.lock(): repo.ui.status( - _("%d files to transfer, %s of data\n") + _(b"%d files to transfer, %s of data\n") % (filecount, util.bytecount(bytecount)) ) progress = repo.ui.makeprogress( - _("clone"), total=bytecount, unit=_("bytes") + _(b"clone"), total=bytecount, unit=_(b"bytes") ) progress.update(0) start = util.timer() @@ -390,25 +390,25 @@ # nesting occurs also in ordinary case (e.g. enabling # clonebundles). - with repo.transaction("clone"): + with repo.transaction(b"clone"): with repo.svfs.backgroundclosing(repo.ui, expectedcount=filecount): for i in pycompat.xrange(filecount): # XXX doesn't support '\n' or '\r' in filenames l = fp.readline() try: - name, size = l.split("\0", 1) + name, size = l.split(b"\0", 1) size = int(size) except (ValueError, TypeError): raise error.ResponseError( - _("unexpected response from remote server:"), l + _(b"unexpected response from remote server:"), l ) if repo.ui.debugflag: repo.ui.debug( - "adding %s (%s)\n" % (name, util.bytecount(size)) + b"adding %s (%s)\n" % (name, util.bytecount(size)) ) # for backwards compat, name was partially encoded path = store.decodedir(name) - with repo.svfs(path, "w", backgroundclose=True) as ofp: + with repo.svfs(path, b"w", backgroundclose=True) as ofp: for chunk in util.filechunkiter(fp, limit=size): progress.increment(step=len(chunk)) ofp.write(chunk) @@ -422,7 +422,7 @@ elapsed = 0.001 progress.complete() repo.ui.status( - _("transferred %s in %.1f seconds (%s/sec)\n") + _(b"transferred %s in %.1f seconds (%s/sec)\n") % ( util.bytecount(bytecount), elapsed, @@ -433,25 +433,28 @@ def readbundle1header(fp): compression = fp.read(2) - if compression != "UN": + if compression != b"UN": raise error.Abort( - _("only uncompressed stream clone bundles are " "supported; got %s") + _( + b"only uncompressed stream clone bundles are " + b"supported; got %s" + ) % compression ) - filecount, bytecount = struct.unpack(">QQ", fp.read(16)) - requireslen = struct.unpack(">H", fp.read(2))[0] + filecount, bytecount = struct.unpack(b">QQ", fp.read(16)) + requireslen = struct.unpack(b">H", fp.read(2))[0] requires = fp.read(requireslen) - if not requires.endswith("\0"): + if not requires.endswith(b"\0"): raise error.Abort( _( - "malformed stream clone bundle: " - "requirements not properly encoded" + b"malformed stream clone bundle: " + b"requirements not properly encoded" ) ) - requirements = set(requires.rstrip("\0").split(",")) + requirements = set(requires.rstrip(b"\0").split(b",")) return filecount, bytecount, requirements @@ -464,15 +467,15 @@ """ if len(repo): raise error.Abort( - _("cannot apply stream clone bundle on non-empty " "repo") + _(b"cannot apply stream clone bundle on non-empty " b"repo") ) filecount, bytecount, requirements = readbundle1header(fp) missingreqs = requirements - repo.supportedformats if missingreqs: raise error.Abort( - _("unable to apply stream clone: " "unsupported format: %s") - % ", ".join(sorted(missingreqs)) + _(b"unable to apply stream clone: " b"unsupported format: %s") + % b", ".join(sorted(missingreqs)) ) consumev1(repo, fp, filecount, bytecount) @@ -497,15 +500,15 @@ _filefull = 1 # full snapshot file # Source of the file -_srcstore = "s" # store (svfs) -_srccache = "c" # cache (cache) +_srcstore = b"s" # store (svfs) +_srccache = b"c" # cache (cache) # This is it's own function so extensions can override it. def _walkstreamfullstorefiles(repo): """list snapshot file from the store""" fnames = [] if not repo.publishing(): - fnames.append("phaseroots") + fnames.append(b"phaseroots") return fnames @@ -553,7 +556,7 @@ """actually emit the stream bundle""" vfsmap = _makemap(repo) progress = repo.ui.makeprogress( - _("bundle"), total=totalfilesize, unit=_("bytes") + _(b"bundle"), total=totalfilesize, unit=_(b"bytes") ) progress.update(0) with maketempcopies() as copy, progress: @@ -570,7 +573,7 @@ fp = vfs(name) size = data elif ftype == _filefull: - fp = open(data, "rb") + fp = open(data, b"rb") size = util.fstat(fp).st_size try: yield util.uvarintencode(size) @@ -609,7 +612,7 @@ if includes or excludes: matcher = narrowspec.match(repo.root, includes, excludes) - repo.ui.debug("scanning\n") + repo.ui.debug(b"scanning\n") for name, ename, size in _walkstreamfiles(repo, matcher): if size: entries.append((_srcstore, name, _fileappend, size)) @@ -618,9 +621,9 @@ if repo.svfs.exists(name): totalfilesize += repo.svfs.lstat(name).st_size entries.append((_srcstore, name, _filefull, None)) - if includeobsmarkers and repo.svfs.exists("obsstore"): - totalfilesize += repo.svfs.lstat("obsstore").st_size - entries.append((_srcstore, "obsstore", _filefull, None)) + if includeobsmarkers and repo.svfs.exists(b"obsstore"): + totalfilesize += repo.svfs.lstat(b"obsstore").st_size + entries.append((_srcstore, b"obsstore", _filefull, None)) for name in cacheutil.cachetocopy(repo): if repo.cachevfs.exists(name): totalfilesize += repo.cachevfs.lstat(name).st_size @@ -653,19 +656,19 @@ """ with repo.lock(): repo.ui.status( - _("%d files to transfer, %s of data\n") + _(b"%d files to transfer, %s of data\n") % (filecount, util.bytecount(filesize)) ) start = util.timer() progress = repo.ui.makeprogress( - _("clone"), total=filesize, unit=_("bytes") + _(b"clone"), total=filesize, unit=_(b"bytes") ) progress.update(0) vfsmap = _makemap(repo) - with repo.transaction("clone"): + with repo.transaction(b"clone"): ctxs = (vfs.backgroundclosing(repo.ui) for vfs in vfsmap.values()) with nested(*ctxs): for i in range(filecount): @@ -678,11 +681,11 @@ if repo.ui.debugflag: repo.ui.debug( - "adding [%s] %s (%s)\n" + b"adding [%s] %s (%s)\n" % (src, name, util.bytecount(datalen)) ) - with vfs(name, "w") as ofp: + with vfs(name, b"w") as ofp: for chunk in util.filechunkiter(fp, limit=datalen): progress.increment(step=len(chunk)) ofp.write(chunk) @@ -695,7 +698,7 @@ if elapsed <= 0: elapsed = 0.001 repo.ui.status( - _("transferred %s in %.1f seconds (%s/sec)\n") + _(b"transferred %s in %.1f seconds (%s/sec)\n") % ( util.bytecount(progress.pos), elapsed, @@ -711,8 +714,8 @@ missingreqs = [r for r in requirements if r not in repo.supported] if missingreqs: raise error.Abort( - _("unable to apply stream clone: " "unsupported format: %s") - % ", ".join(sorted(missingreqs)) + _(b"unable to apply stream clone: " b"unsupported format: %s") + % b", ".join(sorted(missingreqs)) ) consumev2(repo, fp, filecount, filesize) diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -84,8 +84,8 @@ subrepo = subrelpath(self) errormsg = ( stringutil.forcebytestr(ex) - + " " - + _('(in subrepository "%s")') % subrepo + + b" " + + _(b'(in subrepository "%s")') % subrepo ) # avoid handling this exception by raising a SubrepoAbort exception raise SubrepoAbort( @@ -99,18 +99,18 @@ def _updateprompt(ui, sub, dirty, local, remote): if dirty: msg = _( - " subrepository sources for %s differ\n" - "you can use (l)ocal source (%s) or (r)emote source (%s).\n" - "what do you want to do?" - "$$ &Local $$ &Remote" + b" subrepository sources for %s differ\n" + b"you can use (l)ocal source (%s) or (r)emote source (%s).\n" + b"what do you want to do?" + b"$$ &Local $$ &Remote" ) % (subrelpath(sub), local, remote) else: msg = _( - " subrepository sources for %s differ (in checked out " - "version)\n" - "you can use (l)ocal source (%s) or (r)emote source (%s).\n" - "what do you want to do?" - "$$ &Local $$ &Remote" + b" subrepository sources for %s differ (in checked out " + b"version)\n" + b"you can use (l)ocal source (%s) or (r)emote source (%s).\n" + b"what do you want to do?" + b"$$ &Local $$ &Remote" ) % (subrelpath(sub), local, remote) return ui.promptchoice(msg, 0) @@ -121,14 +121,14 @@ if d.lower() == ignore: del dirs[i] break - if vfs.basename(dirname).lower() != ".hg": + if vfs.basename(dirname).lower() != b".hg": continue for f in names: - if f.lower() == "hgrc": + if f.lower() == b"hgrc": ui.warn( _( - "warning: removing potentially hostile 'hgrc' " - "in '%s'\n" + b"warning: removing potentially hostile 'hgrc' " + b"in '%s'\n" ) % vfs.join(dirname) ) @@ -137,41 +137,41 @@ def _auditsubrepopath(repo, path): # sanity check for potentially unsafe paths such as '~' and '$FOO' - if path.startswith("~") or "$" in path or util.expandpath(path) != path: + if path.startswith(b"~") or b"$" in path or util.expandpath(path) != path: raise error.Abort( - _("subrepo path contains illegal component: %s") % path + _(b"subrepo path contains illegal component: %s") % path ) # auditor doesn't check if the path itself is a symlink pathutil.pathauditor(repo.root)(path) if repo.wvfs.islink(path): - raise error.Abort(_("subrepo '%s' traverses symbolic link") % path) + raise error.Abort(_(b"subrepo '%s' traverses symbolic link") % path) SUBREPO_ALLOWED_DEFAULTS = { - "hg": True, - "git": False, - "svn": False, + b"hg": True, + b"git": False, + b"svn": False, } def _checktype(ui, kind): # subrepos.allowed is a master kill switch. If disabled, subrepos are # disabled period. - if not ui.configbool("subrepos", "allowed", True): + if not ui.configbool(b"subrepos", b"allowed", True): raise error.Abort( - _("subrepos not enabled"), - hint=_("see 'hg help config.subrepos' for details"), + _(b"subrepos not enabled"), + hint=_(b"see 'hg help config.subrepos' for details"), ) default = SUBREPO_ALLOWED_DEFAULTS.get(kind, False) - if not ui.configbool("subrepos", "%s:allowed" % kind, default): + if not ui.configbool(b"subrepos", b"%s:allowed" % kind, default): raise error.Abort( - _("%s subrepos not allowed") % kind, - hint=_("see 'hg help config.subrepos' for details"), + _(b"%s subrepos not allowed") % kind, + hint=_(b"see 'hg help config.subrepos' for details"), ) if kind not in types: - raise error.Abort(_("unknown subrepo type %s") % kind) + raise error.Abort(_(b"unknown subrepo type %s") % kind) def subrepo(ctx, path, allowwdir=False, allowcreate=True): @@ -209,9 +209,9 @@ _auditsubrepopath(repo, path) state = ctx.substate[path] _checktype(repo.ui, state[2]) - subrev = "" - if state[2] == "hg": - subrev = "0" * 40 + subrev = b"" + if state[2] == b"hg": + subrev = b"0" * 40 return types[state[2]](pctx, path, (state[0], subrev), True) @@ -265,7 +265,7 @@ This returns None, otherwise. """ if self.dirty(ignoreupdate=ignoreupdate, missing=missing): - return _('uncommitted changes in subrepository "%s"') % subrelpath( + return _(b'uncommitted changes in subrepository "%s"') % subrelpath( self ) @@ -325,7 +325,7 @@ return [] def addremove(self, matcher, prefix, uipathfn, opts): - self.ui.warn("%s: %s" % (prefix, _("addremove is not supported"))) + self.ui.warn(b"%s: %s" % (prefix, _(b"addremove is not supported"))) return 1 def cat(self, match, fm, fntemplate, prefix, **opts): @@ -353,7 +353,7 @@ def fileflags(self, name): """return file flags""" - return "" + return b"" def matchfileset(self, expr, badfn=None): """Resolve the fileset expression for this repo""" @@ -371,13 +371,13 @@ total = len(files) relpath = subrelpath(self) progress = self.ui.makeprogress( - _("archiving (%s)") % relpath, unit=_("files"), total=total + _(b"archiving (%s)") % relpath, unit=_(b"files"), total=total ) progress.update(0) for name in files: flags = self.fileflags(name) - mode = "x" in flags and 0o755 or 0o644 - symlink = "l" in flags + mode = b"x" in flags and 0o755 or 0o644 + symlink = b"l" in flags archiver.addfile( prefix + name, mode, symlink, self.filedata(name, decode) ) @@ -410,13 +410,13 @@ filesystem. Return 0 on success, 1 on any warning. """ warnings.append( - _("warning: removefiles not implemented (%s)") % self._path + _(b"warning: removefiles not implemented (%s)") % self._path ) return 1 def revert(self, substate, *pats, **opts): self.ui.warn( - _("%s: reverting %s subrepos is unsupported\n") + _(b"%s: reverting %s subrepos is unsupported\n") % (substate[0], substate[2]) ) return [] @@ -454,18 +454,18 @@ self._state = state r = ctx.repo() root = r.wjoin(util.localpath(path)) - create = allowcreate and not r.wvfs.exists("%s/.hg" % path) + create = allowcreate and not r.wvfs.exists(b"%s/.hg" % path) # repository constructor does expand variables in path, which is # unsafe since subrepo path might come from untrusted source. if os.path.realpath(util.expandpath(root)) != root: raise error.Abort( - _("subrepo path contains illegal component: %s") % path + _(b"subrepo path contains illegal component: %s") % path ) self._repo = hg.repository(r.baseui, root, create=create) if self._repo.root != root: raise error.ProgrammingError( - "failed to reject unsafe subrepo " - "path: %s (expanded to %s)" % (root, self._repo.root) + b"failed to reject unsafe subrepo " + b"path: %s (expanded to %s)" % (root, self._repo.root) ) # Propagate the parent's --hidden option @@ -473,12 +473,12 @@ self._repo = self._repo.unfiltered() self.ui = self._repo.ui - for s, k in [("ui", "commitsubrepos")]: + for s, k in [(b"ui", b"commitsubrepos")]: v = r.ui.config(s, k) if v: - self.ui.setconfig(s, k, v, "subrepo") + self.ui.setconfig(s, k, v, b"subrepo") # internal config: ui._usedassubrepo - self.ui.setconfig("ui", "_usedassubrepo", "True", "subrepo") + self.ui.setconfig(b"ui", b"_usedassubrepo", b"True", b"subrepo") self._initrepo(r, state[0], create) @annotatesubrepoerror @@ -508,21 +508,21 @@ This method is used to to detect when there are changes that may require a push to a given remote path.""" # sort the files that will be hashed in increasing (likely) file size - filelist = ("bookmarks", "store/phaseroots", "store/00changelog.i") - yield "# %s\n" % _expandedabspath(remotepath) + filelist = (b"bookmarks", b"store/phaseroots", b"store/00changelog.i") + yield b"# %s\n" % _expandedabspath(remotepath) vfs = self._repo.vfs for relname in filelist: filehash = node.hex(hashlib.sha1(vfs.tryread(relname)).digest()) - yield "%s = %s\n" % (relname, filehash) + yield b"%s = %s\n" % (relname, filehash) @propertycache def _cachestorehashvfs(self): - return vfsmod.vfs(self._repo.vfs.join("cache/storehash")) + return vfsmod.vfs(self._repo.vfs.join(b"cache/storehash")) def _readstorehashcache(self, remotepath): """read the store hash cache for a given remote repository""" cachefile = _getstorehashcachename(remotepath) - return self._cachestorehashvfs.tryreadlines(cachefile, "r") + return self._cachestorehashvfs.tryreadlines(cachefile, b"r") def _cachestorehash(self, remotepath): """cache the current store hash @@ -534,7 +534,7 @@ with self._repo.lock(): storehash = list(self._calcstorehash(remotepath)) vfs = self._cachestorehashvfs - vfs.writelines(cachefile, storehash, mode="wb", notindexed=True) + vfs.writelines(cachefile, storehash, mode=b"wb", notindexed=True) def _getctx(self): """fetch the context for this subrepo revision, possibly a workingctx @@ -551,20 +551,20 @@ self._repo._subsource = source if create: - lines = ["[paths]\n"] + lines = [b"[paths]\n"] def addpathconfig(key, value): if value: - lines.append("%s = %s\n" % (key, value)) - self.ui.setconfig("paths", key, value, "subrepo") + lines.append(b"%s = %s\n" % (key, value)) + self.ui.setconfig(b"paths", key, value, b"subrepo") defpath = _abssource(self._repo, abort=False) defpushpath = _abssource(self._repo, True, abort=False) - addpathconfig("default", defpath) + addpathconfig(b"default", defpath) if defpath != defpushpath: - addpathconfig("default-push", defpushpath) + addpathconfig(b"default-push", defpushpath) - self._repo.vfs.write("hgrc", util.tonativeeol("".join(lines))) + self._repo.vfs.write(b"hgrc", util.tonativeeol(b"".join(lines))) @annotatesubrepoerror def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): @@ -578,7 +578,7 @@ # always entry any of its subrepos. Don't corrupt the options that will # be used to process sibling subrepos however. opts = copy.copy(opts) - opts["subrepos"] = True + opts[b"subrepos"] = True return scmutil.addremove(self._repo, m, prefix, uipathfn, opts) @annotatesubrepoerror @@ -598,7 +598,7 @@ return self._repo.status(ctx1, ctx2, **opts) except error.RepoLookupError as inst: self.ui.warn( - _('warning: error "%s" in subrepository "%s"\n') + _(b'warning: error "%s" in subrepository "%s"\n') % (inst, subrelpath(self)) ) return scmutil.status([], [], [], [], [], [], []) @@ -624,13 +624,13 @@ ) except error.RepoLookupError as inst: self.ui.warn( - _('warning: error "%s" in subrepository "%s"\n') + _(b'warning: error "%s" in subrepository "%s"\n') % (inst, subrelpath(self)) ) @annotatesubrepoerror def archive(self, archiver, prefix, match=None, decode=True): - self._get(self._state + ("hg",)) + self._get(self._state + (b"hg",)) files = self.files() if match: files = [f for f in files if match(f)] @@ -643,14 +643,14 @@ for subpath in ctx.substate: s = subrepo(ctx, subpath, True) submatch = matchmod.subdirmatcher(subpath, match) - subprefix = prefix + subpath + "/" + subprefix = prefix + subpath + b"/" total += s.archive(archiver, subprefix, submatch, decode) return total @annotatesubrepoerror def dirty(self, ignoreupdate=False, missing=False): r = self._state[1] - if r == "" and not ignoreupdate: # no state recorded + if r == b"" and not ignoreupdate: # no state recorded return True w = self._repo[None] if r != w.p1().hex() and not ignoreupdate: @@ -659,7 +659,7 @@ return w.dirty(missing=missing) # working directory changed def basestate(self): - return self._repo["."].hex() + return self._repo[b"."].hex() def checknested(self, path): return self._repo._checknested(self._repo.wjoin(path)) @@ -669,22 +669,22 @@ # don't bother committing in the subrepo if it's only been # updated if not self.dirty(True): - return self._repo["."].hex() - self.ui.debug("committing subrepo %s\n" % subrelpath(self)) + return self._repo[b"."].hex() + self.ui.debug(b"committing subrepo %s\n" % subrelpath(self)) n = self._repo.commit(text, user, date) if not n: - return self._repo["."].hex() # different version checked out + return self._repo[b"."].hex() # different version checked out return node.hex(n) @annotatesubrepoerror def phase(self, state): - return self._repo[state or "."].phase() + return self._repo[state or b"."].phase() @annotatesubrepoerror def remove(self): # we can't fully delete the repository as it may contain # local-only history - self.ui.note(_("removing subrepo %s\n") % subrelpath(self)) + self.ui.note(_(b"removing subrepo %s\n") % subrelpath(self)) hg.clean(self._repo, node.nullid, False) def _get(self, state): @@ -713,7 +713,7 @@ # work with that. if parentrepo.shared() and hg.islocal(srcurl): self.ui.status( - _("sharing subrepo %s from %s\n") + _(b"sharing subrepo %s from %s\n") % (subrelpath(self), srcurl) ) shared = hg.share( @@ -728,19 +728,19 @@ # TODO: find a common place for this and this code in the # share.py wrap of the clone command. if parentrepo.shared(): - pool = self.ui.config("share", "pool") + pool = self.ui.config(b"share", b"pool") if pool: pool = util.expandpath(pool) shareopts = { - "pool": pool, - "mode": self.ui.config("share", "poolnaming"), + b"pool": pool, + b"mode": self.ui.config(b"share", b"poolnaming"), } else: shareopts = {} self.ui.status( - _("cloning subrepo %s from %s\n") + _(b"cloning subrepo %s from %s\n") % (subrelpath(self), util.hidepassword(srcurl)) ) other, cloned = hg.clone( @@ -756,7 +756,7 @@ self._cachestorehash(srcurl) else: self.ui.status( - _("pulling subrepo %s from %s\n") + _(b"pulling subrepo %s from %s\n") % (subrelpath(self), util.hidepassword(srcurl)) ) cleansub = self.storeclean(srcurl) @@ -771,13 +771,13 @@ inrepo = self._get(state) source, revision, kind = state repo = self._repo - repo.ui.debug("getting subrepo %s\n" % self._path) + repo.ui.debug(b"getting subrepo %s\n" % self._path) if inrepo: urepo = repo.unfiltered() ctx = urepo[revision] if ctx.hidden(): urepo.ui.warn( - _('revision %s in subrepository "%s" is hidden\n') + _(b'revision %s in subrepository "%s" is hidden\n') % (revision[0:12], self._path) ) repo = urepo @@ -786,22 +786,24 @@ @annotatesubrepoerror def merge(self, state): self._get(state) - cur = self._repo["."] + cur = self._repo[b"."] dst = self._repo[state[1]] anc = dst.ancestor(cur) def mergefunc(): if anc == cur and dst.branch() == cur.branch(): self.ui.debug( - 'updating subrepository "%s"\n' % subrelpath(self) + b'updating subrepository "%s"\n' % subrelpath(self) ) hg.update(self._repo, state[1]) elif anc == dst: self.ui.debug( - 'skipping subrepository "%s"\n' % subrelpath(self) + b'skipping subrepository "%s"\n' % subrelpath(self) ) else: - self.ui.debug('merging subrepository "%s"\n' % subrelpath(self)) + self.ui.debug( + b'merging subrepository "%s"\n' % subrelpath(self) + ) hg.merge(self._repo, state[1], remind=False) wctx = self._repo[None] @@ -816,12 +818,12 @@ @annotatesubrepoerror def push(self, opts): - force = opts.get("force") - newbranch = opts.get("new_branch") - ssh = opts.get("ssh") + force = opts.get(b"force") + newbranch = opts.get(b"new_branch") + ssh = opts.get(b"ssh") # push subrepos depth-first for coherent ordering - c = self._repo["."] + c = self._repo[b"."] subs = c.substate # only repos that are committed for s in sorted(subs): if c.sub(s).push(opts) == 0: @@ -831,15 +833,15 @@ if not force: if self.storeclean(dsturl): self.ui.status( - _("no changes made to subrepo %s since last push to %s\n") + _(b"no changes made to subrepo %s since last push to %s\n") % (subrelpath(self), util.hidepassword(dsturl)) ) return None self.ui.status( - _("pushing subrepo %s to %s\n") + _(b"pushing subrepo %s to %s\n") % (subrelpath(self), util.hidepassword(dsturl)) ) - other = hg.peer(self._repo, {"ssh": ssh}, dsturl) + other = hg.peer(self._repo, {b"ssh": ssh}, dsturl) res = exchange.push(self._repo, other, force, newbranch=newbranch) # the repo is now clean @@ -848,18 +850,18 @@ @annotatesubrepoerror def outgoing(self, ui, dest, opts): - if "rev" in opts or "branch" in opts: + if b"rev" in opts or b"branch" in opts: opts = copy.copy(opts) - opts.pop("rev", None) - opts.pop("branch", None) + opts.pop(b"rev", None) + opts.pop(b"branch", None) return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts) @annotatesubrepoerror def incoming(self, ui, source, opts): - if "rev" in opts or "branch" in opts: + if b"rev" in opts or b"branch" in opts: opts = copy.copy(opts) - opts.pop("rev", None) - opts.pop("branch", None) + opts.pop(b"rev", None) + opts.pop(b"branch", None) return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts) @annotatesubrepoerror @@ -910,7 +912,7 @@ matchers.append(pm) except error.LookupError: self.ui.status( - _("skipping missing subrepository: %s\n") + _(b"skipping missing subrepository: %s\n") % self.wvfs.reljoin(reporelpath(self), subpath) ) if len(matchers) == 1: @@ -965,7 +967,7 @@ # files inside the subrepo # 2. update the subrepo to the revision specified in # the corresponding substate dictionary - self.ui.status(_("reverting subrepo %s\n") % substate[0]) + self.ui.status(_(b"reverting subrepo %s\n") % substate[0]) if not opts.get(r"no_backup"): # Revert all files on the subrepo, creating backups # Note that this will not recursively revert subrepos @@ -984,7 +986,7 @@ ctx = self._repo[opts[r"rev"]] parents = self._repo.dirstate.parents() if opts.get(r"all"): - pats = ["set:modified()"] + pats = [b"set:modified()"] else: pats = [] cmdutil.revert(self.ui, self._repo, ctx, parents, *pats, **opts) @@ -1007,7 +1009,7 @@ # subrepo. Alternately, the previous unshare attempt may have failed # part way through. So recurse whether or not this layer is shared. if self._repo.shared(): - self.ui.status(_("unsharing subrepo '%s'\n") % self._relpath) + self.ui.status(_(b"unsharing subrepo '%s'\n") % self._relpath) hg.unshare(self.ui, self._repo) @@ -1020,7 +1022,7 @@ # explicit warning. ui = self._repo.ui ui.warn( - _("subrepo '%s' is hidden in revision %s\n") + _(b"subrepo '%s' is hidden in revision %s\n") % (self._relpath, node.short(self._ctx.node())) ) return 0 @@ -1028,7 +1030,7 @@ # A missing subrepo revision may be a case of needing to pull it, so # don't treat this as an error. self._repo.ui.warn( - _("subrepo '%s' not found in revision %s\n") + _(b"subrepo '%s' not found in revision %s\n") % (self._relpath, node.short(self._ctx.node())) ) return 0 @@ -1051,13 +1053,13 @@ def __init__(self, ctx, path, state, allowcreate): super(svnsubrepo, self).__init__(ctx, path) self._state = state - self._exe = procutil.findexe("svn") + self._exe = procutil.findexe(b"svn") if not self._exe: raise error.Abort( - _("'svn' executable not found for subrepo '%s'") % self._path + _(b"'svn' executable not found for subrepo '%s'") % self._path ) - def _svncommand(self, commands, filename="", failok=False): + def _svncommand(self, commands, filename=b"", failok=False): cmd = [self._exe] extrakw = {} if not self.ui.interactive(): @@ -1068,8 +1070,8 @@ # instead of being per-command, but we need to support 1.4 so # we have to be intelligent about what commands take # --non-interactive. - if commands[0] in ("update", "checkout", "commit"): - cmd.append("--non-interactive") + if commands[0] in (b"update", b"checkout", b"commit"): + cmd.append(b"--non-interactive") cmd.extend(commands) if filename is not None: path = self.wvfs.reljoin( @@ -1078,11 +1080,11 @@ cmd.append(path) env = dict(encoding.environ) # Avoid localized output, preserve current locale for everything else. - lc_all = env.get("LC_ALL") + lc_all = env.get(b"LC_ALL") if lc_all: - env["LANG"] = lc_all - del env["LC_ALL"] - env["LC_MESSAGES"] = "C" + env[b"LANG"] = lc_all + del env[b"LC_ALL"] + env[b"LC_MESSAGES"] = b"C" p = subprocess.Popen( pycompat.rapply(procutil.tonativestr, cmd), bufsize=-1, @@ -1097,38 +1099,40 @@ if not failok: if p.returncode: raise error.Abort( - stderr or "exited with code %d" % p.returncode + stderr or b"exited with code %d" % p.returncode ) if stderr: - self.ui.warn(stderr + "\n") + self.ui.warn(stderr + b"\n") return stdout, stderr @propertycache def _svnversion(self): - output, err = self._svncommand(["--version", "--quiet"], filename=None) + output, err = self._svncommand( + [b"--version", b"--quiet"], filename=None + ) m = re.search(br"^(\d+)\.(\d+)", output) if not m: - raise error.Abort(_("cannot retrieve svn tool version")) + raise error.Abort(_(b"cannot retrieve svn tool version")) return (int(m.group(1)), int(m.group(2))) def _svnmissing(self): - return not self.wvfs.exists(".svn") + return not self.wvfs.exists(b".svn") def _wcrevs(self): # Get the working directory revision as well as the last # commit revision so we can compare the subrepo state with # both. We used to store the working directory one. - output, err = self._svncommand(["info", "--xml"]) + output, err = self._svncommand([b"info", b"--xml"]) doc = xml.dom.minidom.parseString(output) entries = doc.getElementsByTagName(r"entry") - lastrev, rev = "0", "0" + lastrev, rev = b"0", b"0" if entries: - rev = pycompat.bytestr(entries[0].getAttribute(r"revision")) or "0" + rev = pycompat.bytestr(entries[0].getAttribute(r"revision")) or b"0" commits = entries[0].getElementsByTagName(r"commit") if commits: lastrev = ( pycompat.bytestr(commits[0].getAttribute(r"revision")) - or "0" + or b"0" ) return (lastrev, rev) @@ -1141,7 +1145,7 @@ True if any of these changes concern an external entry and missing is True if any change is a missing entry. """ - output, err = self._svncommand(["status", "--xml"]) + output, err = self._svncommand([b"status", b"--xml"]) externals, changes, missing = [], [], [] doc = xml.dom.minidom.parseString(output) for e in doc.getElementsByTagName(r"entry"): @@ -1171,7 +1175,7 @@ @annotatesubrepoerror def dirty(self, ignoreupdate=False, missing=False): if self._svnmissing(): - return self._state[1] != "" + return self._state[1] != b"" wcchanged = self._wcchanged() changed = wcchanged[0] or (missing and wcchanged[2]) if not changed: @@ -1187,7 +1191,9 @@ # URL exists at lastrev. Test it and fallback to rev it # is not there. try: - self._svncommand(["list", "%s@%s" % (self._state[0], lastrev)]) + self._svncommand( + [b"list", b"%s@%s" % (self._state[0], lastrev)] + ) return lastrev except error.Abort: pass @@ -1201,35 +1207,35 @@ return self.basestate() if extchanged: # Do not try to commit externals - raise error.Abort(_("cannot commit svn externals")) + raise error.Abort(_(b"cannot commit svn externals")) if missing: # svn can commit with missing entries but aborting like hg # seems a better approach. - raise error.Abort(_("cannot commit missing svn entries")) - commitinfo, err = self._svncommand(["commit", "-m", text]) + raise error.Abort(_(b"cannot commit missing svn entries")) + commitinfo, err = self._svncommand([b"commit", b"-m", text]) self.ui.status(commitinfo) - newrev = re.search("Committed revision ([0-9]+).", commitinfo) + newrev = re.search(b"Committed revision ([0-9]+).", commitinfo) if not newrev: if not commitinfo.strip(): # Sometimes, our definition of "changed" differs from # svn one. For instance, svn ignores missing files # when committing. If there are only missing files, no # commit is made, no output and no error code. - raise error.Abort(_("failed to commit svn changes")) + raise error.Abort(_(b"failed to commit svn changes")) raise error.Abort(commitinfo.splitlines()[-1]) newrev = newrev.groups()[0] - self.ui.status(self._svncommand(["update", "-r", newrev])[0]) + self.ui.status(self._svncommand([b"update", b"-r", newrev])[0]) return newrev @annotatesubrepoerror def remove(self): if self.dirty(): self.ui.warn( - _("not removing repo %s because " "it has changes.\n") + _(b"not removing repo %s because " b"it has changes.\n") % self._path ) return - self.ui.note(_("removing subrepo %s\n") % self._path) + self.ui.note(_(b"removing subrepo %s\n") % self._path) self.wvfs.rmtree(forcibly=True) try: @@ -1241,21 +1247,21 @@ @annotatesubrepoerror def get(self, state, overwrite=False): if overwrite: - self._svncommand(["revert", "--recursive"]) - args = ["checkout"] + self._svncommand([b"revert", b"--recursive"]) + args = [b"checkout"] if self._svnversion >= (1, 5): - args.append("--force") + args.append(b"--force") # The revision must be specified at the end of the URL to properly # update to a directory which has since been deleted and recreated. - args.append("%s@%s" % (state[0], state[1])) + args.append(b"%s@%s" % (state[0], state[1])) # SEC: check that the ssh url is safe util.checksafessh(state[0]) status, err = self._svncommand(args, failok=True) - _sanitize(self.ui, self.wvfs, ".svn") - if not re.search("Checked out revision [0-9]+.", status): - if "is already a working copy for a different URL" in err and ( + _sanitize(self.ui, self.wvfs, b".svn") + if not re.search(b"Checked out revision [0-9]+.", status): + if b"is already a working copy for a different URL" in err and ( self._wcchanged()[:2] == (False, False) ): # obstructed but clean working copy, so just blow it away. @@ -1281,12 +1287,12 @@ @annotatesubrepoerror def files(self): - output = self._svncommand(["list", "--recursive", "--xml"])[0] + output = self._svncommand([b"list", b"--recursive", b"--xml"])[0] doc = xml.dom.minidom.parseString(output) paths = [] for e in doc.getElementsByTagName(r"entry"): kind = pycompat.bytestr(e.getAttribute(r"kind")) - if kind != "file": + if kind != b"file": continue name = r"".join( c.data @@ -1297,7 +1303,7 @@ return paths def filedata(self, name, decode): - return self._svncommand(["cat"], name)[0] + return self._svncommand([b"cat"], name)[0] class gitsubrepo(abstractsubrepo): @@ -1310,25 +1316,25 @@ def _ensuregit(self): try: - self._gitexecutable = "git" - out, err = self._gitnodir(["--version"]) + self._gitexecutable = b"git" + out, err = self._gitnodir([b"--version"]) except OSError as e: - genericerror = _("error executing git for subrepo '%s': %s") - notfoundhint = _("check git is installed and in your PATH") + genericerror = _(b"error executing git for subrepo '%s': %s") + notfoundhint = _(b"check git is installed and in your PATH") if e.errno != errno.ENOENT: raise error.Abort( genericerror % (self._path, encoding.strtolocal(e.strerror)) ) elif pycompat.iswindows: try: - self._gitexecutable = "git.cmd" - out, err = self._gitnodir(["--version"]) + self._gitexecutable = b"git.cmd" + out, err = self._gitnodir([b"--version"]) except OSError as e2: if e2.errno == errno.ENOENT: raise error.Abort( _( - "couldn't find 'git' or 'git.cmd'" - " for subrepo '%s'" + b"couldn't find 'git' or 'git.cmd'" + b" for subrepo '%s'" ) % self._path, hint=notfoundhint, @@ -1340,16 +1346,18 @@ ) else: raise error.Abort( - _("couldn't find git for subrepo '%s'") % self._path, + _(b"couldn't find git for subrepo '%s'") % self._path, hint=notfoundhint, ) versionstatus = self._checkversion(out) - if versionstatus == "unknown": - self.ui.warn(_("cannot retrieve git version\n")) - elif versionstatus == "abort": - raise error.Abort(_("git subrepo requires at least 1.6.0 or later")) - elif versionstatus == "warning": - self.ui.warn(_("git subrepo requires at least 1.6.0 or later\n")) + if versionstatus == b"unknown": + self.ui.warn(_(b"cannot retrieve git version\n")) + elif versionstatus == b"abort": + raise error.Abort( + _(b"git subrepo requires at least 1.6.0 or later") + ) + elif versionstatus == b"warning": + self.ui.warn(_(b"git subrepo requires at least 1.6.0 or later\n")) @staticmethod def _gitversion(out): @@ -1392,12 +1400,12 @@ # despite the docstring comment. For now, error on 1.4.0, warn on # 1.5.0 but attempt to continue. if version == -1: - return "unknown" + return b"unknown" if version < (1, 5, 0): - return "abort" + return b"abort" elif version < (1, 6, 0): - return "warning" - return "ok" + return b"warning" + return b"ok" def _gitcommand(self, commands, env=None, stream=False): return self._gitdir(commands, env=env, stream=stream)[0] @@ -1413,23 +1421,23 @@ The methods tries to call the git command. versions prior to 1.6.0 are not supported and very probably fail. """ - self.ui.debug("%s: git %s\n" % (self._relpath, " ".join(commands))) + self.ui.debug(b"%s: git %s\n" % (self._relpath, b" ".join(commands))) if env is None: env = encoding.environ.copy() # disable localization for Git output (issue5176) - env["LC_ALL"] = "C" + env[b"LC_ALL"] = b"C" # fix for Git CVE-2015-7545 - if "GIT_ALLOW_PROTOCOL" not in env: - env["GIT_ALLOW_PROTOCOL"] = "file:git:http:https:ssh" + if b"GIT_ALLOW_PROTOCOL" not in env: + env[b"GIT_ALLOW_PROTOCOL"] = b"file:git:http:https:ssh" # unless ui.quiet is set, print git's stderr, # which is mostly progress and useful info errpipe = None if self.ui.quiet: - errpipe = open(os.devnull, "w") - if self.ui._colormode and len(commands) and commands[0] == "diff": + errpipe = open(os.devnull, b"w") + if self.ui._colormode and len(commands) and commands[0] == b"diff": # insert the argument in the front, # the end of git diff arguments is used for paths - commands.insert(1, "--color") + commands.insert(1, b"--color") p = subprocess.Popen( pycompat.rapply( procutil.tonativestr, [self._gitexecutable] + commands @@ -1451,50 +1459,50 @@ if p.returncode != 0 and p.returncode != 1: # there are certain error codes that are ok command = commands[0] - if command in ("cat-file", "symbolic-ref"): + if command in (b"cat-file", b"symbolic-ref"): return retdata, p.returncode # for all others, abort raise error.Abort( - _("git %s error %d in %s") + _(b"git %s error %d in %s") % (command, p.returncode, self._relpath) ) return retdata, p.returncode def _gitmissing(self): - return not self.wvfs.exists(".git") + return not self.wvfs.exists(b".git") def _gitstate(self): - return self._gitcommand(["rev-parse", "HEAD"]) + return self._gitcommand([b"rev-parse", b"HEAD"]) def _gitcurrentbranch(self): - current, err = self._gitdir(["symbolic-ref", "HEAD", "--quiet"]) + current, err = self._gitdir([b"symbolic-ref", b"HEAD", b"--quiet"]) if err: current = None return current def _gitremote(self, remote): - out = self._gitcommand(["remote", "show", "-n", remote]) - line = out.split("\n")[1] - i = line.index("URL: ") + len("URL: ") + out = self._gitcommand([b"remote", b"show", b"-n", remote]) + line = out.split(b"\n")[1] + i = line.index(b"URL: ") + len(b"URL: ") return line[i:] def _githavelocally(self, revision): - out, code = self._gitdir(["cat-file", "-e", revision]) + out, code = self._gitdir([b"cat-file", b"-e", revision]) return code == 0 def _gitisancestor(self, r1, r2): - base = self._gitcommand(["merge-base", r1, r2]) + base = self._gitcommand([b"merge-base", r1, r2]) return base == r1 def _gitisbare(self): - return self._gitcommand(["config", "--bool", "core.bare"]) == "true" + return self._gitcommand([b"config", b"--bool", b"core.bare"]) == b"true" def _gitupdatestat(self): """This must be run before git diff-index. diff-index only looks at changes to file stat; this command looks at file contents and updates the stat.""" - self._gitcommand(["update-index", "-q", "--refresh"]) + self._gitcommand([b"update-index", b"-q", b"--refresh"]) def _gitbranchmap(self): """returns 2 things: @@ -1504,41 +1512,41 @@ rev2branch = {} out = self._gitcommand( - ["for-each-ref", "--format", "%(objectname) %(refname)"] + [b"for-each-ref", b"--format", b"%(objectname) %(refname)"] ) - for line in out.split("\n"): - revision, ref = line.split(" ") - if not ref.startswith("refs/heads/") and not ref.startswith( - "refs/remotes/" + for line in out.split(b"\n"): + revision, ref = line.split(b" ") + if not ref.startswith(b"refs/heads/") and not ref.startswith( + b"refs/remotes/" ): continue - if ref.startswith("refs/remotes/") and ref.endswith("/HEAD"): + if ref.startswith(b"refs/remotes/") and ref.endswith(b"/HEAD"): continue # ignore remote/HEAD redirects branch2rev[ref] = revision rev2branch.setdefault(revision, []).append(ref) return branch2rev, rev2branch def _gittracking(self, branches): - "return map of remote branch to local tracking branch" + b"return map of remote branch to local tracking branch" # assumes no more than one local tracking branch for each remote tracking = {} for b in branches: - if b.startswith("refs/remotes/"): + if b.startswith(b"refs/remotes/"): continue - bname = b.split("/", 2)[2] - remote = self._gitcommand(["config", "branch.%s.remote" % bname]) + bname = b.split(b"/", 2)[2] + remote = self._gitcommand([b"config", b"branch.%s.remote" % bname]) if remote: - ref = self._gitcommand(["config", "branch.%s.merge" % bname]) + ref = self._gitcommand([b"config", b"branch.%s.merge" % bname]) tracking[ - "refs/remotes/%s/%s" % (remote, ref.split("/", 2)[2]) + b"refs/remotes/%s/%s" % (remote, ref.split(b"/", 2)[2]) ] = b return tracking def _abssource(self, source): - if "://" not in source: + if b"://" not in source: # recognize the scp syntax as an absolute source - colon = source.find(":") - if colon != -1 and "/" not in source[:colon]: + colon = source.find(b":") + if colon != -1 and b"/" not in source[:colon]: return source self._subsource = source return _abssource(self) @@ -1550,27 +1558,27 @@ source = self._abssource(source) self.ui.status( - _("cloning subrepo %s from %s\n") % (self._relpath, source) + _(b"cloning subrepo %s from %s\n") % (self._relpath, source) ) - self._gitnodir(["clone", source, self._abspath]) + self._gitnodir([b"clone", source, self._abspath]) if self._githavelocally(revision): return self.ui.status( - _("pulling subrepo %s from %s\n") - % (self._relpath, self._gitremote("origin")) + _(b"pulling subrepo %s from %s\n") + % (self._relpath, self._gitremote(b"origin")) ) # try only origin: the originally cloned repo - self._gitcommand(["fetch"]) + self._gitcommand([b"fetch"]) if not self._githavelocally(revision): raise error.Abort( - _("revision %s does not exist in subrepository " '"%s"\n') + _(b"revision %s does not exist in subrepository " b'"%s"\n') % (revision, self._relpath) ) @annotatesubrepoerror def dirty(self, ignoreupdate=False, missing=False): if self._gitmissing(): - return self._state[1] != "" + return self._state[1] != b"" if self._gitisbare(): return True if not ignoreupdate and self._state[1] != self._gitstate(): @@ -1578,7 +1586,7 @@ return True # check for staged changes or modified files; ignore untracked files self._gitupdatestat() - out, code = self._gitdir(["diff-index", "--quiet", "HEAD"]) + out, code = self._gitdir([b"diff-index", b"--quiet", b"HEAD"]) return code == 1 def basestate(self): @@ -1593,41 +1601,41 @@ self._fetch(source, revision) # if the repo was set to be bare, unbare it if self._gitisbare(): - self._gitcommand(["config", "core.bare", "false"]) + self._gitcommand([b"config", b"core.bare", b"false"]) if self._gitstate() == revision: - self._gitcommand(["reset", "--hard", "HEAD"]) + self._gitcommand([b"reset", b"--hard", b"HEAD"]) return elif self._gitstate() == revision: if overwrite: # first reset the index to unmark new files for commit, because # reset --hard will otherwise throw away files added for commit, # not just unmark them. - self._gitcommand(["reset", "HEAD"]) - self._gitcommand(["reset", "--hard", "HEAD"]) + self._gitcommand([b"reset", b"HEAD"]) + self._gitcommand([b"reset", b"--hard", b"HEAD"]) return branch2rev, rev2branch = self._gitbranchmap() def checkout(args): - cmd = ["checkout"] + cmd = [b"checkout"] if overwrite: # first reset the index to unmark new files for commit, because # the -f option will otherwise throw away files added for # commit, not just unmark them. - self._gitcommand(["reset", "HEAD"]) - cmd.append("-f") + self._gitcommand([b"reset", b"HEAD"]) + cmd.append(b"-f") self._gitcommand(cmd + args) - _sanitize(self.ui, self.wvfs, ".git") + _sanitize(self.ui, self.wvfs, b".git") def rawcheckout(): # no branch to checkout, check it out with no branch self.ui.warn( - _("checking out detached HEAD in " 'subrepository "%s"\n') + _(b"checking out detached HEAD in " b'subrepository "%s"\n') % self._relpath ) self.ui.warn( - _("check out a git branch if you intend " "to make changes\n") + _(b"check out a git branch if you intend " b"to make changes\n") ) - checkout(["-q", revision]) + checkout([b"-q", revision]) if revision not in rev2branch: rawcheckout() @@ -1635,11 +1643,11 @@ branches = rev2branch[revision] firstlocalbranch = None for b in branches: - if b == "refs/heads/master": + if b == b"refs/heads/master": # master trumps all other branches - checkout(["refs/heads/master"]) + checkout([b"refs/heads/master"]) return - if not firstlocalbranch and not b.startswith("refs/remotes/"): + if not firstlocalbranch and not b.startswith(b"refs/remotes/"): firstlocalbranch = b if firstlocalbranch: checkout([firstlocalbranch]) @@ -1656,8 +1664,8 @@ if remote not in tracking: # create a new local tracking branch - local = remote.split("/", 3)[3] - checkout(["-b", local, remote]) + local = remote.split(b"/", 3)[3] + checkout([b"-b", local, remote]) elif self._gitisancestor(branch2rev[tracking[remote]], remote): # When updating to a tracked remote branch, # if the local tracking branch is downstream of it, @@ -1667,8 +1675,8 @@ # detect this situation and perform this action lazily. if tracking[remote] != self._gitcurrentbranch(): checkout([tracking[remote]]) - self._gitcommand(["merge", "--ff", remote]) - _sanitize(self.ui, self.wvfs, ".git") + self._gitcommand([b"merge", b"--ff", remote]) + _sanitize(self.ui, self.wvfs, b".git") else: # a real merge would be required, just checkout the revision rawcheckout() @@ -1676,16 +1684,16 @@ @annotatesubrepoerror def commit(self, text, user, date): if self._gitmissing(): - raise error.Abort(_("subrepo %s is missing") % self._relpath) - cmd = ["commit", "-a", "-m", text] + raise error.Abort(_(b"subrepo %s is missing") % self._relpath) + cmd = [b"commit", b"-a", b"-m", text] env = encoding.environ.copy() if user: - cmd += ["--author", user] + cmd += [b"--author", user] if date: # git's date parser silently ignores when seconds < 1e9 # convert to ISO8601 - env["GIT_AUTHOR_DATE"] = dateutil.datestr( - date, "%Y-%m-%dT%H:%M:%S %1%2" + env[b"GIT_AUTHOR_DATE"] = dateutil.datestr( + date, b"%Y-%m-%dT%H:%M:%S %1%2" ) self._gitcommand(cmd, env=env) # make sure commit works otherwise HEAD might not exist under certain @@ -1696,16 +1704,16 @@ def merge(self, state): source, revision, kind = state self._fetch(source, revision) - base = self._gitcommand(["merge-base", revision, self._state[1]]) + base = self._gitcommand([b"merge-base", revision, self._state[1]]) self._gitupdatestat() - out, code = self._gitdir(["diff-index", "--quiet", "HEAD"]) + out, code = self._gitdir([b"diff-index", b"--quiet", b"HEAD"]) def mergefunc(): if base == revision: self.get(state) # fast forward merge elif base != self._state[1]: - self._gitcommand(["merge", "--no-commit", revision]) - _sanitize(self.ui, self.wvfs, ".git") + self._gitcommand([b"merge", b"--no-commit", revision]) + _sanitize(self.ui, self.wvfs, b".git") if self.dirty(): if self._gitstate() != revision: @@ -1719,26 +1727,26 @@ @annotatesubrepoerror def push(self, opts): - force = opts.get("force") + force = opts.get(b"force") if not self._state[1]: return True if self._gitmissing(): - raise error.Abort(_("subrepo %s is missing") % self._relpath) + raise error.Abort(_(b"subrepo %s is missing") % self._relpath) # if a branch in origin contains the revision, nothing to do branch2rev, rev2branch = self._gitbranchmap() if self._state[1] in rev2branch: for b in rev2branch[self._state[1]]: - if b.startswith("refs/remotes/origin/"): + if b.startswith(b"refs/remotes/origin/"): return True for b, revision in branch2rev.iteritems(): - if b.startswith("refs/remotes/origin/"): + if b.startswith(b"refs/remotes/origin/"): if self._gitisancestor(self._state[1], revision): return True # otherwise, try to push the currently checked out branch - cmd = ["push"] + cmd = [b"push"] if force: - cmd.append("--force") + cmd.append(b"--force") current = self._gitcurrentbranch() if current: @@ -1746,23 +1754,23 @@ if not self._gitisancestor(self._state[1], current): self.ui.warn( _( - "unrelated git branch checked out " - 'in subrepository "%s"\n' + b"unrelated git branch checked out " + b'in subrepository "%s"\n' ) % self._relpath ) return False self.ui.status( - _('pushing branch %s of subrepository "%s"\n') - % (current.split("/", 2)[2], self._relpath) + _(b'pushing branch %s of subrepository "%s"\n') + % (current.split(b"/", 2)[2], self._relpath) ) - ret = self._gitdir(cmd + ["origin", current]) + ret = self._gitdir(cmd + [b"origin", current]) return ret[1] == 0 else: self.ui.warn( _( - 'no branch checked out in subrepository "%s"\n' - "cannot push revision %s\n" + b'no branch checked out in subrepository "%s"\n' + b"cannot push revision %s\n" ) % (self._relpath, self._state[1]) ) @@ -1789,11 +1797,11 @@ files = [f for f in sorted(set(files)) if match(f)] for f in files: exact = match.exact(f) - command = ["add"] + command = [b"add"] if exact: - command.append("-f") # should be added, even if ignored + command.append(b"-f") # should be added, even if ignored if ui.verbose or not exact: - ui.status(_("adding %s\n") % uipathfn(f)) + ui.status(_(b"adding %s\n") % uipathfn(f)) if f in tracked: # hg prints 'adding' even if already tracked if exact: @@ -1803,7 +1811,7 @@ self._gitcommand(command + [f]) for f in rejected: - ui.warn(_("%s already tracked!\n") % uipathfn(f)) + ui.warn(_(b"%s already tracked!\n") % uipathfn(f)) return rejected @@ -1813,16 +1821,16 @@ return if self.dirty(): self.ui.warn( - _("not removing repo %s because " "it has changes.\n") + _(b"not removing repo %s because " b"it has changes.\n") % self._relpath ) return # we can't fully delete the repository as it may contain # local-only history - self.ui.note(_("removing subrepo %s\n") % self._relpath) - self._gitcommand(["config", "core.bare", "true"]) + self.ui.note(_(b"removing subrepo %s\n") % self._relpath) + self._gitcommand([b"config", b"core.bare", b"true"]) for f, kind in self.wvfs.readdir(): - if f == ".git": + if f == b".git": continue if kind == stat.S_IFDIR: self.wvfs.rmtree(f) @@ -1839,11 +1847,11 @@ # Parse git's native archive command. # This should be much faster than manually traversing the trees # and objects with many subprocess calls. - tarstream = self._gitcommand(["archive", revision], stream=True) + tarstream = self._gitcommand([b"archive", revision], stream=True) tar = tarfile.open(fileobj=tarstream, mode=r"r|") relpath = subrelpath(self) progress = self.ui.makeprogress( - _("archiving (%s)") % relpath, unit=_("files") + _(b"archiving (%s)") % relpath, unit=_(b"files") ) progress.update(0) for info in tar: @@ -1873,7 +1881,7 @@ # TODO: add support for non-plain formatter (see cmdutil.cat()) for f in match.files(): - output = self._gitcommand(["show", "%s:%s" % (rev, f)]) + output = self._gitcommand([b"show", b"%s:%s" % (rev, f)]) fp = cmdutil.makefileobj( self._ctx, fntemplate, pathname=self.wvfs.reljoin(prefix, f) ) @@ -1890,42 +1898,42 @@ modified, added, removed = [], [], [] self._gitupdatestat() if rev2: - command = ["diff-tree", "--no-renames", "-r", rev1, rev2] + command = [b"diff-tree", b"--no-renames", b"-r", rev1, rev2] else: - command = ["diff-index", "--no-renames", rev1] + command = [b"diff-index", b"--no-renames", rev1] out = self._gitcommand(command) - for line in out.split("\n"): - tab = line.find("\t") + for line in out.split(b"\n"): + tab = line.find(b"\t") if tab == -1: continue status, f = line[tab - 1 : tab], line[tab + 1 :] - if status == "M": + if status == b"M": modified.append(f) - elif status == "A": + elif status == b"A": added.append(f) - elif status == "D": + elif status == b"D": removed.append(f) deleted, unknown, ignored, clean = [], [], [], [] - command = ["status", "--porcelain", "-z"] + command = [b"status", b"--porcelain", b"-z"] if opts.get(r"unknown"): - command += ["--untracked-files=all"] + command += [b"--untracked-files=all"] if opts.get(r"ignored"): - command += ["--ignored"] + command += [b"--ignored"] out = self._gitcommand(command) changedfiles = set() changedfiles.update(modified) changedfiles.update(added) changedfiles.update(removed) - for line in out.split("\0"): + for line in out.split(b"\0"): if not line: continue st = line[0:2] # moves and copies show 2 files on one line - if line.find("\0") >= 0: - filename1, filename2 = line[3:].split("\0") + if line.find(b"\0") >= 0: + filename1, filename2 = line[3:].split(b"\0") else: filename1 = line[3:] filename2 = None @@ -1934,14 +1942,14 @@ if filename2: changedfiles.add(filename2) - if st == "??": + if st == b"??": unknown.append(filename1) - elif st == "!!": + elif st == b"!!": ignored.append(filename1) if opts.get(r"clean"): - out = self._gitcommand(["ls-files"]) - for f in out.split("\n"): + out = self._gitcommand([b"ls-files"]) + for f in out.split(b"\n"): if not f in changedfiles: clean.append(f) @@ -1952,52 +1960,52 @@ @annotatesubrepoerror def diff(self, ui, diffopts, node2, match, prefix, **opts): node1 = self._state[1] - cmd = ["diff", "--no-renames"] + cmd = [b"diff", b"--no-renames"] if opts[r"stat"]: - cmd.append("--stat") + cmd.append(b"--stat") else: # for Git, this also implies '-p' - cmd.append("-U%d" % diffopts.context) + cmd.append(b"-U%d" % diffopts.context) if diffopts.noprefix: cmd.extend( - ["--src-prefix=%s/" % prefix, "--dst-prefix=%s/" % prefix] + [b"--src-prefix=%s/" % prefix, b"--dst-prefix=%s/" % prefix] ) else: cmd.extend( - ["--src-prefix=a/%s/" % prefix, "--dst-prefix=b/%s/" % prefix] + [b"--src-prefix=a/%s/" % prefix, b"--dst-prefix=b/%s/" % prefix] ) if diffopts.ignorews: - cmd.append("--ignore-all-space") + cmd.append(b"--ignore-all-space") if diffopts.ignorewsamount: - cmd.append("--ignore-space-change") + cmd.append(b"--ignore-space-change") if ( - self._gitversion(self._gitcommand(["--version"])) >= (1, 8, 4) + self._gitversion(self._gitcommand([b"--version"])) >= (1, 8, 4) and diffopts.ignoreblanklines ): - cmd.append("--ignore-blank-lines") + cmd.append(b"--ignore-blank-lines") cmd.append(node1) if node2: cmd.append(node2) - output = "" + output = b"" if match.always(): - output += self._gitcommand(cmd) + "\n" + output += self._gitcommand(cmd) + b"\n" else: st = self.status(node2)[:3] files = [f for sublist in st for f in sublist] for f in files: if match(f): - output += self._gitcommand(cmd + ["--", f]) + "\n" + output += self._gitcommand(cmd + [b"--", f]) + b"\n" if output.strip(): ui.write(output) @annotatesubrepoerror def revert(self, substate, *pats, **opts): - self.ui.status(_("reverting subrepo %s\n") % substate[0]) + self.ui.status(_(b"reverting subrepo %s\n") % substate[0]) if not opts.get(r"no_backup"): status = self.status(None) names = status.modified @@ -2009,7 +2017,7 @@ self.ui, self._subparent, parentname ) self.ui.note( - _("saving current version of %s as %s\n") + _(b"saving current version of %s as %s\n") % (name, os.path.relpath(bakname)) ) util.rename(self.wvfs.join(name), bakname) @@ -2023,7 +2031,7 @@ types = { - "hg": hgsubrepo, - "svn": svnsubrepo, - "git": gitsubrepo, + b"hg": hgsubrepo, + b"svn": svnsubrepo, + b"git": gitsubrepo, } diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -23,7 +23,7 @@ ) from .utils import stringutil -nullstate = ("", "", "empty") +nullstate = (b"", b"", b"empty") def state(ctx, ui): @@ -43,38 +43,38 @@ raise # handle missing subrepo spec files as removed ui.warn( - _("warning: subrepo spec file '%s' not found\n") + _(b"warning: subrepo spec file '%s' not found\n") % repo.pathto(f) ) return p.parse(f, data, sections, remap, read) else: raise error.Abort( - _("subrepo spec file '%s' not found") % repo.pathto(f) + _(b"subrepo spec file '%s' not found") % repo.pathto(f) ) - if ".hgsub" in ctx: - read(".hgsub") + if b".hgsub" in ctx: + read(b".hgsub") - for path, src in ui.configitems("subpaths"): - p.set("subpaths", path, src, ui.configsource("subpaths", path)) + for path, src in ui.configitems(b"subpaths"): + p.set(b"subpaths", path, src, ui.configsource(b"subpaths", path)) rev = {} - if ".hgsubstate" in ctx: + if b".hgsubstate" in ctx: try: - for i, l in enumerate(ctx[".hgsubstate"].data().splitlines()): + for i, l in enumerate(ctx[b".hgsubstate"].data().splitlines()): l = l.lstrip() if not l: continue try: - revision, path = l.split(" ", 1) + revision, path = l.split(b" ", 1) except ValueError: raise error.Abort( _( - "invalid subrepository revision " - "specifier in '%s' line %d" + b"invalid subrepository revision " + b"specifier in '%s' line %d" ) - % (repo.pathto(".hgsubstate"), (i + 1)) + % (repo.pathto(b".hgsubstate"), (i + 1)) ) rev[path] = revision except IOError as err: @@ -82,7 +82,7 @@ raise def remap(src): - for pattern, repl in p.items("subpaths"): + for pattern, repl in p.items(b"subpaths"): # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub # does a string decode. repl = stringutil.escapestr(repl) @@ -94,21 +94,21 @@ src = re.sub(pattern, repl, src, 1) except re.error as e: raise error.Abort( - _("bad subrepository pattern in %s: %s") + _(b"bad subrepository pattern in %s: %s") % ( - p.source("subpaths", pattern), + p.source(b"subpaths", pattern), stringutil.forcebytestr(e), ) ) return src state = {} - for path, src in p[""].items(): - kind = "hg" - if src.startswith("["): - if "]" not in src: - raise error.Abort(_("missing ] in subrepository source")) - kind, src = src.split("]", 1) + for path, src in p[b""].items(): + kind = b"hg" + if src.startswith(b"["): + if b"]" not in src: + raise error.Abort(_(b"missing ] in subrepository source")) + kind, src = src.split(b"]", 1) kind = kind[1:] src = src.lstrip() # strip any extra whitespace after ']' @@ -116,7 +116,7 @@ parent = _abssource(repo, abort=False) if parent: parent = util.url(parent) - parent.path = posixpath.join(parent.path or "", src) + parent.path = posixpath.join(parent.path or b"", src) parent.path = posixpath.normpath(parent.path) joined = bytes(parent) # Remap the full joined path and use it if it changes, @@ -128,7 +128,7 @@ src = remapped src = remap(src) - state[util.pconvert(path)] = (src.strip(), rev.get(path, ""), kind) + state[util.pconvert(path)] = (src.strip(), rev.get(path, b""), kind) return state @@ -136,11 +136,11 @@ def writestate(repo, state): """rewrite .hgsubstate in (outer) repo with these subrepo states""" lines = [ - "%s %s\n" % (state[s][1], s) + b"%s %s\n" % (state[s][1], s) for s in sorted(state) if state[s][1] != nullstate[1] ] - repo.wwrite(".hgsubstate", "".join(lines), "") + repo.wwrite(b".hgsubstate", b"".join(lines), b"") def submerge(repo, wctx, mctx, actx, overwrite, labels=None): @@ -153,67 +153,67 @@ sa = actx.substate sm = {} - repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx)) + repo.ui.debug(b"subrepo merge %s %s %s\n" % (wctx, mctx, actx)) - def debug(s, msg, r=""): + def debug(s, msg, r=b""): if r: - r = "%s:%s:%s" % r - repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r)) + r = b"%s:%s:%s" % r + repo.ui.debug(b" subrepo %s: %s %s\n" % (s, msg, r)) promptssrc = filemerge.partextras(labels) for s, l in sorted(s1.iteritems()): a = sa.get(s, nullstate) ld = l # local state with possible dirty flag for compares if wctx.sub(s).dirty(): - ld = (l[0], l[1] + "+") + ld = (l[0], l[1] + b"+") if wctx == actx: # overwrite a = ld prompts = promptssrc.copy() - prompts["s"] = s + prompts[b"s"] = s if s in s2: r = s2[s] if ld == r or r == a: # no change or local is newer sm[s] = l continue elif ld == a: # other side changed - debug(s, "other changed, get", r) + debug(s, b"other changed, get", r) wctx.sub(s).get(r, overwrite) sm[s] = r elif ld[0] != r[0]: # sources differ - prompts["lo"] = l[0] - prompts["ro"] = r[0] + prompts[b"lo"] = l[0] + prompts[b"ro"] = r[0] if repo.ui.promptchoice( _( - " subrepository sources for %(s)s differ\n" - "you can use (l)ocal%(l)s source (%(lo)s)" - " or (r)emote%(o)s source (%(ro)s).\n" - "what do you want to do?" - "$$ &Local $$ &Remote" + b" subrepository sources for %(s)s differ\n" + b"you can use (l)ocal%(l)s source (%(lo)s)" + b" or (r)emote%(o)s source (%(ro)s).\n" + b"what do you want to do?" + b"$$ &Local $$ &Remote" ) % prompts, 0, ): - debug(s, "prompt changed, get", r) + debug(s, b"prompt changed, get", r) wctx.sub(s).get(r, overwrite) sm[s] = r elif ld[1] == a[1]: # local side is unchanged - debug(s, "other side changed, get", r) + debug(s, b"other side changed, get", r) wctx.sub(s).get(r, overwrite) sm[s] = r else: - debug(s, "both sides changed") + debug(s, b"both sides changed") srepo = wctx.sub(s) - prompts["sl"] = srepo.shortid(l[1]) - prompts["sr"] = srepo.shortid(r[1]) + prompts[b"sl"] = srepo.shortid(l[1]) + prompts[b"sr"] = srepo.shortid(r[1]) option = repo.ui.promptchoice( _( - " subrepository %(s)s diverged (local revision: %(sl)s, " - "remote revision: %(sr)s)\n" - "you can (m)erge, keep (l)ocal%(l)s or keep " - "(r)emote%(o)s.\n" - "what do you want to do?" - "$$ &Merge $$ &Local $$ &Remote" + b" subrepository %(s)s diverged (local revision: %(sl)s, " + b"remote revision: %(sr)s)\n" + b"you can (m)erge, keep (l)ocal%(l)s or keep " + b"(r)emote%(o)s.\n" + b"what do you want to do?" + b"$$ &Merge $$ &Local $$ &Remote" ) % prompts, 0, @@ -221,59 +221,59 @@ if option == 0: wctx.sub(s).merge(r) sm[s] = l - debug(s, "merge with", r) + debug(s, b"merge with", r) elif option == 1: sm[s] = l - debug(s, "keep local subrepo revision", l) + debug(s, b"keep local subrepo revision", l) else: wctx.sub(s).get(r, overwrite) sm[s] = r - debug(s, "get remote subrepo revision", r) + debug(s, b"get remote subrepo revision", r) elif ld == a: # remote removed, local unchanged - debug(s, "remote removed, remove") + debug(s, b"remote removed, remove") wctx.sub(s).remove() elif a == nullstate: # not present in remote or ancestor - debug(s, "local added, keep") + debug(s, b"local added, keep") sm[s] = l continue else: if repo.ui.promptchoice( _( - " local%(l)s changed subrepository %(s)s" - " which remote%(o)s removed\n" - "use (c)hanged version or (d)elete?" - "$$ &Changed $$ &Delete" + b" local%(l)s changed subrepository %(s)s" + b" which remote%(o)s removed\n" + b"use (c)hanged version or (d)elete?" + b"$$ &Changed $$ &Delete" ) % prompts, 0, ): - debug(s, "prompt remove") + debug(s, b"prompt remove") wctx.sub(s).remove() for s, r in sorted(s2.items()): if s in s1: continue elif s not in sa: - debug(s, "remote added, get", r) + debug(s, b"remote added, get", r) mctx.sub(s).get(r) sm[s] = r elif r != sa[s]: prompts = promptssrc.copy() - prompts["s"] = s + prompts[b"s"] = s if ( repo.ui.promptchoice( _( - " remote%(o)s changed subrepository %(s)s" - " which local%(l)s removed\n" - "use (c)hanged version or (d)elete?" - "$$ &Changed $$ &Delete" + b" remote%(o)s changed subrepository %(s)s" + b" which local%(l)s removed\n" + b"use (c)hanged version or (d)elete?" + b"$$ &Changed $$ &Delete" ) % prompts, 0, ) == 0 ): - debug(s, "prompt recreate", r) + debug(s, b"prompt recreate", r) mctx.sub(s).get(r) sm[s] = r @@ -297,11 +297,11 @@ newstate = wctx.substate.copy() # only manage subrepos and .hgsubstate if .hgsub is present - if ".hgsub" in wctx: + if b".hgsub" in wctx: # we'll decide whether to track this ourselves, thanks for c in status.modified, status.added, status.removed: - if ".hgsubstate" in c: - c.remove(".hgsubstate") + if b".hgsubstate" in c: + c.remove(b".hgsubstate") # compare current state to last committed state # build new substate based on last committed state @@ -314,14 +314,14 @@ continue if not force: raise error.Abort( - _("commit with new subrepo %s excluded") % s + _(b"commit with new subrepo %s excluded") % s ) dirtyreason = wctx.sub(s).dirtyreason(True) if dirtyreason: - if not ui.configbool("ui", "commitsubrepos"): + if not ui.configbool(b"ui", b"commitsubrepos"): raise error.Abort( dirtyreason, - hint=_("use --subrepos for recursive commit"), + hint=_(b"use --subrepos for recursive commit"), ) subs.append(s) commitsubs.add(s) @@ -336,18 +336,18 @@ r = [s for s in p.substate if s not in newstate] subs += [s for s in r if match(s)] if subs: - if not match(".hgsub") and ".hgsub" in ( + if not match(b".hgsub") and b".hgsub" in ( wctx.modified() + wctx.added() ): - raise error.Abort(_("can't commit subrepos without .hgsub")) - status.modified.insert(0, ".hgsubstate") + raise error.Abort(_(b"can't commit subrepos without .hgsub")) + status.modified.insert(0, b".hgsubstate") - elif ".hgsub" in status.removed: + elif b".hgsub" in status.removed: # clean up .hgsubstate when .hgsub is removed - if ".hgsubstate" in wctx and ".hgsubstate" not in ( + if b".hgsubstate" in wctx and b".hgsubstate" not in ( status.modified + status.added + status.removed ): - status.removed.insert(0, ".hgsubstate") + status.removed.insert(0, b".hgsubstate") return subs, commitsubs, newstate @@ -355,7 +355,7 @@ def reporelpath(repo): """return path to this (sub)repo as seen from outermost repo""" parent = repo - while util.safehasattr(parent, "_subparent"): + while util.safehasattr(parent, b"_subparent"): parent = parent._subparent return repo.root[len(pathutil.normasprefix(parent.root)) :] @@ -368,7 +368,7 @@ def _abssource(repo, push=False, abort=True): """return pull/push path of repo - either based on parent repo .hgsub info or on the top repo config. Abort or return None if no source found.""" - if util.safehasattr(repo, "_subparent"): + if util.safehasattr(repo, b"_subparent"): source = util.url(repo._subsource) if source.isabs(): return bytes(source) @@ -376,17 +376,17 @@ parent = _abssource(repo._subparent, push, abort=False) if parent: parent = util.url(util.pconvert(parent)) - parent.path = posixpath.join(parent.path or "", source.path) + parent.path = posixpath.join(parent.path or b"", source.path) parent.path = posixpath.normpath(parent.path) return bytes(parent) else: # recursion reached top repo path = None - if util.safehasattr(repo, "_subtoppath"): + if util.safehasattr(repo, b"_subtoppath"): path = repo._subtoppath - elif push and repo.ui.config("paths", "default-push"): - path = repo.ui.config("paths", "default-push") - elif repo.ui.config("paths", "default"): - path = repo.ui.config("paths", "default") + elif push and repo.ui.config(b"paths", b"default-push"): + path = repo.ui.config(b"paths", b"default-push") + elif repo.ui.config(b"paths", b"default"): + path = repo.ui.config(b"paths", b"default") elif repo.shared(): # chop off the .hg component to get the default path form. This has # already run through vfsmod.vfs(..., realpath=True), so it doesn't @@ -410,7 +410,7 @@ return path if abort: - raise error.Abort(_("default path for subrepository not found")) + raise error.Abort(_(b"default path for subrepository not found")) def newcommitphase(ui, ctx): @@ -418,12 +418,12 @@ substate = getattr(ctx, "substate", None) if not substate: return commitphase - check = ui.config("phases", "checksubrepos") - if check not in ("ignore", "follow", "abort"): + check = ui.config(b"phases", b"checksubrepos") + if check not in (b"ignore", b"follow", b"abort"): raise error.Abort( - _("invalid phases.checksubrepos configuration: %s") % check + _(b"invalid phases.checksubrepos configuration: %s") % check ) - if check == "ignore": + if check == b"ignore": return commitphase maxphase = phases.public maxsub = None @@ -434,11 +434,11 @@ maxphase = subphase maxsub = s if commitphase < maxphase: - if check == "abort": + if check == b"abort": raise error.Abort( _( - "can't commit in %s phase" - " conflicting %s from subrepository %s" + b"can't commit in %s phase" + b" conflicting %s from subrepository %s" ) % ( phases.phasenames[commitphase], @@ -448,8 +448,8 @@ ) ui.warn( _( - "warning: changes are committed in" - " %s phase from subrepository %s\n" + b"warning: changes are committed in" + b" %s phase from subrepository %s\n" ) % (phases.phasenames[maxphase], maxsub) ) diff --git a/mercurial/tagmerge.py b/mercurial/tagmerge.py --- a/mercurial/tagmerge.py +++ b/mercurial/tagmerge.py @@ -86,7 +86,7 @@ hexnullid = hex(nullid) -def readtagsformerge(ui, repo, lines, fn="", keeplinenums=False): +def readtagsformerge(ui, repo, lines, fn=b"", keeplinenums=False): """read the .hgtags file into a structure that is suitable for merging Depending on the keeplinenums flag, clear the line numbers associated @@ -154,7 +154,7 @@ # convert the grouped merged tags dict into a format that resembles the # final .hgtags file (i.e. a list of blocks of 'node tag' pairs) def taglist2string(tlist, tname): - return "\n".join(["%s %s" % (hexnode, tname) for hexnode in tlist]) + return b"\n".join([b"%s %s" % (hexnode, tname) for hexnode in tlist]) finaltags = [] for tname, tags in mergedtags.items(): @@ -170,8 +170,8 @@ # finally we can join the sorted groups to get the final contents of the # merged .hgtags file, and then write it to disk - mergedtagstring = "\n".join([tags for rank, tags in finaltags if tags]) - fcd.write(mergedtagstring + "\n", fcd.flags()) + mergedtagstring = b"\n".join([tags for rank, tags in finaltags if tags]) + fcd.write(mergedtagstring + b"\n", fcd.flags()) def singletagmerge(p1nodes, p2nodes): @@ -229,13 +229,13 @@ # read the p1, p2 and base tags # only keep the line numbers for the p1 tags p1tags = readtagsformerge( - ui, repo, fcd.data().splitlines(), fn="p1 tags", keeplinenums=True + ui, repo, fcd.data().splitlines(), fn=b"p1 tags", keeplinenums=True ) p2tags = readtagsformerge( - ui, repo, fco.data().splitlines(), fn="p2 tags", keeplinenums=False + ui, repo, fco.data().splitlines(), fn=b"p2 tags", keeplinenums=False ) basetags = readtagsformerge( - ui, repo, fca.data().splitlines(), fn="base tags", keeplinenums=False + ui, repo, fca.data().splitlines(), fn=b"base tags", keeplinenums=False ) # recover the list of "lost tags" (i.e. those that were found on the base @@ -267,13 +267,13 @@ numconflicts = len(conflictedtags) ui.warn( _( - "automatic .hgtags merge failed\n" - "the following %d tags are in conflict: %s\n" + b"automatic .hgtags merge failed\n" + b"the following %d tags are in conflict: %s\n" ) - % (numconflicts, ", ".join(sorted(conflictedtags))) + % (numconflicts, b", ".join(sorted(conflictedtags))) ) return True, 1 writemergedtags(fcd, mergedtags) - ui.note(_(".hgtags merged successfully\n")) + ui.note(_(b".hgtags merged successfully\n")) return False, 0 diff --git a/mercurial/tags.py b/mercurial/tags.py --- a/mercurial/tags.py +++ b/mercurial/tags.py @@ -155,10 +155,10 @@ See documentation of difftags output for details about the input. """ - add = "+A %s %s\n" - remove = "-R %s %s\n" - updateold = "-M %s %s\n" - updatenew = "+M %s %s\n" + add = b"+A %s %s\n" + remove = b"-R %s %s\n" + updateold = b"-M %s %s\n" + updatenew = b"+M %s %s\n" for tag, old, new in difflist: # translate to hex if old is not None: @@ -195,7 +195,7 @@ for head in reversed(heads): # oldest to newest assert ( head in repo.changelog.nodemap - ), "tag cache returned bogus head %s" % short(head) + ), b"tag cache returned bogus head %s" % short(head) fnodes = _filterfnodes(tagfnode, reversed(heads)) alltags = _tagsfromfnodes(ui, repo, fnodes) @@ -231,7 +231,7 @@ fctx = None for fnode in fnodes: if fctx is None: - fctx = repo.filectx(".hgtags", fileid=fnode) + fctx = repo.filectx(b".hgtags", fileid=fnode) else: fctx = fctx.filectx(fnode) filetags = _readtags(ui, repo, fctx.data().splitlines(), fctx) @@ -242,7 +242,7 @@ def readlocaltags(ui, repo, alltags, tagtypes): """Read local tags in repo. Update alltags and tagtypes.""" try: - data = repo.vfs.read("localtags") + data = repo.vfs.read(b"localtags") except IOError as inst: if inst.errno != errno.ENOENT: raise @@ -251,7 +251,7 @@ # localtags is in the local encoding; re-encode to UTF-8 on # input for consistency with the rest of this module. filetags = _readtags( - ui, repo, data.splitlines(), "localtags", recode=encoding.fromlocal + ui, repo, data.splitlines(), b"localtags", recode=encoding.fromlocal ) # remove tags pointing to invalid nodes @@ -262,7 +262,7 @@ except (LookupError, ValueError): del filetags[t] - _updatetags(filetags, alltags, "local", tagtypes) + _updatetags(filetags, alltags, b"local", tagtypes) def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False): @@ -289,16 +289,16 @@ count = 0 def dbg(msg): - ui.debug("%s, line %d: %s\n" % (fn, count, msg)) + ui.debug(b"%s, line %d: %s\n" % (fn, count, msg)) for nline, line in enumerate(lines): count += 1 if not line: continue try: - (nodehex, name) = line.split(" ", 1) + (nodehex, name) = line.split(b" ", 1) except ValueError: - dbg("cannot parse entry") + dbg(b"cannot parse entry") continue name = name.strip() if recode: @@ -306,7 +306,7 @@ try: nodebin = bin(nodehex) except TypeError: - dbg("node '%s' is not well formed" % nodehex) + dbg(b"node '%s' is not well formed" % nodehex) continue # update filetags @@ -382,9 +382,9 @@ def _filename(repo): """name of a tagcache file for a given repo or repoview""" - filename = "tags2" + filename = b"tags2" if repo.filtername: - filename = "%s-%s" % (filename, repo.filtername) + filename = b"%s-%s" % (filename, repo.filtername) return filename @@ -407,7 +407,7 @@ info from each returned head. (See findglobaltags().) """ try: - cachefile = repo.cachevfs(_filename(repo), "r") + cachefile = repo.cachevfs(_filename(repo), b"r") # force reading the file for static-http cachelines = iter(cachefile) except IOError: @@ -467,7 +467,7 @@ # N.B. in case 4 (nodes destroyed), "new head" really means "newly # exposed". - if not len(repo.file(".hgtags")): + if not len(repo.file(b".hgtags")): # No tags have ever been committed, so we can avoid a # potentially expensive search. return ([], {}, valid, None, True) @@ -502,8 +502,8 @@ duration = util.timer() - starttime ui.log( - "tagscache", - "%d/%d cache hits/lookups in %0.4f seconds\n", + b"tagscache", + b"%d/%d cache hits/lookups in %0.4f seconds\n", fnodescache.hitcount, fnodescache.lookupcount, duration, @@ -514,21 +514,23 @@ def _writetagcache(ui, repo, valid, cachetags): filename = _filename(repo) try: - cachefile = repo.cachevfs(filename, "w", atomictemp=True) + cachefile = repo.cachevfs(filename, b"w", atomictemp=True) except (OSError, IOError): return ui.log( - "tagscache", - "writing .hg/cache/%s with %d tags\n", + b"tagscache", + b"writing .hg/cache/%s with %d tags\n", filename, len(cachetags), ) if valid[2]: - cachefile.write("%d %s %s\n" % (valid[0], hex(valid[1]), hex(valid[2]))) + cachefile.write( + b"%d %s %s\n" % (valid[0], hex(valid[1]), hex(valid[2])) + ) else: - cachefile.write("%d %s\n" % (valid[0], hex(valid[1]))) + cachefile.write(b"%d %s\n" % (valid[0], hex(valid[1]))) # Tag names in the cache are in UTF-8 -- which is the whole reason # we keep them in UTF-8 throughout this module. If we converted @@ -536,8 +538,8 @@ # the cache. for (name, (node, hist)) in sorted(cachetags.iteritems()): for n in hist: - cachefile.write("%s %s\n" % (hex(n), name)) - cachefile.write("%s %s\n" % (hex(node), name)) + cachefile.write(b"%s %s\n" % (hex(n), name)) + cachefile.write(b"%s %s\n" % (hex(node), name)) try: cachefile.close() @@ -567,11 +569,11 @@ date: date tuple to use if committing""" if not local: - m = matchmod.exact([".hgtags"]) + m = matchmod.exact([b".hgtags"]) if any(repo.status(match=m, unknown=True, ignored=True)): raise error.Abort( - _("working copy of .hgtags is changed"), - hint=_("please commit .hgtags manually"), + _(b"working copy of .hgtags is changed"), + hint=_(b"please commit .hgtags manually"), ) with repo.wlock(): @@ -587,17 +589,17 @@ branches = repo.branchmap() for name in names: - repo.hook("pretag", throw=True, node=hex(node), tag=name, local=local) + repo.hook(b"pretag", throw=True, node=hex(node), tag=name, local=local) if name in branches: repo.ui.warn( - _("warning: tag %s conflicts with existing" " branch name\n") + _(b"warning: tag %s conflicts with existing" b" branch name\n") % name ) def writetags(fp, names, munge, prevtags): fp.seek(0, io.SEEK_END) - if prevtags and not prevtags.endswith("\n"): - fp.write("\n") + if prevtags and not prevtags.endswith(b"\n"): + fp.write(b"\n") for name in names: if munge: m = munge(name) @@ -606,31 +608,31 @@ if repo._tagscache.tagtypes and name in repo._tagscache.tagtypes: old = repo.tags().get(name, nullid) - fp.write("%s %s\n" % (hex(old), m)) - fp.write("%s %s\n" % (hex(node), m)) + fp.write(b"%s %s\n" % (hex(old), m)) + fp.write(b"%s %s\n" % (hex(node), m)) fp.close() - prevtags = "" + prevtags = b"" if local: try: - fp = repo.vfs("localtags", "r+") + fp = repo.vfs(b"localtags", b"r+") except IOError: - fp = repo.vfs("localtags", "a") + fp = repo.vfs(b"localtags", b"a") else: prevtags = fp.read() # local tags are stored in the current charset writetags(fp, names, None, prevtags) for name in names: - repo.hook("tag", node=hex(node), tag=name, local=local) + repo.hook(b"tag", node=hex(node), tag=name, local=local) return try: - fp = repo.wvfs(".hgtags", "rb+") + fp = repo.wvfs(b".hgtags", b"rb+") except IOError as e: if e.errno != errno.ENOENT: raise - fp = repo.wvfs(".hgtags", "ab") + fp = repo.wvfs(b".hgtags", b"ab") else: prevtags = fp.read() @@ -641,23 +643,23 @@ repo.invalidatecaches() - if ".hgtags" not in repo.dirstate: - repo[None].add([".hgtags"]) + if b".hgtags" not in repo.dirstate: + repo[None].add([b".hgtags"]) - m = matchmod.exact([".hgtags"]) + m = matchmod.exact([b".hgtags"]) tagnode = repo.commit( message, user, date, extra=extra, match=m, editor=editor ) for name in names: - repo.hook("tag", node=hex(node), tag=name, local=local) + repo.hook(b"tag", node=hex(node), tag=name, local=local) return tagnode -_fnodescachefile = "hgtagsfnodes1" +_fnodescachefile = b"hgtagsfnodes1" _fnodesrecsize = 4 + 20 # changeset fragment + filenode -_fnodesmissingrec = "\xff" * 24 +_fnodesmissingrec = b"\xff" * 24 class hgtagsfnodescache(object): @@ -692,7 +694,7 @@ try: data = repo.cachevfs.read(_fnodescachefile) except (OSError, IOError): - data = "" + data = b"" self._raw = bytearray(data) # The end state of self._raw is an array that is of the exact length @@ -709,7 +711,7 @@ if rawlen < wantedlen: self._dirtyoffset = rawlen - self._raw.extend("\xff" * (wantedlen - rawlen)) + self._raw.extend(b"\xff" * (wantedlen - rawlen)) elif rawlen > wantedlen: # There's no easy way to truncate array instances. This seems # slightly less evil than copying a potentially large array slice. @@ -737,7 +739,7 @@ self.lookupcount += 1 offset = rev * _fnodesrecsize - record = "%s" % self._raw[offset : offset + _fnodesrecsize] + record = b"%s" % self._raw[offset : offset + _fnodesrecsize] properprefix = node[0:4] # Validate and return existing entry. @@ -772,13 +774,13 @@ p1fnode = None if p1fnode is not None: mctx = ctx.manifestctx() - fnode = mctx.readfast().get(".hgtags") + fnode = mctx.readfast().get(b".hgtags") if fnode is None: fnode = p1fnode if fnode is None: # Populate missing entry. try: - fnode = ctx.filenode(".hgtags") + fnode = ctx.filenode(b".hgtags") except error.LookupError: # No .hgtags file on this revision. fnode = nullid @@ -823,14 +825,14 @@ lock = repo.wlock(wait=False) except error.LockError: repo.ui.log( - "tagscache", - "not writing .hg/cache/%s because " - "lock cannot be acquired\n" % _fnodescachefile, + b"tagscache", + b"not writing .hg/cache/%s because " + b"lock cannot be acquired\n" % _fnodescachefile, ) return try: - f = repo.cachevfs.open(_fnodescachefile, "ab") + f = repo.cachevfs.open(_fnodescachefile, b"ab") try: # if the file has been truncated actualoffset = f.tell() @@ -840,8 +842,8 @@ f.seek(self._dirtyoffset) f.truncate() repo.ui.log( - "tagscache", - "writing %d bytes to cache/%s\n" + b"tagscache", + b"writing %d bytes to cache/%s\n" % (len(data), _fnodescachefile), ) f.write(data) @@ -850,8 +852,8 @@ f.close() except (IOError, OSError) as inst: repo.ui.log( - "tagscache", - "couldn't write cache/%s: %s\n" + b"tagscache", + b"couldn't write cache/%s: %s\n" % (_fnodescachefile, stringutil.forcebytestr(inst)), ) finally: diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -43,26 +43,26 @@ templatefilter = registrar.templatefilter(filters) -@templatefilter("addbreaks", intype=bytes) +@templatefilter(b"addbreaks", intype=bytes) def addbreaks(text): """Any text. Add an XHTML "
" tag before the end of every line except the last. """ - return text.replace("\n", "
\n") + return text.replace(b"\n", b"
\n") agescales = [ - ("year", 3600 * 24 * 365, "Y"), - ("month", 3600 * 24 * 30, "M"), - ("week", 3600 * 24 * 7, "W"), - ("day", 3600 * 24, "d"), - ("hour", 3600, "h"), - ("minute", 60, "m"), - ("second", 1, "s"), + (b"year", 3600 * 24 * 365, b"Y"), + (b"month", 3600 * 24 * 30, b"M"), + (b"week", 3600 * 24 * 7, b"W"), + (b"day", 3600 * 24, b"d"), + (b"hour", 3600, b"h"), + (b"minute", 60, b"m"), + (b"second", 1, b"s"), ] -@templatefilter("age", intype=templateutil.date) +@templatefilter(b"age", intype=templateutil.date) def age(date, abbrev=False): """Date. Returns a human-readable date/time difference between the given date/time and the current date/time. @@ -71,12 +71,12 @@ def plural(t, c): if c == 1: return t - return t + "s" + return t + b"s" def fmt(t, c, a): if abbrev: - return "%d%s" % (c, a) - return "%d %s" % (c, plural(t, c)) + return b"%d%s" % (c, a) + return b"%d %s" % (c, plural(t, c)) now = time.time() then = date[0] @@ -85,7 +85,7 @@ future = True delta = max(1, int(then - now)) if delta > agescales[0][1] * 30: - return "in the distant future" + return b"in the distant future" else: delta = max(1, int(now - then)) if delta > agescales[0][1] * 2: @@ -95,11 +95,11 @@ n = delta // s if n >= 2 or s == 1: if future: - return "%s from now" % fmt(t, n, a) - return "%s ago" % fmt(t, n, a) + return b"%s from now" % fmt(t, n, a) + return b"%s ago" % fmt(t, n, a) -@templatefilter("basename", intype=bytes) +@templatefilter(b"basename", intype=bytes) def basename(path): """Any text. Treats the text as a path, and returns the last component of the path after splitting by the path separator. @@ -108,13 +108,13 @@ return os.path.basename(path) -@templatefilter("cbor") +@templatefilter(b"cbor") def cbor(obj): """Any object. Serializes the object to CBOR bytes.""" return b"".join(cborutil.streamencode(obj)) -@templatefilter("commondir") +@templatefilter(b"commondir") def commondir(filelist): """List of text. Treats each list item as file name with / as path separator and returns the longest common directory @@ -142,30 +142,30 @@ try: if not filelist: - return "" - dirlist = [f.lstrip("/").split("/")[:-1] for f in filelist] + return b"" + dirlist = [f.lstrip(b"/").split(b"/")[:-1] for f in filelist] if len(dirlist) == 1: - return "/".join(dirlist[0]) + return b"/".join(dirlist[0]) a = min(dirlist) b = max(dirlist) # The common prefix of a and b is shared with all # elements of the list since Python sorts lexicographical # and [1, x] after [1]. - return "/".join(common(a, b)) + return b"/".join(common(a, b)) except TypeError: - raise error.ParseError(_("argument is not a list of text")) + raise error.ParseError(_(b"argument is not a list of text")) -@templatefilter("count") +@templatefilter(b"count") def count(i): """List or text. Returns the length as an integer.""" try: return len(i) except TypeError: - raise error.ParseError(_("not countable")) + raise error.ParseError(_(b"not countable")) -@templatefilter("dirname", intype=bytes) +@templatefilter(b"dirname", intype=bytes) def dirname(path): """Any text. Treats the text as a path, and strips the last component of the path after splitting by the path separator. @@ -173,23 +173,23 @@ return os.path.dirname(path) -@templatefilter("domain", intype=bytes) +@templatefilter(b"domain", intype=bytes) def domain(author): """Any text. Finds the first string that looks like an email address, and extracts just the domain component. Example: ``User `` becomes ``example.com``. """ - f = author.find("@") + f = author.find(b"@") if f == -1: - return "" + return b"" author = author[f + 1 :] - f = author.find(">") + f = author.find(b">") if f >= 0: author = author[:f] return author -@templatefilter("email", intype=bytes) +@templatefilter(b"email", intype=bytes) def email(text): """Any text. Extracts the first string that looks like an email address. Example: ``User `` becomes @@ -198,23 +198,23 @@ return stringutil.email(text) -@templatefilter("escape", intype=bytes) +@templatefilter(b"escape", intype=bytes) def escape(text): """Any text. Replaces the special XML/XHTML characters "&", "<" and ">" with XML entities, and filters out NUL characters. """ - return url.escape(text.replace("\0", ""), True) + return url.escape(text.replace(b"\0", b""), True) para_re = None space_re = None -def fill(text, width, initindent="", hangindent=""): +def fill(text, width, initindent=b"", hangindent=b""): """fill many paragraphs with optional indentation.""" global para_re, space_re if para_re is None: - para_re = re.compile("(\n\n|\n\\s*[-*]\\s*)", re.M) + para_re = re.compile(b"(\n\n|\n\\s*[-*]\\s*)", re.M) space_re = re.compile(br" +") def findparas(): @@ -234,10 +234,10 @@ yield text[start : m.start(0)], m.group(1) start = m.end(1) - return "".join( + return b"".join( [ stringutil.wrap( - space_re.sub(" ", stringutil.wrap(para, width)), + space_re.sub(b" ", stringutil.wrap(para, width)), width, initindent, hangindent, @@ -248,28 +248,28 @@ ) -@templatefilter("fill68", intype=bytes) +@templatefilter(b"fill68", intype=bytes) def fill68(text): """Any text. Wraps the text to fit in 68 columns.""" return fill(text, 68) -@templatefilter("fill76", intype=bytes) +@templatefilter(b"fill76", intype=bytes) def fill76(text): """Any text. Wraps the text to fit in 76 columns.""" return fill(text, 76) -@templatefilter("firstline", intype=bytes) +@templatefilter(b"firstline", intype=bytes) def firstline(text): """Any text. Returns the first line of text.""" try: - return text.splitlines(True)[0].rstrip("\r\n") + return text.splitlines(True)[0].rstrip(b"\r\n") except IndexError: - return "" + return b"" -@templatefilter("hex", intype=bytes) +@templatefilter(b"hex", intype=bytes) def hexfilter(text): """Any text. Convert a binary Mercurial node identifier into its long hexadecimal representation. @@ -277,36 +277,36 @@ return node.hex(text) -@templatefilter("hgdate", intype=templateutil.date) +@templatefilter(b"hgdate", intype=templateutil.date) def hgdate(text): """Date. Returns the date as a pair of numbers: "1157407993 25200" (Unix timestamp, timezone offset). """ - return "%d %d" % text + return b"%d %d" % text -@templatefilter("isodate", intype=templateutil.date) +@templatefilter(b"isodate", intype=templateutil.date) def isodate(text): """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00 +0200". """ - return dateutil.datestr(text, "%Y-%m-%d %H:%M %1%2") + return dateutil.datestr(text, b"%Y-%m-%d %H:%M %1%2") -@templatefilter("isodatesec", intype=templateutil.date) +@templatefilter(b"isodatesec", intype=templateutil.date) def isodatesec(text): """Date. Returns the date in ISO 8601 format, including seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date filter. """ - return dateutil.datestr(text, "%Y-%m-%d %H:%M:%S %1%2") + return dateutil.datestr(text, b"%Y-%m-%d %H:%M:%S %1%2") def indent(text, prefix): """indent each non-empty line of text after first with prefix.""" lines = text.splitlines() num_lines = len(lines) - endswithnewline = text[-1:] == "\n" + endswithnewline = text[-1:] == b"\n" def indenter(): for i in pycompat.xrange(num_lines): @@ -315,72 +315,72 @@ yield prefix yield l if i < num_lines - 1 or endswithnewline: - yield "\n" + yield b"\n" - return "".join(indenter()) + return b"".join(indenter()) -@templatefilter("json") +@templatefilter(b"json") def json(obj, paranoid=True): """Any object. Serializes the object to a JSON formatted text.""" if obj is None: - return "null" + return b"null" elif obj is False: - return "false" + return b"false" elif obj is True: - return "true" + return b"true" elif isinstance(obj, (int, long, float)): return pycompat.bytestr(obj) elif isinstance(obj, bytes): - return '"%s"' % encoding.jsonescape(obj, paranoid=paranoid) + return b'"%s"' % encoding.jsonescape(obj, paranoid=paranoid) elif isinstance(obj, type(u"")): raise error.ProgrammingError( - "Mercurial only does output with bytes: %r" % obj + b"Mercurial only does output with bytes: %r" % obj ) - elif util.safehasattr(obj, "keys"): + elif util.safehasattr(obj, b"keys"): out = [ - '"%s": %s' + b'"%s": %s' % (encoding.jsonescape(k, paranoid=paranoid), json(v, paranoid)) for k, v in sorted(obj.iteritems()) ] - return "{" + ", ".join(out) + "}" - elif util.safehasattr(obj, "__iter__"): + return b"{" + b", ".join(out) + b"}" + elif util.safehasattr(obj, b"__iter__"): out = [json(i, paranoid) for i in obj] - return "[" + ", ".join(out) + "]" - raise error.ProgrammingError("cannot encode %r" % obj) + return b"[" + b", ".join(out) + b"]" + raise error.ProgrammingError(b"cannot encode %r" % obj) -@templatefilter("lower", intype=bytes) +@templatefilter(b"lower", intype=bytes) def lower(text): """Any text. Converts the text to lowercase.""" return encoding.lower(text) -@templatefilter("nonempty", intype=bytes) +@templatefilter(b"nonempty", intype=bytes) def nonempty(text): """Any text. Returns '(none)' if the string is empty.""" - return text or "(none)" + return text or b"(none)" -@templatefilter("obfuscate", intype=bytes) +@templatefilter(b"obfuscate", intype=bytes) def obfuscate(text): """Any text. Returns the input text rendered as a sequence of XML entities. """ text = unicode(text, pycompat.sysstr(encoding.encoding), r"replace") - return "".join(["&#%d;" % ord(c) for c in text]) + return b"".join([b"&#%d;" % ord(c) for c in text]) -@templatefilter("permissions", intype=bytes) +@templatefilter(b"permissions", intype=bytes) def permissions(flags): - if "l" in flags: - return "lrwxrwxrwx" - if "x" in flags: - return "-rwxr-xr-x" - return "-rw-r--r--" + if b"l" in flags: + return b"lrwxrwxrwx" + if b"x" in flags: + return b"-rwxr-xr-x" + return b"-rw-r--r--" -@templatefilter("person", intype=bytes) +@templatefilter(b"person", intype=bytes) def person(author): """Any text. Returns the name before an email address, interpreting it as per RFC 5322. @@ -388,32 +388,32 @@ return stringutil.person(author) -@templatefilter("revescape", intype=bytes) +@templatefilter(b"revescape", intype=bytes) def revescape(text): """Any text. Escapes all "special" characters, except @. Forward slashes are escaped twice to prevent web servers from prematurely unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz". """ - return urlreq.quote(text, safe="/@").replace("/", "%252F") + return urlreq.quote(text, safe=b"/@").replace(b"/", b"%252F") -@templatefilter("rfc3339date", intype=templateutil.date) +@templatefilter(b"rfc3339date", intype=templateutil.date) def rfc3339date(text): """Date. Returns a date using the Internet date format specified in RFC 3339: "2009-08-18T13:00:13+02:00". """ - return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2") + return dateutil.datestr(text, b"%Y-%m-%dT%H:%M:%S%1:%2") -@templatefilter("rfc822date", intype=templateutil.date) +@templatefilter(b"rfc822date", intype=templateutil.date) def rfc822date(text): """Date. Returns a date using the same format used in email headers: "Tue, 18 Aug 2009 13:00:13 +0200". """ - return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2") + return dateutil.datestr(text, b"%a, %d %b %Y %H:%M:%S %1%2") -@templatefilter("short", intype=bytes) +@templatefilter(b"short", intype=bytes) def short(text): """Changeset hash. Returns the short form of a changeset hash, i.e. a 12 hexadecimal digit string. @@ -421,7 +421,7 @@ return text[:12] -@templatefilter("shortbisect", intype=bytes) +@templatefilter(b"shortbisect", intype=bytes) def shortbisect(label): """Any text. Treats `label` as a bisection status, and returns a single-character representing the status (G: good, B: bad, @@ -430,33 +430,33 @@ """ if label: return label[0:1].upper() - return " " + return b" " -@templatefilter("shortdate", intype=templateutil.date) +@templatefilter(b"shortdate", intype=templateutil.date) def shortdate(text): """Date. Returns a date like "2006-09-18".""" return dateutil.shortdate(text) -@templatefilter("slashpath", intype=bytes) +@templatefilter(b"slashpath", intype=bytes) def slashpath(path): """Any text. Replaces the native path separator with slash.""" return util.pconvert(path) -@templatefilter("splitlines", intype=bytes) +@templatefilter(b"splitlines", intype=bytes) def splitlines(text): """Any text. Split text into a list of lines.""" - return templateutil.hybridlist(text.splitlines(), name="line") + return templateutil.hybridlist(text.splitlines(), name=b"line") -@templatefilter("stringescape", intype=bytes) +@templatefilter(b"stringescape", intype=bytes) def stringescape(text): return stringutil.escapestr(text) -@templatefilter("stringify", intype=bytes) +@templatefilter(b"stringify", intype=bytes) def stringify(thing): """Any type. Turns the value into text by converting values into text and concatenating them. @@ -464,33 +464,33 @@ return thing # coerced by the intype -@templatefilter("stripdir", intype=bytes) +@templatefilter(b"stripdir", intype=bytes) def stripdir(text): """Treat the text as path and strip a directory level, if possible. For example, "foo" and "foo/bar" becomes "foo". """ dir = os.path.dirname(text) - if dir == "": + if dir == b"": return os.path.basename(text) else: return dir -@templatefilter("tabindent", intype=bytes) +@templatefilter(b"tabindent", intype=bytes) def tabindent(text): """Any text. Returns the text, with every non-empty line except the first starting with a tab character. """ - return indent(text, "\t") + return indent(text, b"\t") -@templatefilter("upper", intype=bytes) +@templatefilter(b"upper", intype=bytes) def upper(text): """Any text. Converts the text to uppercase.""" return encoding.upper(text) -@templatefilter("urlescape", intype=bytes) +@templatefilter(b"urlescape", intype=bytes) def urlescape(text): """Any text. Escapes all "special" characters. For example, "foo bar" becomes "foo%20bar". @@ -498,35 +498,35 @@ return urlreq.quote(text) -@templatefilter("user", intype=bytes) +@templatefilter(b"user", intype=bytes) def userfilter(text): """Any text. Returns a short representation of a user name or email address.""" return stringutil.shortuser(text) -@templatefilter("emailuser", intype=bytes) +@templatefilter(b"emailuser", intype=bytes) def emailuser(text): """Any text. Returns the user portion of an email address.""" return stringutil.emailuser(text) -@templatefilter("utf8", intype=bytes) +@templatefilter(b"utf8", intype=bytes) def utf8(text): """Any text. Converts from the local character encoding to UTF-8.""" return encoding.fromlocal(text) -@templatefilter("xmlescape", intype=bytes) +@templatefilter(b"xmlescape", intype=bytes) def xmlescape(text): text = ( - text.replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace('"', """) - .replace("'", "'") + text.replace(b"&", b"&") + .replace(b"<", b"<") + .replace(b">", b">") + .replace(b'"', b""") + .replace(b"'", b"'") ) # ' invalid in HTML - return re.sub("[\x00-\x08\x0B\x0C\x0E-\x1F]", " ", text) + return re.sub(b"[\x00-\x08\x0B\x0C\x0E-\x1F]", b" ", text) def websub(text, websubtable): diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py --- a/mercurial/templatefuncs.py +++ b/mercurial/templatefuncs.py @@ -49,21 +49,21 @@ templatefunc = registrar.templatefunc(funcs) -@templatefunc("date(date[, fmt])") +@templatefunc(b"date(date[, fmt])") def date(context, mapping, args): """Format a date. See :hg:`help dates` for formatting strings. The default is a Unix date format, including the timezone: "Mon Sep 04 15:13:13 2006 0700".""" if not (1 <= len(args) <= 2): # i18n: "date" is a keyword - raise error.ParseError(_("date expects one or two arguments")) + raise error.ParseError(_(b"date expects one or two arguments")) date = evaldate( context, mapping, args[0], # i18n: "date" is a keyword - _("date expects a date information"), + _(b"date expects a date information"), ) fmt = None if len(args) == 2: @@ -74,34 +74,34 @@ return dateutil.datestr(date, fmt) -@templatefunc("dict([[key=]value...])", argspec="*args **kwargs") +@templatefunc(b"dict([[key=]value...])", argspec=b"*args **kwargs") def dict_(context, mapping, args): """Construct a dict from key-value pairs. A key may be omitted if a value expression can provide an unambiguous name.""" data = util.sortdict() - for v in args["args"]: + for v in args[b"args"]: k = templateutil.findsymbolicname(v) if not k: - raise error.ParseError(_("dict key cannot be inferred")) - if k in data or k in args["kwargs"]: - raise error.ParseError(_("duplicated dict key '%s' inferred") % k) + raise error.ParseError(_(b"dict key cannot be inferred")) + if k in data or k in args[b"kwargs"]: + raise error.ParseError(_(b"duplicated dict key '%s' inferred") % k) data[k] = evalfuncarg(context, mapping, v) data.update( (k, evalfuncarg(context, mapping, v)) - for k, v in args["kwargs"].iteritems() + for k, v in args[b"kwargs"].iteritems() ) return templateutil.hybriddict(data) -@templatefunc("diff([includepattern [, excludepattern]])", requires={"ctx"}) +@templatefunc(b"diff([includepattern [, excludepattern]])", requires={b"ctx"}) def diff(context, mapping, args): """Show a diff, optionally specifying files to include or exclude.""" if len(args) > 2: # i18n: "diff" is a keyword - raise error.ParseError(_("diff expects zero, one, or two arguments")) + raise error.ParseError(_(b"diff expects zero, one, or two arguments")) def getpatterns(i): if i < len(args): @@ -110,72 +110,74 @@ return [s] return [] - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1))) - return "".join(chunks) + return b"".join(chunks) -@templatefunc("extdata(source)", argspec="source", requires={"ctx", "cache"}) +@templatefunc( + b"extdata(source)", argspec=b"source", requires={b"ctx", b"cache"} +) def extdata(context, mapping, args): """Show a text read from the specified extdata source. (EXPERIMENTAL)""" - if "source" not in args: + if b"source" not in args: # i18n: "extdata" is a keyword - raise error.ParseError(_("extdata expects one argument")) + raise error.ParseError(_(b"extdata expects one argument")) - source = evalstring(context, mapping, args["source"]) + source = evalstring(context, mapping, args[b"source"]) if not source: - sym = templateutil.findsymbolicname(args["source"]) + sym = templateutil.findsymbolicname(args[b"source"]) if sym: raise error.ParseError( - _("empty data source specified"), - hint=_("did you mean extdata('%s')?") % sym, + _(b"empty data source specified"), + hint=_(b"did you mean extdata('%s')?") % sym, ) else: - raise error.ParseError(_("empty data source specified")) - cache = context.resource(mapping, "cache").setdefault("extdata", {}) - ctx = context.resource(mapping, "ctx") + raise error.ParseError(_(b"empty data source specified")) + cache = context.resource(mapping, b"cache").setdefault(b"extdata", {}) + ctx = context.resource(mapping, b"ctx") if source in cache: data = cache[source] else: data = cache[source] = scmutil.extdatasource(ctx.repo(), source) - return data.get(ctx.rev(), "") + return data.get(ctx.rev(), b"") -@templatefunc("files(pattern)", requires={"ctx"}) +@templatefunc(b"files(pattern)", requires={b"ctx"}) def files(context, mapping, args): """All files of the current changeset matching the pattern. See :hg:`help patterns`.""" if not len(args) == 1: # i18n: "files" is a keyword - raise error.ParseError(_("files expects one argument")) + raise error.ParseError(_(b"files expects one argument")) raw = evalstring(context, mapping, args[0]) - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") m = ctx.match([raw]) files = list(ctx.matches(m)) - return templateutil.compatfileslist(context, mapping, "file", files) + return templateutil.compatfileslist(context, mapping, b"file", files) -@templatefunc("fill(text[, width[, initialident[, hangindent]]])") +@templatefunc(b"fill(text[, width[, initialident[, hangindent]]])") def fill(context, mapping, args): """Fill many paragraphs with optional indentation. See the "fill" filter.""" if not (1 <= len(args) <= 4): # i18n: "fill" is a keyword - raise error.ParseError(_("fill expects one to four arguments")) + raise error.ParseError(_(b"fill expects one to four arguments")) text = evalstring(context, mapping, args[0]) width = 76 - initindent = "" - hangindent = "" + initindent = b"" + hangindent = b"" if 2 <= len(args) <= 4: width = evalinteger( context, mapping, args[1], # i18n: "fill" is a keyword - _("fill expects an integer width"), + _(b"fill expects an integer width"), ) try: initindent = evalstring(context, mapping, args[2]) @@ -186,13 +188,13 @@ return templatefilters.fill(text, width, initindent, hangindent) -@templatefunc("filter(iterable[, expr])") +@templatefunc(b"filter(iterable[, expr])") def filter_(context, mapping, args): """Remove empty elements from a list or a dict. If expr specified, it's applied to each element to test emptiness.""" if not (1 <= len(args) <= 2): # i18n: "filter" is a keyword - raise error.ParseError(_("filter expects one or two arguments")) + raise error.ParseError(_(b"filter expects one or two arguments")) iterable = evalwrapped(context, mapping, args[0]) if len(args) == 1: @@ -203,79 +205,79 @@ def select(w): if not isinstance(w, templateutil.mappable): - raise error.ParseError(_("not filterable by expression")) + raise error.ParseError(_(b"not filterable by expression")) lm = context.overlaymap(mapping, w.tomap(context)) return evalboolean(context, lm, args[1]) return iterable.filter(context, mapping, select) -@templatefunc("formatnode(node)", requires={"ui"}) +@templatefunc(b"formatnode(node)", requires={b"ui"}) def formatnode(context, mapping, args): """Obtain the preferred form of a changeset hash. (DEPRECATED)""" if len(args) != 1: # i18n: "formatnode" is a keyword - raise error.ParseError(_("formatnode expects one argument")) + raise error.ParseError(_(b"formatnode expects one argument")) - ui = context.resource(mapping, "ui") + ui = context.resource(mapping, b"ui") node = evalstring(context, mapping, args[0]) if ui.debugflag: return node return templatefilters.short(node) -@templatefunc("mailmap(author)", requires={"repo", "cache"}) +@templatefunc(b"mailmap(author)", requires={b"repo", b"cache"}) def mailmap(context, mapping, args): """Return the author, updated according to the value set in the .mailmap file""" if len(args) != 1: - raise error.ParseError(_("mailmap expects one argument")) + raise error.ParseError(_(b"mailmap expects one argument")) author = evalstring(context, mapping, args[0]) - cache = context.resource(mapping, "cache") - repo = context.resource(mapping, "repo") + cache = context.resource(mapping, b"cache") + repo = context.resource(mapping, b"repo") - if "mailmap" not in cache: - data = repo.wvfs.tryread(".mailmap") - cache["mailmap"] = stringutil.parsemailmap(data) + if b"mailmap" not in cache: + data = repo.wvfs.tryread(b".mailmap") + cache[b"mailmap"] = stringutil.parsemailmap(data) - return stringutil.mapname(cache["mailmap"], author) + return stringutil.mapname(cache[b"mailmap"], author) @templatefunc( - "pad(text, width[, fillchar=' '[, left=False[, truncate=False]]])", - argspec="text width fillchar left truncate", + b"pad(text, width[, fillchar=' '[, left=False[, truncate=False]]])", + argspec=b"text width fillchar left truncate", ) def pad(context, mapping, args): """Pad text with a fill character.""" - if "text" not in args or "width" not in args: + if b"text" not in args or b"width" not in args: # i18n: "pad" is a keyword - raise error.ParseError(_("pad() expects two to four arguments")) + raise error.ParseError(_(b"pad() expects two to four arguments")) width = evalinteger( context, mapping, - args["width"], + args[b"width"], # i18n: "pad" is a keyword - _("pad() expects an integer width"), + _(b"pad() expects an integer width"), ) - text = evalstring(context, mapping, args["text"]) + text = evalstring(context, mapping, args[b"text"]) truncate = False left = False - fillchar = " " - if "fillchar" in args: - fillchar = evalstring(context, mapping, args["fillchar"]) + fillchar = b" " + if b"fillchar" in args: + fillchar = evalstring(context, mapping, args[b"fillchar"]) if len(color.stripeffects(fillchar)) != 1: # i18n: "pad" is a keyword - raise error.ParseError(_("pad() expects a single fill character")) - if "left" in args: - left = evalboolean(context, mapping, args["left"]) - if "truncate" in args: - truncate = evalboolean(context, mapping, args["truncate"]) + raise error.ParseError(_(b"pad() expects a single fill character")) + if b"left" in args: + left = evalboolean(context, mapping, args[b"left"]) + if b"truncate" in args: + truncate = evalboolean(context, mapping, args[b"truncate"]) fillwidth = width - encoding.colwidth(color.stripeffects(text)) if fillwidth < 0 and truncate: @@ -288,7 +290,7 @@ return text + fillchar * fillwidth -@templatefunc("indent(text, indentchars[, firstline])") +@templatefunc(b"indent(text, indentchars[, firstline])") def indent(context, mapping, args): """Indents all non-empty lines with the characters given in the indentchars string. An optional @@ -296,7 +298,7 @@ if present.""" if not (2 <= len(args) <= 3): # i18n: "indent" is a keyword - raise error.ParseError(_("indent() expects two or three arguments")) + raise error.ParseError(_(b"indent() expects two or three arguments")) text = evalstring(context, mapping, args[0]) indent = evalstring(context, mapping, args[1]) @@ -310,14 +312,14 @@ return templatefilters.indent(firstline + text, indent) -@templatefunc("get(dict, key)") +@templatefunc(b"get(dict, key)") def get(context, mapping, args): """Get an attribute/key from an object. Some keywords are complex types. This function allows you to obtain the value of an attribute on these types.""" if len(args) != 2: # i18n: "get" is a keyword - raise error.ParseError(_("get() expects two arguments")) + raise error.ParseError(_(b"get() expects two arguments")) dictarg = evalwrapped(context, mapping, args[0]) key = evalrawexp(context, mapping, args[1]) @@ -325,34 +327,34 @@ return dictarg.getmember(context, mapping, key) except error.ParseError as err: # i18n: "get" is a keyword - hint = _("get() expects a dict as first argument") + hint = _(b"get() expects a dict as first argument") raise error.ParseError(bytes(err), hint=hint) -@templatefunc("config(section, name[, default])", requires={"ui"}) +@templatefunc(b"config(section, name[, default])", requires={b"ui"}) def config(context, mapping, args): """Returns the requested hgrc config option as a string.""" - fn = context.resource(mapping, "ui").config + fn = context.resource(mapping, b"ui").config return _config(context, mapping, args, fn, evalstring) -@templatefunc("configbool(section, name[, default])", requires={"ui"}) +@templatefunc(b"configbool(section, name[, default])", requires={b"ui"}) def configbool(context, mapping, args): """Returns the requested hgrc config option as a boolean.""" - fn = context.resource(mapping, "ui").configbool + fn = context.resource(mapping, b"ui").configbool return _config(context, mapping, args, fn, evalboolean) -@templatefunc("configint(section, name[, default])", requires={"ui"}) +@templatefunc(b"configint(section, name[, default])", requires={b"ui"}) def configint(context, mapping, args): """Returns the requested hgrc config option as an integer.""" - fn = context.resource(mapping, "ui").configint + fn = context.resource(mapping, b"ui").configint return _config(context, mapping, args, fn, evalinteger) def _config(context, mapping, args, configfn, defaultfn): if not (2 <= len(args) <= 3): - raise error.ParseError(_("config expects two or three arguments")) + raise error.ParseError(_(b"config expects two or three arguments")) # The config option can come from any section, though we specifically # reserve the [templateconfig] section for dynamically defining options @@ -366,13 +368,13 @@ return configfn(section, name) -@templatefunc("if(expr, then[, else])") +@templatefunc(b"if(expr, then[, else])") def if_(context, mapping, args): """Conditionally execute based on the result of an expression.""" if not (2 <= len(args) <= 3): # i18n: "if" is a keyword - raise error.ParseError(_("if expects two or three arguments")) + raise error.ParseError(_(b"if expects two or three arguments")) test = evalboolean(context, mapping, args[0]) if test: @@ -381,13 +383,13 @@ return evalrawexp(context, mapping, args[2]) -@templatefunc("ifcontains(needle, haystack, then[, else])") +@templatefunc(b"ifcontains(needle, haystack, then[, else])") def ifcontains(context, mapping, args): """Conditionally execute based on whether the item "needle" is in "haystack".""" if not (3 <= len(args) <= 4): # i18n: "ifcontains" is a keyword - raise error.ParseError(_("ifcontains expects three or four arguments")) + raise error.ParseError(_(b"ifcontains expects three or four arguments")) haystack = evalwrapped(context, mapping, args[1]) try: @@ -402,13 +404,13 @@ return evalrawexp(context, mapping, args[3]) -@templatefunc("ifeq(expr1, expr2, then[, else])") +@templatefunc(b"ifeq(expr1, expr2, then[, else])") def ifeq(context, mapping, args): """Conditionally execute based on whether 2 items are equivalent.""" if not (3 <= len(args) <= 4): # i18n: "ifeq" is a keyword - raise error.ParseError(_("ifeq expects three or four arguments")) + raise error.ParseError(_(b"ifeq expects three or four arguments")) test = evalstring(context, mapping, args[0]) match = evalstring(context, mapping, args[1]) @@ -418,30 +420,30 @@ return evalrawexp(context, mapping, args[3]) -@templatefunc("join(list, sep)") +@templatefunc(b"join(list, sep)") def join(context, mapping, args): """Join items in a list with a delimiter.""" if not (1 <= len(args) <= 2): # i18n: "join" is a keyword - raise error.ParseError(_("join expects one or two arguments")) + raise error.ParseError(_(b"join expects one or two arguments")) joinset = evalwrapped(context, mapping, args[0]) - joiner = " " + joiner = b" " if len(args) > 1: joiner = evalstring(context, mapping, args[1]) return joinset.join(context, mapping, joiner) -@templatefunc("label(label, expr)", requires={"ui"}) +@templatefunc(b"label(label, expr)", requires={b"ui"}) def label(context, mapping, args): """Apply a label to generated content. Content with a label applied can result in additional post-processing, such as automatic colorization.""" if len(args) != 2: # i18n: "label" is a keyword - raise error.ParseError(_("label expects two arguments")) + raise error.ParseError(_(b"label expects two arguments")) - ui = context.resource(mapping, "ui") + ui = context.resource(mapping, b"ui") thing = evalstring(context, mapping, args[1]) # preserve unknown symbol as literal so effects like 'red', 'bold', # etc. don't need to be quoted @@ -450,7 +452,7 @@ return ui.label(thing, label) -@templatefunc("latesttag([pattern])") +@templatefunc(b"latesttag([pattern])") def latesttag(context, mapping, args): """The global tags matching the given pattern on the most recent globally tagged ancestor of this changeset. @@ -460,7 +462,7 @@ """ if len(args) > 1: # i18n: "latesttag" is a keyword - raise error.ParseError(_("latesttag expects at most one argument")) + raise error.ParseError(_(b"latesttag expects at most one argument")) pattern = None if len(args) == 1: @@ -468,20 +470,20 @@ return templatekw.showlatesttags(context, mapping, pattern) -@templatefunc("localdate(date[, tz])") +@templatefunc(b"localdate(date[, tz])") def localdate(context, mapping, args): """Converts a date to the specified timezone. The default is local date.""" if not (1 <= len(args) <= 2): # i18n: "localdate" is a keyword - raise error.ParseError(_("localdate expects one or two arguments")) + raise error.ParseError(_(b"localdate expects one or two arguments")) date = evaldate( context, mapping, args[0], # i18n: "localdate" is a keyword - _("localdate expects a date information"), + _(b"localdate expects a date information"), ) if len(args) >= 2: tzoffset = None @@ -495,50 +497,50 @@ tzoffset = int(tz) except (TypeError, ValueError): # i18n: "localdate" is a keyword - raise error.ParseError(_("localdate expects a timezone")) + raise error.ParseError(_(b"localdate expects a timezone")) else: tzoffset = dateutil.makedate()[1] return templateutil.date((date[0], tzoffset)) -@templatefunc("max(iterable)") +@templatefunc(b"max(iterable)") def max_(context, mapping, args, **kwargs): """Return the max of an iterable""" if len(args) != 1: # i18n: "max" is a keyword - raise error.ParseError(_("max expects one argument")) + raise error.ParseError(_(b"max expects one argument")) iterable = evalwrapped(context, mapping, args[0]) try: return iterable.getmax(context, mapping) except error.ParseError as err: # i18n: "max" is a keyword - hint = _("max first argument should be an iterable") + hint = _(b"max first argument should be an iterable") raise error.ParseError(bytes(err), hint=hint) -@templatefunc("min(iterable)") +@templatefunc(b"min(iterable)") def min_(context, mapping, args, **kwargs): """Return the min of an iterable""" if len(args) != 1: # i18n: "min" is a keyword - raise error.ParseError(_("min expects one argument")) + raise error.ParseError(_(b"min expects one argument")) iterable = evalwrapped(context, mapping, args[0]) try: return iterable.getmin(context, mapping) except error.ParseError as err: # i18n: "min" is a keyword - hint = _("min first argument should be an iterable") + hint = _(b"min first argument should be an iterable") raise error.ParseError(bytes(err), hint=hint) -@templatefunc("mod(a, b)") +@templatefunc(b"mod(a, b)") def mod(context, mapping, args): """Calculate a mod b such that a / b + a mod b == a""" if not len(args) == 2: # i18n: "mod" is a keyword - raise error.ParseError(_("mod expects two arguments")) + raise error.ParseError(_(b"mod expects two arguments")) func = lambda a, b: a % b return templateutil.runarithmetic( @@ -546,69 +548,70 @@ ) -@templatefunc("obsfateoperations(markers)") +@templatefunc(b"obsfateoperations(markers)") def obsfateoperations(context, mapping, args): """Compute obsfate related information based on markers (EXPERIMENTAL)""" if len(args) != 1: # i18n: "obsfateoperations" is a keyword - raise error.ParseError(_("obsfateoperations expects one argument")) + raise error.ParseError(_(b"obsfateoperations expects one argument")) markers = evalfuncarg(context, mapping, args[0]) try: data = obsutil.markersoperations(markers) - return templateutil.hybridlist(data, name="operation") + return templateutil.hybridlist(data, name=b"operation") except (TypeError, KeyError): # i18n: "obsfateoperations" is a keyword - errmsg = _("obsfateoperations first argument should be an iterable") + errmsg = _(b"obsfateoperations first argument should be an iterable") raise error.ParseError(errmsg) -@templatefunc("obsfatedate(markers)") +@templatefunc(b"obsfatedate(markers)") def obsfatedate(context, mapping, args): """Compute obsfate related information based on markers (EXPERIMENTAL)""" if len(args) != 1: # i18n: "obsfatedate" is a keyword - raise error.ParseError(_("obsfatedate expects one argument")) + raise error.ParseError(_(b"obsfatedate expects one argument")) markers = evalfuncarg(context, mapping, args[0]) try: # TODO: maybe this has to be a wrapped list of date wrappers? data = obsutil.markersdates(markers) - return templateutil.hybridlist(data, name="date", fmt="%d %d") + return templateutil.hybridlist(data, name=b"date", fmt=b"%d %d") except (TypeError, KeyError): # i18n: "obsfatedate" is a keyword - errmsg = _("obsfatedate first argument should be an iterable") + errmsg = _(b"obsfatedate first argument should be an iterable") raise error.ParseError(errmsg) -@templatefunc("obsfateusers(markers)") +@templatefunc(b"obsfateusers(markers)") def obsfateusers(context, mapping, args): """Compute obsfate related information based on markers (EXPERIMENTAL)""" if len(args) != 1: # i18n: "obsfateusers" is a keyword - raise error.ParseError(_("obsfateusers expects one argument")) + raise error.ParseError(_(b"obsfateusers expects one argument")) markers = evalfuncarg(context, mapping, args[0]) try: data = obsutil.markersusers(markers) - return templateutil.hybridlist(data, name="user") + return templateutil.hybridlist(data, name=b"user") except (TypeError, KeyError, ValueError): # i18n: "obsfateusers" is a keyword msg = _( - "obsfateusers first argument should be an iterable of " "obsmakers" + b"obsfateusers first argument should be an iterable of " + b"obsmakers" ) raise error.ParseError(msg) -@templatefunc("obsfateverb(successors, markers)") +@templatefunc(b"obsfateverb(successors, markers)") def obsfateverb(context, mapping, args): """Compute obsfate related information based on successors (EXPERIMENTAL)""" if len(args) != 2: # i18n: "obsfateverb" is a keyword - raise error.ParseError(_("obsfateverb expects two arguments")) + raise error.ParseError(_(b"obsfateverb expects two arguments")) successors = evalfuncarg(context, mapping, args[0]) markers = evalfuncarg(context, mapping, args[1]) @@ -617,33 +620,33 @@ return obsutil.obsfateverb(successors, markers) except TypeError: # i18n: "obsfateverb" is a keyword - errmsg = _("obsfateverb first argument should be countable") + errmsg = _(b"obsfateverb first argument should be countable") raise error.ParseError(errmsg) -@templatefunc("relpath(path)", requires={"repo"}) +@templatefunc(b"relpath(path)", requires={b"repo"}) def relpath(context, mapping, args): """Convert a repository-absolute path into a filesystem path relative to the current working directory.""" if len(args) != 1: # i18n: "relpath" is a keyword - raise error.ParseError(_("relpath expects one argument")) + raise error.ParseError(_(b"relpath expects one argument")) - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") path = evalstring(context, mapping, args[0]) return repo.pathto(path) -@templatefunc("revset(query[, formatargs...])", requires={"repo", "cache"}) +@templatefunc(b"revset(query[, formatargs...])", requires={b"repo", b"cache"}) def revset(context, mapping, args): """Execute a revision set query. See :hg:`help revset`.""" if not len(args) > 0: # i18n: "revset" is a keyword - raise error.ParseError(_("revset expects one or more arguments")) + raise error.ParseError(_(b"revset expects one or more arguments")) raw = evalstring(context, mapping, args[0]) - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") def query(expr): m = revsetmod.match(repo.ui, expr, lookup=revsetmod.lookupfn(repo)) @@ -653,30 +656,30 @@ formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]] revs = query(revsetlang.formatspec(raw, *formatargs)) else: - cache = context.resource(mapping, "cache") - revsetcache = cache.setdefault("revsetcache", {}) + cache = context.resource(mapping, b"cache") + revsetcache = cache.setdefault(b"revsetcache", {}) if raw in revsetcache: revs = revsetcache[raw] else: revs = query(raw) revsetcache[raw] = revs - return templatekw.showrevslist(context, mapping, "revision", revs) + return templatekw.showrevslist(context, mapping, b"revision", revs) -@templatefunc("rstdoc(text, style)") +@templatefunc(b"rstdoc(text, style)") def rstdoc(context, mapping, args): """Format reStructuredText.""" if len(args) != 2: # i18n: "rstdoc" is a keyword - raise error.ParseError(_("rstdoc expects two arguments")) + raise error.ParseError(_(b"rstdoc expects two arguments")) text = evalstring(context, mapping, args[0]) style = evalstring(context, mapping, args[1]) - return minirst.format(text, style=style, keep=["verbose"]) + return minirst.format(text, style=style, keep=[b"verbose"]) -@templatefunc("search(pattern, text)") +@templatefunc(b"search(pattern, text)") def search(context, mapping, args): """Look for the first text matching the regular expression pattern. Groups are accessible as ``{1}``, ``{2}``, ... in %-mapped template.""" @@ -700,7 +703,7 @@ # i18n: "search" is a keyword _(b"invalid group %(group)s in search pattern: %(pat)s") % { - b"group": b", ".join("'%s'" % g for g in sorted(badgroups)), + b"group": b", ".join(b"'%s'" % g for g in sorted(badgroups)), b"pat": pat, } ) @@ -715,16 +718,16 @@ return templateutil.mappingdict(lm, tmpl=b"{0}") -@templatefunc("separate(sep, args...)", argspec="sep *args") +@templatefunc(b"separate(sep, args...)", argspec=b"sep *args") def separate(context, mapping, args): """Add a separator between non-empty arguments.""" - if "sep" not in args: + if b"sep" not in args: # i18n: "separate" is a keyword - raise error.ParseError(_("separate expects at least one argument")) + raise error.ParseError(_(b"separate expects at least one argument")) - sep = evalstring(context, mapping, args["sep"]) + sep = evalstring(context, mapping, args[b"sep"]) first = True - for arg in args["args"]: + for arg in args[b"args"]: argstr = evalstring(context, mapping, arg) if not argstr: continue @@ -735,13 +738,13 @@ yield argstr -@templatefunc("shortest(node, minlength=4)", requires={"repo", "cache"}) +@templatefunc(b"shortest(node, minlength=4)", requires={b"repo", b"cache"}) def shortest(context, mapping, args): """Obtain the shortest representation of a node.""" if not (1 <= len(args) <= 2): # i18n: "shortest" is a keyword - raise error.ParseError(_("shortest() expects one or two arguments")) + raise error.ParseError(_(b"shortest() expects one or two arguments")) hexnode = evalstring(context, mapping, args[0]) @@ -752,10 +755,10 @@ mapping, args[1], # i18n: "shortest" is a keyword - _("shortest() expects an integer minlength"), + _(b"shortest() expects an integer minlength"), ) - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") if len(hexnode) > 40: return hexnode elif len(hexnode) == 40: @@ -772,20 +775,20 @@ return hexnode if not node: return hexnode - cache = context.resource(mapping, "cache") + cache = context.resource(mapping, b"cache") try: return scmutil.shortesthexnodeidprefix(repo, node, minlength, cache) except error.RepoLookupError: return hexnode -@templatefunc("strip(text[, chars])") +@templatefunc(b"strip(text[, chars])") def strip(context, mapping, args): """Strip characters from a string. By default, strips all leading and trailing whitespace.""" if not (1 <= len(args) <= 2): # i18n: "strip" is a keyword - raise error.ParseError(_("strip expects one or two arguments")) + raise error.ParseError(_(b"strip expects one or two arguments")) text = evalstring(context, mapping, args[0]) if len(args) == 2: @@ -794,13 +797,13 @@ return text.strip() -@templatefunc("sub(pattern, replacement, expression)") +@templatefunc(b"sub(pattern, replacement, expression)") def sub(context, mapping, args): """Perform text substitution using regular expressions.""" if len(args) != 3: # i18n: "sub" is a keyword - raise error.ParseError(_("sub expects three arguments")) + raise error.ParseError(_(b"sub expects three arguments")) pat = evalstring(context, mapping, args[0]) rpl = evalstring(context, mapping, args[1]) @@ -809,36 +812,36 @@ patre = re.compile(pat) except re.error: # i18n: "sub" is a keyword - raise error.ParseError(_("sub got an invalid pattern: %s") % pat) + raise error.ParseError(_(b"sub got an invalid pattern: %s") % pat) try: yield patre.sub(rpl, src) except re.error: # i18n: "sub" is a keyword - raise error.ParseError(_("sub got an invalid replacement: %s") % rpl) + raise error.ParseError(_(b"sub got an invalid replacement: %s") % rpl) -@templatefunc("startswith(pattern, text)") +@templatefunc(b"startswith(pattern, text)") def startswith(context, mapping, args): """Returns the value from the "text" argument if it begins with the content from the "pattern" argument.""" if len(args) != 2: # i18n: "startswith" is a keyword - raise error.ParseError(_("startswith expects two arguments")) + raise error.ParseError(_(b"startswith expects two arguments")) patn = evalstring(context, mapping, args[0]) text = evalstring(context, mapping, args[1]) if text.startswith(patn): return text - return "" + return b"" -@templatefunc("word(number, text[, separator])") +@templatefunc(b"word(number, text[, separator])") def word(context, mapping, args): """Return the nth word from a string.""" if not (2 <= len(args) <= 3): # i18n: "word" is a keyword raise error.ParseError( - _("word expects two or three arguments, got %d") % len(args) + _(b"word expects two or three arguments, got %d") % len(args) ) num = evalinteger( @@ -846,7 +849,7 @@ mapping, args[0], # i18n: "word" is a keyword - _("word expects an integer index"), + _(b"word expects an integer index"), ) text = evalstring(context, mapping, args[1]) if len(args) == 3: @@ -856,7 +859,7 @@ tokens = text.split(splitter) if num >= len(tokens) or num < -len(tokens): - return "" + return b"" else: return tokens[num] diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -41,13 +41,13 @@ def getlatesttags(context, mapping, pattern=None): """return date, distance and name for the latest tag of rev""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") - cache = context.resource(mapping, "cache") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") + cache = context.resource(mapping, b"cache") - cachename = "latesttags" + cachename = b"latesttags" if pattern is not None: - cachename += "-" + pattern + cachename += b"-" + pattern match = stringutil.stringmatcher(pattern)[2] else: match = util.always @@ -55,7 +55,7 @@ if cachename not in cache: # Cache mapping from rev to a tuple with tag date, tag # distance and tag name - cache[cachename] = {-1: (0, 0, ["null"])} + cache[cachename] = {-1: (0, 0, [b"null"])} latesttags = cache[cachename] rev = ctx.rev() @@ -68,7 +68,7 @@ tags = [ t for t in ctx.tags() - if (repo.tagtype(t) and repo.tagtype(t) != "local" and match(t)) + if (repo.tagtype(t) and repo.tagtype(t) != b"local" and match(t)) ] if tags: latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)] @@ -87,10 +87,10 @@ if ctx.rev() is None: # only() doesn't support wdir prevs = [c.rev() for c in ctx.parents()] - changes = repo.revs("only(%ld, %s)", prevs, tag) + changes = repo.revs(b"only(%ld, %s)", prevs, tag) changessincetag = len(changes) + 1 else: - changes = repo.revs("only(%d, %s)", ctx.rev(), tag) + changes = repo.revs(b"only(%d, %s)", ctx.rev(), tag) changessincetag = len(changes) # Smallest number of changes since tag wins. Date is # used as tiebreaker. @@ -113,143 +113,145 @@ _ = pycompat.identity # temporarily disable gettext # i18n: column positioning for "hg log" columns = _( - "bookmark: %s\n" - "branch: %s\n" - "changeset: %s\n" - "copies: %s\n" - "date: %s\n" - "extra: %s=%s\n" - "files+: %s\n" - "files-: %s\n" - "files: %s\n" - "instability: %s\n" - "manifest: %s\n" - "obsolete: %s\n" - "parent: %s\n" - "phase: %s\n" - "summary: %s\n" - "tag: %s\n" - "user: %s\n" + b"bookmark: %s\n" + b"branch: %s\n" + b"changeset: %s\n" + b"copies: %s\n" + b"date: %s\n" + b"extra: %s=%s\n" + b"files+: %s\n" + b"files-: %s\n" + b"files: %s\n" + b"instability: %s\n" + b"manifest: %s\n" + b"obsolete: %s\n" + b"parent: %s\n" + b"phase: %s\n" + b"summary: %s\n" + b"tag: %s\n" + b"user: %s\n" ) return dict( zip( - [s.split(":", 1)[0] for s in columns.splitlines()], + [s.split(b":", 1)[0] for s in columns.splitlines()], i18n._(columns).splitlines(True), ) ) # basic internal templates -_changeidtmpl = "{rev}:{node|formatnode}" +_changeidtmpl = b"{rev}:{node|formatnode}" # default templates internally used for rendering of lists defaulttempl = { - "parent": _changeidtmpl + " ", - "manifest": _changeidtmpl, - "file_copy": "{name} ({source})", - "envvar": "{key}={value}", - "extra": "{key}={value|stringescape}", + b"parent": _changeidtmpl + b" ", + b"manifest": _changeidtmpl, + b"file_copy": b"{name} ({source})", + b"envvar": b"{key}={value}", + b"extra": b"{key}={value|stringescape}", } # filecopy is preserved for compatibility reasons -defaulttempl["filecopy"] = defaulttempl["file_copy"] +defaulttempl[b"filecopy"] = defaulttempl[b"file_copy"] # keywords are callables (see registrar.templatekeyword for details) keywords = {} templatekeyword = registrar.templatekeyword(keywords) -@templatekeyword("author", requires={"ctx"}) +@templatekeyword(b"author", requires={b"ctx"}) def showauthor(context, mapping): """Alias for ``{user}``""" return showuser(context, mapping) -@templatekeyword("bisect", requires={"repo", "ctx"}) +@templatekeyword(b"bisect", requires={b"repo", b"ctx"}) def showbisect(context, mapping): """String. The changeset bisection status.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") return hbisect.label(repo, ctx.node()) -@templatekeyword("branch", requires={"ctx"}) +@templatekeyword(b"branch", requires={b"ctx"}) def showbranch(context, mapping): """String. The name of the branch on which the changeset was committed. """ - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.branch() -@templatekeyword("branches", requires={"ctx"}) +@templatekeyword(b"branches", requires={b"ctx"}) def showbranches(context, mapping): """List of strings. The name of the branch on which the changeset was committed. Will be empty if the branch name was default. (DEPRECATED) """ - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") branch = ctx.branch() - if branch != "default": + if branch != b"default": return compatlist( - context, mapping, "branch", [branch], plural="branches" + context, mapping, b"branch", [branch], plural=b"branches" ) - return compatlist(context, mapping, "branch", [], plural="branches") + return compatlist(context, mapping, b"branch", [], plural=b"branches") -@templatekeyword("bookmarks", requires={"repo", "ctx"}) +@templatekeyword(b"bookmarks", requires={b"repo", b"ctx"}) def showbookmarks(context, mapping): """List of strings. Any bookmarks associated with the changeset. Also sets 'active', the name of the active bookmark. """ - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") bookmarks = ctx.bookmarks() active = repo._activebookmark - makemap = lambda v: {"bookmark": v, "active": active, "current": active} - f = _showcompatlist(context, mapping, "bookmark", bookmarks) + makemap = lambda v: {b"bookmark": v, b"active": active, b"current": active} + f = _showcompatlist(context, mapping, b"bookmark", bookmarks) return _hybrid(f, bookmarks, makemap, pycompat.identity) -@templatekeyword("children", requires={"ctx"}) +@templatekeyword(b"children", requires={b"ctx"}) def showchildren(context, mapping): """List of strings. The children of the changeset.""" - ctx = context.resource(mapping, "ctx") - childrevs = ["%d:%s" % (cctx.rev(), cctx) for cctx in ctx.children()] - return compatlist(context, mapping, "children", childrevs, element="child") + ctx = context.resource(mapping, b"ctx") + childrevs = [b"%d:%s" % (cctx.rev(), cctx) for cctx in ctx.children()] + return compatlist( + context, mapping, b"children", childrevs, element=b"child" + ) # Deprecated, but kept alive for help generation a purpose. -@templatekeyword("currentbookmark", requires={"repo", "ctx"}) +@templatekeyword(b"currentbookmark", requires={b"repo", b"ctx"}) def showcurrentbookmark(context, mapping): """String. The active bookmark, if it is associated with the changeset. (DEPRECATED)""" return showactivebookmark(context, mapping) -@templatekeyword("activebookmark", requires={"repo", "ctx"}) +@templatekeyword(b"activebookmark", requires={b"repo", b"ctx"}) def showactivebookmark(context, mapping): """String. The active bookmark, if it is associated with the changeset.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") active = repo._activebookmark if active and active in ctx.bookmarks(): return active - return "" + return b"" -@templatekeyword("date", requires={"ctx"}) +@templatekeyword(b"date", requires={b"ctx"}) def showdate(context, mapping): """Date information. The date when the changeset was committed.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") # the default string format is '' because # python-hglib splits date at decimal separator. - return templateutil.date(ctx.date(), showfmt="%d.0%d") + return templateutil.date(ctx.date(), showfmt=b"%d.0%d") -@templatekeyword("desc", requires={"ctx"}) +@templatekeyword(b"desc", requires={b"ctx"}) def showdescription(context, mapping): """String. The text of the changeset description.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") s = ctx.description() if isinstance(s, encoding.localstr): # try hard to preserve utf-8 bytes @@ -260,144 +262,146 @@ return s.strip() -@templatekeyword("diffstat", requires={"ui", "ctx"}) +@templatekeyword(b"diffstat", requires={b"ui", b"ctx"}) def showdiffstat(context, mapping): """String. Statistics of changes with the following format: "modified files: +added/-removed lines" """ - ui = context.resource(mapping, "ui") - ctx = context.resource(mapping, "ctx") - diffopts = diffutil.diffallopts(ui, {"noprefix": False}) + ui = context.resource(mapping, b"ui") + ctx = context.resource(mapping, b"ctx") + diffopts = diffutil.diffallopts(ui, {b"noprefix": False}) diff = ctx.diff(opts=diffopts) stats = patch.diffstatdata(util.iterlines(diff)) maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats) - return "%d: +%d/-%d" % (len(stats), adds, removes) + return b"%d: +%d/-%d" % (len(stats), adds, removes) -@templatekeyword("envvars", requires={"ui"}) +@templatekeyword(b"envvars", requires={b"ui"}) def showenvvars(context, mapping): """A dictionary of environment variables. (EXPERIMENTAL)""" - ui = context.resource(mapping, "ui") + ui = context.resource(mapping, b"ui") env = ui.exportableenviron() env = util.sortdict((k, env[k]) for k in sorted(env)) - return compatdict(context, mapping, "envvar", env, plural="envvars") + return compatdict(context, mapping, b"envvar", env, plural=b"envvars") -@templatekeyword("extras", requires={"ctx"}) +@templatekeyword(b"extras", requires={b"ctx"}) def showextras(context, mapping): """List of dicts with key, value entries of the 'extras' field of this changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") extras = ctx.extra() extras = util.sortdict((k, extras[k]) for k in sorted(extras)) - makemap = lambda k: {"key": k, "value": extras[k]} + makemap = lambda k: {b"key": k, b"value": extras[k]} c = [makemap(k) for k in extras] - f = _showcompatlist(context, mapping, "extra", c, plural="extras") + f = _showcompatlist(context, mapping, b"extra", c, plural=b"extras") return _hybrid( f, extras, makemap, - lambda k: "%s=%s" % (k, stringutil.escapestr(extras[k])), + lambda k: b"%s=%s" % (k, stringutil.escapestr(extras[k])), ) def _getfilestatus(context, mapping, listall=False): - ctx = context.resource(mapping, "ctx") - revcache = context.resource(mapping, "revcache") - if "filestatus" not in revcache or revcache["filestatusall"] < listall: + ctx = context.resource(mapping, b"ctx") + revcache = context.resource(mapping, b"revcache") + if b"filestatus" not in revcache or revcache[b"filestatusall"] < listall: stat = ctx.p1().status( ctx, listignored=listall, listclean=listall, listunknown=listall ) - revcache["filestatus"] = stat - revcache["filestatusall"] = listall - return revcache["filestatus"] + revcache[b"filestatus"] = stat + revcache[b"filestatusall"] = listall + return revcache[b"filestatus"] def _getfilestatusmap(context, mapping, listall=False): - revcache = context.resource(mapping, "revcache") - if "filestatusmap" not in revcache or revcache["filestatusall"] < listall: + revcache = context.resource(mapping, b"revcache") + if b"filestatusmap" not in revcache or revcache[b"filestatusall"] < listall: stat = _getfilestatus(context, mapping, listall=listall) - revcache["filestatusmap"] = statmap = {} - for char, files in zip(pycompat.iterbytestr("MAR!?IC"), stat): + revcache[b"filestatusmap"] = statmap = {} + for char, files in zip(pycompat.iterbytestr(b"MAR!?IC"), stat): statmap.update((f, char) for f in files) - return revcache["filestatusmap"] # {path: statchar} + return revcache[b"filestatusmap"] # {path: statchar} -@templatekeyword("file_copies", requires={"repo", "ctx", "cache", "revcache"}) +@templatekeyword( + b"file_copies", requires={b"repo", b"ctx", b"cache", b"revcache"} +) def showfilecopies(context, mapping): """List of strings. Files copied in this changeset with their sources. """ - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") - cache = context.resource(mapping, "cache") - copies = context.resource(mapping, "revcache").get("copies") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") + cache = context.resource(mapping, b"cache") + copies = context.resource(mapping, b"revcache").get(b"copies") if copies is None: - if "getcopies" not in cache: - cache["getcopies"] = scmutil.getcopiesfn(repo) - getcopies = cache["getcopies"] + if b"getcopies" not in cache: + cache[b"getcopies"] = scmutil.getcopiesfn(repo) + getcopies = cache[b"getcopies"] copies = getcopies(ctx) return templateutil.compatfilecopiesdict( - context, mapping, "file_copy", copies + context, mapping, b"file_copy", copies ) # showfilecopiesswitch() displays file copies only if copy records are # provided before calling the templater, usually with a --copies # command line switch. -@templatekeyword("file_copies_switch", requires={"revcache"}) +@templatekeyword(b"file_copies_switch", requires={b"revcache"}) def showfilecopiesswitch(context, mapping): """List of strings. Like "file_copies" but displayed only if the --copied switch is set. """ - copies = context.resource(mapping, "revcache").get("copies") or [] + copies = context.resource(mapping, b"revcache").get(b"copies") or [] return templateutil.compatfilecopiesdict( - context, mapping, "file_copy", copies + context, mapping, b"file_copy", copies ) -@templatekeyword("file_adds", requires={"ctx", "revcache"}) +@templatekeyword(b"file_adds", requires={b"ctx", b"revcache"}) def showfileadds(context, mapping): """List of strings. Files added by this changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return templateutil.compatfileslist( - context, mapping, "file_add", ctx.filesadded() + context, mapping, b"file_add", ctx.filesadded() ) -@templatekeyword("file_dels", requires={"ctx", "revcache"}) +@templatekeyword(b"file_dels", requires={b"ctx", b"revcache"}) def showfiledels(context, mapping): """List of strings. Files removed by this changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return templateutil.compatfileslist( - context, mapping, "file_del", ctx.filesremoved() + context, mapping, b"file_del", ctx.filesremoved() ) -@templatekeyword("file_mods", requires={"ctx", "revcache"}) +@templatekeyword(b"file_mods", requires={b"ctx", b"revcache"}) def showfilemods(context, mapping): """List of strings. Files modified by this changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return templateutil.compatfileslist( - context, mapping, "file_mod", ctx.filesmodified() + context, mapping, b"file_mod", ctx.filesmodified() ) -@templatekeyword("files", requires={"ctx"}) +@templatekeyword(b"files", requires={b"ctx"}) def showfiles(context, mapping): """List of strings. All files modified, added, or removed by this changeset. """ - ctx = context.resource(mapping, "ctx") - return templateutil.compatfileslist(context, mapping, "file", ctx.files()) + ctx = context.resource(mapping, b"ctx") + return templateutil.compatfileslist(context, mapping, b"file", ctx.files()) -@templatekeyword("graphnode", requires={"repo", "ctx"}) +@templatekeyword(b"graphnode", requires={b"repo", b"ctx"}) def showgraphnode(context, mapping): """String. The character representing the changeset node in an ASCII revision graph.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") return getgraphnode(repo, ctx) @@ -410,37 +414,37 @@ if wpnodes[1] == nullid: wpnodes = wpnodes[:1] if ctx.node() in wpnodes: - return "@" + return b"@" else: - return "" + return b"" def getgraphnodesymbol(ctx): if ctx.obsolete(): - return "x" + return b"x" elif ctx.isunstable(): - return "*" + return b"*" elif ctx.closesbranch(): - return "_" + return b"_" else: - return "o" + return b"o" -@templatekeyword("graphwidth", requires=()) +@templatekeyword(b"graphwidth", requires=()) def showgraphwidth(context, mapping): """Integer. The width of the graph drawn by 'log --graph' or zero.""" # just hosts documentation; should be overridden by template mapping return 0 -@templatekeyword("index", requires=()) +@templatekeyword(b"index", requires=()) def showindex(context, mapping): """Integer. The current iteration of the loop. (0 indexed)""" # just hosts documentation; should be overridden by template mapping - raise error.Abort(_("can't use index in this context")) + raise error.Abort(_(b"can't use index in this context")) -@templatekeyword("latesttag", requires={"repo", "ctx", "cache"}) +@templatekeyword(b"latesttag", requires={b"repo", b"ctx", b"cache"}) def showlatesttag(context, mapping): """List of strings. The global tags on the most recent globally tagged ancestor of this changeset. If no such tags exist, the list @@ -457,54 +461,54 @@ # branches in a stable manner- it is the date the tagged cset was created, # not the date the tag was created. Therefore it isn't made visible here. makemap = lambda v: { - "changes": _showchangessincetag, - "distance": latesttags[1], - "latesttag": v, # BC with {latesttag % '{latesttag}'} - "tag": v, + b"changes": _showchangessincetag, + b"distance": latesttags[1], + b"latesttag": v, # BC with {latesttag % '{latesttag}'} + b"tag": v, } tags = latesttags[2] - f = _showcompatlist(context, mapping, "latesttag", tags, separator=":") + f = _showcompatlist(context, mapping, b"latesttag", tags, separator=b":") return _hybrid(f, tags, makemap, pycompat.identity) -@templatekeyword("latesttagdistance", requires={"repo", "ctx", "cache"}) +@templatekeyword(b"latesttagdistance", requires={b"repo", b"ctx", b"cache"}) def showlatesttagdistance(context, mapping): """Integer. Longest path to the latest tag.""" return getlatesttags(context, mapping)[1] -@templatekeyword("changessincelatesttag", requires={"repo", "ctx", "cache"}) +@templatekeyword(b"changessincelatesttag", requires={b"repo", b"ctx", b"cache"}) def showchangessincelatesttag(context, mapping): """Integer. All ancestors not in the latest tag.""" tag = getlatesttags(context, mapping)[2][0] - mapping = context.overlaymap(mapping, {"tag": tag}) + mapping = context.overlaymap(mapping, {b"tag": tag}) return _showchangessincetag(context, mapping) def _showchangessincetag(context, mapping): - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") offset = 0 revs = [ctx.rev()] - tag = context.symbol(mapping, "tag") + tag = context.symbol(mapping, b"tag") # The only() revset doesn't currently support wdir() if ctx.rev() is None: offset = 1 revs = [p.rev() for p in ctx.parents()] - return len(repo.revs("only(%ld, %s)", revs, tag)) + offset + return len(repo.revs(b"only(%ld, %s)", revs, tag)) + offset # teach templater latesttags.changes is switched to (context, mapping) API -_showchangessincetag._requires = {"repo", "ctx"} +_showchangessincetag._requires = {b"repo", b"ctx"} -@templatekeyword("manifest", requires={"repo", "ctx"}) +@templatekeyword(b"manifest", requires={b"repo", b"ctx"}) def showmanifest(context, mapping): - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") mnode = ctx.manifestnode() if mnode is None: mnode = wdirid @@ -512,14 +516,14 @@ else: mrev = repo.manifestlog.rev(mnode) mhex = hex(mnode) - mapping = context.overlaymap(mapping, {"rev": mrev, "node": mhex}) - f = context.process("manifest", mapping) + mapping = context.overlaymap(mapping, {b"rev": mrev, b"node": mhex}) + f = context.process(b"manifest", mapping) return templateutil.hybriditem( - f, None, f, lambda x: {"rev": mrev, "node": mhex} + f, None, f, lambda x: {b"rev": mrev, b"node": mhex} ) -@templatekeyword("obsfate", requires={"ui", "repo", "ctx"}) +@templatekeyword(b"obsfate", requires={b"ui", b"repo", b"ctx"}) def showobsfate(context, mapping): # this function returns a list containing pre-formatted obsfate strings. # @@ -527,23 +531,23 @@ # the verbosity templatekw available. succsandmarkers = showsuccsandmarkers(context, mapping) - ui = context.resource(mapping, "ui") - repo = context.resource(mapping, "repo") + ui = context.resource(mapping, b"ui") + repo = context.resource(mapping, b"repo") values = [] for x in succsandmarkers.tovalue(context, mapping): v = obsutil.obsfateprinter( - ui, repo, x["successors"], x["markers"], scmutil.formatchangeid + ui, repo, x[b"successors"], x[b"markers"], scmutil.formatchangeid ) values.append(v) - return compatlist(context, mapping, "fate", values) + return compatlist(context, mapping, b"fate", values) def shownames(context, mapping, namespace): """helper method to generate a template keyword for a namespace""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") ns = repo.names[namespace] names = ns.names(repo, ctx.node()) return compatlist( @@ -551,127 +555,127 @@ ) -@templatekeyword("namespaces", requires={"repo", "ctx"}) +@templatekeyword(b"namespaces", requires={b"repo", b"ctx"}) def shownamespaces(context, mapping): """Dict of lists. Names attached to this changeset per namespace.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") namespaces = util.sortdict() def makensmapfn(ns): # 'name' for iterating over namespaces, templatename for local reference - return lambda v: {"name": v, ns.templatename: v} + return lambda v: {b"name": v, ns.templatename: v} for k, ns in repo.names.iteritems(): names = ns.names(repo, ctx.node()) - f = _showcompatlist(context, mapping, "name", names) + f = _showcompatlist(context, mapping, b"name", names) namespaces[k] = _hybrid(f, names, makensmapfn(ns), pycompat.identity) - f = _showcompatlist(context, mapping, "namespace", list(namespaces)) + f = _showcompatlist(context, mapping, b"namespace", list(namespaces)) def makemap(ns): return { - "namespace": ns, - "names": namespaces[ns], - "builtin": repo.names[ns].builtin, - "colorname": repo.names[ns].colorname, + b"namespace": ns, + b"names": namespaces[ns], + b"builtin": repo.names[ns].builtin, + b"colorname": repo.names[ns].colorname, } return _hybrid(f, namespaces, makemap, pycompat.identity) -@templatekeyword("negrev", requires={"repo", "ctx"}) +@templatekeyword(b"negrev", requires={b"repo", b"ctx"}) def shownegrev(context, mapping): """Integer. The repository-local changeset negative revision number, which counts in the opposite direction.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") rev = ctx.rev() if rev is None or rev < 0: # wdir() or nullrev? return None - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") return rev - len(repo) -@templatekeyword("node", requires={"ctx"}) +@templatekeyword(b"node", requires={b"ctx"}) def shownode(context, mapping): """String. The changeset identification hash, as a 40 hexadecimal digit string. """ - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.hex() -@templatekeyword("obsolete", requires={"ctx"}) +@templatekeyword(b"obsolete", requires={b"ctx"}) def showobsolete(context, mapping): """String. Whether the changeset is obsolete. (EXPERIMENTAL)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") if ctx.obsolete(): - return "obsolete" - return "" + return b"obsolete" + return b"" -@templatekeyword("path", requires={"fctx"}) +@templatekeyword(b"path", requires={b"fctx"}) def showpath(context, mapping): """String. Repository-absolute path of the current file. (EXPERIMENTAL)""" - fctx = context.resource(mapping, "fctx") + fctx = context.resource(mapping, b"fctx") return fctx.path() -@templatekeyword("peerurls", requires={"repo"}) +@templatekeyword(b"peerurls", requires={b"repo"}) def showpeerurls(context, mapping): """A dictionary of repository locations defined in the [paths] section of your configuration file.""" - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") # see commands.paths() for naming of dictionary keys paths = repo.ui.paths urls = util.sortdict((k, p.rawloc) for k, p in sorted(paths.iteritems())) def makemap(k): p = paths[k] - d = {"name": k, "url": p.rawloc} + d = {b"name": k, b"url": p.rawloc} d.update((o, v) for o, v in sorted(p.suboptions.iteritems())) return d - return _hybrid(None, urls, makemap, lambda k: "%s=%s" % (k, urls[k])) + return _hybrid(None, urls, makemap, lambda k: b"%s=%s" % (k, urls[k])) -@templatekeyword("predecessors", requires={"repo", "ctx"}) +@templatekeyword(b"predecessors", requires={b"repo", b"ctx"}) def showpredecessors(context, mapping): """Returns the list of the closest visible predecessors. (EXPERIMENTAL)""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") predecessors = sorted(obsutil.closestpredecessors(repo, ctx.node())) predecessors = pycompat.maplist(hex, predecessors) return _hybrid( None, predecessors, - lambda x: {"ctx": repo[x]}, + lambda x: {b"ctx": repo[x]}, lambda x: scmutil.formatchangeid(repo[x]), ) -@templatekeyword("reporoot", requires={"repo"}) +@templatekeyword(b"reporoot", requires={b"repo"}) def showreporoot(context, mapping): """String. The root directory of the current repository.""" - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") return repo.root -@templatekeyword("size", requires={"fctx"}) +@templatekeyword(b"size", requires={b"fctx"}) def showsize(context, mapping): """Integer. Size of the current file in bytes. (EXPERIMENTAL)""" - fctx = context.resource(mapping, "fctx") + fctx = context.resource(mapping, b"fctx") return fctx.size() # requires 'fctx' to denote {status} depends on (ctx, path) pair -@templatekeyword("status", requires={"ctx", "fctx", "revcache"}) +@templatekeyword(b"status", requires={b"ctx", b"fctx", b"revcache"}) def showstatus(context, mapping): """String. Status code of the current file. (EXPERIMENTAL)""" - path = templateutil.runsymbol(context, mapping, "path") + path = templateutil.runsymbol(context, mapping, b"path") path = templateutil.stringify(context, mapping, path) if not path: return @@ -681,15 +685,15 @@ return statmap.get(path) -@templatekeyword("successorssets", requires={"repo", "ctx"}) +@templatekeyword(b"successorssets", requires={b"repo", b"ctx"}) def showsuccessorssets(context, mapping): """Returns a string of sets of successors for a changectx. Format used is: [ctx1, ctx2], [ctx3] if ctx has been split into ctx1 and ctx2 while also diverged into ctx3. (EXPERIMENTAL)""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") if not ctx.obsolete(): - return "" + return b"" ssets = obsutil.successorssets(repo, ctx.node(), closest=True) ssets = [[hex(n) for n in ss] for ss in ssets] @@ -699,7 +703,7 @@ h = _hybrid( None, ss, - lambda x: {"ctx": repo[x]}, + lambda x: {b"ctx": repo[x]}, lambda x: scmutil.formatchangeid(repo[x]), ) data.append(h) @@ -709,22 +713,22 @@ return templateutil.stringify(context, mapping, d) def gen(data): - yield "; ".join(render(d) for d in data) + yield b"; ".join(render(d) for d in data) return _hybrid( - gen(data), data, lambda x: {"successorset": x}, pycompat.identity + gen(data), data, lambda x: {b"successorset": x}, pycompat.identity ) -@templatekeyword("succsandmarkers", requires={"repo", "ctx"}) +@templatekeyword(b"succsandmarkers", requires={b"repo", b"ctx"}) def showsuccsandmarkers(context, mapping): """Returns a list of dict for each final successor of ctx. The dict contains successors node id in "successors" keys and the list of obs-markers from ctx to the set of successors in "markers". (EXPERIMENTAL) """ - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") values = obsutil.successorsandmarkers(repo, ctx) @@ -735,19 +739,19 @@ data = [] for i in values: # Format successors - successors = i["successors"] + successors = i[b"successors"] successors = [hex(n) for n in successors] successors = _hybrid( None, successors, - lambda x: {"ctx": repo[x]}, + lambda x: {b"ctx": repo[x]}, lambda x: scmutil.formatchangeid(repo[x]), ) # Format markers finalmarkers = [] - for m in i["markers"]: + for m in i[b"markers"]: hexprec = hex(m[0]) hexsucs = tuple(hex(n) for n in m[1]) hexparents = None @@ -756,130 +760,130 @@ newmarker = (hexprec, hexsucs) + m[2:5] + (hexparents,) + m[6:] finalmarkers.append(newmarker) - data.append({"successors": successors, "markers": finalmarkers}) + data.append({b"successors": successors, b"markers": finalmarkers}) return templateutil.mappinglist(data) -@templatekeyword("p1", requires={"ctx"}) +@templatekeyword(b"p1", requires={b"ctx"}) def showp1(context, mapping): """Changeset. The changeset's first parent. ``{p1.rev}`` for the revision number, and ``{p1.node}`` for the identification hash.""" - ctx = context.resource(mapping, "ctx") - return templateutil.mappingdict({"ctx": ctx.p1()}, tmpl=_changeidtmpl) + ctx = context.resource(mapping, b"ctx") + return templateutil.mappingdict({b"ctx": ctx.p1()}, tmpl=_changeidtmpl) -@templatekeyword("p2", requires={"ctx"}) +@templatekeyword(b"p2", requires={b"ctx"}) def showp2(context, mapping): """Changeset. The changeset's second parent. ``{p2.rev}`` for the revision number, and ``{p2.node}`` for the identification hash.""" - ctx = context.resource(mapping, "ctx") - return templateutil.mappingdict({"ctx": ctx.p2()}, tmpl=_changeidtmpl) + ctx = context.resource(mapping, b"ctx") + return templateutil.mappingdict({b"ctx": ctx.p2()}, tmpl=_changeidtmpl) -@templatekeyword("p1rev", requires={"ctx"}) +@templatekeyword(b"p1rev", requires={b"ctx"}) def showp1rev(context, mapping): """Integer. The repository-local revision number of the changeset's first parent, or -1 if the changeset has no parents. (DEPRECATED)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.p1().rev() -@templatekeyword("p2rev", requires={"ctx"}) +@templatekeyword(b"p2rev", requires={b"ctx"}) def showp2rev(context, mapping): """Integer. The repository-local revision number of the changeset's second parent, or -1 if the changeset has no second parent. (DEPRECATED)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.p2().rev() -@templatekeyword("p1node", requires={"ctx"}) +@templatekeyword(b"p1node", requires={b"ctx"}) def showp1node(context, mapping): """String. The identification hash of the changeset's first parent, as a 40 digit hexadecimal string. If the changeset has no parents, all digits are 0. (DEPRECATED)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.p1().hex() -@templatekeyword("p2node", requires={"ctx"}) +@templatekeyword(b"p2node", requires={b"ctx"}) def showp2node(context, mapping): """String. The identification hash of the changeset's second parent, as a 40 digit hexadecimal string. If the changeset has no second parent, all digits are 0. (DEPRECATED)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.p2().hex() -@templatekeyword("parents", requires={"repo", "ctx"}) +@templatekeyword(b"parents", requires={b"repo", b"ctx"}) def showparents(context, mapping): """List of strings. The parents of the changeset in "rev:node" format. If the changeset has only one "natural" parent (the predecessor revision) nothing is shown.""" - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") pctxs = scmutil.meaningfulparents(repo, ctx) prevs = [p.rev() for p in pctxs] parents = [ - [("rev", p.rev()), ("node", p.hex()), ("phase", p.phasestr())] + [(b"rev", p.rev()), (b"node", p.hex()), (b"phase", p.phasestr())] for p in pctxs ] - f = _showcompatlist(context, mapping, "parent", parents) + f = _showcompatlist(context, mapping, b"parent", parents) return _hybrid( f, prevs, - lambda x: {"ctx": repo[x]}, + lambda x: {b"ctx": repo[x]}, lambda x: scmutil.formatchangeid(repo[x]), keytype=int, ) -@templatekeyword("phase", requires={"ctx"}) +@templatekeyword(b"phase", requires={b"ctx"}) def showphase(context, mapping): """String. The changeset phase name.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.phasestr() -@templatekeyword("phaseidx", requires={"ctx"}) +@templatekeyword(b"phaseidx", requires={b"ctx"}) def showphaseidx(context, mapping): """Integer. The changeset phase index. (ADVANCED)""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.phase() -@templatekeyword("rev", requires={"ctx"}) +@templatekeyword(b"rev", requires={b"ctx"}) def showrev(context, mapping): """Integer. The repository-local changeset revision number.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return scmutil.intrev(ctx) def showrevslist(context, mapping, name, revs): """helper to generate a list of revisions in which a mapped template will be evaluated""" - repo = context.resource(mapping, "repo") + repo = context.resource(mapping, b"repo") # revs may be a smartset; don't compute it until f() has to be evaluated def f(): - srevs = ["%d" % r for r in revs] + srevs = [b"%d" % r for r in revs] return _showcompatlist(context, mapping, name, srevs) return _hybrid( f, revs, - lambda x: {name: x, "ctx": repo[x]}, + lambda x: {name: x, b"ctx": repo[x]}, pycompat.identity, keytype=int, ) -@templatekeyword("subrepos", requires={"ctx"}) +@templatekeyword(b"subrepos", requires={b"ctx"}) def showsubrepos(context, mapping): """List of strings. Updated subrepositories in the changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") substate = ctx.substate if not substate: - return compatlist(context, mapping, "subrepo", []) + return compatlist(context, mapping, b"subrepo", []) psubstate = ctx.p1().substate or {} subrepos = [] for sub in substate: @@ -888,91 +892,91 @@ for sub in psubstate: if sub not in substate: subrepos.append(sub) # removed in ctx - return compatlist(context, mapping, "subrepo", sorted(subrepos)) + return compatlist(context, mapping, b"subrepo", sorted(subrepos)) # don't remove "showtags" definition, even though namespaces will put # a helper function for "tags" keyword into "keywords" map automatically, # because online help text is built without namespaces initialization -@templatekeyword("tags", requires={"repo", "ctx"}) +@templatekeyword(b"tags", requires={b"repo", b"ctx"}) def showtags(context, mapping): """List of strings. Any tags associated with the changeset.""" - return shownames(context, mapping, "tags") + return shownames(context, mapping, b"tags") -@templatekeyword("termwidth", requires={"ui"}) +@templatekeyword(b"termwidth", requires={b"ui"}) def showtermwidth(context, mapping): """Integer. The width of the current terminal.""" - ui = context.resource(mapping, "ui") + ui = context.resource(mapping, b"ui") return ui.termwidth() -@templatekeyword("user", requires={"ctx"}) +@templatekeyword(b"user", requires={b"ctx"}) def showuser(context, mapping): """String. The unmodified author of the changeset.""" - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return ctx.user() -@templatekeyword("instabilities", requires={"ctx"}) +@templatekeyword(b"instabilities", requires={b"ctx"}) def showinstabilities(context, mapping): """List of strings. Evolution instabilities affecting the changeset. (EXPERIMENTAL) """ - ctx = context.resource(mapping, "ctx") + ctx = context.resource(mapping, b"ctx") return compatlist( context, mapping, - "instability", + b"instability", ctx.instabilities(), - plural="instabilities", + plural=b"instabilities", ) -@templatekeyword("verbosity", requires={"ui"}) +@templatekeyword(b"verbosity", requires={b"ui"}) def showverbosity(context, mapping): """String. The current output verbosity in 'debug', 'quiet', 'verbose', or ''.""" - ui = context.resource(mapping, "ui") + ui = context.resource(mapping, b"ui") # see logcmdutil.changesettemplater for priority of these flags if ui.debugflag: - return "debug" + return b"debug" elif ui.quiet: - return "quiet" + return b"quiet" elif ui.verbose: - return "verbose" - return "" + return b"verbose" + return b"" -@templatekeyword("whyunstable", requires={"repo", "ctx"}) +@templatekeyword(b"whyunstable", requires={b"repo", b"ctx"}) def showwhyunstable(context, mapping): """List of dicts explaining all instabilities of a changeset. (EXPERIMENTAL) """ - repo = context.resource(mapping, "repo") - ctx = context.resource(mapping, "ctx") + repo = context.resource(mapping, b"repo") + ctx = context.resource(mapping, b"ctx") def formatnode(ctx): - return "%s (%s)" % (scmutil.formatchangeid(ctx), ctx.phasestr()) + return b"%s (%s)" % (scmutil.formatchangeid(ctx), ctx.phasestr()) entries = obsutil.whyunstable(repo, ctx) for entry in entries: - if entry.get("divergentnodes"): - dnodes = entry["divergentnodes"] + if entry.get(b"divergentnodes"): + dnodes = entry[b"divergentnodes"] dnhybrid = _hybrid( None, [dnode.hex() for dnode in dnodes], - lambda x: {"ctx": repo[x]}, + lambda x: {b"ctx": repo[x]}, lambda x: formatnode(repo[x]), ) - entry["divergentnodes"] = dnhybrid + entry[b"divergentnodes"] = dnhybrid tmpl = ( - '{instability}:{if(divergentnodes, " ")}{divergentnodes} ' - "{reason} {node|short}" + b'{instability}:{if(divergentnodes, " ")}{divergentnodes} ' + b"{reason} {node|short}" ) - return templateutil.mappinglist(entries, tmpl=tmpl, sep="\n") + return templateutil.mappinglist(entries, tmpl=tmpl, sep=b"\n") def loadkeyword(ui, extname, registrarobj): diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -85,22 +85,22 @@ elements = { # token-type: binding-strength, primary, prefix, infix, suffix - "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), - ".": (18, None, None, (".", 18), None), - "%": (15, None, None, ("%", 15), None), - "|": (15, None, None, ("|", 15), None), - "*": (5, None, None, ("*", 5), None), - "/": (5, None, None, ("/", 5), None), - "+": (4, None, None, ("+", 4), None), - "-": (4, None, ("negate", 19), ("-", 4), None), - "=": (3, None, None, ("keyvalue", 3), None), - ",": (2, None, None, ("list", 2), None), - ")": (0, None, None, None, None), - "integer": (0, "integer", None, None, None), - "symbol": (0, "symbol", None, None, None), - "string": (0, "string", None, None, None), - "template": (0, "template", None, None, None), - "end": (0, None, None, None, None), + b"(": (20, None, (b"group", 1, b")"), (b"func", 1, b")"), None), + b".": (18, None, None, (b".", 18), None), + b"%": (15, None, None, (b"%", 15), None), + b"|": (15, None, None, (b"|", 15), None), + b"*": (5, None, None, (b"*", 5), None), + b"/": (5, None, None, (b"/", 5), None), + b"+": (4, None, None, (b"+", 4), None), + b"-": (4, None, (b"negate", 19), (b"-", 4), None), + b"=": (3, None, None, (b"keyvalue", 3), None), + b",": (2, None, None, (b"list", 2), None), + b")": (0, None, None, None, None), + b"integer": (0, b"integer", None, None, None), + b"symbol": (0, b"symbol", None, None, None), + b"string": (0, b"string", None, None, None), + b"template": (0, b"template", None, None, None), + b"end": (0, None, None, None, None), } @@ -113,28 +113,28 @@ c = program[pos] if c.isspace(): # skip inter-token whitespace pass - elif c in "(=,).%|+-*/": # handle simple operators + elif c in b"(=,).%|+-*/": # handle simple operators yield (c, None, pos) - elif c in "\"'": # handle quoted templates + elif c in b"\"'": # handle quoted templates s = pos + 1 data, pos = _parsetemplate(program, s, end, c) - yield ("template", data, s) + yield (b"template", data, s) pos -= 1 - elif c == "r" and program[pos : pos + 2] in ("r'", 'r"'): + elif c == b"r" and program[pos : pos + 2] in (b"r'", b'r"'): # handle quoted strings c = program[pos + 1] s = pos = pos + 2 while pos < end: # find closing quote d = program[pos] - if d == "\\": # skip over escaped characters + if d == b"\\": # skip over escaped characters pos += 2 continue if d == c: - yield ("string", program[s:pos], s) + yield (b"string", program[s:pos], s) break pos += 1 else: - raise error.ParseError(_("unterminated string"), s) + raise error.ParseError(_(b"unterminated string"), s) elif c.isdigit(): s = pos while pos < end: @@ -142,12 +142,12 @@ if not d.isdigit(): break pos += 1 - yield ("integer", program[s:pos], s) + yield (b"integer", program[s:pos], s) pos -= 1 elif ( - c == "\\" + c == b"\\" and program[pos : pos + 2] in (br"\'", br"\"") - or c == "r" + or c == b"r" and program[pos : pos + 3] in (br"r\'", br"r\"") ): # handle escaped quoted strings for compatibility with 2.9.2-3.4, @@ -160,51 +160,51 @@ # {f("\\\\ {g(\"\\\"\")}"} \\ {g("\"")} [r'\\', {g("\"")}] # ~~~~~~~~ # escaped quoted string - if c == "r": + if c == b"r": pos += 1 - token = "string" + token = b"string" else: - token = "template" + token = b"template" quote = program[pos : pos + 2] s = pos = pos + 2 while pos < end: # find closing escaped quote - if program.startswith("\\\\\\", pos, end): + if program.startswith(b"\\\\\\", pos, end): pos += 4 # skip over double escaped characters continue if program.startswith(quote, pos, end): # interpret as if it were a part of an outer string data = parser.unescapestr(program[s:pos]) - if token == "template": + if token == b"template": data = _parsetemplate(data, 0, len(data))[0] yield (token, data, s) pos += 1 break pos += 1 else: - raise error.ParseError(_("unterminated string"), s) - elif c.isalnum() or c in "_": + raise error.ParseError(_(b"unterminated string"), s) + elif c.isalnum() or c in b"_": s = pos pos += 1 while pos < end: # find end of symbol d = program[pos] - if not (d.isalnum() or d == "_"): + if not (d.isalnum() or d == b"_"): break pos += 1 sym = program[s:pos] - yield ("symbol", sym, s) + yield (b"symbol", sym, s) pos -= 1 elif c == term: - yield ("end", None, pos) + yield (b"end", None, pos) return else: - raise error.ParseError(_("syntax error"), pos) + raise error.ParseError(_(b"syntax error"), pos) pos += 1 if term: - raise error.ParseError(_("unterminated template expansion"), start) - yield ("end", None, pos) + raise error.ParseError(_(b"unterminated template expansion"), start) + yield (b"end", None, pos) -def _parsetemplate(tmpl, start, stop, quote=""): +def _parsetemplate(tmpl, start, stop, quote=b""): r""" >>> _parsetemplate(b'foo{bar}"baz', 0, 12) ([('string', 'foo'), ('symbol', 'bar'), ('string', '"baz')], 12) @@ -219,15 +219,15 @@ """ parsed = [] for typ, val, pos in _scantemplate(tmpl, start, stop, quote): - if typ == "string": + if typ == b"string": parsed.append((typ, val)) - elif typ == "template": + elif typ == b"template": parsed.append(val) - elif typ == "end": + elif typ == b"end": return parsed, pos else: - raise error.ProgrammingError("unexpected type: %s" % typ) - raise error.ProgrammingError("unterminated scanning of template") + raise error.ProgrammingError(b"unexpected type: %s" % typ) + raise error.ProgrammingError(b"unterminated scanning of template") def scantemplate(tmpl, raw=False): @@ -252,16 +252,16 @@ for typ, val, pos in _scantemplate(tmpl, 0, len(tmpl), raw=raw): if last: yield last + (pos,) - if typ == "end": + if typ == b"end": return else: last = (typ, pos) - raise error.ProgrammingError("unterminated scanning of template") + raise error.ProgrammingError(b"unterminated scanning of template") -def _scantemplate(tmpl, start, stop, quote="", raw=False): +def _scantemplate(tmpl, start, stop, quote=b"", raw=False): """Parse template string into chunks of strings and template expressions""" - sepchars = "{" + quote + sepchars = b"{" + quote unescape = [parser.unescapestr, pycompat.identity][raw] pos = start p = parser.parser(elements) @@ -272,49 +272,49 @@ key=lambda n: (n < 0, n), ) if n < 0: - yield ("string", unescape(tmpl[pos:stop]), pos) + yield (b"string", unescape(tmpl[pos:stop]), pos) pos = stop break c = tmpl[n : n + 1] bs = 0 # count leading backslashes if not raw: - bs = (n - pos) - len(tmpl[pos:n].rstrip("\\")) + bs = (n - pos) - len(tmpl[pos:n].rstrip(b"\\")) if bs % 2 == 1: # escaped (e.g. '\{', '\\\{', but not '\\{') - yield ("string", unescape(tmpl[pos : n - 1]) + c, pos) + yield (b"string", unescape(tmpl[pos : n - 1]) + c, pos) pos = n + 1 continue if n > pos: - yield ("string", unescape(tmpl[pos:n]), pos) + yield (b"string", unescape(tmpl[pos:n]), pos) if c == quote: - yield ("end", None, n + 1) + yield (b"end", None, n + 1) return - parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, "}")) - if not tmpl.startswith("}", pos): - raise error.ParseError(_("invalid token"), pos) - yield ("template", parseres, n) + parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, b"}")) + if not tmpl.startswith(b"}", pos): + raise error.ParseError(_(b"invalid token"), pos) + yield (b"template", parseres, n) pos += 1 if quote: - raise error.ParseError(_("unterminated string"), start) + raise error.ParseError(_(b"unterminated string"), start) except error.ParseError as inst: if len(inst.args) > 1: # has location loc = inst.args[1] # Offset the caret location by the number of newlines before the # location of the error, since we will replace one-char newlines # with the two-char literal r'\n'. - offset = tmpl[:loc].count("\n") - tmpl = tmpl.replace("\n", br"\n") + offset = tmpl[:loc].count(b"\n") + tmpl = tmpl.replace(b"\n", br"\n") # We want the caret to point to the place in the template that # failed to parse, but in a hint we get a open paren at the # start. Therefore, we print "loc + 1" spaces (instead of "loc") # to line up the caret with the location of the error. inst.hint = ( - tmpl + "\n" + " " * (loc + 1 + offset) + "^ " + _("here") + tmpl + b"\n" + b" " * (loc + 1 + offset) + b"^ " + _(b"here") ) raise - yield ("end", None, pos) + yield (b"end", None, pos) def _unnesttemplatelist(tree): @@ -339,14 +339,14 @@ if not isinstance(tree, tuple): return tree op = tree[0] - if op != "template": + if op != b"template": return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:]) assert len(tree) == 2 xs = tuple(_unnesttemplatelist(x) for x in tree[1]) if not xs: - return ("string", "") # empty template "" - elif len(xs) == 1 and xs[0][0] == "string": + return (b"string", b"") # empty template "" + elif len(xs) == 1 and xs[0][0] == b"string": return xs[0] # fast path for string with no template fragment "x" else: return (op,) + xs @@ -355,8 +355,8 @@ def parse(tmpl): """Parse template string into tree""" parsed, pos = _parsetemplate(tmpl, 0, len(tmpl)) - assert pos == len(tmpl), "unquoted template should be consumed" - return _unnesttemplatelist(("template", parsed)) + assert pos == len(tmpl), b"unquoted template should be consumed" + return _unnesttemplatelist((b"template", parsed)) def _parseexpr(expr): @@ -378,18 +378,18 @@ p = parser.parser(elements) tree, pos = p.parse(tokenize(expr, 0, len(expr))) if pos != len(expr): - raise error.ParseError(_("invalid token"), pos) + raise error.ParseError(_(b"invalid token"), pos) return _unnesttemplatelist(tree) def prettyformat(tree): - return parser.prettyformat(tree, ("integer", "string", "symbol")) + return parser.prettyformat(tree, (b"integer", b"string", b"symbol")) def compileexp(exp, context, curmethods): """Compile parsed template tree to (func, data) pair""" if not exp: - raise error.ParseError(_("missing argument")) + raise error.ParseError(_(b"missing argument")) t = exp[0] return curmethods[t](exp, context) @@ -398,15 +398,15 @@ def getsymbol(exp): - if exp[0] == "symbol": + if exp[0] == b"symbol": return exp[1] - raise error.ParseError(_("expected a symbol, got '%s'") % exp[0]) + raise error.ParseError(_(b"expected a symbol, got '%s'") % exp[0]) def getlist(x): if not x: return [] - if x[0] == "list": + if x[0] == b"list": return getlist(x[1]) + [x[2]] return [x] @@ -414,18 +414,18 @@ def gettemplate(exp, context): """Compile given template tree or load named template from map file; returns (func, data) pair""" - if exp[0] in ("template", "string"): + if exp[0] in (b"template", b"string"): return compileexp(exp, context, methods) - if exp[0] == "symbol": + if exp[0] == b"symbol": # unlike runsymbol(), here 'symbol' is always taken as template name # even if it exists in mapping. this allows us to override mapping # by web templates, e.g. 'changelogtag' is redefined in map file. return context._load(exp[1]) - raise error.ParseError(_("expected template specifier")) + raise error.ParseError(_(b"expected template specifier")) def _runrecursivesymbol(context, mapping, key): - raise error.Abort(_("recursive reference '%s' in template") % key) + raise error.Abort(_(b"recursive reference '%s' in template") % key) def buildtemplate(exp, context): @@ -443,7 +443,7 @@ f = context._funcs[n] args = _buildfuncargs(exp[1], context, methods, n, f._argspec) return (f, args) - raise error.ParseError(_("unknown function '%s'") % n) + raise error.ParseError(_(b"unknown function '%s'") % n) def buildmap(exp, context): @@ -478,10 +478,10 @@ if n in context._filters: args = _buildfuncargs(exp[2], context, exprmethods, n, argspec=None) if len(args) != 1: - raise error.ParseError(_("filter %s expects one argument") % n) + raise error.ParseError(_(b"filter %s expects one argument") % n) f = context._filters[n] return (templateutil.runfilter, (args[0], f)) - raise error.ParseError(_("unknown function '%s'") % n) + raise error.ParseError(_(b"unknown function '%s'") % n) def _buildfuncargs(exp, context, curmethods, funcname, argspec): @@ -518,8 +518,8 @@ getlist(exp), funcname, argspec, - keyvaluenode="keyvalue", - keynode="symbol", + keyvaluenode=b"keyvalue", + keynode=b"symbol", ) compargs = util.sortdict() if varkey: @@ -531,54 +531,54 @@ def buildkeyvaluepair(exp, content): - raise error.ParseError(_("can't use a key-value pair in this context")) + raise error.ParseError(_(b"can't use a key-value pair in this context")) def buildlist(exp, context): raise error.ParseError( - _("can't use a list in this context"), - hint=_("check place of comma and parens"), + _(b"can't use a list in this context"), + hint=_(b"check place of comma and parens"), ) # methods to interpret function arguments or inner expressions (e.g. {_(x)}) exprmethods = { - "integer": lambda e, c: (templateutil.runinteger, e[1]), - "string": lambda e, c: (templateutil.runstring, e[1]), - "symbol": lambda e, c: (templateutil.runsymbol, e[1]), - "template": buildtemplate, - "group": lambda e, c: compileexp(e[1], c, exprmethods), - ".": buildmember, - "|": buildfilter, - "%": buildmap, - "func": buildfunc, - "keyvalue": buildkeyvaluepair, - "list": buildlist, - "+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b), - "-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b), - "negate": buildnegate, - "*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b), - "/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b), + b"integer": lambda e, c: (templateutil.runinteger, e[1]), + b"string": lambda e, c: (templateutil.runstring, e[1]), + b"symbol": lambda e, c: (templateutil.runsymbol, e[1]), + b"template": buildtemplate, + b"group": lambda e, c: compileexp(e[1], c, exprmethods), + b".": buildmember, + b"|": buildfilter, + b"%": buildmap, + b"func": buildfunc, + b"keyvalue": buildkeyvaluepair, + b"list": buildlist, + b"+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b), + b"-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b), + b"negate": buildnegate, + b"*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b), + b"/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b), } # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"}) methods = exprmethods.copy() -methods["integer"] = exprmethods["symbol"] # '{1}' as variable +methods[b"integer"] = exprmethods[b"symbol"] # '{1}' as variable class _aliasrules(parser.basealiasrules): """Parsing and expansion rule set of template aliases""" - _section = _("template alias") + _section = _(b"template alias") _parse = staticmethod(_parseexpr) @staticmethod def _trygetfunc(tree): """Return (name, args) if tree is func(...) or ...|filter; otherwise None""" - if tree[0] == "func" and tree[1][0] == "symbol": + if tree[0] == b"func" and tree[1][0] == b"symbol": return tree[1][1], getlist(tree[2]) - if tree[0] == "|" and tree[2][0] == "symbol": + if tree[0] == b"|" and tree[2][0] == b"symbol": return tree[2][1], [tree[1]] @@ -593,7 +593,7 @@ def unquotestring(s): """unwrap quotes if any; otherwise returns unmodified string""" - if len(s) < 2 or s[0] not in "'\"" or s[0] != s[-1]: + if len(s) < 2 or s[0] not in b"'\"" or s[0] != s[-1]: return s return s[1:-1] @@ -721,7 +721,7 @@ v = self._resources.lookup(mapping, key) if v is None: raise templateutil.ResourceUnavailable( - _("template resource not available: %s") % key + _(b"template resource not available: %s") % key ) return v @@ -783,36 +783,36 @@ def stylelist(): paths = templatepaths() if not paths: - return _("no templates found, try `hg debuginstall` for more info") + return _(b"no templates found, try `hg debuginstall` for more info") dirlist = os.listdir(paths[0]) stylelist = [] for file in dirlist: - split = file.split(".") - if split[-1] in ("orig", "rej"): + split = file.split(b".") + if split[-1] in (b"orig", b"rej"): continue - if split[0] == "map-cmdline": + if split[0] == b"map-cmdline": stylelist.append(split[1]) - return ", ".join(sorted(stylelist)) + return b", ".join(sorted(stylelist)) def _readmapfile(mapfile): """Load template elements from the given map file""" if not os.path.exists(mapfile): raise error.Abort( - _("style '%s' not found") % mapfile, - hint=_("available styles: %s") % stylelist(), + _(b"style '%s' not found") % mapfile, + hint=_(b"available styles: %s") % stylelist(), ) base = os.path.dirname(mapfile) conf = config.config(includepaths=templatepaths()) - conf.read(mapfile, remap={"": "templates"}) + conf.read(mapfile, remap={b"": b"templates"}) cache = {} tmap = {} aliases = [] - val = conf.get("templates", "__base__") - if val and val[0] not in "'\"": + val = conf.get(b"templates", b"__base__") + if val and val[0] not in b"'\"": # treat as a pointer to a base class for this style path = util.normpath(os.path.join(base, val)) @@ -823,27 +823,27 @@ if os.path.isfile(p2): path = p2 break - p3 = util.normpath(os.path.join(p2, "map")) + p3 = util.normpath(os.path.join(p2, b"map")) if os.path.isfile(p3): path = p3 break cache, tmap, aliases = _readmapfile(path) - for key, val in conf["templates"].items(): + for key, val in conf[b"templates"].items(): if not val: raise error.ParseError( - _("missing value"), conf.source("templates", key) + _(b"missing value"), conf.source(b"templates", key) ) - if val[0] in "'\"": + if val[0] in b"'\"": if val[0] != val[-1]: raise error.ParseError( - _("unmatched quotes"), conf.source("templates", key) + _(b"unmatched quotes"), conf.source(b"templates", key) ) cache[key] = unquotestring(val) - elif key != "__base__": + elif key != b"__base__": tmap[key] = os.path.join(base, val) - aliases.extend(conf["templatealias"].items()) + aliases.extend(conf[b"templatealias"].items()) return cache, tmap, aliases @@ -867,10 +867,10 @@ self.cache[t] = util.readfile(self._map[t]) except KeyError as inst: raise templateutil.TemplateNotFound( - _('"%s" not in template map') % inst.args[0] + _(b'"%s" not in template map') % inst.args[0] ) except IOError as inst: - reason = _("template file %s: %s") % ( + reason = _(b"template file %s: %s") % ( self._map[t], stringutil.forcebytestr(inst.args[1]), ) @@ -887,7 +887,7 @@ if not tree: return op = tree[0] - if op == "symbol": + if op == b"symbol": s = tree[1] if s in syms[0]: return # avoid recursion: s -> cache[s] -> s @@ -896,14 +896,14 @@ # s may be a reference for named template self._findsymbolsused(self.load(s), syms) return - if op in {"integer", "string"}: + if op in {b"integer", b"string"}: return # '{arg|func}' == '{func(arg)}' - if op == "|": + if op == b"|": syms[1].add(getsymbol(tree[2])) self._findsymbolsused(tree[1], syms) return - if op == "func": + if op == b"func": syms[1].add(getsymbol(tree[1])) self._findsymbolsused(tree[2], syms) return @@ -997,7 +997,7 @@ This may load additional templates from the map file. """ - return self.symbolsused("") + return self.symbolsused(b"") def symbolsused(self, t): """Look up (keywords, filters/functions) referenced from the name @@ -1009,7 +1009,7 @@ def renderdefault(self, mapping): """Render the default unnamed template and return result as string""" - return self.render("", mapping) + return self.render(b"", mapping) def render(self, t, mapping): """Render the specified named template and return result as string""" @@ -1028,7 +1028,7 @@ def templatepaths(): """return locations used for template files.""" - pathsrel = ["templates"] + pathsrel = [b"templates"] paths = [os.path.normpath(os.path.join(util.datapath, f)) for f in pathsrel] return [p for p in paths if os.path.isdir(p)] @@ -1069,8 +1069,8 @@ and pycompat.osaltsep in style ): continue - locations = [os.path.join(style, "map"), "map-" + style] - locations.append("map") + locations = [os.path.join(style, b"map"), b"map-" + style] + locations.append(b"map") for path in paths: for location in locations: @@ -1078,4 +1078,4 @@ if os.path.isfile(mapfile): return style, mapfile - raise RuntimeError("No hgweb templates found in %r" % paths) + raise RuntimeError(b"No hgweb templates found in %r" % paths) diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py --- a/mercurial/templateutil.py +++ b/mercurial/templateutil.py @@ -130,7 +130,7 @@ def getmember(self, context, mapping, key): raise error.ParseError( - _("%r is not a dictionary") % pycompat.bytestr(self._value) + _(b"%r is not a dictionary") % pycompat.bytestr(self._value) ) def getmin(self, context, mapping): @@ -141,17 +141,17 @@ def _getby(self, context, mapping, func): if not self._value: - raise error.ParseError(_("empty string")) + raise error.ParseError(_(b"empty string")) return func(pycompat.iterbytestr(self._value)) def filter(self, context, mapping, select): raise error.ParseError( - _("%r is not filterable") % pycompat.bytestr(self._value) + _(b"%r is not filterable") % pycompat.bytestr(self._value) ) def itermaps(self, context): raise error.ParseError( - _("%r is not iterable of mappings") % pycompat.bytestr(self._value) + _(b"%r is not iterable of mappings") % pycompat.bytestr(self._value) ) def join(self, context, mapping, sep): @@ -174,27 +174,27 @@ self._value = value def contains(self, context, mapping, item): - raise error.ParseError(_("%r is not iterable") % self._value) + raise error.ParseError(_(b"%r is not iterable") % self._value) def getmember(self, context, mapping, key): - raise error.ParseError(_("%r is not a dictionary") % self._value) + raise error.ParseError(_(b"%r is not a dictionary") % self._value) def getmin(self, context, mapping): - raise error.ParseError(_("%r is not iterable") % self._value) + raise error.ParseError(_(b"%r is not iterable") % self._value) def getmax(self, context, mapping): - raise error.ParseError(_("%r is not iterable") % self._value) + raise error.ParseError(_(b"%r is not iterable") % self._value) def filter(self, context, mapping, select): - raise error.ParseError(_("%r is not iterable") % self._value) + raise error.ParseError(_(b"%r is not iterable") % self._value) def itermaps(self, context): raise error.ParseError( - _("%r is not iterable of mappings") % self._value + _(b"%r is not iterable of mappings") % self._value ) def join(self, context, mapping, sep): - raise error.ParseError(_("%r is not iterable") % self._value) + raise error.ParseError(_(b"%r is not iterable") % self._value) def show(self, context, mapping): if self._value is None: @@ -216,35 +216,35 @@ class date(mappable, wrapped): """Wrapper for date tuple""" - def __init__(self, value, showfmt="%d %d"): + def __init__(self, value, showfmt=b"%d %d"): # value may be (float, int), but public interface shouldn't support # floating-point timestamp self._unixtime, self._tzoffset = map(int, value) self._showfmt = showfmt def contains(self, context, mapping, item): - raise error.ParseError(_("date is not iterable")) + raise error.ParseError(_(b"date is not iterable")) def getmember(self, context, mapping, key): - raise error.ParseError(_("date is not a dictionary")) + raise error.ParseError(_(b"date is not a dictionary")) def getmin(self, context, mapping): - raise error.ParseError(_("date is not iterable")) + raise error.ParseError(_(b"date is not iterable")) def getmax(self, context, mapping): - raise error.ParseError(_("date is not iterable")) + raise error.ParseError(_(b"date is not iterable")) def filter(self, context, mapping, select): - raise error.ParseError(_("date is not iterable")) + raise error.ParseError(_(b"date is not iterable")) def join(self, context, mapping, sep): - raise error.ParseError(_("date is not iterable")) + raise error.ParseError(_(b"date is not iterable")) def show(self, context, mapping): return self._showfmt % (self._unixtime, self._tzoffset) def tomap(self, context): - return {"unixtime": self._unixtime, "tzoffset": self._tzoffset} + return {b"unixtime": self._unixtime, b"tzoffset": self._tzoffset} def tobool(self, context, mapping): return True @@ -278,8 +278,8 @@ def getmember(self, context, mapping, key): # TODO: maybe split hybrid list/dict types? - if not util.safehasattr(self._values, "get"): - raise error.ParseError(_("not a dictionary")) + if not util.safehasattr(self._values, b"get"): + raise error.ParseError(_(b"not a dictionary")) key = unwrapastype(context, mapping, key, self._keytype) return self._wrapvalue(key, self._values.get(key)) @@ -291,20 +291,20 @@ def _getby(self, context, mapping, func): if not self._values: - raise error.ParseError(_("empty sequence")) + raise error.ParseError(_(b"empty sequence")) val = func(self._values) return self._wrapvalue(val, val) def _wrapvalue(self, key, val): if val is None: return - if util.safehasattr(val, "_makemap"): + if util.safehasattr(val, b"_makemap"): # a nested hybrid list/dict, which has its own way of map operation return val return hybriditem(None, key, val, self._makemap) def filter(self, context, mapping, select): - if util.safehasattr(self._values, "get"): + if util.safehasattr(self._values, b"get"): values = { k: v for k, v in self._values.iteritems() @@ -327,7 +327,7 @@ # TODO: switch gen to (context, mapping) API? gen = self._gen if gen is None: - return self.join(context, mapping, " ") + return self.join(context, mapping, b" ") if callable(gen): return gen() return gen @@ -338,7 +338,7 @@ def tovalue(self, context, mapping): # TODO: make it non-recursive for trivial lists/dicts xs = self._values - if util.safehasattr(xs, "get"): + if util.safehasattr(xs, b"get"): return { k: unwrapvalue(context, mapping, v) for k, v in xs.iteritems() } @@ -413,28 +413,30 @@ Template mappings may be nested. """ - def __init__(self, name=None, tmpl=None, sep=""): + def __init__(self, name=None, tmpl=None, sep=b""): if name is not None and tmpl is not None: - raise error.ProgrammingError("name and tmpl are mutually exclusive") + raise error.ProgrammingError( + b"name and tmpl are mutually exclusive" + ) self._name = name self._tmpl = tmpl self._defaultsep = sep def contains(self, context, mapping, item): - raise error.ParseError(_("not comparable")) + raise error.ParseError(_(b"not comparable")) def getmember(self, context, mapping, key): - raise error.ParseError(_("not a dictionary")) + raise error.ParseError(_(b"not a dictionary")) def getmin(self, context, mapping): - raise error.ParseError(_("not comparable")) + raise error.ParseError(_(b"not comparable")) def getmax(self, context, mapping): - raise error.ParseError(_("not comparable")) + raise error.ParseError(_(b"not comparable")) def filter(self, context, mapping, select): # implement if necessary; we'll need a wrapped type for a mapping dict - raise error.ParseError(_("not filterable without template")) + raise error.ParseError(_(b"not filterable without template")) def join(self, context, mapping, sep): mapsiter = _iteroverlaymaps(context, mapping, self.itermaps(context)) @@ -443,7 +445,7 @@ elif self._tmpl: itemiter = (context.expand(self._tmpl, m) for m in mapsiter) else: - raise error.ParseError(_("not displayable without template")) + raise error.ParseError(_(b"not displayable without template")) return joinitems(itemiter, sep) def show(self, context, mapping): @@ -472,7 +474,7 @@ mapping dicts. """ - def __init__(self, make, args=(), name=None, tmpl=None, sep=""): + def __init__(self, make, args=(), name=None, tmpl=None, sep=b""): super(mappinggenerator, self).__init__(name, tmpl, sep) self._make = make self._args = args @@ -487,7 +489,7 @@ class mappinglist(_mappingsequence): """Wrapper for list of template mappings""" - def __init__(self, mappings, name=None, tmpl=None, sep=""): + def __init__(self, mappings, name=None, tmpl=None, sep=b""): super(mappinglist, self).__init__(name, tmpl, sep) self._mappings = mappings @@ -556,7 +558,7 @@ return self._make(context, *self._args) def getmember(self, context, mapping, key): - raise error.ParseError(_("not a dictionary")) + raise error.ParseError(_(b"not a dictionary")) def getmin(self, context, mapping): return self._getby(context, mapping, min) @@ -567,7 +569,7 @@ def _getby(self, context, mapping, func): xs = self.tovalue(context, mapping) if not xs: - raise error.ParseError(_("empty sequence")) + raise error.ParseError(_(b"empty sequence")) return func(xs) @staticmethod @@ -582,13 +584,13 @@ return mappedgenerator(self._filteredgen, args) def itermaps(self, context): - raise error.ParseError(_("list of strings is not mappable")) + raise error.ParseError(_(b"list of strings is not mappable")) def join(self, context, mapping, sep): return joinitems(self._gen(context), sep) def show(self, context, mapping): - return self.join(context, mapping, "") + return self.join(context, mapping, b"") def tobool(self, context, mapping): return _nonempty(self._gen(context)) @@ -597,11 +599,11 @@ return [stringify(context, mapping, x) for x in self._gen(context)] -def hybriddict(data, key="key", value="value", fmt=None, gen=None): +def hybriddict(data, key=b"key", value=b"value", fmt=None, gen=None): """Wrap data to support both dict-like and string-like operations""" prefmt = pycompat.identity if fmt is None: - fmt = "%s=%s" + fmt = b"%s=%s" prefmt = pycompat.bytestr return hybrid( gen, @@ -615,7 +617,7 @@ """Wrap data to support both list-like and string-like operations""" prefmt = pycompat.identity if fmt is None: - fmt = "%s" + fmt = b"%s" prefmt = pycompat.bytestr return hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % prefmt(x)) @@ -625,11 +627,11 @@ mapping, name, data, - key="key", - value="value", + key=b"key", + value=b"value", fmt=None, plural=None, - separator=" ", + separator=b" ", ): """Wrap data like hybriddict(), but also supports old-style list template @@ -649,7 +651,7 @@ element=None, fmt=None, plural=None, - separator=" ", + separator=b" ", ): """Wrap data like hybridlist(), but also supports old-style list template @@ -668,14 +670,14 @@ keywords. """ # no need to provide {path} to old-style list template - c = [{"name": k, "source": v} for k, v in copies] - f = _showcompatlist(context, mapping, name, c, plural="file_copies") + c = [{b"name": k, b"source": v} for k, v in copies] + f = _showcompatlist(context, mapping, name, c, plural=b"file_copies") copies = util.sortdict(copies) return hybrid( f, copies, - lambda k: {"name": k, "path": k, "source": copies[k]}, - lambda k: "%s (%s)" % (k, copies[k]), + lambda k: {b"name": k, b"path": k, b"source": copies[k]}, + lambda k: b"%s (%s)" % (k, copies[k]), ) @@ -687,10 +689,14 @@ keywords. """ f = _showcompatlist(context, mapping, name, files) - return hybrid(f, files, lambda x: {"file": x, "path": x}, pycompat.identity) + return hybrid( + f, files, lambda x: {b"file": x, b"path": x}, pycompat.identity + ) -def _showcompatlist(context, mapping, name, values, plural=None, separator=" "): +def _showcompatlist( + context, mapping, name, values, plural=None, separator=b" " +): """Return a generator that renders old-style list template name is name of key in template map. @@ -713,9 +719,9 @@ expand 'end_foos'. """ if not plural: - plural = name + "s" + plural = name + b"s" if not values: - noname = "no_" + plural + noname = b"no_" + plural if context.preload(noname): yield context.process(noname, mapping) return @@ -728,7 +734,7 @@ r.update(mapping) yield r return - startname = "start_" + plural + startname = b"start_" + plural if context.preload(startname): yield context.process(startname, mapping) @@ -749,7 +755,7 @@ vmapping = context.overlaymap(mapping, vmapping) return context.process(tag, vmapping) - lastname = "last_" + name + lastname = b"last_" + name if context.preload(lastname): last = values.pop() else: @@ -758,7 +764,7 @@ yield one(v) if last is not None: yield one(last, tag=lastname) - endname = "end_" + plural + endname = b"end_" + plural if context.preload(endname): yield context.process(endname, mapping) @@ -773,12 +779,12 @@ # We can only hit this on Python 3, and it's here to guard # against infinite recursion. raise error.ProgrammingError( - "Mercurial IO including templates is done" - " with bytes, not strings, got %r" % thing + b"Mercurial IO including templates is done" + b" with bytes, not strings, got %r" % thing ) elif thing is None: pass - elif not util.safehasattr(thing, "__iter__"): + elif not util.safehasattr(thing, b"__iter__"): yield pycompat.bytestr(thing) else: for i in thing: @@ -788,7 +794,7 @@ yield i elif i is None: pass - elif not util.safehasattr(i, "__iter__"): + elif not util.safehasattr(i, b"__iter__"): yield pycompat.bytestr(i) else: for j in flatten(context, mapping, i): @@ -895,7 +901,7 @@ try: return dateutil.parsedate(thing) except AttributeError: - raise error.ParseError(err or _("not a date tuple nor a string")) + raise error.ParseError(err or _(b"not a date tuple nor a string")) except error.ParseError: if not err: raise @@ -912,7 +918,7 @@ try: return int(thing) except (TypeError, ValueError): - raise error.ParseError(err or _("not an integer")) + raise error.ParseError(err or _(b"not an integer")) def evalstring(context, mapping, arg): @@ -943,7 +949,7 @@ try: f = _unwrapfuncbytype[typ] except KeyError: - raise error.ProgrammingError("invalid type specified: %r" % typ) + raise error.ProgrammingError(b"invalid type specified: %r" % typ) return f(context, mapping, thing) @@ -957,12 +963,12 @@ def _recursivesymbolblocker(key): def showrecursion(context, mapping): - raise error.Abort(_("recursive reference '%s' in template") % key) + raise error.Abort(_(b"recursive reference '%s' in template") % key) return showrecursion -def runsymbol(context, mapping, key, default=""): +def runsymbol(context, mapping, key, default=b""): v = context.symbol(mapping, key) if v is None: # put poison to cut recursion. we can't move this to parsing phase @@ -1003,8 +1009,8 @@ fn = pycompat.sysbytes(filt.__name__) sym = findsymbolicname(arg) if not sym: - return _("incompatible use of template filter '%s'") % fn - return _("template filter '%s' is not compatible with keyword '%s'") % ( + return _(b"incompatible use of template filter '%s'") % fn + return _(b"template filter '%s' is not compatible with keyword '%s'") % ( fn, sym, ) @@ -1015,7 +1021,7 @@ of partial mappings to override the original""" for i, nm in enumerate(newmappings): lm = context.overlaymap(origmapping, nm) - lm["index"] = i + lm[b"index"] = i yield lm @@ -1026,7 +1032,7 @@ sym = findsymbolicname(darg) if not sym: raise - hint = _("keyword '%s' does not support map operation") % sym + hint = _(b"keyword '%s' does not support map operation") % sym raise error.ParseError(bytes(err), hint=hint) for lm in _iteroverlaymaps(context, mapping, diter): yield evalrawexp(context, lm, targ) @@ -1050,13 +1056,13 @@ sym = findsymbolicname(darg) if not sym: raise - hint = _("keyword '%s' does not support member operation") % sym + hint = _(b"keyword '%s' does not support member operation") % sym raise error.ParseError(bytes(err), hint=hint) def runnegate(context, mapping, data): data = evalinteger( - context, mapping, data, _("negation needs an integer argument") + context, mapping, data, _(b"negation needs an integer argument") ) return -data @@ -1064,15 +1070,15 @@ def runarithmetic(context, mapping, data): func, left, right = data left = evalinteger( - context, mapping, left, _("arithmetic only defined on integers") + context, mapping, left, _(b"arithmetic only defined on integers") ) right = evalinteger( - context, mapping, right, _("arithmetic only defined on integers") + context, mapping, right, _(b"arithmetic only defined on integers") ) try: return func(left, right) except ZeroDivisionError: - raise error.Abort(_("division by zero is not defined")) + raise error.Abort(_(b"division by zero is not defined")) def joinitems(itemiter, sep): diff --git a/mercurial/testing/storage.py b/mercurial/testing/storage.py --- a/mercurial/testing/storage.py +++ b/mercurial/testing/storage.py @@ -40,8 +40,8 @@ def testempty(self): f = self._makefilefn() - self.assertEqual(len(f), 0, "new file store has 0 length by default") - self.assertEqual(list(f), [], "iter yields nothing by default") + self.assertEqual(len(f), 0, b"new file store has 0 length by default") + self.assertEqual(list(f), [], b"iter yields nothing by default") gen = iter(f) with self.assertRaises(StopIteration): @@ -414,7 +414,7 @@ self.assertEqual(f.storageinfo(), {}) self.assertEqual( f.storageinfo(revisionscount=True, trackedsize=True), - {"revisionscount": 0, "trackedsize": 0}, + {b"revisionscount": 0, b"trackedsize": 0}, ) self.assertEqual(f.size(nullrev), 0) @@ -472,7 +472,7 @@ self.assertEqual(f.storageinfo(), {}) self.assertEqual( f.storageinfo(revisionscount=True, trackedsize=True), - {"revisionscount": 1, "trackedsize": len(fulltext)}, + {b"revisionscount": 1, b"trackedsize": len(fulltext)}, ) self.assertEqual(f.size(0), len(fulltext)) @@ -541,8 +541,10 @@ self.assertEqual( f.storageinfo(revisionscount=True, trackedsize=True), { - "revisionscount": 3, - "trackedsize": len(fulltext0) + len(fulltext1) + len(fulltext2), + b"revisionscount": 3, + b"trackedsize": len(fulltext0) + + len(fulltext1) + + len(fulltext2), }, ) @@ -679,17 +681,19 @@ # Unrecognized nodesorder value raises ProgrammingError. with self.assertRaises(error.ProgrammingError): - list(f.emitrevisions([], nodesorder="bad")) + list(f.emitrevisions([], nodesorder=b"bad")) # nodesorder=storage is recognized. But we can't test it thoroughly # because behavior is storage-dependent. - res = list(f.emitrevisions([node2, node1, node0], nodesorder="storage")) + res = list( + f.emitrevisions([node2, node1, node0], nodesorder=b"storage") + ) self.assertEqual(len(res), 3) self.assertEqual({o.node for o in res}, {node0, node1, node2}) # nodesorder=nodes forces the order. gen = f.emitrevisions( - [node2, node0], nodesorder="nodes", revisiondata=True + [node2, node0], nodesorder=b"nodes", revisiondata=True ) rev = next(gen) diff --git a/mercurial/transaction.py b/mercurial/transaction.py --- a/mercurial/transaction.py +++ b/mercurial/transaction.py @@ -28,18 +28,20 @@ # These are the file generators that should only be executed after the # finalizers are done, since they rely on the output of the finalizers (like # the changelog having been written). -postfinalizegenerators = {"bookmarks", "dirstate"} +postfinalizegenerators = {b"bookmarks", b"dirstate"} -gengroupall = "all" -gengroupprefinalize = "prefinalize" -gengrouppostfinalize = "postfinalize" +gengroupall = b"all" +gengroupprefinalize = b"prefinalize" +gengrouppostfinalize = b"postfinalize" def active(func): def _active(self, *args, **kwds): if self._count == 0: raise error.Abort( - _("cannot use transaction when it is already committed/aborted") + _( + b"cannot use transaction when it is already committed/aborted" + ) ) return func(self, *args, **kwds) @@ -58,21 +60,21 @@ ): for f, o, _ignore in entries: if o or not unlink: - checkambig = checkambigfiles and (f, "") in checkambigfiles + checkambig = checkambigfiles and (f, b"") in checkambigfiles try: - fp = opener(f, "a", checkambig=checkambig) + fp = opener(f, b"a", checkambig=checkambig) if fp.tell() < o: raise error.Abort( _( - "attempted to truncate %s to %d bytes, but it was " - "already %d bytes\n" + b"attempted to truncate %s to %d bytes, but it was " + b"already %d bytes\n" ) % (f, o, fp.tell()) ) fp.truncate(o) fp.close() except IOError: - report(_("failed to truncate %s\n") % f) + report(_(b"failed to truncate %s\n") % f) raise else: try: @@ -84,7 +86,7 @@ backupfiles = [] for l, f, b, c in backupentries: if l not in vfsmap and c: - report("couldn't handle %s: unknown cache location %s\n" % (b, l)) + report(b"couldn't handle %s: unknown cache location %s\n" % (b, l)) vfs = vfsmap[l] try: if f and b: @@ -95,7 +97,7 @@ util.copyfile(backuppath, filepath, checkambig=checkambig) backupfiles.append(b) except IOError: - report(_("failed to recover %s\n") % f) + report(_(b"failed to recover %s\n") % f) else: target = f or b try: @@ -107,7 +109,7 @@ if not c: raise - backuppath = "%s.backupfiles" % journal + backuppath = b"%s.backupfiles" % journal if opener.exists(backuppath): opener.unlink(backuppath) opener.unlink(journal) @@ -155,7 +157,7 @@ self._opener = opener # a map to access file in various {location -> vfs} vfsmap = vfsmap.copy() - vfsmap[""] = opener # set default value + vfsmap[b""] = opener # set default value self._vfsmap = vfsmap self._after = after self._entries = [] @@ -186,7 +188,7 @@ # a dict of arguments to be passed to hooks self.hookargs = {} - self._file = opener.open(self._journal, "w") + self._file = opener.open(self._journal, b"w") # a list of ('location', 'path', 'backuppath', cache) entries. # - if 'backuppath' is empty, no file existed at backup time @@ -196,9 +198,9 @@ # (cache is currently unused) self._backupentries = [] self._backupmap = {} - self._backupjournal = "%s.backupfiles" % self._journal - self._backupsfile = opener.open(self._backupjournal, "w") - self._backupsfile.write("%d\n" % version) + self._backupjournal = b"%s.backupfiles" % self._journal + self._backupsfile = opener.open(self._backupjournal, b"w") + self._backupsfile.write(b"%d\n" % version) if createmode is not None: opener.chmod(self._journal, createmode & 0o666) @@ -265,11 +267,11 @@ self._entries.append((file, offset, data)) self._map[file] = len(self._entries) - 1 # add enough data to the journal to do the truncate - self._file.write("%s\0%d\n" % (file, offset)) + self._file.write(b"%s\0%d\n" % (file, offset)) self._file.flush() @active - def addbackup(self, file, hardlink=True, location=""): + def addbackup(self, file, hardlink=True, location=b""): """Adds a backup of the file to the transaction Calling addbackup() creates a hardlink backup of the specified file @@ -280,21 +282,21 @@ * `hardlink`: use a hardlink to quickly create the backup """ if self._queue: - msg = 'cannot use transaction.addbackup inside "group"' + msg = b'cannot use transaction.addbackup inside "group"' raise error.ProgrammingError(msg) if file in self._map or file in self._backupmap: return vfs = self._vfsmap[location] dirname, filename = vfs.split(file) - backupfilename = "%s.backup.%s" % (self._journal, filename) + backupfilename = b"%s.backup.%s" % (self._journal, filename) backupfile = vfs.reljoin(dirname, backupfilename) if vfs.exists(file): filepath = vfs.join(file) backuppath = vfs.join(backupfile) util.copyfile(filepath, backuppath, hardlink=hardlink) else: - backupfile = "" + backupfile = b"" self._addbackupentry((location, file, backupfile, False)) @@ -302,20 +304,22 @@ """register a new backup entry and write it to disk""" self._backupentries.append(entry) self._backupmap[entry[1]] = len(self._backupentries) - 1 - self._backupsfile.write("%s\0%s\0%s\0%d\n" % entry) + self._backupsfile.write(b"%s\0%s\0%s\0%d\n" % entry) self._backupsfile.flush() @active - def registertmp(self, tmpfile, location=""): + def registertmp(self, tmpfile, location=b""): """register a temporary transaction file Such files will be deleted when the transaction exits (on both failure and success). """ - self._addbackupentry((location, "", tmpfile, False)) + self._addbackupentry((location, b"", tmpfile, False)) @active - def addfilegenerator(self, genid, filenames, genfunc, order=0, location=""): + def addfilegenerator( + self, genid, filenames, genfunc, order=0, location=b"" + ): """add a function to generates some files at transaction commit The `genfunc` argument is a function capable of generating proper @@ -348,7 +352,7 @@ if genid in self._filegenerators: del self._filegenerators[genid] - def _generatefiles(self, suffix="", group=gengroupall): + def _generatefiles(self, suffix=b"", group=gengroupall): # write files registered for generation any = False for id, entry in sorted(self._filegenerators.iteritems()): @@ -375,7 +379,7 @@ self.addbackup(name, location=location) checkambig = (name, location) in self._checkambigfiles files.append( - vfs(name, "w", atomictemp=True, checkambig=checkambig) + vfs(name, b"w", atomictemp=True, checkambig=checkambig) ) genfunc(*files) for f in files: @@ -406,7 +410,7 @@ raise KeyError(file) index = self._map[file] self._entries[index] = (file, offset, data) - self._file.write("%s\0%d\n" % (file, offset)) + self._file.write(b"%s\0%d\n" % (file, offset)) self._file.flush() @active @@ -448,7 +452,7 @@ # remove callback since the data will have been flushed any = self._pendingcallback.pop(cat)(self) self._anypending = self._anypending or any - self._anypending |= self._generatefiles(suffix=".pending") + self._anypending |= self._generatefiles(suffix=b".pending") return self._anypending @active @@ -512,7 +516,7 @@ for l, f, b, c in self._backupentries: if l not in self._vfsmap and c: self._report( - "couldn't remove %s: unknown cache location %s\n" % (b, l) + b"couldn't remove %s: unknown cache location %s\n" % (b, l) ) continue vfs = self._vfsmap[l] @@ -524,7 +528,7 @@ raise # Abort may be raise by read only opener self._report( - "couldn't remove %s: %s\n" % (vfs.join(b), inst) + b"couldn't remove %s: %s\n" % (vfs.join(b), inst) ) self._entries = [] self._writeundo() @@ -538,7 +542,8 @@ for l, _f, b, c in self._backupentries: if l not in self._vfsmap and c: self._report( - "couldn't remove %s: unknown cache location" "%s\n" % (b, l) + b"couldn't remove %s: unknown cache location" + b"%s\n" % (b, l) ) continue vfs = self._vfsmap[l] @@ -550,7 +555,7 @@ raise # Abort may be raise by read only opener self._report( - "couldn't remove %s: %s\n" % (vfs.join(b), inst) + b"couldn't remove %s: %s\n" % (vfs.join(b), inst) ) self._backupentries = [] self._journal = None @@ -577,19 +582,19 @@ if self._undoname is None: return undobackupfile = self._opener.open( - "%s.backupfiles" % self._undoname, "w" + b"%s.backupfiles" % self._undoname, b"w" ) - undobackupfile.write("%d\n" % version) + undobackupfile.write(b"%d\n" % version) for l, f, b, c in self._backupentries: if not f: # temporary file continue if not b: - u = "" + u = b"" else: if l not in self._vfsmap and c: self._report( - "couldn't remove %s: unknown cache location" - "%s\n" % (b, l) + b"couldn't remove %s: unknown cache location" + b"%s\n" % (b, l) ) continue vfs = self._vfsmap[l] @@ -598,7 +603,7 @@ uname = name.replace(self._journal, self._undoname, 1) u = vfs.reljoin(base, uname) util.copyfile(vfs.join(b), vfs.join(u), hardlink=True) - undobackupfile.write("%s\0%s\0%s\0%d\n" % (l, f, u, c)) + undobackupfile.write(b"%s\0%s\0%s\0%d\n" % (l, f, u, c)) undobackupfile.close() def _abort(self): @@ -615,7 +620,7 @@ self._opener.unlink(self._journal) return - self._report(_("transaction abort!\n")) + self._report(_(b"transaction abort!\n")) try: for cat in sorted(self._abortcallback): @@ -632,11 +637,11 @@ False, checkambigfiles=self._checkambigfiles, ) - self._report(_("rollback completed\n")) + self._report(_(b"rollback completed\n")) except BaseException as exc: - self._report(_("rollback failed - please run hg recover\n")) + self._report(_(b"rollback failed - please run hg recover\n")) self._report( - _("(failure reason: %s)\n") % stringutil.forcebytestr(exc) + _(b"(failure reason: %s)\n") % stringutil.forcebytestr(exc) ) finally: self._journal = None @@ -668,12 +673,14 @@ fp.close() for l in lines: try: - f, o = l.split("\0") + f, o = l.split(b"\0") entries.append((f, int(o), None)) except ValueError: - report(_("couldn't read journal entry %r!\n") % pycompat.bytestr(l)) + report( + _(b"couldn't read journal entry %r!\n") % pycompat.bytestr(l) + ) - backupjournal = "%s.backupfiles" % file + backupjournal = b"%s.backupfiles" % file if opener.exists(backupjournal): fp = opener.open(backupjournal) lines = fp.readlines() @@ -684,13 +691,13 @@ if line: # Shave off the trailing newline line = line[:-1] - l, f, b, c = line.split("\0") + l, f, b, c = line.split(b"\0") backupentries.append((l, f, b, bool(c))) else: report( _( - "journal was created by a different version of " - "Mercurial\n" + b"journal was created by a different version of " + b"Mercurial\n" ) ) diff --git a/mercurial/treediscovery.py b/mercurial/treediscovery.py --- a/mercurial/treediscovery.py +++ b/mercurial/treediscovery.py @@ -39,7 +39,7 @@ if not heads: with remote.commandexecutor() as e: - heads = e.callcommand("heads", {}).result() + heads = e.callcommand(b"heads", {}).result() if repo.changelog.tip() == nullid: base.add(nullid) @@ -49,7 +49,7 @@ # assume we're closer to the tip than the root # and start by examining the heads - repo.ui.status(_("searching for changes\n")) + repo.ui.status(_(b"searching for changes\n")) unknown = [] for h in heads: @@ -63,14 +63,14 @@ req = set(unknown) reqcnt = 0 - progress = repo.ui.makeprogress(_("searching"), unit=_("queries")) + progress = repo.ui.makeprogress(_(b"searching"), unit=_(b"queries")) # search through remote branches # a 'branch' here is a linear segment of history, with four parts: # head, root, first parent, second parent # (a branch always has two parents (or none) by definition) with remote.commandexecutor() as e: - branches = e.callcommand("branches", {"nodes": unknown}).result() + branches = e.callcommand(b"branches", {b"nodes": unknown}).result() unknown = collections.deque(branches) while unknown: @@ -80,15 +80,15 @@ if n[0] in seen: continue - repo.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) + repo.ui.debug(b"examining %s:%s\n" % (short(n[0]), short(n[1]))) if n[0] == nullid: # found the end of the branch pass elif n in seenbranch: - repo.ui.debug("branch already found\n") + repo.ui.debug(b"branch already found\n") continue elif n[1] and knownnode(n[1]): # do we know the base? repo.ui.debug( - "found incomplete branch %s:%s\n" + b"found incomplete branch %s:%s\n" % (short(n[0]), short(n[1])) ) search.append(n[0:2]) # schedule branch range for scanning @@ -96,7 +96,7 @@ else: if n[1] not in seen and n[1] not in fetch: if knownnode(n[2]) and knownnode(n[3]): - repo.ui.debug("found new changeset %s\n" % short(n[1])) + repo.ui.debug(b"found new changeset %s\n" % short(n[1])) fetch.add(n[1]) # earliest unknown for p in n[2:4]: if knownnode(p): @@ -112,17 +112,17 @@ reqcnt += 1 progress.increment() repo.ui.debug( - "request %d: %s\n" % (reqcnt, " ".join(map(short, r))) + b"request %d: %s\n" % (reqcnt, b" ".join(map(short, r))) ) for p in pycompat.xrange(0, len(r), 10): with remote.commandexecutor() as e: branches = e.callcommand( - "branches", {"nodes": r[p : p + 10],} + b"branches", {b"nodes": r[p : p + 10],} ).result() for b in branches: repo.ui.debug( - "received %s:%s\n" % (short(b[0]), short(b[1])) + b"received %s:%s\n" % (short(b[0]), short(b[1])) ) unknown.append(b) @@ -133,24 +133,24 @@ progress.increment() with remote.commandexecutor() as e: - between = e.callcommand("between", {"pairs": search}).result() + between = e.callcommand(b"between", {b"pairs": search}).result() for n, l in zip(search, between): l.append(n[1]) p = n[0] f = 1 for i in l: - repo.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i))) + repo.ui.debug(b"narrowing %d:%d %s\n" % (f, len(l), short(i))) if knownnode(i): if f <= 2: repo.ui.debug( - "found new branch changeset %s\n" % short(p) + b"found new branch changeset %s\n" % short(p) ) fetch.add(p) base.add(i) else: repo.ui.debug( - "narrowed branch search to %s:%s\n" + b"narrowed branch search to %s:%s\n" % (short(p), short(i)) ) newsearch.append((p, i)) @@ -161,22 +161,22 @@ # sanity check our fetch list for f in fetch: if knownnode(f): - raise error.RepoError(_("already have changeset ") + short(f[:4])) + raise error.RepoError(_(b"already have changeset ") + short(f[:4])) base = list(base) if base == [nullid]: if force: - repo.ui.warn(_("warning: repository is unrelated\n")) + repo.ui.warn(_(b"warning: repository is unrelated\n")) else: - raise error.Abort(_("repository is unrelated")) + raise error.Abort(_(b"repository is unrelated")) repo.ui.debug( - "found new changesets starting at " - + " ".join([short(f) for f in fetch]) - + "\n" + b"found new changesets starting at " + + b" ".join([short(f) for f in fetch]) + + b"\n" ) progress.complete() - repo.ui.debug("%d total queries\n" % reqcnt) + repo.ui.debug(b"%d total queries\n" % reqcnt) return base, list(fetch), heads diff --git a/mercurial/txnutil.py b/mercurial/txnutil.py --- a/mercurial/txnutil.py +++ b/mercurial/txnutil.py @@ -16,7 +16,7 @@ """return whether 'root' may have pending changes, which are visible to this process. """ - return root == encoding.environ.get("HG_PENDING") + return root == encoding.environ.get(b"HG_PENDING") def trypending(root, vfs, filename, **kwargs): @@ -29,7 +29,7 @@ """ if mayhavepending(root): try: - return (vfs("%s.pending" % filename, **kwargs), True) + return (vfs(b"%s.pending" % filename, **kwargs), True) except IOError as inst: if inst.errno != errno.ENOENT: raise diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -46,7 +46,7 @@ urlreq = util.urlreq # for use with str.translate(None, _keepalnum), to keep just alphanumerics -_keepalnum = "".join( +_keepalnum = b"".join( c for c in map(pycompat.bytechr, range(256)) if not c.isalnum() ) @@ -79,7 +79,7 @@ """ samplehgrcs = { - "user": b"""# example user config (see 'hg help config' for more info) + b"user": b"""# example user config (see 'hg help config' for more info) [ui] # name and email, e.g. # username = Jane Doe @@ -106,7 +106,7 @@ # rebase = # uncommit = """, - "cloned": b"""# example repository config (see 'hg help config' for more info) + b"cloned": b"""# example repository config (see 'hg help config' for more info) [paths] default = %s @@ -121,7 +121,7 @@ # name and email (local to this repository, optional), e.g. # username = Jane Doe """, - "local": b"""# example repository config (see 'hg help config' for more info) + b"local": b"""# example repository config (see 'hg help config' for more info) [paths] # path aliases to other clones of this repo in URLs or filesystem paths # (see 'hg help config.paths' for more info) @@ -135,7 +135,7 @@ # name and email (local to this repository, optional), e.g. # username = Jane Doe """, - "global": b"""# example system-wide hg config (see 'hg help config' for more info) + b"global": b"""# example system-wide hg config (see 'hg help config' for more info) [ui] # uncomment to disable color in command output @@ -285,8 +285,8 @@ self.httppasswordmgrdb = httppasswordmgrdbproxy() self._blockedtimes = collections.defaultdict(int) - allowed = self.configlist("experimental", "exportableenviron") - if "*" in allowed: + allowed = self.configlist(b"experimental", b"exportableenviron") + if b"*" in allowed: self._exportableenviron = self.environ else: self._exportableenviron = {} @@ -300,9 +300,9 @@ u = cls() # we always trust global config files and environment variables for t, f in rcutil.rccomponents(): - if t == "path": + if t == b"path": u.readconfig(f, trust=True) - elif t == "items": + elif t == b"items": sections = set() for section, name, value, source in f: # do not set u._ocfg @@ -313,14 +313,14 @@ for section in sections: u.fixconfig(section=section) else: - raise error.ProgrammingError("unknown rctype: %s" % t) + raise error.ProgrammingError(b"unknown rctype: %s" % t) u._maybetweakdefaults() return u def _maybetweakdefaults(self): - if not self.configbool("ui", "tweakdefaults"): + if not self.configbool(b"ui", b"tweakdefaults"): return - if self._tweaked or self.plain("tweakdefaults"): + if self._tweaked or self.plain(b"tweakdefaults"): return # Note: it is SUPER IMPORTANT that you set self._tweaked to @@ -331,11 +331,11 @@ # avoid this weirdness. self._tweaked = True tmpcfg = config.config() - tmpcfg.parse("", tweakrc) + tmpcfg.parse(b"", tweakrc) for section in tmpcfg: for name, value in tmpcfg.items(section): if not self.hasconfig(section, name): - self.setconfig(section, name, value, "") + self.setconfig(section, name, value, b"") def copy(self): return self.__class__(self) @@ -353,7 +353,7 @@ try: yield finally: - self._blockedtimes[key + "_blocked"] += ( + self._blockedtimes[key + b"_blocked"] += ( util.timer() - starttime ) * 1000 @@ -366,9 +366,9 @@ lets you advise Mercurial that something risky is happening so that control-C etc can be blocked if desired. """ - enabled = self.configbool("experimental", "nointerrupt") + enabled = self.configbool(b"experimental", b"nointerrupt") if enabled and self.configbool( - "experimental", "nointerrupt-interactiveonly" + b"experimental", b"nointerrupt-interactiveonly" ): enabled = self.interactive() if self._uninterruptible or not enabled: @@ -379,9 +379,9 @@ return def warn(): - self.warn(_("shutting down cleanly\n")) + self.warn(_(b"shutting down cleanly\n")) self.warn( - _("press ^C again to terminate immediately (dangerous)\n") + _(b"press ^C again to terminate immediately (dangerous)\n") ) return True @@ -401,7 +401,7 @@ return True tusers, tgroups = self._trustusers, self._trustgroups - if "*" in tusers or "*" in tgroups: + if b"*" in tusers or b"*" in tgroups: return True user = util.username(st.st_uid) @@ -411,7 +411,10 @@ if self._reportuntrusted: self.warn( - _("not trusting file %s from untrusted " "user %s, group %s\n") + _( + b"not trusting file %s from untrusted " + b"user %s, group %s\n" + ) % (f, user, group) ) return False @@ -435,37 +438,37 @@ except error.ConfigError as inst: if trusted: raise - self.warn(_("ignored: %s\n") % stringutil.forcebytestr(inst)) + self.warn(_(b"ignored: %s\n") % stringutil.forcebytestr(inst)) if self.plain(): for k in ( - "debug", - "fallbackencoding", - "quiet", - "slash", - "logtemplate", - "message-output", - "statuscopies", - "style", - "traceback", - "verbose", + b"debug", + b"fallbackencoding", + b"quiet", + b"slash", + b"logtemplate", + b"message-output", + b"statuscopies", + b"style", + b"traceback", + b"verbose", ): - if k in cfg["ui"]: - del cfg["ui"][k] - for k, v in cfg.items("defaults"): - del cfg["defaults"][k] - for k, v in cfg.items("commands"): - del cfg["commands"][k] + if k in cfg[b"ui"]: + del cfg[b"ui"][k] + for k, v in cfg.items(b"defaults"): + del cfg[b"defaults"][k] + for k, v in cfg.items(b"commands"): + del cfg[b"commands"][k] # Don't remove aliases from the configuration if in the exceptionlist - if self.plain("alias"): - for k, v in cfg.items("alias"): - del cfg["alias"][k] - if self.plain("revsetalias"): - for k, v in cfg.items("revsetalias"): - del cfg["revsetalias"][k] - if self.plain("templatealias"): - for k, v in cfg.items("templatealias"): - del cfg["templatealias"][k] + if self.plain(b"alias"): + for k, v in cfg.items(b"alias"): + del cfg[b"alias"][k] + if self.plain(b"revsetalias"): + for k, v in cfg.items(b"revsetalias"): + del cfg[b"revsetalias"][k] + if self.plain(b"templatealias"): + for k, v in cfg.items(b"templatealias"): + del cfg[b"templatealias"][k] if trusted: self._tcfg.update(cfg) @@ -474,51 +477,51 @@ self._ucfg.update(self._ocfg) if root is None: - root = os.path.expanduser("~") + root = os.path.expanduser(b"~") self.fixconfig(root=root) def fixconfig(self, root=None, section=None): - if section in (None, "paths"): + if section in (None, b"paths"): # expand vars and ~ # translate paths relative to root (or home) into absolute paths root = root or encoding.getcwd() for c in self._tcfg, self._ucfg, self._ocfg: - for n, p in c.items("paths"): + for n, p in c.items(b"paths"): # Ignore sub-options. - if ":" in n: + if b":" in n: continue if not p: continue - if "%%" in p: - s = self.configsource("paths", n) or "none" + if b"%%" in p: + s = self.configsource(b"paths", n) or b"none" self.warn( - _("(deprecated '%%' in path %s=%s from %s)\n") + _(b"(deprecated '%%' in path %s=%s from %s)\n") % (n, p, s) ) - p = p.replace("%%", "%") + p = p.replace(b"%%", b"%") p = util.expandpath(p) if not util.hasscheme(p) and not os.path.isabs(p): p = os.path.normpath(os.path.join(root, p)) - c.set("paths", n, p) + c.set(b"paths", n, p) - if section in (None, "ui"): + if section in (None, b"ui"): # update ui options self._fmsgout, self._fmsgerr = _selectmsgdests(self) - self.debugflag = self.configbool("ui", "debug") - self.verbose = self.debugflag or self.configbool("ui", "verbose") - self.quiet = not self.debugflag and self.configbool("ui", "quiet") + self.debugflag = self.configbool(b"ui", b"debug") + self.verbose = self.debugflag or self.configbool(b"ui", b"verbose") + self.quiet = not self.debugflag and self.configbool(b"ui", b"quiet") if self.verbose and self.quiet: self.quiet = self.verbose = False self._reportuntrusted = self.debugflag or self.configbool( - "ui", "report_untrusted" + b"ui", b"report_untrusted" ) - self.tracebackflag = self.configbool("ui", "traceback") - self.logblockedtimes = self.configbool("ui", "logblockedtimes") + self.tracebackflag = self.configbool(b"ui", b"traceback") + self.logblockedtimes = self.configbool(b"ui", b"logblockedtimes") - if section in (None, "trusted"): + if section in (None, b"trusted"): # update trust information - self._trustusers.update(self.configlist("trusted", "users")) - self._trustgroups.update(self.configlist("trusted", "groups")) + self._trustusers.update(self.configlist(b"trusted", b"users")) + self._trustgroups.update(self.configlist(b"trusted", b"groups")) if section in (None, b"devel", b"ui") and self.debugflag: tracked = set() @@ -540,7 +543,7 @@ self._tcfg.restore(data[1]) self._ucfg.restore(data[2]) - def setconfig(self, section, name, value, source=""): + def setconfig(self, section, name, value, source=b""): for cfg in (self._ocfg, self._tcfg, self._ucfg): cfg.set(section, name, value, source) self.fixconfig(section=section) @@ -573,18 +576,18 @@ else: itemdefault = item.default else: - msg = "accessing unregistered config item: '%s.%s'" + msg = b"accessing unregistered config item: '%s.%s'" msg %= (section, name) - self.develwarn(msg, 2, "warn-config-unknown") + self.develwarn(msg, 2, b"warn-config-unknown") if default is _unset: if item is None: value = default elif item.default is configitems.dynamicdefault: value = None - msg = "config item requires an explicit default value: '%s.%s'" + msg = b"config item requires an explicit default value: '%s.%s'" msg %= (section, name) - self.develwarn(msg, 2, "warn-config-default") + self.develwarn(msg, 2, b"warn-config-default") else: value = itemdefault elif ( @@ -593,11 +596,11 @@ and default != itemdefault ): msg = ( - "specifying a mismatched default value for a registered " - "config item: '%s.%s' '%s'" + b"specifying a mismatched default value for a registered " + b"config item: '%s.%s' '%s'" ) msg %= (section, name, pycompat.bytestr(default)) - self.develwarn(msg, 2, "warn-config-default") + self.develwarn(msg, 2, b"warn-config-default") for s, n in alternates: candidate = self._data(untrusted).get(s, n, None) @@ -610,8 +613,8 @@ uvalue = self._ucfg.get(s, n) if uvalue is not None and uvalue != value: self.debug( - "ignoring untrusted configuration option " - "%s.%s = %s\n" % (s, n, uvalue) + b"ignoring untrusted configuration option " + b"%s.%s = %s\n" % (s, n, uvalue) ) return value @@ -628,31 +631,31 @@ main = self.config(section, name, default, untrusted=untrusted) data = self._data(untrusted) sub = {} - prefix = "%s:" % name + prefix = b"%s:" % name for k, v in data.items(section): if k.startswith(prefix): sub[k[len(prefix) :]] = v if self.debugflag and not untrusted and self._reportuntrusted: for k, v in sub.items(): - uvalue = self._ucfg.get(section, "%s:%s" % (name, k)) + uvalue = self._ucfg.get(section, b"%s:%s" % (name, k)) if uvalue is not None and uvalue != v: self.debug( - "ignoring untrusted configuration option " - "%s:%s.%s = %s\n" % (section, name, k, uvalue) + b"ignoring untrusted configuration option " + b"%s:%s.%s = %s\n" % (section, name, k, uvalue) ) return main, sub def configpath(self, section, name, default=_unset, untrusted=False): - "get a path config item, expanded relative to repo root or config file" + b"get a path config item, expanded relative to repo root or config file" v = self.config(section, name, default, untrusted) if v is None: return None - if not os.path.isabs(v) or "://" not in v: + if not os.path.isabs(v) or b"://" not in v: src = self.configsource(section, name, untrusted) - if ":" in src: - base = os.path.dirname(src.rsplit(":")[0]) + if b":" in src: + base = os.path.dirname(src.rsplit(b":")[0]) v = os.path.join(base, os.path.expanduser(v)) return v @@ -689,7 +692,7 @@ b = stringutil.parsebool(v) if b is None: raise error.ConfigError( - _("%s.%s is not a boolean ('%s')") % (section, name, v) + _(b"%s.%s is not a boolean ('%s')") % (section, name, v) ) return b @@ -727,7 +730,7 @@ if desc is None: desc = pycompat.sysbytes(convert.__name__) raise error.ConfigError( - _("%s.%s is not a valid %s ('%s')") % (section, name, desc, v) + _(b"%s.%s is not a valid %s ('%s')") % (section, name, desc, v) ) def configint(self, section, name, default=_unset, untrusted=False): @@ -750,7 +753,7 @@ """ return self.configwith( - int, section, name, default, "integer", untrusted + int, section, name, default, b"integer", untrusted ) def configbytes(self, section, name, default=_unset, untrusted=False): @@ -786,7 +789,7 @@ return util.sizetoint(value) except error.ParseError: raise error.ConfigError( - _("%s.%s is not a byte quantity ('%s')") + _(b"%s.%s is not a byte quantity ('%s')") % (section, name, value) ) @@ -804,7 +807,7 @@ """ # default is not always a list v = self.configwith( - config.parselist, section, name, default, "list", untrusted + config.parselist, section, name, default, b"list", untrusted ) if isinstance(v, bytes): return config.parselist(v) @@ -822,7 +825,7 @@ """ if self.config(section, name, default, untrusted): return self.configwith( - dateutil.parsedate, section, name, default, "date", untrusted + dateutil.parsedate, section, name, default, b"date", untrusted ) if default is _unset: return None @@ -849,13 +852,13 @@ def configitems(self, section, untrusted=False, ignoresub=False): items = self._data(untrusted).items(section) if ignoresub: - items = [i for i in items if ":" not in i[0]] + items = [i for i in items if b":" not in i[0]] if self.debugflag and not untrusted and self._reportuntrusted: for k, v in self._ucfg.items(section): if self._tcfg.get(section, k) != v: self.debug( - "ignoring untrusted configuration option " - "%s.%s = %s\n" % (section, k, v) + b"ignoring untrusted configuration option " + b"%s.%s = %s\n" % (section, k, v) ) return items @@ -882,16 +885,18 @@ - True otherwise """ if ( - "HGPLAIN" not in encoding.environ - and "HGPLAINEXCEPT" not in encoding.environ + b"HGPLAIN" not in encoding.environ + and b"HGPLAINEXCEPT" not in encoding.environ ): return False exceptions = ( - encoding.environ.get("HGPLAINEXCEPT", "").strip().split(",") + encoding.environ.get(b"HGPLAINEXCEPT", b"").strip().split(b",") ) # TODO: add support for HGPLAIN=+feature,-feature syntax - if "+strictflags" not in encoding.environ.get("HGPLAIN", "").split(","): - exceptions.append("strictflags") + if b"+strictflags" not in encoding.environ.get(b"HGPLAIN", b"").split( + b"," + ): + exceptions.append(b"strictflags") if feature and exceptions: return feature not in exceptions return True @@ -906,34 +911,34 @@ ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname". If no username could be found, raise an Abort error. """ - user = encoding.environ.get("HGUSER") + user = encoding.environ.get(b"HGUSER") if user is None: - user = self.config("ui", "username") + user = self.config(b"ui", b"username") if user is not None: user = os.path.expandvars(user) if user is None: - user = encoding.environ.get("EMAIL") + user = encoding.environ.get(b"EMAIL") if user is None and acceptempty: return user - if user is None and self.configbool("ui", "askusername"): - user = self.prompt(_("enter a commit username:"), default=None) + if user is None and self.configbool(b"ui", b"askusername"): + user = self.prompt(_(b"enter a commit username:"), default=None) if user is None and not self.interactive(): try: - user = "%s@%s" % ( + user = b"%s@%s" % ( procutil.getuser(), encoding.strtolocal(socket.getfqdn()), ) - self.warn(_("no username found, using '%s' instead\n") % user) + self.warn(_(b"no username found, using '%s' instead\n") % user) except KeyError: pass if not user: raise error.Abort( - _("no username supplied"), - hint=_("use 'hg config --edit' " "to set your username"), + _(b"no username supplied"), + hint=_(b"use 'hg config --edit' " b"to set your username"), ) - if "\n" in user: + if b"\n" in user: raise error.Abort( - _("username %r contains a newline\n") % pycompat.bytestr(user) + _(b"username %r contains a newline\n") % pycompat.bytestr(user) ) return user @@ -1030,7 +1035,7 @@ else: self._bufferapplylabels = None - return "".join(self._buffers.pop()) + return b"".join(self._buffers.pop()) def _isbuffered(self, dest): if dest is self._fout: @@ -1048,7 +1053,7 @@ def canbatchlabeledwrites(self): """check if write calls with labels are batchable""" # Windows color printing is special, see ``write``. - return self._colormode != "win32" + return self._colormode != b"win32" def write(self, *args, **opts): """write args to output @@ -1070,7 +1075,7 @@ # inlined _write() for speed if self._buffers: - label = opts.get(r"label", "") + label = opts.get(r"label", b"") if label and self._bufferapplylabels: self._buffers[-1].extend(self.label(a, label) for a in args) else: @@ -1084,19 +1089,19 @@ # opencode timeblockedsection because this is a critical path starttime = util.timer() try: - if self._colormode == "win32": + if self._colormode == b"win32": # windows color printing is its own can of crab, defer to # the color module and that is it. color.win32print(self, dest.write, msg, **opts) else: if self._colormode is not None: - label = opts.get(r"label", "") + label = opts.get(r"label", b"") msg = self.label(msg, label) dest.write(msg) except IOError as err: raise error.StdioError(err) finally: - self._blockedtimes["stdio_blocked"] += ( + self._blockedtimes[b"stdio_blocked"] += ( util.timer() - starttime ) * 1000 @@ -1106,7 +1111,7 @@ def _write(self, dest, *args, **opts): # update write() as well if you touch this code if self._isbuffered(dest): - label = opts.get(r"label", "") + label = opts.get(r"label", b"") if label and self._bufferapplylabels: self._buffers[-1].extend(self.label(a, label) for a in args) else: @@ -1128,13 +1133,13 @@ # channel for machine-readable output with metadata, where # no extra colorization is necessary. dest.write(msg, **opts) - elif self._colormode == "win32": + elif self._colormode == b"win32": # windows color printing is its own can of crab, defer to # the color module and that is it. color.win32print(self, dest.write, msg, **opts) else: if self._colormode is not None: - label = opts.get(r"label", "") + label = opts.get(r"label", b"") msg = self.label(msg, label) dest.write(msg) # stderr may be buffered under win32 when redirected to files, @@ -1151,7 +1156,7 @@ return raise error.StdioError(err) finally: - self._blockedtimes["stdio_blocked"] += ( + self._blockedtimes[b"stdio_blocked"] += ( util.timer() - starttime ) * 1000 @@ -1177,12 +1182,12 @@ if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): raise error.StdioError(err) finally: - self._blockedtimes["stdio_blocked"] += ( + self._blockedtimes[b"stdio_blocked"] += ( util.timer() - starttime ) * 1000 def _isatty(self, fh): - if self.configbool("ui", "nontty"): + if self.configbool(b"ui", b"nontty"): return False return procutil.isatty(fh) @@ -1239,27 +1244,27 @@ # how pager should do is already determined return - if not command.startswith("internal-always-") and ( + if not command.startswith(b"internal-always-") and ( # explicit --pager=on (= 'internal-always-' prefix) should # take precedence over disabling factors below - command in self.configlist("pager", "ignore") - or not self.configbool("ui", "paginate") - or not self.configbool("pager", "attend-" + command, True) - or encoding.environ.get("TERM") == "dumb" + command in self.configlist(b"pager", b"ignore") + or not self.configbool(b"ui", b"paginate") + or not self.configbool(b"pager", b"attend-" + command, True) + or encoding.environ.get(b"TERM") == b"dumb" # TODO: if we want to allow HGPLAINEXCEPT=pager, # formatted() will need some adjustment. or not self.formatted() or self.plain() or self._buffers # TODO: expose debugger-enabled on the UI object - or "--debugger" in pycompat.sysargv + or b"--debugger" in pycompat.sysargv ): # We only want to paginate if the ui appears to be # interactive, the user didn't say HGPLAIN or # HGPLAINEXCEPT=pager, and the user didn't specify --debug. return - pagercmd = self.config("pager", "pager", rcutil.fallbackpager) + pagercmd = self.config(b"pager", b"pager", rcutil.fallbackpager) if not pagercmd: return @@ -1269,25 +1274,25 @@ pagerenv[name] = value self.debug( - "starting pager for command %s\n" % stringutil.pprint(command) + b"starting pager for command %s\n" % stringutil.pprint(command) ) self.flush() wasformatted = self.formatted() - if util.safehasattr(signal, "SIGPIPE"): + if util.safehasattr(signal, b"SIGPIPE"): signal.signal(signal.SIGPIPE, _catchterm) if self._runpager(pagercmd, pagerenv): self.pageractive = True # Preserve the formatted-ness of the UI. This is important # because we mess with stdout, which might confuse # auto-detection of things being formatted. - self.setconfig("ui", "formatted", wasformatted, "pager") - self.setconfig("ui", "interactive", False, "pager") + self.setconfig(b"ui", b"formatted", wasformatted, b"pager") + self.setconfig(b"ui", b"interactive", False, b"pager") # If pagermode differs from color.mode, reconfigure color now that # pageractive is set. cm = self._colormode - if cm != self.config("color", "pagermode", cm): + if cm != self.config(b"color", b"pagermode", cm): color.setup(self) else: # If the pager can't be spawned in dispatch when --pager=on is @@ -1301,14 +1306,14 @@ This is separate in part so that extensions (like chg) can override how a pager is invoked. """ - if command == "cat": + if command == b"cat": # Save ourselves some work. return False # If the command doesn't contain any of these characters, we # assume it's a binary and exec it directly. This means for # simple pager command configurations, we can degrade # gracefully and tell the user about their broken pager. - shell = any(c in command for c in "|&;<>()$`\\\"' \t\n*?[#~=%") + shell = any(c in command for c in b"|&;<>()$`\\\"' \t\n*?[#~=%") if pycompat.iswindows and not shell: # Window's built-in `more` cannot be invoked with shell=False, but @@ -1319,7 +1324,7 @@ fullcmd = procutil.findexe(command) if not fullcmd: self.warn( - _("missing pager command '%s', skipping pager\n") % command + _(b"missing pager command '%s', skipping pager\n") % command ) return False @@ -1339,7 +1344,7 @@ except OSError as e: if e.errno == errno.ENOENT and not shell: self.warn( - _("missing pager command '%s', skipping pager\n") % command + _(b"missing pager command '%s', skipping pager\n") % command ) return False raise @@ -1354,7 +1359,7 @@ @self.atexit def killpager(): - if util.safehasattr(signal, "SIGINT"): + if util.safehasattr(signal, b"SIGINT"): signal.signal(signal.SIGINT, signal.SIG_IGN) # restore original fds, closing pager.stdin copies in the process os.dup2(stdoutfd, procutil.stdout.fileno()) @@ -1397,51 +1402,51 @@ Then histedit will use the text interface and chunkselector will use the default curses interface (crecord at the moment). """ - alldefaults = frozenset(["text", "curses"]) + alldefaults = frozenset([b"text", b"curses"]) featureinterfaces = { - "chunkselector": ["text", "curses",], - "histedit": ["text", "curses",], + b"chunkselector": [b"text", b"curses",], + b"histedit": [b"text", b"curses",], } # Feature-specific interface if feature not in featureinterfaces.keys(): # Programming error, not user error - raise ValueError("Unknown feature requested %s" % feature) + raise ValueError(b"Unknown feature requested %s" % feature) availableinterfaces = frozenset(featureinterfaces[feature]) if alldefaults > availableinterfaces: # Programming error, not user error. We need a use case to # define the right thing to do here. raise ValueError( - "Feature %s does not handle all default interfaces" % feature + b"Feature %s does not handle all default interfaces" % feature ) - if self.plain() or encoding.environ.get("TERM") == "dumb": - return "text" + if self.plain() or encoding.environ.get(b"TERM") == b"dumb": + return b"text" # Default interface for all the features - defaultinterface = "text" - i = self.config("ui", "interface") + defaultinterface = b"text" + i = self.config(b"ui", b"interface") if i in alldefaults: defaultinterface = i choseninterface = defaultinterface - f = self.config("ui", "interface.%s" % feature) + f = self.config(b"ui", b"interface.%s" % feature) if f in availableinterfaces: choseninterface = f if i is not None and defaultinterface != i: if f is not None: - self.warn(_("invalid value for ui.interface: %s\n") % (i,)) + self.warn(_(b"invalid value for ui.interface: %s\n") % (i,)) else: self.warn( - _("invalid value for ui.interface: %s (using %s)\n") + _(b"invalid value for ui.interface: %s (using %s)\n") % (i, choseninterface) ) if f is not None and choseninterface != f: self.warn( - _("invalid value for ui.interface.%s: %s (using %s)\n") + _(b"invalid value for ui.interface.%s: %s (using %s)\n") % (feature, f, choseninterface) ) @@ -1461,7 +1466,7 @@ This function refers to input only; for output, see `ui.formatted()'. """ - i = self.configbool("ui", "interactive") + i = self.configbool(b"ui", b"interactive") if i is None: # some environments replace stdin without implementing isatty # usually those are non-interactive @@ -1472,9 +1477,9 @@ def termwidth(self): """how wide is the terminal in columns? """ - if "COLUMNS" in encoding.environ: + if b"COLUMNS" in encoding.environ: try: - return int(encoding.environ["COLUMNS"]) + return int(encoding.environ[b"COLUMNS"]) except ValueError: pass return scmutil.termsize(self)[0] @@ -1499,7 +1504,7 @@ if self.plain(): return False - i = self.configbool("ui", "formatted") + i = self.configbool(b"ui", b"formatted") if i is None: # some environments replace stdout without implementing isatty # usually those are non-interactive @@ -1507,7 +1512,7 @@ return i - def _readline(self, prompt=" ", promptopts=None): + def _readline(self, prompt=b" ", promptopts=None): # Replacing stdin/stdout temporarily is a hard problem on Python 3 # because they have to be text streams with *no buffering*. Instead, # we use rawinput() only if call_readline() will be invoked by @@ -1530,20 +1535,20 @@ except Exception: usereadline = False - if self._colormode == "win32" or not usereadline: + if self._colormode == b"win32" or not usereadline: if not promptopts: promptopts = {} self._writemsgnobuf( - self._fmsgout, prompt, type="prompt", **promptopts + self._fmsgout, prompt, type=b"prompt", **promptopts ) self.flush() - prompt = " " + prompt = b" " else: - prompt = self.label(prompt, "ui.prompt") + " " + prompt = self.label(prompt, b"ui.prompt") + b" " # prompt ' ' must exist; otherwise readline may delete entire line # - http://bugs.python.org/issue12833 - with self.timeblockedsection("stdio"): + with self.timeblockedsection(b"stdio"): if usereadline: line = encoding.strtolocal(pycompat.rawinput(prompt)) # When stdin is in binary mode on Windows, it can cause @@ -1560,7 +1565,7 @@ return line - def prompt(self, msg, default="y"): + def prompt(self, msg, default=b"y"): """Prompt user with msg, read response. If ui is not interactive, the default is returned. """ @@ -1569,17 +1574,17 @@ def _prompt(self, msg, **opts): default = opts[r"default"] if not self.interactive(): - self._writemsg(self._fmsgout, msg, " ", type="prompt", **opts) + self._writemsg(self._fmsgout, msg, b" ", type=b"prompt", **opts) self._writemsg( - self._fmsgout, default or "", "\n", type="promptecho" + self._fmsgout, default or b"", b"\n", type=b"promptecho" ) return default try: r = self._readline(prompt=msg, promptopts=opts) if not r: r = default - if self.configbool("ui", "promptecho"): - self._writemsg(self._fmsgout, r, "\n", type="promptecho") + if self.configbool(b"ui", b"promptecho"): + self._writemsg(self._fmsgout, r, b"\n", type=b"promptecho") return r except EOFError: raise error.ResponseExpected() @@ -1606,11 +1611,11 @@ # except an ampersand followed by a character. m = re.match(br"(?s)(.+?)\$\$([^\$]*&[^ \$].*)", prompt) msg = m.group(1) - choices = [p.strip(" ") for p in m.group(2).split("$$")] + choices = [p.strip(b" ") for p in m.group(2).split(b"$$")] def choicetuple(s): - ampidx = s.index("&") - return s[ampidx + 1 : ampidx + 2].lower(), s.replace("&", "", 1) + ampidx = s.index(b"&") + return s[ampidx + 1 : ampidx + 2].lower(), s.replace(b"&", b"", 1) return (msg, [choicetuple(s) for s in choices]) @@ -1632,7 +1637,7 @@ if r.lower() in resps: return resps.index(r.lower()) # TODO: shouldn't it be a warning? - self._writemsg(self._fmsgout, _("unrecognized response\n")) + self._writemsg(self._fmsgout, _(b"unrecognized response\n")) def getpass(self, prompt=None, default=None): if not self.interactive(): @@ -1640,18 +1645,18 @@ try: self._writemsg( self._fmsgerr, - prompt or _("password: "), - type="prompt", + prompt or _(b"password: "), + type=b"prompt", password=True, ) # disable getpass() only if explicitly specified. it's still valid # to interact with tty even if fin is not a tty. - with self.timeblockedsection("stdio"): - if self.configbool("ui", "nontty"): + with self.timeblockedsection(b"stdio"): + if self.configbool(b"ui", b"nontty"): l = self._fin.readline() if not l: raise EOFError - return l.rstrip("\n") + return l.rstrip(b"\n") else: return getpass.getpass(r"") except EOFError: @@ -1663,21 +1668,21 @@ This adds an output label of "ui.status". """ if not self.quiet: - self._writemsg(self._fmsgout, type="status", *msg, **opts) + self._writemsg(self._fmsgout, type=b"status", *msg, **opts) def warn(self, *msg, **opts): """write warning message to output (stderr) This adds an output label of "ui.warning". """ - self._writemsg(self._fmsgerr, type="warning", *msg, **opts) + self._writemsg(self._fmsgerr, type=b"warning", *msg, **opts) def error(self, *msg, **opts): """write error message to output (stderr) This adds an output label of "ui.error". """ - self._writemsg(self._fmsgerr, type="error", *msg, **opts) + self._writemsg(self._fmsgerr, type=b"error", *msg, **opts) def note(self, *msg, **opts): """write note to output (if ui.verbose is True) @@ -1685,7 +1690,7 @@ This adds an output label of "ui.note". """ if self.verbose: - self._writemsg(self._fmsgout, type="note", *msg, **opts) + self._writemsg(self._fmsgout, type=b"note", *msg, **opts) def debug(self, *msg, **opts): """write debug message to output (if ui.debugflag is True) @@ -1693,7 +1698,7 @@ This adds an output label of "ui.debug". """ if self.debugflag: - self._writemsg(self._fmsgout, type="debug", *msg, **opts) + self._writemsg(self._fmsgout, type=b"debug", *msg, **opts) self.log(b"debug", b"%s", b"".join(msg)) def edit( @@ -1708,60 +1713,62 @@ ): if action is None: self.develwarn( - "action is None but will soon be a required " - "parameter to ui.edit()" + b"action is None but will soon be a required " + b"parameter to ui.edit()" ) extra_defaults = { - "prefix": "editor", - "suffix": ".txt", + b"prefix": b"editor", + b"suffix": b".txt", } if extra is not None: - if extra.get("suffix") is not None: + if extra.get(b"suffix") is not None: self.develwarn( - "extra.suffix is not None but will soon be " - "ignored by ui.edit()" + b"extra.suffix is not None but will soon be " + b"ignored by ui.edit()" ) extra_defaults.update(extra) extra = extra_defaults - if action == "diff": - suffix = ".diff" + if action == b"diff": + suffix = b".diff" elif action: - suffix = ".%s.hg.txt" % action + suffix = b".%s.hg.txt" % action else: - suffix = extra["suffix"] + suffix = extra[b"suffix"] rdir = None - if self.configbool("experimental", "editortmpinhg"): + if self.configbool(b"experimental", b"editortmpinhg"): rdir = repopath (fd, name) = pycompat.mkstemp( - prefix="hg-" + extra["prefix"] + "-", suffix=suffix, dir=rdir + prefix=b"hg-" + extra[b"prefix"] + b"-", suffix=suffix, dir=rdir ) try: f = os.fdopen(fd, r"wb") f.write(util.tonativeeol(text)) f.close() - environ = {"HGUSER": user} - if "transplant_source" in extra: - environ.update({"HGREVISION": hex(extra["transplant_source"])}) - for label in ("intermediate-source", "source", "rebase_source"): + environ = {b"HGUSER": user} + if b"transplant_source" in extra: + environ.update( + {b"HGREVISION": hex(extra[b"transplant_source"])} + ) + for label in (b"intermediate-source", b"source", b"rebase_source"): if label in extra: - environ.update({"HGREVISION": extra[label]}) + environ.update({b"HGREVISION": extra[label]}) break if editform: - environ.update({"HGEDITFORM": editform}) + environ.update({b"HGEDITFORM": editform}) if pending: - environ.update({"HG_PENDING": pending}) + environ.update({b"HG_PENDING": pending}) editor = self.geteditor() self.system( - '%s "%s"' % (editor, name), + b'%s "%s"' % (editor, name), environ=environ, onerr=error.Abort, - errprefix=_("edit failed"), - blockedtag="editor", + errprefix=_(b"edit failed"), + blockedtag=b"editor", ) f = open(name, r"rb") @@ -1791,19 +1798,19 @@ # Long cmds tend to be because of an absolute path on cmd. Keep # the tail end instead cmdsuffix = cmd.translate(None, _keepalnum)[-85:] - blockedtag = "unknown_system_" + cmdsuffix + blockedtag = b"unknown_system_" + cmdsuffix out = self._fout if any(s[1] for s in self._bufferstates): out = self with self.timeblockedsection(blockedtag): rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out) if rc and onerr: - errmsg = "%s %s" % ( + errmsg = b"%s %s" % ( os.path.basename(cmd.split(None, 1)[0]), procutil.explainexit(rc), ) if errprefix: - errmsg = "%s: %s" % (errprefix, errmsg) + errmsg = b"%s: %s" % (errprefix, errmsg) raise onerr(errmsg) return rc @@ -1828,10 +1835,10 @@ # exclude frame where 'exc' was chained and rethrown from exctb self.write_err( - "Traceback (most recent call last):\n", - "".join(exctb[:-1]), - "".join(causetb), - "".join(exconly), + b"Traceback (most recent call last):\n", + b"".join(exctb[:-1]), + b"".join(causetb), + b"".join(exconly), ) else: output = traceback.format_exception(exc[0], exc[1], exc[2]) @@ -1840,15 +1847,15 @@ def geteditor(self): """return editor to use""" - if pycompat.sysplatform == "plan9": + if pycompat.sysplatform == b"plan9": # vi is the MIPS instruction simulator on Plan 9. We # instead default to E to plumb commit messages to # avoid confusion. - editor = "E" + editor = b"E" else: - editor = "vi" - return encoding.environ.get("HGEDITOR") or self.config( - "ui", "editor", editor + editor = b"vi" + return encoding.environ.get(b"HGEDITOR") or self.config( + b"ui", b"editor", editor ) @util.propertycache @@ -1857,7 +1864,7 @@ if ( self.quiet or self.debugflag - or self.configbool("progress", "disable") + or self.configbool(b"progress", b"disable") or not progress.shouldprint(self) ): return None @@ -1870,7 +1877,7 @@ if self._progbar is not None and self._progbar.printed: self._progbar.clear() - def progress(self, topic, pos, item="", unit="", total=None): + def progress(self, topic, pos, item=b"", unit=b"", total=None): """show a progress message By default a textual progress bar will be displayed if an operation @@ -1885,14 +1892,16 @@ All topics should be marked closed by setting pos to None at termination. """ - self.deprecwarn("use ui.makeprogress() instead of ui.progress()", "5.1") + self.deprecwarn( + b"use ui.makeprogress() instead of ui.progress()", b"5.1" + ) progress = self.makeprogress(topic, unit, total) if pos is not None: progress.update(pos, item=item) else: progress.complete() - def makeprogress(self, topic, unit="", total=None): + def makeprogress(self, topic, unit=b"", total=None): """Create a progress helper for the specified topic""" if getattr(self._fmsgerr, "structured", False): # channel for machine-readable output with metadata, just send @@ -1981,25 +1990,26 @@ Use 'stacklevel' to report the offender some layers further up in the stack. """ - if not self.configbool("devel", "all-warnings"): - if config is None or not self.configbool("devel", config): + if not self.configbool(b"devel", b"all-warnings"): + if config is None or not self.configbool(b"devel", config): return - msg = "devel-warn: " + msg + msg = b"devel-warn: " + msg stacklevel += 1 # get in develwarn if self.tracebackflag: util.debugstacktrace(msg, stacklevel, self._ferr, self._fout) self.log( - "develwarn", - "%s at:\n%s" % (msg, "".join(util.getstackframes(stacklevel))), + b"develwarn", + b"%s at:\n%s" + % (msg, b"".join(util.getstackframes(stacklevel))), ) else: curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe, 2) fname, lineno, fmsg = calframe[stacklevel][1:4] fname, fmsg = pycompat.sysbytes(fname), pycompat.sysbytes(fmsg) - self.write_err("%s at: %s:%d (%s)\n" % (msg, fname, lineno, fmsg)) + self.write_err(b"%s at: %s:%d (%s)\n" % (msg, fname, lineno, fmsg)) self.log( - "develwarn", "%s at: %s:%d (%s)\n", msg, fname, lineno, fmsg + b"develwarn", b"%s at: %s:%d (%s)\n", msg, fname, lineno, fmsg ) curframe = calframe = None # avoid cycles @@ -2010,15 +2020,15 @@ - version: last version where the API will be supported, """ if not ( - self.configbool("devel", "all-warnings") - or self.configbool("devel", "deprec-warn") + self.configbool(b"devel", b"all-warnings") + or self.configbool(b"devel", b"deprec-warn") ): return msg += ( - "\n(compatibility will be dropped after Mercurial-%s," - " update your code.)" + b"\n(compatibility will be dropped after Mercurial-%s," + b" update your code.)" ) % version - self.develwarn(msg, stacklevel=stacklevel, config="deprec-warn") + self.develwarn(msg, stacklevel=stacklevel, config=b"deprec-warn") def exportableenviron(self): """The environment variables that are safe to export, e.g. through @@ -2027,7 +2037,7 @@ return self._exportableenviron @contextlib.contextmanager - def configoverride(self, overrides, source=""): + def configoverride(self, overrides, source=b""): """Context manager for temporary config overrides `overrides` must be a dict of the following structure: {(section, name) : value}""" @@ -2042,8 +2052,8 @@ self.restoreconfig(backup) # just restoring ui.quiet config to the previous value is not enough # as it does not update ui.quiet class member - if ("ui", "quiet") in overrides: - self.fixconfig(section="ui") + if (b"ui", b"quiet") in overrides: + self.fixconfig(section=b"ui") class paths(dict): @@ -2056,11 +2066,11 @@ def __init__(self, ui): dict.__init__(self) - for name, loc in ui.configitems("paths", ignoresub=True): + for name, loc in ui.configitems(b"paths", ignoresub=True): # No location is the same as not existing. if not loc: continue - loc, sub = ui.configsuboptions("paths", name) + loc, sub = ui.configsuboptions(b"paths", name) self[name] = path(ui, name, rawloc=loc, suboptions=sub) def getpath(self, name, default=None): @@ -2098,7 +2108,7 @@ # We don't pass sub-options in, so no need to pass ui instance. return path(None, None, rawloc=name) except ValueError: - raise error.RepoError(_("repository %s does not exist") % name) + raise error.RepoError(_(b"repository %s does not exist") % name) _pathsuboptions = {} @@ -2126,19 +2136,22 @@ return register -@pathsuboption("pushurl", "pushloc") +@pathsuboption(b"pushurl", b"pushloc") def pushurlpathoption(ui, path, value): u = util.url(value) # Actually require a URL. if not u.scheme: - ui.warn(_("(paths.%s:pushurl not a URL; ignoring)\n") % path.name) + ui.warn(_(b"(paths.%s:pushurl not a URL; ignoring)\n") % path.name) return None # Don't support the #foo syntax in the push URL to declare branch to # push. if u.fragment: ui.warn( - _('("#fragment" in paths.%s:pushurl not supported; ' "ignoring)\n") + _( + b'("#fragment" in paths.%s:pushurl not supported; ' + b"ignoring)\n" + ) % path.name ) u.fragment = None @@ -2146,7 +2159,7 @@ return bytes(u) -@pathsuboption("pushrev", "pushrev") +@pathsuboption(b"pushrev", b"pushrev") def pushrevpathoption(ui, path, value): return value @@ -2167,7 +2180,7 @@ ``ValueError`` is raised. """ if not rawloc: - raise ValueError("rawloc must be defined") + raise ValueError(b"rawloc must be defined") # Locations may define branches via syntax #. u = util.url(rawloc) @@ -2181,13 +2194,14 @@ self.name = name self.rawloc = rawloc - self.loc = "%s" % u + self.loc = b"%s" % u # When given a raw location but not a symbolic name, validate the # location is valid. if not name and not u.scheme and not self._isvalidlocalpath(self.loc): raise ValueError( - "location is not a URL or path to a local " "repo: %s" % rawloc + b"location is not a URL or path to a local " + b"repo: %s" % rawloc ) suboptions = suboptions or {} @@ -2209,7 +2223,7 @@ 'valid' in this case (like when pulling from a git repo into a hg one).""" try: - return os.path.isdir(os.path.join(path, ".hg")) + return os.path.isdir(os.path.join(path, b".hg")) # Python 2 may return TypeError. Python 3, ValueError. except (TypeError, ValueError): return False @@ -2270,5 +2284,5 @@ """ # TODO: maybe change 'type' to a mandatory option if r"type" in opts and not getattr(dest, "structured", False): - opts[r"label"] = opts.get(r"label", "") + " ui.%s" % opts.pop(r"type") + opts[r"label"] = opts.get(r"label", b"") + b" ui.%s" % opts.pop(r"type") write(dest, *args, **opts) diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -193,7 +193,7 @@ self.repo2 = repo2 self._url = url - self.ui.setconfig("phases", "publish", False, "unionrepo") + self.ui.setconfig(b"phases", b"publish", False, b"unionrepo") @localrepo.unfilteredpropertycache def changelog(self): @@ -236,25 +236,25 @@ def instance(ui, path, create, intents=None, createopts=None): if create: - raise error.Abort(_("cannot create new union repository")) - parentpath = ui.config("bundle", "mainreporoot") + raise error.Abort(_(b"cannot create new union repository")) + parentpath = ui.config(b"bundle", b"mainreporoot") if not parentpath: # try to find the correct path to the working directory repo parentpath = cmdutil.findrepo(encoding.getcwd()) if parentpath is None: - parentpath = "" + parentpath = b"" if parentpath: # Try to make the full path relative so we get a nice, short URL. # In particular, we don't want temp dir names in test outputs. cwd = encoding.getcwd() if parentpath == cwd: - parentpath = "" + parentpath = b"" else: cwd = pathutil.normasprefix(cwd) if parentpath.startswith(cwd): parentpath = parentpath[len(cwd) :] - if path.startswith("union:"): - s = path.split(":", 1)[1].split("+", 1) + if path.startswith(b"union:"): + s = path.split(b":", 1)[1].split(b"+", 1) if len(s) == 1: repopath, repopath2 = parentpath, s[0] else: @@ -270,7 +270,7 @@ repo1 = localrepo.instance(ui, repopath1, create=False) repo2 = localrepo.instance(ui, repopath2, create=False) - url = "union:%s+%s" % ( + url = b"union:%s+%s" % ( util.expandpath(repopath1), util.expandpath(repopath2), ) diff --git a/mercurial/upgrade.py b/mercurial/upgrade.py --- a/mercurial/upgrade.py +++ b/mercurial/upgrade.py @@ -28,7 +28,7 @@ # list of requirements that request a clone of all revlog if added/removed RECLONES_REQUIREMENTS = { - "generaldelta", + b"generaldelta", localrepo.SPARSEREVLOG_REQUIREMENT, } @@ -41,9 +41,9 @@ """ return { # Introduced in Mercurial 0.9.2. - "revlogv1", + b"revlogv1", # Introduced in Mercurial 0.9.2. - "store", + b"store", } @@ -56,12 +56,12 @@ return { # The upgrade code does not yet support these experimental features. # This is an artificial limitation. - "treemanifest", + b"treemanifest", # This was a precursor to generaldelta and was never enabled by default. # It should (hopefully) not exist in the wild. - "parentdelta", + b"parentdelta", # Upgrade should operate on the actual store, not the shared link. - "shared", + b"shared", } @@ -79,7 +79,7 @@ engine = compression.compengines[name] if engine.available() and engine.revlogheader(): supported.add(b"exp-compression-%s" % name) - if engine.name() == "zstd": + if engine.name() == b"zstd": supported.add(b"revlog-compression-zstd") return supported @@ -93,18 +93,18 @@ Extensions should monkeypatch this to add their custom requirements. """ supported = { - "dotencode", - "fncache", - "generaldelta", - "revlogv1", - "store", + b"dotencode", + b"fncache", + b"generaldelta", + b"revlogv1", + b"store", localrepo.SPARSEREVLOG_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] if engine.available() and engine.revlogheader(): supported.add(b"exp-compression-%s" % name) - if engine.name() == "zstd": + if engine.name() == b"zstd": supported.add(b"revlog-compression-zstd") return supported @@ -120,16 +120,16 @@ future, unknown requirements from accidentally being added. """ supported = { - "dotencode", - "fncache", - "generaldelta", + b"dotencode", + b"fncache", + b"generaldelta", localrepo.SPARSEREVLOG_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] if engine.available() and engine.revlogheader(): supported.add(b"exp-compression-%s" % name) - if engine.name() == "zstd": + if engine.name() == b"zstd": supported.add(b"revlog-compression-zstd") return supported @@ -138,8 +138,8 @@ return set() -deficiency = "deficiency" -optimisation = "optimization" +deficiency = b"deficiency" +optimisation = b"optimization" class improvement(object): @@ -259,129 +259,129 @@ @registerformatvariant class fncache(requirementformatvariant): - name = "fncache" + name = b"fncache" - _requirement = "fncache" + _requirement = b"fncache" default = True description = _( - "long and reserved filenames may not work correctly; " - "repository performance is sub-optimal" + b"long and reserved filenames may not work correctly; " + b"repository performance is sub-optimal" ) upgrademessage = _( - "repository will be more resilient to storing " - "certain paths and performance of certain " - "operations should be improved" + b"repository will be more resilient to storing " + b"certain paths and performance of certain " + b"operations should be improved" ) @registerformatvariant class dotencode(requirementformatvariant): - name = "dotencode" + name = b"dotencode" - _requirement = "dotencode" + _requirement = b"dotencode" default = True description = _( - "storage of filenames beginning with a period or " - "space may not work correctly" + b"storage of filenames beginning with a period or " + b"space may not work correctly" ) upgrademessage = _( - "repository will be better able to store files " - "beginning with a space or period" + b"repository will be better able to store files " + b"beginning with a space or period" ) @registerformatvariant class generaldelta(requirementformatvariant): - name = "generaldelta" + name = b"generaldelta" - _requirement = "generaldelta" + _requirement = b"generaldelta" default = True description = _( - "deltas within internal storage are unable to " - "choose optimal revisions; repository is larger and " - "slower than it could be; interaction with other " - "repositories may require extra network and CPU " - 'resources, making "hg push" and "hg pull" slower' + b"deltas within internal storage are unable to " + b"choose optimal revisions; repository is larger and " + b"slower than it could be; interaction with other " + b"repositories may require extra network and CPU " + b'resources, making "hg push" and "hg pull" slower' ) upgrademessage = _( - "repository storage will be able to create " - "optimal deltas; new repository data will be " - "smaller and read times should decrease; " - "interacting with other repositories using this " - "storage model should require less network and " - 'CPU resources, making "hg push" and "hg pull" ' - "faster" + b"repository storage will be able to create " + b"optimal deltas; new repository data will be " + b"smaller and read times should decrease; " + b"interacting with other repositories using this " + b"storage model should require less network and " + b'CPU resources, making "hg push" and "hg pull" ' + b"faster" ) @registerformatvariant class sparserevlog(requirementformatvariant): - name = "sparserevlog" + name = b"sparserevlog" _requirement = localrepo.SPARSEREVLOG_REQUIREMENT default = True description = _( - "in order to limit disk reading and memory usage on older " - "version, the span of a delta chain from its root to its " - "end is limited, whatever the relevant data in this span. " - "This can severly limit Mercurial ability to build good " - "chain of delta resulting is much more storage space being " - "taken and limit reusability of on disk delta during " - "exchange." + b"in order to limit disk reading and memory usage on older " + b"version, the span of a delta chain from its root to its " + b"end is limited, whatever the relevant data in this span. " + b"This can severly limit Mercurial ability to build good " + b"chain of delta resulting is much more storage space being " + b"taken and limit reusability of on disk delta during " + b"exchange." ) upgrademessage = _( - "Revlog supports delta chain with more unused data " - "between payload. These gaps will be skipped at read " - "time. This allows for better delta chains, making a " - "better compression and faster exchange with server." + b"Revlog supports delta chain with more unused data " + b"between payload. These gaps will be skipped at read " + b"time. This allows for better delta chains, making a " + b"better compression and faster exchange with server." ) @registerformatvariant class sidedata(requirementformatvariant): - name = "sidedata" + name = b"sidedata" _requirement = localrepo.SIDEDATA_REQUIREMENT default = False description = _( - "Allows storage of extra data alongside a revision, " - "unlocking various caching options." + b"Allows storage of extra data alongside a revision, " + b"unlocking various caching options." ) - upgrademessage = _("Allows storage of extra data alongside a revision.") + upgrademessage = _(b"Allows storage of extra data alongside a revision.") @registerformatvariant class removecldeltachain(formatvariant): - name = "plain-cl-delta" + name = b"plain-cl-delta" default = True description = _( - "changelog storage is using deltas instead of " - "raw entries; changelog reading and any " - "operation relying on changelog data are slower " - "than they could be" + b"changelog storage is using deltas instead of " + b"raw entries; changelog reading and any " + b"operation relying on changelog data are slower " + b"than they could be" ) upgrademessage = _( - "changelog storage will be reformated to " - "store raw entries; changelog reading will be " - "faster; changelog size may be reduced" + b"changelog storage will be reformated to " + b"store raw entries; changelog reading will be " + b"faster; changelog size may be reduced" ) @staticmethod @@ -399,16 +399,16 @@ @registerformatvariant class compressionengine(formatvariant): - name = "compression" - default = "zlib" + name = b"compression" + default = b"zlib" description = _( - "Compresion algorithm used to compress data. " - "Some engine are faster than other" + b"Compresion algorithm used to compress data. " + b"Some engine are faster than other" ) upgrademessage = _( - "revlog content will be recompressed with the new " "algorithm." + b"revlog content will be recompressed with the new " b"algorithm." ) @classmethod @@ -417,49 +417,49 @@ # strickly speaking, revlog seems to support mixed compression style. # # The compression used for new entries will be "the last one" - compression = "zlib" + compression = b"zlib" for req in repo.requirements: prefix = req.startswith - if prefix("revlog-compression-") or prefix("exp-compression-"): - compression = req.split("-", 2)[2] + if prefix(b"revlog-compression-") or prefix(b"exp-compression-"): + compression = req.split(b"-", 2)[2] return compression @classmethod def fromconfig(cls, repo): - return repo.ui.config("format", "revlog-compression") + return repo.ui.config(b"format", b"revlog-compression") @registerformatvariant class compressionlevel(formatvariant): - name = "compression-level" - default = "default" + name = b"compression-level" + default = b"default" - description = _("compression level") + description = _(b"compression level") - upgrademessage = _("revlog content will be recompressed") + upgrademessage = _(b"revlog content will be recompressed") @classmethod def fromrepo(cls, repo): comp = compressionengine.fromrepo(repo) level = None - if comp == "zlib": - level = repo.ui.configint("storage", "revlog.zlib.level") - elif comp == "zstd": - level = repo.ui.configint("storage", "revlog.zstd.level") + if comp == b"zlib": + level = repo.ui.configint(b"storage", b"revlog.zlib.level") + elif comp == b"zstd": + level = repo.ui.configint(b"storage", b"revlog.zstd.level") if level is None: - return "default" + return b"default" return bytes(level) @classmethod def fromconfig(cls, repo): comp = compressionengine.fromconfig(repo) level = None - if comp == "zlib": - level = repo.ui.configint("storage", "revlog.zlib.level") - elif comp == "zstd": - level = repo.ui.configint("storage", "revlog.zstd.level") + if comp == b"zlib": + level = repo.ui.configint(b"storage", b"revlog.zlib.level") + elif comp == b"zstd": + level = repo.ui.configint(b"storage", b"revlog.zstd.level") if level is None: - return "default" + return b"default" return bytes(level) @@ -485,10 +485,10 @@ # forms in script when comparing result is anoying enough to add # backward compatibility for a while. legacy_opts_map = { - "redeltaparent": "re-delta-parent", - "redeltamultibase": "re-delta-multibase", - "redeltaall": "re-delta-all", - "redeltafulladd": "re-delta-fulladd", + b"redeltaparent": b"re-delta-parent", + b"redeltamultibase": b"re-delta-multibase", + b"redeltaall": b"re-delta-all", + b"redeltafulladd": b"re-delta-fulladd", } @@ -500,82 +500,82 @@ optimizations.append( improvement( - name="re-delta-parent", + name=b"re-delta-parent", type=optimisation, description=_( - "deltas within internal storage will be recalculated to " - "choose an optimal base revision where this was not " - "already done; the size of the repository may shrink and " - "various operations may become faster; the first time " - "this optimization is performed could slow down upgrade " - "execution considerably; subsequent invocations should " - "not run noticeably slower" + b"deltas within internal storage will be recalculated to " + b"choose an optimal base revision where this was not " + b"already done; the size of the repository may shrink and " + b"various operations may become faster; the first time " + b"this optimization is performed could slow down upgrade " + b"execution considerably; subsequent invocations should " + b"not run noticeably slower" ), upgrademessage=_( - "deltas within internal storage will choose a new " - "base revision if needed" + b"deltas within internal storage will choose a new " + b"base revision if needed" ), ) ) optimizations.append( improvement( - name="re-delta-multibase", + name=b"re-delta-multibase", type=optimisation, description=_( - "deltas within internal storage will be recalculated " - "against multiple base revision and the smallest " - "difference will be used; the size of the repository may " - "shrink significantly when there are many merges; this " - "optimization will slow down execution in proportion to " - "the number of merges in the repository and the amount " - "of files in the repository; this slow down should not " - "be significant unless there are tens of thousands of " - "files and thousands of merges" + b"deltas within internal storage will be recalculated " + b"against multiple base revision and the smallest " + b"difference will be used; the size of the repository may " + b"shrink significantly when there are many merges; this " + b"optimization will slow down execution in proportion to " + b"the number of merges in the repository and the amount " + b"of files in the repository; this slow down should not " + b"be significant unless there are tens of thousands of " + b"files and thousands of merges" ), upgrademessage=_( - "deltas within internal storage will choose an " - "optimal delta by computing deltas against multiple " - "parents; may slow down execution time " - "significantly" + b"deltas within internal storage will choose an " + b"optimal delta by computing deltas against multiple " + b"parents; may slow down execution time " + b"significantly" ), ) ) optimizations.append( improvement( - name="re-delta-all", + name=b"re-delta-all", type=optimisation, description=_( - "deltas within internal storage will always be " - "recalculated without reusing prior deltas; this will " - "likely make execution run several times slower; this " - "optimization is typically not needed" + b"deltas within internal storage will always be " + b"recalculated without reusing prior deltas; this will " + b"likely make execution run several times slower; this " + b"optimization is typically not needed" ), upgrademessage=_( - "deltas within internal storage will be fully " - "recomputed; this will likely drastically slow down " - "execution time" + b"deltas within internal storage will be fully " + b"recomputed; this will likely drastically slow down " + b"execution time" ), ) ) optimizations.append( improvement( - name="re-delta-fulladd", + name=b"re-delta-fulladd", type=optimisation, description=_( - "every revision will be re-added as if it was new " - "content. It will go through the full storage " - "mechanism giving extensions a chance to process it " - '(eg. lfs). This is similar to "re-delta-all" but even ' - "slower since more logic is involved." + b"every revision will be re-added as if it was new " + b"content. It will go through the full storage " + b"mechanism giving extensions a chance to process it " + b'(eg. lfs). This is similar to "re-delta-all" but even ' + b"slower since more logic is involved." ), upgrademessage=_( - "each revision will be added as new content to the " - "internal storage; this will likely drastically slow " - "down execution time, but some extensions might need " - "it" + b"each revision will be added as new content to the " + b"internal storage; this will likely drastically slow " + b"down execution time, but some extensions might need " + b"it" ), ) ) @@ -621,10 +621,10 @@ An instance of the appropriate class is returned. """ - if path == "00changelog.i": + if path == b"00changelog.i": return changelog.changelog(repo.svfs) - elif path.endswith("00manifest.i"): - mandir = path[: -len("00manifest.i")] + elif path.endswith(b"00manifest.i"): + mandir = path[: -len(b"00manifest.i")] return manifest.manifestrevlog(repo.svfs, tree=mandir) else: # reverse of "/".join(("data", path + ".i")) @@ -649,7 +649,7 @@ olddata = oldvfs.join(oldrl.datafile) newdata = newvfs.join(newrl.datafile) - with newvfs(newrl.indexfile, "w"): + with newvfs(newrl.indexfile, b"w"): pass # create all the directories util.copyfile(oldindex, newindex) @@ -658,12 +658,12 @@ util.copyfile(olddata, newdata) if not ( - unencodedname.endswith("00changelog.i") - or unencodedname.endswith("00manifest.i") + unencodedname.endswith(b"00changelog.i") + or unencodedname.endswith(b"00manifest.i") ): destrepo.svfs.fncache.add(unencodedname) if copydata: - destrepo.svfs.fncache.add(unencodedname[:-2] + ".d") + destrepo.svfs.fncache.add(unencodedname[:-2] + b".d") UPGRADE_CHANGELOG = object() @@ -679,9 +679,9 @@ """check is a revlog is selected for cloning The store entry is checked against the passed filter""" - if entry.endswith("00changelog.i"): + if entry.endswith(b"00changelog.i"): return UPGRADE_CHANGELOG in revlogfilter - elif entry.endswith("00manifest.i"): + elif entry.endswith(b"00manifest.i"): return UPGRADE_MANIFEST in revlogfilter return UPGRADE_FILELOG in revlogfilter @@ -720,7 +720,7 @@ # Perform a pass to collect metadata. This validates we can open all # source files and allows a unified progress bar to be displayed. for unencoded, encoded, size in alldatafiles: - if unencoded.endswith(".d"): + if unencoded.endswith(b".d"): continue rl = _revlogfrompath(srcrepo, unencoded) @@ -732,9 +732,9 @@ storedsize=True, ) - revcount += info["revisionscount"] or 0 - datasize = info["storedsize"] or 0 - rawsize = info["trackedsize"] or 0 + revcount += info[b"revisionscount"] or 0 + datasize = info[b"storedsize"] or 0 + rawsize = info[b"trackedsize"] or 0 srcsize += datasize srcrawsize += rawsize @@ -755,20 +755,20 @@ fsrcsize += datasize frawsize += rawsize else: - error.ProgrammingError("unknown revlog type") + error.ProgrammingError(b"unknown revlog type") if not revcount: return ui.write( _( - "migrating %d total revisions (%d in filelogs, %d in manifests, " - "%d in changelog)\n" + b"migrating %d total revisions (%d in filelogs, %d in manifests, " + b"%d in changelog)\n" ) % (revcount, frevcount, mrevcount, crevcount) ) ui.write( - _("migrating %s in store; %s tracked data\n") + _(b"migrating %s in store; %s tracked data\n") % ((util.bytecount(srcsize), util.bytecount(srcrawsize))) ) @@ -782,24 +782,24 @@ # FUTURE this operation can be farmed off to worker processes. seen = set() for unencoded, encoded, size in alldatafiles: - if unencoded.endswith(".d"): + if unencoded.endswith(b".d"): continue oldrl = _revlogfrompath(srcrepo, unencoded) - if isinstance(oldrl, changelog.changelog) and "c" not in seen: + if isinstance(oldrl, changelog.changelog) and b"c" not in seen: ui.write( _( - "finished migrating %d manifest revisions across %d " - "manifests; change in size: %s\n" + b"finished migrating %d manifest revisions across %d " + b"manifests; change in size: %s\n" ) % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)) ) ui.write( _( - "migrating changelog containing %d revisions " - "(%s in store; %s tracked data)\n" + b"migrating changelog containing %d revisions " + b"(%s in store; %s tracked data)\n" ) % ( crevcount, @@ -807,23 +807,23 @@ util.bytecount(crawsize), ) ) - seen.add("c") + seen.add(b"c") progress = srcrepo.ui.makeprogress( - _("changelog revisions"), total=crevcount + _(b"changelog revisions"), total=crevcount ) - elif isinstance(oldrl, manifest.manifestrevlog) and "m" not in seen: + elif isinstance(oldrl, manifest.manifestrevlog) and b"m" not in seen: ui.write( _( - "finished migrating %d filelog revisions across %d " - "filelogs; change in size: %s\n" + b"finished migrating %d filelog revisions across %d " + b"filelogs; change in size: %s\n" ) % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)) ) ui.write( _( - "migrating %d manifests containing %d revisions " - "(%s in store; %s tracked data)\n" + b"migrating %d manifests containing %d revisions " + b"(%s in store; %s tracked data)\n" ) % ( mcount, @@ -832,17 +832,17 @@ util.bytecount(mrawsize), ) ) - seen.add("m") + seen.add(b"m") if progress: progress.complete() progress = srcrepo.ui.makeprogress( - _("manifest revisions"), total=mrevcount + _(b"manifest revisions"), total=mrevcount ) - elif "f" not in seen: + elif b"f" not in seen: ui.write( _( - "migrating %d filelogs containing %d revisions " - "(%s in store; %s tracked data)\n" + b"migrating %d filelogs containing %d revisions " + b"(%s in store; %s tracked data)\n" ) % ( fcount, @@ -851,16 +851,16 @@ util.bytecount(frawsize), ) ) - seen.add("f") + seen.add(b"f") if progress: progress.complete() progress = srcrepo.ui.makeprogress( - _("file revisions"), total=frevcount + _(b"file revisions"), total=frevcount ) if matchrevlog(revlogs, unencoded): ui.note( - _("cloning %d revisions from %s\n") % (len(oldrl), unencoded) + _(b"cloning %d revisions from %s\n") % (len(oldrl), unencoded) ) newrl = _revlogfrompath(dstrepo, unencoded) oldrl.clone( @@ -871,14 +871,14 @@ forcedeltabothparents=forcedeltabothparents, ) else: - msg = _("blindly copying %s containing %i revisions\n") + msg = _(b"blindly copying %s containing %i revisions\n") ui.note(msg % (unencoded, len(oldrl))) _copyrevlog(tr, dstrepo, oldrl, unencoded) newrl = _revlogfrompath(dstrepo, unencoded) info = newrl.storageinfo(storedsize=True) - datasize = info["storedsize"] or 0 + datasize = info[b"storedsize"] or 0 dstsize += datasize @@ -892,14 +892,17 @@ progress.complete() ui.write( - _("finished migrating %d changelog revisions; change in size: " "%s\n") + _( + b"finished migrating %d changelog revisions; change in size: " + b"%s\n" + ) % (crevcount, util.bytecount(cdstsize - csrcsize)) ) ui.write( _( - "finished migrating %d total revisions; total change in store " - "size: %s\n" + b"finished migrating %d total revisions; total change in store " + b"size: %s\n" ) % (revcount, util.bytecount(dstsize - srcsize)) ) @@ -922,16 +925,16 @@ Function should return ``True`` if the file is to be copied. """ # Skip revlogs. - if path.endswith((".i", ".d")): + if path.endswith((b".i", b".d")): return False # Skip transaction related files. - if path.startswith("undo"): + if path.startswith(b"undo"): return False # Only copy regular files. if mode != stat.S_IFREG: return False # Skip other skipped files. - if path in ("lock", "fncache"): + if path in (b"lock", b"fncache"): return False return True @@ -962,53 +965,53 @@ ui.write( _( - "(it is safe to interrupt this process any time before " - "data migration completes)\n" + b"(it is safe to interrupt this process any time before " + b"data migration completes)\n" ) ) - if "re-delta-all" in actions: + if b"re-delta-all" in actions: deltareuse = revlog.revlog.DELTAREUSENEVER - elif "re-delta-parent" in actions: + elif b"re-delta-parent" in actions: deltareuse = revlog.revlog.DELTAREUSESAMEREVS - elif "re-delta-multibase" in actions: + elif b"re-delta-multibase" in actions: deltareuse = revlog.revlog.DELTAREUSESAMEREVS - elif "re-delta-fulladd" in actions: + elif b"re-delta-fulladd" in actions: deltareuse = revlog.revlog.DELTAREUSEFULLADD else: deltareuse = revlog.revlog.DELTAREUSEALWAYS - with dstrepo.transaction("upgrade") as tr: + with dstrepo.transaction(b"upgrade") as tr: _clonerevlogs( ui, srcrepo, dstrepo, tr, deltareuse, - "re-delta-multibase" in actions, + b"re-delta-multibase" in actions, revlogs=revlogs, ) # Now copy other files in the store directory. # The sorted() makes execution deterministic. - for p, kind, st in sorted(srcrepo.store.vfs.readdir("", stat=True)): + for p, kind, st in sorted(srcrepo.store.vfs.readdir(b"", stat=True)): if not _filterstorefile(srcrepo, dstrepo, requirements, p, kind, st): continue - srcrepo.ui.write(_("copying %s\n") % p) + srcrepo.ui.write(_(b"copying %s\n") % p) src = srcrepo.store.rawvfs.join(p) dst = dstrepo.store.rawvfs.join(p) util.copyfile(src, dst, copystat=True) _finishdatamigration(ui, srcrepo, dstrepo, requirements) - ui.write(_("data fully migrated to temporary repository\n")) + ui.write(_(b"data fully migrated to temporary repository\n")) - backuppath = pycompat.mkdtemp(prefix="upgradebackup.", dir=srcrepo.path) + backuppath = pycompat.mkdtemp(prefix=b"upgradebackup.", dir=srcrepo.path) backupvfs = vfsmod.vfs(backuppath) # Make a backup of requires file first, as it is the first to be modified. - util.copyfile(srcrepo.vfs.join("requires"), backupvfs.join("requires")) + util.copyfile(srcrepo.vfs.join(b"requires"), backupvfs.join(b"requires")) # We install an arbitrary requirement that clients must not support # as a mechanism to lock out new clients during the data swap. This is @@ -1016,29 +1019,29 @@ # an inconsistent state. ui.write( _( - "marking source repository as being upgraded; clients will be " - "unable to read from repository\n" + b"marking source repository as being upgraded; clients will be " + b"unable to read from repository\n" ) ) scmutil.writerequires( - srcrepo.vfs, srcrepo.requirements | {"upgradeinprogress"} + srcrepo.vfs, srcrepo.requirements | {b"upgradeinprogress"} ) - ui.write(_("starting in-place swap of repository data\n")) - ui.write(_("replaced files will be backed up at %s\n") % backuppath) + ui.write(_(b"starting in-place swap of repository data\n")) + ui.write(_(b"replaced files will be backed up at %s\n") % backuppath) # Now swap in the new store directory. Doing it as a rename should make # the operation nearly instantaneous and atomic (at least in well-behaved # environments). - ui.write(_("replacing store...\n")) + ui.write(_(b"replacing store...\n")) tstart = util.timer() - util.rename(srcrepo.spath, backupvfs.join("store")) + util.rename(srcrepo.spath, backupvfs.join(b"store")) util.rename(dstrepo.spath, srcrepo.spath) elapsed = util.timer() - tstart ui.write( _( - "store replacement complete; repository was inconsistent for " - "%0.1fs\n" + b"store replacement complete; repository was inconsistent for " + b"%0.1fs\n" ) % elapsed ) @@ -1047,8 +1050,8 @@ # out legacy clients. ui.write( _( - "finalizing requirements file and making repository readable " - "again\n" + b"finalizing requirements file and making repository readable " + b"again\n" ) ) scmutil.writerequires(srcrepo.vfs, requirements) @@ -1057,7 +1060,7 @@ # reference to its new location. So clean it up manually. Alternatively, we # could update srcrepo.svfs and other variables to point to the new # location. This is simpler. - backupvfs.unlink("store/lock") + backupvfs.unlink(b"store/lock") return backuppath @@ -1078,7 +1081,7 @@ repo = repo.unfiltered() revlogs = set(UPGRADE_ALL_REVLOGS) - specentries = (("c", changelog), ("m", manifest)) + specentries = ((b"c", changelog), (b"m", manifest)) specified = [(y, x) for (y, x) in specentries if x is not None] if specified: # we have some limitation on revlogs to be recloned @@ -1086,34 +1089,34 @@ revlogs = set() for r, enabled in specified: if enabled: - if r == "c": + if r == b"c": revlogs.add(UPGRADE_CHANGELOG) - elif r == "m": + elif r == b"m": revlogs.add(UPGRADE_MANIFEST) else: # none are enabled for r, __ in specified: - if r == "c": + if r == b"c": revlogs.discard(UPGRADE_CHANGELOG) - elif r == "m": + elif r == b"m": revlogs.discard(UPGRADE_MANIFEST) # Ensure the repository can be upgraded. missingreqs = requiredsourcerequirements(repo) - repo.requirements if missingreqs: raise error.Abort( - _("cannot upgrade repository; requirement " "missing: %s") - % _(", ").join(sorted(missingreqs)) + _(b"cannot upgrade repository; requirement " b"missing: %s") + % _(b", ").join(sorted(missingreqs)) ) blockedreqs = blocksourcerequirements(repo) & repo.requirements if blockedreqs: raise error.Abort( _( - "cannot upgrade repository; unsupported source " - "requirement: %s" + b"cannot upgrade repository; unsupported source " + b"requirement: %s" ) - % _(", ").join(sorted(blockedreqs)) + % _(b", ").join(sorted(blockedreqs)) ) # FUTURE there is potentially a need to control the wanted requirements via @@ -1128,28 +1131,31 @@ ) if noremovereqs: raise error.Abort( - _("cannot upgrade repository; requirement would be " "removed: %s") - % _(", ").join(sorted(noremovereqs)) + _( + b"cannot upgrade repository; requirement would be " + b"removed: %s" + ) + % _(b", ").join(sorted(noremovereqs)) ) noaddreqs = newreqs - repo.requirements - allowednewrequirements(repo) if noaddreqs: raise error.Abort( _( - "cannot upgrade repository; do not support adding " - "requirement: %s" + b"cannot upgrade repository; do not support adding " + b"requirement: %s" ) - % _(", ").join(sorted(noaddreqs)) + % _(b", ").join(sorted(noaddreqs)) ) unsupportedreqs = newreqs - supporteddestrequirements(repo) if unsupportedreqs: raise error.Abort( _( - "cannot upgrade repository; do not support " - "destination requirement: %s" + b"cannot upgrade repository; do not support " + b"destination requirement: %s" ) - % _(", ").join(sorted(unsupportedreqs)) + % _(b", ").join(sorted(unsupportedreqs)) ) # Find and validate all improvements that can be made. @@ -1164,9 +1170,9 @@ if optimize: # anything left is unknown raise error.Abort( - _("unknown optimization action requested: %s") - % ", ".join(sorted(optimize)), - hint=_("run without arguments to see valid " "optimizations"), + _(b"unknown optimization action requested: %s") + % b", ".join(sorted(optimize)), + hint=_(b"run without arguments to see valid " b"optimizations"), ) deficiencies = finddeficiencies(repo) @@ -1185,36 +1191,36 @@ incompatible = RECLONES_REQUIREMENTS & (removedreqs | addedreqs) if incompatible: msg = _( - "ignoring revlogs selection flags, format requirements " - "change: %s\n" + b"ignoring revlogs selection flags, format requirements " + b"change: %s\n" ) - ui.warn(msg % ", ".join(sorted(incompatible))) + ui.warn(msg % b", ".join(sorted(incompatible))) revlogs = UPGRADE_ALL_REVLOGS def printrequirements(): - ui.write(_("requirements\n")) + ui.write(_(b"requirements\n")) ui.write( - _(" preserved: %s\n") - % _(", ").join(sorted(newreqs & repo.requirements)) + _(b" preserved: %s\n") + % _(b", ").join(sorted(newreqs & repo.requirements)) ) if repo.requirements - newreqs: ui.write( - _(" removed: %s\n") - % _(", ").join(sorted(repo.requirements - newreqs)) + _(b" removed: %s\n") + % _(b", ").join(sorted(repo.requirements - newreqs)) ) if newreqs - repo.requirements: ui.write( - _(" added: %s\n") - % _(", ").join(sorted(newreqs - repo.requirements)) + _(b" added: %s\n") + % _(b", ").join(sorted(newreqs - repo.requirements)) ) - ui.write("\n") + ui.write(b"\n") def printupgradeactions(): for a in actions: - ui.write("%s\n %s\n\n" % (a.name, a.upgrademessage)) + ui.write(b"%s\n %s\n\n" % (a.name, a.upgrademessage)) if not run: fromconfig = [] @@ -1231,33 +1237,36 @@ if fromconfig: ui.write( _( - "repository lacks features recommended by " - "current config options:\n\n" + b"repository lacks features recommended by " + b"current config options:\n\n" ) ) for i in fromconfig: - ui.write("%s\n %s\n\n" % (i.name, i.description)) + ui.write(b"%s\n %s\n\n" % (i.name, i.description)) if onlydefault: ui.write( _( - "repository lacks features used by the default " - "config options:\n\n" + b"repository lacks features used by the default " + b"config options:\n\n" ) ) for i in onlydefault: - ui.write("%s\n %s\n\n" % (i.name, i.description)) + ui.write(b"%s\n %s\n\n" % (i.name, i.description)) - ui.write("\n") + ui.write(b"\n") else: ui.write( - _("(no feature deficiencies found in existing " "repository)\n") + _( + b"(no feature deficiencies found in existing " + b"repository)\n" + ) ) ui.write( _( - 'performing an upgrade with "--run" will make the following ' - "changes:\n\n" + b'performing an upgrade with "--run" will make the following ' + b"changes:\n\n" ) ) @@ -1269,36 +1278,36 @@ if unusedoptimize: ui.write( _( - "additional optimizations are available by specifying " - '"--optimize ":\n\n' + b"additional optimizations are available by specifying " + b'"--optimize ":\n\n' ) ) for i in unusedoptimize: - ui.write(_("%s\n %s\n\n") % (i.name, i.description)) + ui.write(_(b"%s\n %s\n\n") % (i.name, i.description)) return # Else we're in the run=true case. - ui.write(_("upgrade will perform the following actions:\n\n")) + ui.write(_(b"upgrade will perform the following actions:\n\n")) printrequirements() printupgradeactions() upgradeactions = [a.name for a in actions] - ui.write(_("beginning upgrade...\n")) + ui.write(_(b"beginning upgrade...\n")) with repo.wlock(), repo.lock(): - ui.write(_("repository locked and read-only\n")) + ui.write(_(b"repository locked and read-only\n")) # Our strategy for upgrading the repository is to create a new, # temporary repository, write data to it, then do a swap of the # data. There are less heavyweight ways to do this, but it is easier # to create a new repo object than to instantiate all the components # (like the store) separately. - tmppath = pycompat.mkdtemp(prefix="upgrade.", dir=repo.path) + tmppath = pycompat.mkdtemp(prefix=b"upgrade.", dir=repo.path) backuppath = None try: ui.write( _( - "creating temporary repository to stage migrated " - "data: %s\n" + b"creating temporary repository to stage migrated " + b"data: %s\n" ) % tmppath ) @@ -1312,22 +1321,22 @@ ui, repo, dstrepo, newreqs, upgradeactions, revlogs=revlogs ) if not (backup or backuppath is None): - ui.write(_("removing old repository content%s\n") % backuppath) + ui.write(_(b"removing old repository content%s\n") % backuppath) repo.vfs.rmtree(backuppath, forcibly=True) backuppath = None finally: - ui.write(_("removing temporary repository %s\n") % tmppath) + ui.write(_(b"removing temporary repository %s\n") % tmppath) repo.vfs.rmtree(tmppath, forcibly=True) if backuppath: ui.warn( - _("copy of old repository backed up at %s\n") % backuppath + _(b"copy of old repository backed up at %s\n") % backuppath ) ui.warn( _( - "the old repository will not be deleted; remove " - "it to free up disk space once the upgraded " - "repository is verified\n" + b"the old repository will not be deleted; remove " + b"it to free up disk space once the upgraded " + b"repository is verified\n" ) ) diff --git a/mercurial/url.py b/mercurial/url.py --- a/mercurial/url.py +++ b/mercurial/url.py @@ -71,26 +71,26 @@ res = httpconnectionmod.readauthforuri(self.ui, authuri, user) if res: group, auth = res - user, passwd = auth.get("username"), auth.get("password") - self.ui.debug("using auth.%s.* for authentication\n" % group) + user, passwd = auth.get(b"username"), auth.get(b"password") + self.ui.debug(b"using auth.%s.* for authentication\n" % group) if not user or not passwd: u = util.url(pycompat.bytesurl(authuri)) u.query = None if not self.ui.interactive(): raise error.Abort( - _("http authorization required for %s") + _(b"http authorization required for %s") % util.hidepassword(bytes(u)) ) self.ui.write( - _("http authorization required for %s\n") + _(b"http authorization required for %s\n") % util.hidepassword(bytes(u)) ) - self.ui.write(_("realm: %s\n") % pycompat.bytesurl(realm)) + self.ui.write(_(b"realm: %s\n") % pycompat.bytesurl(realm)) if user: - self.ui.write(_("user: %s\n") % user) + self.ui.write(_(b"user: %s\n") % user) else: - user = self.ui.prompt(_("user:"), default=None) + user = self.ui.prompt(_(b"user:"), default=None) if not passwd: passwd = self.ui.getpass() @@ -100,8 +100,8 @@ return (pycompat.strurl(user), pycompat.strurl(passwd)) def _writedebug(self, user, passwd): - msg = _("http auth: user %s, password %s\n") - self.ui.debug(msg % (user, passwd and "*" * len(passwd) or "not set")) + msg = _(b"http auth: user %s, password %s\n") + self.ui.debug(msg % (user, passwd and b"*" * len(passwd) or b"not set")) def find_stored_password(self, authuri): return self.passwddb.find_user_password(None, authuri) @@ -109,36 +109,36 @@ class proxyhandler(urlreq.proxyhandler): def __init__(self, ui): - proxyurl = ui.config("http_proxy", "host") or encoding.environ.get( - "http_proxy" + proxyurl = ui.config(b"http_proxy", b"host") or encoding.environ.get( + b"http_proxy" ) # XXX proxyauthinfo = None if proxyurl: # proxy can be proper url or host[:port] if not ( - proxyurl.startswith("http:") or proxyurl.startswith("https:") + proxyurl.startswith(b"http:") or proxyurl.startswith(b"https:") ): - proxyurl = "http://" + proxyurl + "/" + proxyurl = b"http://" + proxyurl + b"/" proxy = util.url(proxyurl) if not proxy.user: - proxy.user = ui.config("http_proxy", "user") - proxy.passwd = ui.config("http_proxy", "passwd") + proxy.user = ui.config(b"http_proxy", b"user") + proxy.passwd = ui.config(b"http_proxy", b"passwd") # see if we should use a proxy for this url - no_list = ["localhost", "127.0.0.1"] + no_list = [b"localhost", b"127.0.0.1"] no_list.extend( - [p.lower() for p in ui.configlist("http_proxy", "no")] + [p.lower() for p in ui.configlist(b"http_proxy", b"no")] ) no_list.extend( [ p.strip().lower() - for p in encoding.environ.get("no_proxy", "").split(",") + for p in encoding.environ.get(b"no_proxy", b"").split(b",") if p.strip() ] ) # "http_proxy.always" config is for running tests on localhost - if ui.configbool("http_proxy", "always"): + if ui.configbool(b"http_proxy", b"always"): self.no_list = [] else: self.no_list = no_list @@ -147,7 +147,7 @@ # expects them to be. proxyurl = str(proxy) proxies = {r"http": proxyurl, r"https": proxyurl} - ui.debug("proxying through %s\n" % util.hidepassword(bytes(proxy))) + ui.debug(b"proxying through %s\n" % util.hidepassword(bytes(proxy))) else: proxies = {} @@ -155,13 +155,13 @@ self.ui = ui def proxy_open(self, req, proxy, type_): - host = pycompat.bytesurl(urllibcompat.gethost(req)).split(":")[0] + host = pycompat.bytesurl(urllibcompat.gethost(req)).split(b":")[0] for e in self.no_list: if host == e: return None - if e.startswith("*.") and host.endswith(e[2:]): + if e.startswith(b"*.") and host.endswith(e[2:]): return None - if e.startswith(".") and host.endswith(e[1:]): + if e.startswith(b".") and host.endswith(e[1:]): return None return urlreq.proxyhandler.proxy_open(self, req, proxy, type_) @@ -181,7 +181,7 @@ return _sendfile -has_https = util.safehasattr(urlreq, "httpshandler") +has_https = util.safehasattr(urlreq, b"httpshandler") class httpconnection(keepalive.HTTPConnection): @@ -212,8 +212,8 @@ if new_tunnel or tunnel_host == urllibcompat.getfullurl(req): # has proxy u = util.url(pycompat.bytesurl(tunnel_host)) - if new_tunnel or u.scheme == "https": # only use CONNECT for HTTPS - h.realhostport = ":".join([u.host, (u.port or "443")]) + if new_tunnel or u.scheme == b"https": # only use CONNECT for HTTPS + h.realhostport = b":".join([u.host, (u.port or b"443")]) h.headers = req.headers.copy() h.headers.update(handler.parent.addheaders) return @@ -230,10 +230,10 @@ if x.lower().startswith(r"proxy-") ] ) - self.send("CONNECT %s HTTP/1.0\r\n" % self.realhostport) + self.send(b"CONNECT %s HTTP/1.0\r\n" % self.realhostport) for header in proxyheaders.iteritems(): - self.send("%s: %s\r\n" % header) - self.send("\r\n") + self.send(b"%s: %s\r\n" % header) + self.send(b"\r\n") # majority of the following code is duplicated from # httplib.HTTPConnection as there are no adequate places to @@ -241,7 +241,7 @@ # strict was removed in Python 3.4. kwargs = {} if not pycompat.ispy3: - kwargs["strict"] = self.strict + kwargs[b"strict"] = self.strict res = self.response_class(self.sock, method=self._method, **kwargs) @@ -250,20 +250,20 @@ if status != httplib.CONTINUE: break # skip lines that are all whitespace - list(iter(lambda: res.fp.readline().strip(), "")) + list(iter(lambda: res.fp.readline().strip(), b"")) res.status = status res.reason = reason.strip() if res.status == 200: # skip lines until we find a blank line - list(iter(res.fp.readline, "\r\n")) + list(iter(res.fp.readline, b"\r\n")) return True - if version == "HTTP/1.0": + if version == b"HTTP/1.0": res.version = 10 - elif version.startswith("HTTP/1."): + elif version.startswith(b"HTTP/1."): res.version = 11 - elif version == "HTTP/0.9": + elif version == b"HTTP/0.9": res.version = 9 else: raise httplib.UnknownProtocol(version) @@ -279,8 +279,8 @@ res.msg.fp = None # are we using the chunked-style of transfer encoding? - trenc = res.msg.getheader("transfer-encoding") - if trenc and trenc.lower() == "chunked": + trenc = res.msg.getheader(b"transfer-encoding") + if trenc and trenc.lower() == b"chunked": res.chunked = 1 res.chunk_left = None else: @@ -292,7 +292,7 @@ # do we have a Content-Length? # NOTE: RFC 2616, section 4.4, #3 says we ignore this if # transfer-encoding is "chunked" - length = res.msg.getheader("content-length") + length = res.msg.getheader(b"content-length") if length and not res.chunked: try: res.length = int(length) @@ -309,7 +309,7 @@ status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or 100 <= status < 200 - or res._method == "HEAD" # 1xx codes + or res._method == b"HEAD" # 1xx codes ): res.length = 0 @@ -403,7 +403,7 @@ host = self.host if self.realhostport: # use CONNECT proxy _generic_proxytunnel(self) - host = self.realhostport.rsplit(":", 1)[0] + host = self.realhostport.rsplit(b":", 1)[0] self.sock = sslutil.wrapsocket( self.sock, self.key_file, @@ -433,7 +433,7 @@ if res: group, auth = res self.auth = auth - self.ui.debug("using auth.%s.* for authentication\n" % group) + self.ui.debug(b"using auth.%s.* for authentication\n" % group) else: self.auth = None return self.do_open(self._makeconnection, req) @@ -450,9 +450,9 @@ # if the user has specified different key/cert files in # hgrc, we prefer these - if self.auth and "key" in self.auth and "cert" in self.auth: - keyfile = self.auth["key"] - certfile = self.auth["cert"] + if self.auth and b"key" in self.auth and b"cert" in self.auth: + keyfile = self.auth[b"key"] + certfile = self.auth[b"cert"] conn = httpsconnection( host, port, keyfile, certfile, *args, **kwargs @@ -520,7 +520,7 @@ realm, urllibcompat.getfullurl(req) ) if pw is not None: - raw = "%s:%s" % (pycompat.bytesurl(user), pycompat.bytesurl(pw)) + raw = b"%s:%s" % (pycompat.bytesurl(user), pycompat.bytesurl(pw)) auth = r"Basic %s" % pycompat.strurl(base64.b64encode(raw).strip()) if req.get_header(self.auth_header, None) == auth: return None @@ -535,7 +535,7 @@ def __init__(self, ui): self.cookiejar = None - cookiefile = ui.config("auth", "cookiefile") + cookiefile = ui.config(b"auth", b"cookiefile") if not cookiefile: return @@ -549,8 +549,8 @@ except util.cookielib.LoadError as e: ui.warn( _( - "(error loading cookie file %s: %s; continuing without " - "cookies)\n" + b"(error loading cookie file %s: %s; continuing without " + b"cookies)\n" ) % (cookiefile, stringutil.forcebytestr(e)) ) @@ -595,7 +595,7 @@ ``sendaccept`` allows controlling whether the ``Accept`` request header is sent. The header is sent by default. """ - timeout = ui.configwith(float, "http", "timeout") + timeout = ui.configwith(float, b"http", b"timeout") handlers = [] if loggingfh: @@ -621,8 +621,8 @@ if user != saveduser or passwd: passmgr.add_password(realm, uris, user, passwd) ui.debug( - "http auth: user %s, password %s\n" - % (user, passwd and "*" * len(passwd) or "not set") + b"http auth: user %s, password %s\n" + % (user, passwd and b"*" * len(passwd) or b"not set") ) handlers.extend( @@ -653,7 +653,7 @@ # The custom user agent is for lfs, because unfortunately some servers # do look at this value. if not useragent: - agent = "mercurial/proto-1.0 (Mercurial %s)" % util.version() + agent = b"mercurial/proto-1.0 (Mercurial %s)" % util.version() opener.addheaders = [(r"User-agent", pycompat.sysstr(agent))] else: opener.addheaders = [(r"User-agent", pycompat.sysstr(useragent))] @@ -675,7 +675,7 @@ url_, authinfo = u.authinfo() else: path = util.normpath(os.path.abspath(url_)) - url_ = "file://" + pycompat.bytesurl(urlreq.pathname2url(path)) + url_ = b"file://" + pycompat.bytesurl(urlreq.pathname2url(path)) authinfo = None return opener(ui, authinfo, sendaccept=sendaccept).open( pycompat.strurl(url_), data @@ -700,27 +700,27 @@ got = len(e.partial) total = e.expected + got msg = _( - "HTTP request error (incomplete response; " - "expected %d bytes got %d)" + b"HTTP request error (incomplete response; " + b"expected %d bytes got %d)" ) % (total, got) else: - msg = _("HTTP request error (incomplete response)") + msg = _(b"HTTP request error (incomplete response)") raise error.PeerTransportError( msg, hint=_( - "this may be an intermittent network failure; " - "if the error persists, consider contacting the " - "network or server operator" + b"this may be an intermittent network failure; " + b"if the error persists, consider contacting the " + b"network or server operator" ), ) except httplib.HTTPException as e: raise error.PeerTransportError( - _("HTTP request error (%s)") % e, + _(b"HTTP request error (%s)") % e, hint=_( - "this may be an intermittent network failure; " - "if the error persists, consider contacting the " - "network or server operator" + b"this may be an intermittent network failure; " + b"if the error persists, consider contacting the " + b"network or server operator" ), ) diff --git a/mercurial/urllibcompat.py b/mercurial/urllibcompat.py --- a/mercurial/urllibcompat.py +++ b/mercurial/urllibcompat.py @@ -45,56 +45,56 @@ urlreq._registeraliases( urllib.parse, ( - "splitattr", - "splitpasswd", - "splitport", - "splituser", - "urlparse", - "urlunparse", + b"splitattr", + b"splitpasswd", + b"splitport", + b"splituser", + b"urlparse", + b"urlunparse", ), ) - urlreq._registeralias(urllib.parse, "parse_qs", "parseqs") - urlreq._registeralias(urllib.parse, "parse_qsl", "parseqsl") - urlreq._registeralias(urllib.parse, "unquote_to_bytes", "unquote") + urlreq._registeralias(urllib.parse, b"parse_qs", b"parseqs") + urlreq._registeralias(urllib.parse, b"parse_qsl", b"parseqsl") + urlreq._registeralias(urllib.parse, b"unquote_to_bytes", b"unquote") import urllib.request urlreq._registeraliases( urllib.request, ( - "AbstractHTTPHandler", - "BaseHandler", - "build_opener", - "FileHandler", - "FTPHandler", - "ftpwrapper", - "HTTPHandler", - "HTTPSHandler", - "install_opener", - "pathname2url", - "HTTPBasicAuthHandler", - "HTTPDigestAuthHandler", - "HTTPPasswordMgrWithDefaultRealm", - "ProxyHandler", - "Request", - "url2pathname", - "urlopen", + b"AbstractHTTPHandler", + b"BaseHandler", + b"build_opener", + b"FileHandler", + b"FTPHandler", + b"ftpwrapper", + b"HTTPHandler", + b"HTTPSHandler", + b"install_opener", + b"pathname2url", + b"HTTPBasicAuthHandler", + b"HTTPDigestAuthHandler", + b"HTTPPasswordMgrWithDefaultRealm", + b"ProxyHandler", + b"Request", + b"url2pathname", + b"urlopen", ), ) import urllib.response - urlreq._registeraliases(urllib.response, ("addclosehook", "addinfourl",)) + urlreq._registeraliases(urllib.response, (b"addclosehook", b"addinfourl",)) import urllib.error - urlerr._registeraliases(urllib.error, ("HTTPError", "URLError",)) + urlerr._registeraliases(urllib.error, (b"HTTPError", b"URLError",)) import http.server httpserver._registeraliases( http.server, ( - "HTTPServer", - "BaseHTTPRequestHandler", - "SimpleHTTPRequestHandler", - "CGIHTTPRequestHandler", + b"HTTPServer", + b"BaseHTTPRequestHandler", + b"SimpleHTTPRequestHandler", + b"CGIHTTPRequestHandler", ), ) @@ -145,48 +145,50 @@ urlreq._registeraliases( urllib, ( - "addclosehook", - "addinfourl", - "ftpwrapper", - "pathname2url", - "quote", - "splitattr", - "splitpasswd", - "splitport", - "splituser", - "unquote", - "url2pathname", - "urlencode", + b"addclosehook", + b"addinfourl", + b"ftpwrapper", + b"pathname2url", + b"quote", + b"splitattr", + b"splitpasswd", + b"splitport", + b"splituser", + b"unquote", + b"url2pathname", + b"urlencode", ), ) urlreq._registeraliases( urllib2, ( - "AbstractHTTPHandler", - "BaseHandler", - "build_opener", - "FileHandler", - "FTPHandler", - "HTTPBasicAuthHandler", - "HTTPDigestAuthHandler", - "HTTPHandler", - "HTTPPasswordMgrWithDefaultRealm", - "HTTPSHandler", - "install_opener", - "ProxyHandler", - "Request", - "urlopen", + b"AbstractHTTPHandler", + b"BaseHandler", + b"build_opener", + b"FileHandler", + b"FTPHandler", + b"HTTPBasicAuthHandler", + b"HTTPDigestAuthHandler", + b"HTTPHandler", + b"HTTPPasswordMgrWithDefaultRealm", + b"HTTPSHandler", + b"install_opener", + b"ProxyHandler", + b"Request", + b"urlopen", ), ) - urlreq._registeraliases(urlparse, ("urlparse", "urlunparse",)) - urlreq._registeralias(urlparse, "parse_qs", "parseqs") - urlreq._registeralias(urlparse, "parse_qsl", "parseqsl") - urlerr._registeraliases(urllib2, ("HTTPError", "URLError",)) + urlreq._registeraliases(urlparse, (b"urlparse", b"urlunparse",)) + urlreq._registeralias(urlparse, b"parse_qs", b"parseqs") + urlreq._registeralias(urlparse, b"parse_qsl", b"parseqsl") + urlerr._registeraliases(urllib2, (b"HTTPError", b"URLError",)) httpserver._registeraliases( - BaseHTTPServer, ("HTTPServer", "BaseHTTPRequestHandler",) + BaseHTTPServer, (b"HTTPServer", b"BaseHTTPRequestHandler",) ) - httpserver._registeraliases(SimpleHTTPServer, ("SimpleHTTPRequestHandler",)) - httpserver._registeraliases(CGIHTTPServer, ("CGIHTTPRequestHandler",)) + httpserver._registeraliases( + SimpleHTTPServer, (b"SimpleHTTPRequestHandler",) + ) + httpserver._registeraliases(CGIHTTPServer, (b"CGIHTTPRequestHandler",)) def gethost(req): return req.get_host() diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -151,7 +151,7 @@ # python 2.6 still have deprecation warning enabled by default. We do not want # to display anything to standard user so detect if we are running test and # only use python deprecation warning in this case. -_dowarn = bool(encoding.environ.get("HGEMITWARNINGS")) +_dowarn = bool(encoding.environ.get(b"HGEMITWARNINGS")) if _dowarn: # explicitly unfilter our warning for python 2.7 # @@ -186,19 +186,19 @@ """ if _dowarn: msg += ( - "\n(compatibility will be dropped after Mercurial-%s," - " update your code.)" + b"\n(compatibility will be dropped after Mercurial-%s," + b" update your code.)" ) % version warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1) DIGESTS = { - "md5": hashlib.md5, - "sha1": hashlib.sha1, - "sha512": hashlib.sha512, + b"md5": hashlib.md5, + b"sha1": hashlib.sha1, + b"sha512": hashlib.sha512, } # List of digest types from strongest to weakest -DIGESTS_BY_STRENGTH = ["sha512", "sha1", "md5"] +DIGESTS_BY_STRENGTH = [b"sha512", b"sha1", b"md5"] for k in DIGESTS_BY_STRENGTH: assert k in DIGESTS @@ -221,11 +221,11 @@ 'sha1' """ - def __init__(self, digests, s=""): + def __init__(self, digests, s=b""): self._hashes = {} for k in digests: if k not in DIGESTS: - raise error.Abort(_("unknown digest type: %s") % k) + raise error.Abort(_(b"unknown digest type: %s") % k) self._hashes[k] = DIGESTS[k]() if s: self.update(s) @@ -236,7 +236,7 @@ def __getitem__(self, key): if key not in DIGESTS: - raise error.Abort(_("unknown digest type: %s") % k) + raise error.Abort(_(b"unknown digest type: %s") % k) return nodemod.hex(self._hashes[key].digest()) def __iter__(self): @@ -277,14 +277,14 @@ def validate(self): if self._size != self._got: raise error.Abort( - _("size mismatch: expected %d, got %d") + _(b"size mismatch: expected %d, got %d") % (self._size, self._got) ) for k, v in self._digests.items(): if v != self._digester[k]: # i18n: first parameter is a digest name raise error.Abort( - _("%s mismatch: expected %s, got %s") + _(b"%s mismatch: expected %s, got %s") % (k, v, self._digester[k]) ) @@ -363,15 +363,15 @@ if len(self._buffer) > 1: # this should not happen because both read and readline end with a # _frombuffer call that collapse it. - self._buffer = ["".join(self._buffer)] + self._buffer = [b"".join(self._buffer)] self._lenbuf = len(self._buffer[0]) lfi = -1 if self._buffer: - lfi = self._buffer[-1].find("\n") + lfi = self._buffer[-1].find(b"\n") while (not self._eof) and lfi < 0: self._fillbuffer() if self._buffer: - lfi = self._buffer[-1].find("\n") + lfi = self._buffer[-1].find(b"\n") size = lfi + 1 if lfi < 0: # end of file size = self._lenbuf @@ -385,10 +385,10 @@ The data are removed from the buffer.""" if size == 0 or not self._buffer: - return "" + return b"" buf = self._buffer[0] if len(self._buffer) > 1: - buf = "".join(self._buffer) + buf = b"".join(self._buffer) data = buf[:size] buf = buf[len(data) :] @@ -420,7 +420,7 @@ # Empty files cannot be mmapped, but mmapread should still work. Check # if the file is empty, and if so, return an empty buffer. if os.fstat(fd).st_size == 0: - return "" + return b"" raise @@ -787,29 +787,29 @@ def _writedata(self, data): if not self.logdata: if self.logdataapis: - self.fh.write("\n") + self.fh.write(b"\n") self.fh.flush() return # Simple case writes all data on a single line. if b"\n" not in data: if self.logdataapis: - self.fh.write(": %s\n" % stringutil.escapestr(data)) + self.fh.write(b": %s\n" % stringutil.escapestr(data)) else: self.fh.write( - "%s> %s\n" % (self.name, stringutil.escapestr(data)) + b"%s> %s\n" % (self.name, stringutil.escapestr(data)) ) self.fh.flush() return # Data with newlines is written to multiple lines. if self.logdataapis: - self.fh.write(":\n") + self.fh.write(b":\n") lines = data.splitlines(True) for line in lines: self.fh.write( - "%s> %s\n" % (self.name, stringutil.escapestr(line)) + b"%s> %s\n" % (self.name, stringutil.escapestr(line)) ) self.fh.flush() @@ -832,9 +832,9 @@ return # Python 3 can return None from reads at EOF instead of empty strings. if res is None: - res = "" - - if size == -1 and res == "": + res = b"" + + if size == -1 and res == b"": # Suppress pointless read(-1) calls that return # nothing. These happen _a lot_ on Python 3, and there # doesn't seem to be a better workaround to have matching @@ -842,7 +842,7 @@ return if self.logdataapis: - self.fh.write("%s> read(%d) -> %d" % (self.name, size, len(res))) + self.fh.write(b"%s> read(%d) -> %d" % (self.name, size, len(res))) self._writedata(res) @@ -851,7 +851,7 @@ return if self.logdataapis: - self.fh.write("%s> readline() -> %d" % (self.name, len(res))) + self.fh.write(b"%s> readline() -> %d" % (self.name, len(res))) self._writedata(res) @@ -861,7 +861,7 @@ if self.logdataapis: self.fh.write( - "%s> readinto(%d) -> %r" % (self.name, len(dest), res) + b"%s> readinto(%d) -> %r" % (self.name, len(dest), res) ) data = dest[0:res] if res is not None else b"" @@ -883,7 +883,7 @@ res = len(data) if self.logdataapis: - self.fh.write("%s> write(%d) -> %r" % (self.name, len(data), res)) + self.fh.write(b"%s> write(%d) -> %r" % (self.name, len(data), res)) self._writedata(data) @@ -891,7 +891,7 @@ if not self.writes: return - self.fh.write("%s> flush() -> %r\n" % (self.name, res)) + self.fh.write(b"%s> flush() -> %r\n" % (self.name, res)) # For observedbufferedinputpipe. def bufferedread(self, res, size): @@ -900,7 +900,7 @@ if self.logdataapis: self.fh.write( - "%s> bufferedread(%d) -> %d" % (self.name, size, len(res)) + b"%s> bufferedread(%d) -> %d" % (self.name, size, len(res)) ) self._writedata(res) @@ -911,7 +911,7 @@ if self.logdataapis: self.fh.write( - "%s> bufferedreadline() -> %d" % (self.name, len(res)) + b"%s> bufferedreadline() -> %d" % (self.name, len(res)) ) self._writedata(res) @@ -958,7 +958,7 @@ if not self.states: return - self.fh.write("%s> makefile(%r, %r)\n" % (self.name, mode, bufsize)) + self.fh.write(b"%s> makefile(%r, %r)\n" % (self.name, mode, bufsize)) def recv(self, res, size, flags=0): if not self.reads: @@ -966,7 +966,7 @@ if self.logdataapis: self.fh.write( - "%s> recv(%d, %d) -> %d" % (self.name, size, flags, len(res)) + b"%s> recv(%d, %d) -> %d" % (self.name, size, flags, len(res)) ) self._writedata(res) @@ -976,7 +976,7 @@ if self.logdataapis: self.fh.write( - "%s> recvfrom(%d, %d) -> %d" + b"%s> recvfrom(%d, %d) -> %d" % (self.name, size, flags, len(res[0])) ) @@ -988,7 +988,7 @@ if self.logdataapis: self.fh.write( - "%s> recvfrom_into(%d, %d) -> %d" + b"%s> recvfrom_into(%d, %d) -> %d" % (self.name, size, flags, res[0]) ) @@ -1000,7 +1000,7 @@ if self.logdataapis: self.fh.write( - "%s> recv_into(%d, %d) -> %d" % (self.name, size, flags, res) + b"%s> recv_into(%d, %d) -> %d" % (self.name, size, flags, res) ) self._writedata(buf[0:res]) @@ -1010,7 +1010,7 @@ return self.fh.write( - "%s> send(%d, %d) -> %d" % (self.name, len(data), flags, len(res)) + b"%s> send(%d, %d) -> %d" % (self.name, len(data), flags, len(res)) ) self._writedata(data) @@ -1020,7 +1020,9 @@ if self.logdataapis: # Returns None on success. So don't bother reporting return value. - self.fh.write("%s> sendall(%d, %d)" % (self.name, len(data), flags)) + self.fh.write( + b"%s> sendall(%d, %d)" % (self.name, len(data), flags) + ) self._writedata(data) @@ -1035,7 +1037,7 @@ if self.logdataapis: self.fh.write( - "%s> sendto(%d, %d, %r) -> %d" + b"%s> sendto(%d, %d, %r) -> %d" % (self.name, len(data), flags, address, res) ) @@ -1045,26 +1047,26 @@ if not self.states: return - self.fh.write("%s> setblocking(%r)\n" % (self.name, flag)) + self.fh.write(b"%s> setblocking(%r)\n" % (self.name, flag)) def settimeout(self, res, value): if not self.states: return - self.fh.write("%s> settimeout(%r)\n" % (self.name, value)) + self.fh.write(b"%s> settimeout(%r)\n" % (self.name, value)) def gettimeout(self, res): if not self.states: return - self.fh.write("%s> gettimeout() -> %f\n" % (self.name, res)) + self.fh.write(b"%s> gettimeout() -> %f\n" % (self.name, res)) def setsockopt(self, res, level, optname, value): if not self.states: return self.fh.write( - "%s> setsockopt(%r, %r, %r) -> %r\n" + b"%s> setsockopt(%r, %r, %r) -> %r\n" % (self.name, level, optname, value, res) ) @@ -1100,7 +1102,7 @@ return __version__.version except ImportError: - return "unknown" + return b"unknown" def versiontuple(v=None, n=4): @@ -1162,14 +1164,14 @@ v = version() m = remod.match(br"(\d+(?:\.\d+){,2})[\+-]?(.*)", v) if not m: - vparts, extra = "", v + vparts, extra = b"", v elif m.group(2): vparts, extra = m.groups() else: vparts, extra = m.group(1), None vints = [] - for i in vparts.split("."): + for i in vparts.split(b"."): try: vints.append(int(i)) except ValueError: @@ -1744,11 +1746,11 @@ min = nmin if min > max: min = max - yield "".join(buf) + yield b"".join(buf) blen = 0 buf = [] if buf: - yield "".join(buf) + yield b"".join(buf) def always(fn): @@ -1806,19 +1808,19 @@ if os.path.isabs(n1): if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]: return os.path.join(root, localpath(n2)) - n2 = "/".join((pconvert(root), n2)) - a, b = splitpath(n1), n2.split("/") + n2 = b"/".join((pconvert(root), n2)) + a, b = splitpath(n1), n2.split(b"/") a.reverse() b.reverse() while a and b and a[-1] == b[-1]: a.pop() b.pop() b.reverse() - return pycompat.ossep.join(([".."] * len(a)) + b) or "." + return pycompat.ossep.join(([b".."] * len(a)) + b) or b"." # the location of data files matching the source code -if procutil.mainfrozen() and getattr(sys, "frozen", None) != "macosx_app": +if procutil.mainfrozen() and getattr(sys, "frozen", None) != b"macosx_app": # executable version (py2exe) doesn't support __file__ datapath = os.path.dirname(pycompat.sysexecutable) else: @@ -1843,19 +1845,19 @@ # a whilelist of known filesystems where hardlink works reliably _hardlinkfswhitelist = { - "apfs", - "btrfs", - "ext2", - "ext3", - "ext4", - "hfs", - "jfs", - "NTFS", - "reiserfs", - "tmpfs", - "ufs", - "xfs", - "zfs", + b"apfs", + b"btrfs", + b"ext2", + b"ext3", + b"ext4", + b"hfs", + b"jfs", + b"NTFS", + b"reiserfs", + b"tmpfs", + b"ufs", + b"xfs", + b"zfs", } @@ -1920,7 +1922,7 @@ def settopic(): if progress: - progress.topic = _("linking") if hardlink else _("copying") + progress.topic = _(b"linking") if hardlink else _(b"copying") if os.path.isdir(src): if hardlink is None: @@ -1958,30 +1960,30 @@ _winreservednames = { - "con", - "prn", - "aux", - "nul", - "com1", - "com2", - "com3", - "com4", - "com5", - "com6", - "com7", - "com8", - "com9", - "lpt1", - "lpt2", - "lpt3", - "lpt4", - "lpt5", - "lpt6", - "lpt7", - "lpt8", - "lpt9", + b"con", + b"prn", + b"aux", + b"nul", + b"com1", + b"com2", + b"com3", + b"com4", + b"com5", + b"com6", + b"com7", + b"com8", + b"com9", + b"lpt1", + b"lpt2", + b"lpt3", + b"lpt4", + b"lpt5", + b"lpt6", + b"lpt7", + b"lpt8", + b"lpt9", } -_winreservedchars = ':*?"<>|' +_winreservedchars = b':*?"<>|' def checkwinfilename(path): @@ -2008,33 +2010,39 @@ >>> checkwinfilename(b"foo\\/bar") "directory name ends with '\\', which is invalid on Windows" """ - if path.endswith("\\"): - return _("filename ends with '\\', which is invalid on Windows") - if "\\/" in path: - return _("directory name ends with '\\', which is invalid on Windows") - for n in path.replace("\\", "/").split("/"): + if path.endswith(b"\\"): + return _(b"filename ends with '\\', which is invalid on Windows") + if b"\\/" in path: + return _(b"directory name ends with '\\', which is invalid on Windows") + for n in path.replace(b"\\", b"/").split(b"/"): if not n: continue for c in _filenamebytestr(n): if c in _winreservedchars: return ( - _("filename contains '%s', which is reserved " "on Windows") + _( + b"filename contains '%s', which is reserved " + b"on Windows" + ) % c ) if ord(c) <= 31: return _( - "filename contains '%s', which is invalid " "on Windows" + b"filename contains '%s', which is invalid " b"on Windows" ) % stringutil.escapestr(c) - base = n.split(".")[0] + base = n.split(b".")[0] if base and base.lower() in _winreservednames: return ( - _("filename contains '%s', which is reserved " "on Windows") + _(b"filename contains '%s', which is reserved " b"on Windows") % base ) t = n[-1:] - if t in ". " and n not in "..": + if t in b". " and n not in b"..": return ( - _("filename ends with '%s', which is not allowed " "on Windows") + _( + b"filename ends with '%s', which is not allowed " + b"on Windows" + ) % t ) @@ -2078,7 +2086,7 @@ raise except AttributeError: # no symlink in os pass - with posixfile(pathname, "rb") as fp: + with posixfile(pathname, b"rb") as fp: return fp.read() @@ -2130,7 +2138,7 @@ global _re2 try: # check if match works, see issue3964 - _re2 = bool(re2.match(r"\[([^\[]+)\]", "[ui]")) + _re2 = bool(re2.match(r"\[([^\[]+)\]", b"[ui]")) except ImportError: _re2 = False @@ -2144,9 +2152,9 @@ self._checkre2() if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0: if flags & remod.IGNORECASE: - pat = "(?i)" + pat + pat = b"(?i)" + pat if flags & remod.MULTILINE: - pat = "(?m)" + pat + pat = b"(?m)" + pat try: return re2.compile(pat) except re2.error: @@ -2192,7 +2200,7 @@ if pycompat.osaltsep: seps = seps + pycompat.osaltsep # Protect backslashes. This gets silly very quickly. - seps.replace("\\", "\\\\") + seps.replace(b"\\", b"\\\\") pattern = remod.compile(br"([^%s]+)|([%s]+)" % (seps, seps)) dir = os.path.normpath(root) result = [] @@ -2215,7 +2223,7 @@ result.append(found or part) dir = os.path.join(dir, part) - return "".join(result) + return b"".join(result) def checknlink(testfile): @@ -2226,12 +2234,12 @@ f1, f2, fp = None, None, None try: fd, f1 = pycompat.mkstemp( - prefix=".%s-" % os.path.basename(testfile), - suffix="1~", + prefix=b".%s-" % os.path.basename(testfile), + suffix=b"1~", dir=os.path.dirname(testfile), ) os.close(fd) - f2 = "%s2~" % f1[:-2] + f2 = b"%s2~" % f1[:-2] oslink(f1, f2) # nlinks() may behave differently for files on Windows shares if @@ -2280,7 +2288,7 @@ Returns the name of the temporary file. """ d, fn = os.path.split(name) - fd, temp = pycompat.mkstemp(prefix=".%s-" % fn, suffix="~", dir=d) + fd, temp = pycompat.mkstemp(prefix=b".%s-" % fn, suffix=b"~", dir=d) os.close(fd) # Temporary files are created with mode 0600, which is usually not # what we want. If the original file already exists, just copy @@ -2291,14 +2299,14 @@ return temp try: try: - ifp = posixfile(name, "rb") + ifp = posixfile(name, b"rb") except IOError as inst: if inst.errno == errno.ENOENT: return temp if not getattr(inst, "filename", None): inst.filename = name raise - ofp = posixfile(temp, "wb") + ofp = posixfile(temp, b"wb") for chunk in filechunkiter(ifp): ofp.write(chunk) ifp.close() @@ -2432,13 +2440,13 @@ or repo.wlock). """ - def __init__(self, name, mode="w+b", createmode=None, checkambig=False): + def __init__(self, name, mode=b"w+b", createmode=None, checkambig=False): self.__name = name # permanent name self._tempname = mktempcopy( name, - emptyok=("w" in mode), + emptyok=(b"w" in mode), createmode=createmode, - enforcewritable=("w" in mode), + enforcewritable=(b"w" in mode), ) self._fp = posixfile(self._tempname, mode) @@ -2541,17 +2549,17 @@ def readfile(path): - with open(path, "rb") as fp: + with open(path, b"rb") as fp: return fp.read() def writefile(path, text): - with open(path, "wb") as fp: + with open(path, b"wb") as fp: fp.write(text) def appendfile(path, text): - with open(path, "ab") as fp: + with open(path, b"ab") as fp: fp.write(text) @@ -2583,7 +2591,7 @@ If size parameter is omitted, read everything""" if l is None: - return "".join(self.iter) + return b"".join(self.iter) left = l buf = [] @@ -2635,7 +2643,7 @@ self._chunkoffset += left left -= chunkremaining - return "".join(buf) + return b"".join(buf) def filechunkiter(f, size=131072, limit=None): @@ -2727,23 +2735,23 @@ ParseError: fromline must be strictly positive """ if toline - fromline < 0: - raise error.ParseError(_("line range must be positive")) + raise error.ParseError(_(b"line range must be positive")) if fromline < 1: - raise error.ParseError(_("fromline must be strictly positive")) + raise error.ParseError(_(b"fromline must be strictly positive")) return fromline - 1, toline bytecount = unitcountfn( - (100, 1 << 30, _("%.0f GB")), - (10, 1 << 30, _("%.1f GB")), - (1, 1 << 30, _("%.2f GB")), - (100, 1 << 20, _("%.0f MB")), - (10, 1 << 20, _("%.1f MB")), - (1, 1 << 20, _("%.2f MB")), - (100, 1 << 10, _("%.0f KB")), - (10, 1 << 10, _("%.1f KB")), - (1, 1 << 10, _("%.2f KB")), - (1, 1, _("%.0f bytes")), + (100, 1 << 30, _(b"%.0f GB")), + (10, 1 << 30, _(b"%.1f GB")), + (1, 1 << 30, _(b"%.2f GB")), + (100, 1 << 20, _(b"%.0f MB")), + (10, 1 << 20, _(b"%.1f MB")), + (1, 1 << 20, _(b"%.2f MB")), + (100, 1 << 10, _(b"%.0f KB")), + (10, 1 << 10, _(b"%.1f KB")), + (1, 1 << 10, _(b"%.2f KB")), + (1, 1, _(b"%.0f bytes")), ) @@ -2771,18 +2779,18 @@ def tolf(s): - return _eolre.sub("\n", s) + return _eolre.sub(b"\n", s) def tocrlf(s): - return _eolre.sub("\r\n", s) + return _eolre.sub(b"\r\n", s) def _crlfwriter(fp): return transformingwriter(fp, tocrlf) -if pycompat.oslinesep == "\r\n": +if pycompat.oslinesep == b"\r\n": tonativeeol = tocrlf fromnativeeol = tolf nativeeolwriter = _crlfwriter @@ -2791,7 +2799,7 @@ fromnativeeol = pycompat.identity nativeeolwriter = pycompat.identity -if pyplatform.python_implementation() == "CPython" and sys.version_info < ( +if pyplatform.python_implementation() == b"CPython" and sys.version_info < ( 3, 0, ): @@ -2822,14 +2830,14 @@ if sys.version_info >= (2, 7, 4): # fp.readline deals with EINTR correctly, use it as a workaround. def _safeiterfile(fp): - return iter(fp.readline, "") + return iter(fp.readline, b"") else: # fp.read* are broken too, manually deal with EINTR in a stupid way. # note: this may block longer than necessary because of bufsize. def _safeiterfile(fp, bufsize=4096): fd = fp.fileno() - line = "" + line = b"" while True: try: buf = os.read(fd, bufsize) @@ -2840,11 +2848,11 @@ else: raise line += buf - if "\n" in buf: + if b"\n" in buf: splitted = line.splitlines(True) - line = "" + line = b"" for l in splitted: - if l[-1] == "\n": + if l[-1] == b"\n": yield l else: line = l @@ -2893,9 +2901,9 @@ its escaping. """ fn = fn or (lambda s: s) - patterns = "|".join(mapping.keys()) + patterns = b"|".join(mapping.keys()) if escape_prefix: - patterns += "|" + prefix + patterns += b"|" + prefix if len(prefix) > 1: prefix_char = prefix[1:] else: @@ -2921,7 +2929,7 @@ return socket.getservbyname(pycompat.sysstr(port)) except socket.error: raise error.Abort( - _("no port number associated with service '%s'") % port + _(b"no port number associated with service '%s'") % port ) @@ -2999,38 +3007,38 @@ """ - _safechars = "!~*'()+" - _safepchars = "/!~*'()+:\\" - _matchscheme = remod.compile("^[a-zA-Z0-9+.\\-]+:").match + _safechars = b"!~*'()+" + _safepchars = b"/!~*'()+:\\" + _matchscheme = remod.compile(b"^[a-zA-Z0-9+.\\-]+:").match def __init__(self, path, parsequery=True, parsefragment=True): # We slowly chomp away at path until we have only the path left self.scheme = self.user = self.passwd = self.host = None self.port = self.path = self.query = self.fragment = None self._localpath = True - self._hostport = "" + self._hostport = b"" self._origpath = path - if parsefragment and "#" in path: - path, self.fragment = path.split("#", 1) + if parsefragment and b"#" in path: + path, self.fragment = path.split(b"#", 1) # special case for Windows drive letters and UNC paths - if hasdriveletter(path) or path.startswith("\\\\"): + if hasdriveletter(path) or path.startswith(b"\\\\"): self.path = path return # For compatibility reasons, we can't handle bundle paths as # normal URLS - if path.startswith("bundle:"): - self.scheme = "bundle" + if path.startswith(b"bundle:"): + self.scheme = b"bundle" path = path[7:] - if path.startswith("//"): + if path.startswith(b"//"): path = path[2:] self.path = path return if self._matchscheme(path): - parts = path.split(":", 1) + parts = path.split(b":", 1) if parts[0]: self.scheme, path = parts self._localpath = False @@ -3038,23 +3046,23 @@ if not path: path = None if self._localpath: - self.path = "" + self.path = b"" return else: if self._localpath: self.path = path return - if parsequery and "?" in path: - path, self.query = path.split("?", 1) + if parsequery and b"?" in path: + path, self.query = path.split(b"?", 1) if not path: path = None if not self.query: self.query = None # // is required to specify a host/authority - if path and path.startswith("//"): - parts = path[2:].split("/", 1) + if path and path.startswith(b"//"): + parts = path[2:].split(b"/", 1) if len(parts) > 1: self.host, path = parts else: @@ -3065,37 +3073,41 @@ # path of file:///d is /d # path of file:///d:/ is d:/, not /d:/ if path and not hasdriveletter(path): - path = "/" + path - - if self.host and "@" in self.host: - self.user, self.host = self.host.rsplit("@", 1) - if ":" in self.user: - self.user, self.passwd = self.user.split(":", 1) + path = b"/" + path + + if self.host and b"@" in self.host: + self.user, self.host = self.host.rsplit(b"@", 1) + if b":" in self.user: + self.user, self.passwd = self.user.split(b":", 1) if not self.host: self.host = None # Don't split on colons in IPv6 addresses without ports if ( self.host - and ":" in self.host - and not (self.host.startswith("[") and self.host.endswith("]")) + and b":" in self.host + and not ( + self.host.startswith(b"[") and self.host.endswith(b"]") + ) ): self._hostport = self.host - self.host, self.port = self.host.rsplit(":", 1) + self.host, self.port = self.host.rsplit(b":", 1) if not self.host: self.host = None if ( self.host - and self.scheme == "file" - and self.host not in ("localhost", "127.0.0.1", "[::1]") + and self.scheme == b"file" + and self.host not in (b"localhost", b"127.0.0.1", b"[::1]") ): - raise error.Abort(_("file:// URLs can only refer to localhost")) + raise error.Abort( + _(b"file:// URLs can only refer to localhost") + ) self.path = path # leave the query string escaped - for a in ("user", "passwd", "host", "port", "path", "fragment"): + for a in (b"user", b"passwd", b"host", b"port", b"path", b"fragment"): v = getattr(self, a) if v is not None: setattr(self, a, urlreq.unquote(v)) @@ -3104,19 +3116,19 @@ def __repr__(self): attrs = [] for a in ( - "scheme", - "user", - "passwd", - "host", - "port", - "path", - "query", - "fragment", + b"scheme", + b"user", + b"passwd", + b"host", + b"port", + b"path", + b"query", + b"fragment", ): v = getattr(self, a) if v is not None: - attrs.append("%s: %r" % (a, pycompat.bytestr(v))) - return "" % ", ".join(attrs) + attrs.append(b"%s: %r" % (a, pycompat.bytestr(v))) + return b"" % b", ".join(attrs) def __bytes__(self): r"""Join the URL's components back into a URL string. @@ -3154,38 +3166,38 @@ """ if self._localpath: s = self.path - if self.scheme == "bundle": - s = "bundle:" + s + if self.scheme == b"bundle": + s = b"bundle:" + s if self.fragment: - s += "#" + self.fragment + s += b"#" + self.fragment return s - s = self.scheme + ":" + s = self.scheme + b":" if self.user or self.passwd or self.host: - s += "//" + s += b"//" elif self.scheme and ( not self.path - or self.path.startswith("/") + or self.path.startswith(b"/") or hasdriveletter(self.path) ): - s += "//" + s += b"//" if hasdriveletter(self.path): - s += "/" + s += b"/" if self.user: s += urlreq.quote(self.user, safe=self._safechars) if self.passwd: - s += ":" + urlreq.quote(self.passwd, safe=self._safechars) + s += b":" + urlreq.quote(self.passwd, safe=self._safechars) if self.user or self.passwd: - s += "@" + s += b"@" if self.host: - if not (self.host.startswith("[") and self.host.endswith("]")): + if not (self.host.startswith(b"[") and self.host.endswith(b"]")): s += urlreq.quote(self.host) else: s += self.host if self.port: - s += ":" + urlreq.quote(self.port) + s += b":" + urlreq.quote(self.port) if self.host: - s += "/" + s += b"/" if self.path: # TODO: similar to the query string, we should not unescape the # path when we store it, the path might contain '%2f' = '/', @@ -3193,9 +3205,9 @@ s += urlreq.quote(self.path, safe=self._safepchars) if self.query: # we store the query in escaped form. - s += "?" + self.query + s += b"?" + self.query if self.fragment is not None: - s += "#" + urlreq.quote(self.fragment, safe=self._safepchars) + s += b"#" + urlreq.quote(self.fragment, safe=self._safepchars) return s __str__ = encoding.strmethod(__bytes__) @@ -3213,37 +3225,39 @@ # URIs must not contain credentials. The host is passed in the # URIs list because Python < 2.4.3 uses only that to search for # a password. - return (s, (None, (s, self.host), self.user, self.passwd or "")) + return (s, (None, (s, self.host), self.user, self.passwd or b"")) def isabs(self): - if self.scheme and self.scheme != "file": + if self.scheme and self.scheme != b"file": return True # remote URL if hasdriveletter(self.path): return True # absolute for our purposes - can't be joined() if self.path.startswith(br"\\"): return True # Windows UNC path - if self.path.startswith("/"): + if self.path.startswith(b"/"): return True # POSIX-style return False def localpath(self): - if self.scheme == "file" or self.scheme == "bundle": - path = self.path or "/" + if self.scheme == b"file" or self.scheme == b"bundle": + path = self.path or b"/" # For Windows, we need to promote hosts containing drive # letters to paths with drive letters. if hasdriveletter(self._hostport): - path = self._hostport + "/" + self.path + path = self._hostport + b"/" + self.path elif ( self.host is not None and self.path and not hasdriveletter(path) ): - path = "/" + path + path = b"/" + path return path return self._origpath def islocal(self): """whether localpath will return something that posixfile can open""" return ( - not self.scheme or self.scheme == "file" or self.scheme == "bundle" + not self.scheme + or self.scheme == b"file" + or self.scheme == b"bundle" ) @@ -3252,7 +3266,7 @@ def hasdriveletter(path): - return path and path[1:2] == ":" and path[0:1].isalpha() + return path and path[1:2] == b":" and path[0:1].isalpha() def urllocalpath(path): @@ -3270,9 +3284,9 @@ Raises an error.Abort when the url is unsafe. """ path = urlreq.unquote(path) - if path.startswith("ssh://-") or path.startswith("svn+ssh://-"): + if path.startswith(b"ssh://-") or path.startswith(b"svn+ssh://-"): raise error.Abort( - _("potentially unsafe url: %r") % (pycompat.bytestr(path),) + _(b"potentially unsafe url: %r") % (pycompat.bytestr(path),) ) @@ -3280,7 +3294,7 @@ """hide user credential in a url string""" u = url(u) if u.passwd: - u.passwd = "***" + u.passwd = b"***" return bytes(u) @@ -3292,19 +3306,19 @@ timecount = unitcountfn( - (1, 1e3, _("%.0f s")), - (100, 1, _("%.1f s")), - (10, 1, _("%.2f s")), - (1, 1, _("%.3f s")), - (100, 0.001, _("%.1f ms")), - (10, 0.001, _("%.2f ms")), - (1, 0.001, _("%.3f ms")), - (100, 0.000001, _("%.1f us")), - (10, 0.000001, _("%.2f us")), - (1, 0.000001, _("%.3f us")), - (100, 0.000000001, _("%.1f ns")), - (10, 0.000000001, _("%.2f ns")), - (1, 0.000000001, _("%.3f ns")), + (1, 1e3, _(b"%.0f s")), + (100, 1, _(b"%.1f s")), + (10, 1, _(b"%.2f s")), + (1, 1, _(b"%.3f s")), + (100, 0.001, _(b"%.1f ms")), + (10, 0.001, _(b"%.2f ms")), + (1, 0.001, _(b"%.3f ms")), + (100, 0.000001, _(b"%.1f us")), + (10, 0.000001, _(b"%.2f us")), + (1, 0.000001, _(b"%.3f us")), + (100, 0.000000001, _(b"%.1f ns")), + (10, 0.000000001, _(b"%.2f ns")), + (1, 0.000000001, _(b"%.3f ns")), ) @@ -3322,7 +3336,7 @@ level = attr.ib(default=1) def __bytes__(self): - return timecount(self.elapsed) if self.elapsed else "" + return timecount(self.elapsed) if self.elapsed else b"" __str__ = encoding.strmethod(__bytes__) @@ -3366,9 +3380,9 @@ result = func(*args, **kwargs) stderr = procutil.stderr stderr.write( - "%s%s: %s\n" + b"%s%s: %s\n" % ( - " " * time_stats.level * 2, + b" " * time_stats.level * 2, pycompat.bytestr(func.__name__), time_stats, ) @@ -3379,13 +3393,13 @@ _sizeunits = ( - ("m", 2 ** 20), - ("k", 2 ** 10), - ("g", 2 ** 30), - ("kb", 2 ** 10), - ("mb", 2 ** 20), - ("gb", 2 ** 30), - ("b", 1), + (b"m", 2 ** 20), + (b"k", 2 ** 10), + (b"g", 2 ** 30), + (b"kb", 2 ** 10), + (b"mb", 2 ** 20), + (b"gb", 2 ** 30), + (b"b", 1), ) @@ -3406,7 +3420,7 @@ return int(float(t[: -len(k)]) * u) return int(t) except ValueError: - raise error.ParseError(_("couldn't parse size: %s") % s) + raise error.ParseError(_(b"couldn't parse size: %s") % s) class hooks(object): @@ -3428,7 +3442,7 @@ return results -def getstackframes(skip=0, line=" %-*s in %s\n", fileline="%s:%d", depth=0): +def getstackframes(skip=0, line=b" %-*s in %s\n", fileline=b"%s:%d", depth=0): """Yields lines for a nicely formatted stacktrace. Skips the 'skip' last entries, then return the last 'depth' entries. Each file+linenumber is formatted according to fileline. @@ -3454,7 +3468,11 @@ def debugstacktrace( - msg="stacktrace", skip=0, f=procutil.stderr, otherf=procutil.stdout, depth=0 + msg=b"stacktrace", + skip=0, + f=procutil.stderr, + otherf=procutil.stdout, + depth=0, ): """Writes a message to f (stderr) with a nicely formatted stacktrace. Skips the 'skip' entries closest to the call, then show 'depth' entries. @@ -3464,7 +3482,7 @@ """ if otherf: otherf.flush() - f.write("%s at:\n" % msg.rstrip()) + f.write(b"%s at:\n" % msg.rstrip()) for line in getstackframes(skip + 1, depth=depth): f.write(line) f.flush() @@ -3482,7 +3500,7 @@ addpath(f) elif skip is not None: raise error.ProgrammingError( - "skip character is only supported " "with a dict source" + b"skip character is only supported " b"with a dict source" ) else: for f in map: @@ -3519,11 +3537,11 @@ def finddirs(path): - pos = path.rfind("/") + pos = path.rfind(b"/") while pos != -1: yield path[:pos] - pos = path.rfind("/", 0, pos) - yield "" + pos = path.rfind(b"/", 0, pos) + yield b"" # convenient shortcut @@ -3545,11 +3563,11 @@ if others is None: others = set() - fn = "%s~%s" % (f, tag) + fn = b"%s~%s" % (f, tag) if fn not in ctx and fn not in others: return fn for n in itertools.count(1): - fn = "%s~%s~%s" % (f, tag, n) + fn = b"%s~%s~%s" % (f, tag, n) if fn not in ctx and fn not in others: return fn @@ -3559,7 +3577,7 @@ s = stream.read(n) if len(s) < n: raise error.Abort( - _("stream ended unexpectedly" " (got %d bytes, expected %d)") + _(b"stream ended unexpectedly" b" (got %d bytes, expected %d)") % (len(s), n) ) return s @@ -3589,7 +3607,7 @@ ProgrammingError: negative value for uvarint: -1 """ if value < 0: - raise error.ProgrammingError("negative value for uvarint: %d" % value) + raise error.ProgrammingError(b"negative value for uvarint: %d" % value) bits = value & 0x7F value >>= 7 bytes = [] @@ -3599,7 +3617,7 @@ value >>= 7 bytes.append(pycompat.bytechr(bits)) - return "".join(bytes) + return b"".join(bytes) def uvarintdecodestream(fh): diff --git a/mercurial/utils/cborutil.py b/mercurial/utils/cborutil.py --- a/mercurial/utils/cborutil.py +++ b/mercurial/utils/cborutil.py @@ -125,7 +125,7 @@ def streamencodeint(v): if v >= 18446744073709551616 or v < -18446744073709551616: - raise ValueError("big integers not supported") + raise ValueError(b"big integers not supported") if v >= 0: yield encodelength(MAJOR_TYPE_UINT, v) @@ -241,7 +241,7 @@ break if not fn: - raise ValueError("do not know how to encode %s" % type(v)) + raise ValueError(b"do not know how to encode %s" % type(v)) return fn(v) @@ -263,9 +263,9 @@ STRUCT_BIG_UBYTE = struct.Struct(r">B") -STRUCT_BIG_USHORT = struct.Struct(">H") -STRUCT_BIG_ULONG = struct.Struct(">L") -STRUCT_BIG_ULONGLONG = struct.Struct(">Q") +STRUCT_BIG_USHORT = struct.Struct(b">H") +STRUCT_BIG_ULONG = struct.Struct(b">L") +STRUCT_BIG_ULONGLONG = struct.Struct(b">Q") SPECIAL_NONE = 0 SPECIAL_START_INDEFINITE_BYTESTRING = 1 @@ -355,7 +355,7 @@ return True, None, 1, SPECIAL_START_INDEFINITE_BYTESTRING elif majortype == MAJOR_TYPE_STRING: - raise CBORDecodeError("string major type not supported") + raise CBORDecodeError(b"string major type not supported") elif majortype == MAJOR_TYPE_ARRAY: # Beginning of arrays are treated as uints in order to decode their @@ -404,13 +404,13 @@ if special != SPECIAL_START_ARRAY: raise CBORDecodeError( - "expected array after finite set " "semantic tag" + b"expected array after finite set " b"semantic tag" ) return True, size, readcount + readcount2 + 1, SPECIAL_START_SET else: - raise CBORDecodeError("semantic tag %d not allowed" % tagvalue) + raise CBORDecodeError(b"semantic tag %d not allowed" % tagvalue) elif majortype == MAJOR_TYPE_SPECIAL: # Only specific values for the information field are allowed. @@ -424,7 +424,7 @@ return True, None, 1, SPECIAL_INDEFINITE_BREAK # If value is 24, subtype is in next byte. else: - raise CBORDecodeError("special type %d not allowed" % subtype) + raise CBORDecodeError(b"special type %d not allowed" % subtype) else: assert False @@ -457,10 +457,10 @@ if allowindefinite: return True, None, 0 else: - raise CBORDecodeError("indefinite length uint not allowed here") + raise CBORDecodeError(b"indefinite length uint not allowed here") elif subtype >= 28: raise CBORDecodeError( - "unsupported subtype on integer type: %d" % subtype + b"unsupported subtype on integer type: %d" % subtype ) if subtype == 24: @@ -472,7 +472,7 @@ elif subtype == 27: s = STRUCT_BIG_ULONGLONG else: - raise CBORDecodeError("bounds condition checking violation") + raise CBORDecodeError(b"bounds condition checking violation") if len(b) - offset >= s.size: return True, s.unpack_from(b, offset)[0], s.size @@ -641,19 +641,19 @@ elif special == SPECIAL_START_ARRAY: self._collectionstack.append( - {"remaining": value, "v": [],} + {b"remaining": value, b"v": [],} ) self._state = self._STATE_WANT_ARRAY_VALUE elif special == SPECIAL_START_MAP: self._collectionstack.append( - {"remaining": value, "v": {},} + {b"remaining": value, b"v": {},} ) self._state = self._STATE_WANT_MAP_KEY elif special == SPECIAL_START_SET: self._collectionstack.append( - {"remaining": value, "v": set(),} + {b"remaining": value, b"v": set(),} ) self._state = self._STATE_WANT_SET_VALUE @@ -662,7 +662,7 @@ else: raise CBORDecodeError( - "unhandled special state: %d" % special + b"unhandled special state: %d" % special ) # This value becomes an element of the current array. @@ -670,8 +670,8 @@ # Simple values get appended. if special == SPECIAL_NONE: c = self._collectionstack[-1] - c["v"].append(value) - c["remaining"] -= 1 + c[b"v"].append(value) + c[b"remaining"] -= 1 # self._state doesn't need changed. @@ -680,11 +680,11 @@ lastc = self._collectionstack[-1] newvalue = [] - lastc["v"].append(newvalue) - lastc["remaining"] -= 1 + lastc[b"v"].append(newvalue) + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue,} + {b"remaining": value, b"v": newvalue,} ) # self._state doesn't need changed. @@ -694,11 +694,11 @@ lastc = self._collectionstack[-1] newvalue = {} - lastc["v"].append(newvalue) - lastc["remaining"] -= 1 + lastc[b"v"].append(newvalue) + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue} + {b"remaining": value, b"v": newvalue} ) self._state = self._STATE_WANT_MAP_KEY @@ -707,25 +707,25 @@ lastc = self._collectionstack[-1] newvalue = set() - lastc["v"].append(newvalue) - lastc["remaining"] -= 1 + lastc[b"v"].append(newvalue) + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue,} + {b"remaining": value, b"v": newvalue,} ) self._state = self._STATE_WANT_SET_VALUE elif special == SPECIAL_START_INDEFINITE_BYTESTRING: raise CBORDecodeError( - "indefinite length bytestrings " - "not allowed as array values" + b"indefinite length bytestrings " + b"not allowed as array values" ) else: raise CBORDecodeError( - "unhandled special item when " - "expecting array value: %d" % special + b"unhandled special item when " + b"expecting array value: %d" % special ) # This value becomes the key of the current map instance. @@ -736,8 +736,8 @@ elif special == SPECIAL_START_INDEFINITE_BYTESTRING: raise CBORDecodeError( - "indefinite length bytestrings " - "not allowed as map keys" + b"indefinite length bytestrings " + b"not allowed as map keys" ) elif special in ( @@ -746,14 +746,14 @@ SPECIAL_START_SET, ): raise CBORDecodeError( - "collections not supported as map " "keys" + b"collections not supported as map " b"keys" ) # We do not allow special values to be used as map keys. else: raise CBORDecodeError( - "unhandled special item when " - "expecting map key: %d" % special + b"unhandled special item when " + b"expecting map key: %d" % special ) # This value becomes the value of the current map key. @@ -761,8 +761,8 @@ # Simple values simply get inserted into the map. if special == SPECIAL_NONE: lastc = self._collectionstack[-1] - lastc["v"][self._currentmapkey] = value - lastc["remaining"] -= 1 + lastc[b"v"][self._currentmapkey] = value + lastc[b"remaining"] -= 1 self._state = self._STATE_WANT_MAP_KEY @@ -771,11 +771,11 @@ lastc = self._collectionstack[-1] newvalue = [] - lastc["v"][self._currentmapkey] = newvalue - lastc["remaining"] -= 1 + lastc[b"v"][self._currentmapkey] = newvalue + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue,} + {b"remaining": value, b"v": newvalue,} ) self._state = self._STATE_WANT_ARRAY_VALUE @@ -785,11 +785,11 @@ lastc = self._collectionstack[-1] newvalue = {} - lastc["v"][self._currentmapkey] = newvalue - lastc["remaining"] -= 1 + lastc[b"v"][self._currentmapkey] = newvalue + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue,} + {b"remaining": value, b"v": newvalue,} ) self._state = self._STATE_WANT_MAP_KEY @@ -799,25 +799,25 @@ lastc = self._collectionstack[-1] newvalue = set() - lastc["v"][self._currentmapkey] = newvalue - lastc["remaining"] -= 1 + lastc[b"v"][self._currentmapkey] = newvalue + lastc[b"remaining"] -= 1 self._collectionstack.append( - {"remaining": value, "v": newvalue,} + {b"remaining": value, b"v": newvalue,} ) self._state = self._STATE_WANT_SET_VALUE elif special == SPECIAL_START_INDEFINITE_BYTESTRING: raise CBORDecodeError( - "indefinite length bytestrings not " - "allowed as map values" + b"indefinite length bytestrings not " + b"allowed as map values" ) else: raise CBORDecodeError( - "unhandled special item when " - "expecting map value: %d" % special + b"unhandled special item when " + b"expecting map value: %d" % special ) self._currentmapkey = None @@ -826,13 +826,13 @@ elif self._state == self._STATE_WANT_SET_VALUE: if special == SPECIAL_NONE: lastc = self._collectionstack[-1] - lastc["v"].add(value) - lastc["remaining"] -= 1 + lastc[b"v"].add(value) + lastc[b"remaining"] -= 1 elif special == SPECIAL_START_INDEFINITE_BYTESTRING: raise CBORDecodeError( - "indefinite length bytestrings not " - "allowed as set values" + b"indefinite length bytestrings not " + b"allowed as set values" ) elif special in ( @@ -841,14 +841,14 @@ SPECIAL_START_SET, ): raise CBORDecodeError( - "collections not allowed as set " "values" + b"collections not allowed as set " b"values" ) # We don't allow non-trivial types to exist as set values. else: raise CBORDecodeError( - "unhandled special item when " - "expecting set value: %d" % special + b"unhandled special item when " + b"expecting set value: %d" % special ) # This value represents the first chunk in an indefinite length @@ -879,8 +879,8 @@ else: raise CBORDecodeError( - "unexpected special value when " - "expecting bytestring chunk: %d" % special + b"unexpected special value when " + b"expecting bytestring chunk: %d" % special ) # This value represents the non-initial chunk in an indefinite @@ -901,13 +901,13 @@ else: raise CBORDecodeError( - "unexpected special value when " - "expecting bytestring chunk: %d" % special + b"unexpected special value when " + b"expecting bytestring chunk: %d" % special ) else: raise CBORDecodeError( - "unhandled decoder state: %d" % self._state + b"unhandled decoder state: %d" % self._state ) # We could have just added the final value in a collection. End @@ -924,7 +924,7 @@ # Or we are expecting more items for this collection. lastc = self._collectionstack[-1] - if lastc["remaining"]: + if lastc[b"remaining"]: break # The collection at the top of the stack is complete. @@ -941,11 +941,11 @@ list: self._STATE_WANT_ARRAY_VALUE, dict: self._STATE_WANT_MAP_KEY, set: self._STATE_WANT_SET_VALUE, - }[type(self._collectionstack[-1]["v"])] + }[type(self._collectionstack[-1][b"v"])] # If this is the root collection, emit it. else: - self._decodedvalues.append(lastc["v"]) + self._decodedvalues.append(lastc[b"v"]) self._state = self._STATE_NONE return ( @@ -1053,9 +1053,9 @@ havevalues, readcount, wantbytes = decoder.decode(b) if readcount != len(b): - raise CBORDecodeError("input data not fully consumed") + raise CBORDecodeError(b"input data not fully consumed") if decoder.inprogress: - raise CBORDecodeError("input data not complete") + raise CBORDecodeError(b"input data not complete") return decoder.getavailable() diff --git a/mercurial/utils/compression.py b/mercurial/utils/compression.py --- a/mercurial/utils/compression.py +++ b/mercurial/utils/compression.py @@ -24,8 +24,8 @@ # compression code -SERVERROLE = "server" -CLIENTROLE = "client" +SERVERROLE = b"server" +CLIENTROLE = b"client" compewireprotosupport = collections.namedtuple( r"compenginewireprotosupport", @@ -85,13 +85,13 @@ The argument must be a ``compressionengine`` instance. """ if not isinstance(engine, compressionengine): - raise ValueError(_("argument must be a compressionengine")) + raise ValueError(_(b"argument must be a compressionengine")) name = engine.name() if name in self._engines: raise error.Abort( - _("compression engine %s already registered") % name + _(b"compression engine %s already registered") % name ) bundleinfo = engine.bundletype() @@ -100,11 +100,11 @@ if bundlename in self._bundlenames: raise error.Abort( - _("bundle name %s already registered") % bundlename + _(b"bundle name %s already registered") % bundlename ) if bundletype in self._bundletypes: raise error.Abort( - _("bundle type %s already registered by %s") + _(b"bundle type %s already registered by %s") % (bundletype, self._bundletypes[bundletype]) ) @@ -120,8 +120,8 @@ if wiretype in self._wiretypes: raise error.Abort( _( - "wire protocol compression %s already " - "registered by %s" + b"wire protocol compression %s already " + b"registered by %s" ) % (wiretype, self._wiretypes[wiretype]) ) @@ -131,7 +131,7 @@ revlogheader = engine.revlogheader() if revlogheader and revlogheader in self._revlogheaders: raise error.Abort( - _("revlog header %s already registered by %s") + _(b"revlog header %s already registered by %s") % (revlogheader, self._revlogheaders[revlogheader]) ) @@ -158,7 +158,7 @@ engine = self._engines[self._bundlenames[bundlename]] if not engine.available(): raise error.Abort( - _("compression engine %s could not be loaded") % engine.name() + _(b"compression engine %s could not be loaded") % engine.name() ) return engine @@ -172,7 +172,7 @@ engine = self._engines[self._bundletypes[bundletype]] if not engine.available(): raise error.Abort( - _("compression engine %s could not be loaded") % engine.name() + _(b"compression engine %s could not be loaded") % engine.name() ) return engine @@ -186,7 +186,7 @@ """ assert role in (SERVERROLE, CLIENTROLE) - attr = "serverpriority" if role == SERVERROLE else "clientpriority" + attr = b"serverpriority" if role == SERVERROLE else b"clientpriority" engines = [self._engines[e] for e in self._wiretypes.values()] if onlyavailable: @@ -205,7 +205,7 @@ engine = self._engines[self._wiretypes[wiretype]] if not engine.available(): raise error.Abort( - _("compression engine %s could not be loaded") % engine.name() + _(b"compression engine %s could not be loaded") % engine.name() ) return engine @@ -360,7 +360,7 @@ newbuf = self._pending[0] buf.append(newbuf[self._pos : self._pos + l]) self._pos += l - return "".join(buf) + return b"".join(buf) newbuf = self._pending.pop(0) if self._pos: @@ -372,12 +372,12 @@ self._pos = 0 if self._eof: - return "".join(buf) + return b"".join(buf) chunk = self._reader(65536) self._decompress(chunk) if not chunk and not self._pending and not self._eof: # No progress and no new data, bail out - return "".join(buf) + return b"".join(buf) class _GzipCompressedStreamReader(_CompressedStreamReader): @@ -391,9 +391,9 @@ self._pending.append(newbuf) d = self._decompobj.copy() try: - d.decompress("x") + d.decompress(b"x") d.flush() - if d.unused_data == "x": + if d.unused_data == b"x": self._eof = True except zlib.error: pass @@ -410,7 +410,7 @@ self._pending.append(newbuf) try: while True: - newbuf = self._decompobj.decompress("") + newbuf = self._decompobj.decompress(b"") if newbuf: self._pending.append(newbuf) else: @@ -422,7 +422,7 @@ class _TruncatedBZ2CompressedStreamReader(_BZ2CompressedStreamReader): def __init__(self, fh): super(_TruncatedBZ2CompressedStreamReader, self).__init__(fh) - newbuf = self._decompobj.decompress("BZ") + newbuf = self._decompobj.decompress(b"BZ") if newbuf: self._pending.append(newbuf) @@ -439,7 +439,7 @@ self._pending.append(newbuf) try: while True: - newbuf = self._decompobj.decompress("") + newbuf = self._decompobj.decompress(b"") if newbuf: self._pending.append(newbuf) else: @@ -450,7 +450,7 @@ class _zlibengine(compressionengine): def name(self): - return "zlib" + return b"zlib" def bundletype(self): """zlib compression using the DEFLATE algorithm. @@ -459,18 +459,18 @@ algorithm strikes a reasonable balance between compression ratio and size. """ - return "gzip", "GZ" + return b"gzip", b"GZ" def wireprotosupport(self): - return compewireprotosupport("zlib", 20, 20) + return compewireprotosupport(b"zlib", 20, 20) def revlogheader(self): - return "x" + return b"x" def compressstream(self, it, opts=None): opts = opts or {} - z = zlib.compressobj(opts.get("level", -1)) + z = zlib.compressobj(opts.get(b"level", -1)) for chunk in it: data = z.compress(chunk) # Not all calls to compress emit data. It is cheaper to inspect @@ -521,7 +521,7 @@ parts.append(z.flush()) if sum(map(len, parts)) < insize: - return "".join(parts) + return b"".join(parts) return None def decompress(self, data): @@ -529,14 +529,14 @@ return zlib.decompress(data) except zlib.error as e: raise error.StorageError( - _("revlog decompress error: %s") + _(b"revlog decompress error: %s") % stringutil.forcebytestr(e) ) def revlogcompressor(self, opts=None): level = None if opts is not None: - level = opts.get("zlib.level") + level = opts.get(b"zlib.level") return self.zlibrevlogcompressor(level) @@ -545,7 +545,7 @@ class _bz2engine(compressionengine): def name(self): - return "bz2" + return b"bz2" def bundletype(self): """An algorithm that produces smaller bundles than ``gzip``. @@ -559,16 +559,16 @@ If available, the ``zstd`` engine can yield similar or better compression at much higher speeds. """ - return "bzip2", "BZ" + return b"bzip2", b"BZ" # We declare a protocol name but don't advertise by default because # it is slow. def wireprotosupport(self): - return compewireprotosupport("bzip2", 0, 0) + return compewireprotosupport(b"bzip2", 0, 0) def compressstream(self, it, opts=None): opts = opts or {} - z = bz2.BZ2Compressor(opts.get("level", 9)) + z = bz2.BZ2Compressor(opts.get(b"level", 9)) for chunk in it: data = z.compress(chunk) if data: @@ -585,10 +585,10 @@ class _truncatedbz2engine(compressionengine): def name(self): - return "bz2truncated" + return b"bz2truncated" def bundletype(self): - return None, "_truncatedBZ" + return None, b"_truncatedBZ" # We don't implement compressstream because it is hackily handled elsewhere. @@ -601,20 +601,20 @@ class _noopengine(compressionengine): def name(self): - return "none" + return b"none" def bundletype(self): """No compression is performed. Use this compression engine to explicitly disable compression. """ - return "none", "UN" + return b"none", b"UN" # Clients always support uncompressed payloads. Servers don't because # unless you are on a fast network, uncompressed payloads can easily # saturate your network pipe. def wireprotosupport(self): - return compewireprotosupport("none", 0, 10) + return compewireprotosupport(b"none", 0, 10) # We don't implement revlogheader because it is handled specially # in the revlog class. @@ -638,7 +638,7 @@ class _zstdengine(compressionengine): def name(self): - return "zstd" + return b"zstd" @propertycache def _module(self): @@ -668,20 +668,20 @@ If this engine is available and backwards compatibility is not a concern, it is likely the best available engine. """ - return "zstd", "ZS" + return b"zstd", b"ZS" def wireprotosupport(self): - return compewireprotosupport("zstd", 50, 50) + return compewireprotosupport(b"zstd", 50, 50) def revlogheader(self): - return "\x28" + return b"\x28" def compressstream(self, it, opts=None): opts = opts or {} # zstd level 3 is almost always significantly faster than zlib # while providing no worse compression. It strikes a good balance # between speed and compression. - level = opts.get("level", 3) + level = opts.get(b"level", 3) zstd = self._module z = zstd.ZstdCompressor(level=level).compressobj() @@ -732,7 +732,7 @@ chunks.append(z.flush()) if sum(map(len, chunks)) < insize: - return "".join(chunks) + return b"".join(chunks) return None def decompress(self, data): @@ -752,18 +752,18 @@ pos = pos2 # Frame should be exhausted, so no finish() API. - return "".join(chunks) + return b"".join(chunks) except Exception as e: raise error.StorageError( - _("revlog decompress error: %s") + _(b"revlog decompress error: %s") % stringutil.forcebytestr(e) ) def revlogcompressor(self, opts=None): opts = opts or {} - level = opts.get("zstd.level") + level = opts.get(b"zstd.level") if level is None: - level = opts.get("level") + level = opts.get(b"level") if level is None: level = 3 return self.zstdrevlogcompressor(self._module, level=level) diff --git a/mercurial/utils/dateutil.py b/mercurial/utils/dateutil.py --- a/mercurial/utils/dateutil.py +++ b/mercurial/utils/dateutil.py @@ -20,40 +20,40 @@ # used by parsedate defaultdateformats = ( - "%Y-%m-%dT%H:%M:%S", # the 'real' ISO8601 - "%Y-%m-%dT%H:%M", # without seconds - "%Y-%m-%dT%H%M%S", # another awful but legal variant without : - "%Y-%m-%dT%H%M", # without seconds - "%Y-%m-%d %H:%M:%S", # our common legal variant - "%Y-%m-%d %H:%M", # without seconds - "%Y-%m-%d %H%M%S", # without : - "%Y-%m-%d %H%M", # without seconds - "%Y-%m-%d %I:%M:%S%p", - "%Y-%m-%d %H:%M", - "%Y-%m-%d %I:%M%p", - "%Y-%m-%d", - "%m-%d", - "%m/%d", - "%m/%d/%y", - "%m/%d/%Y", - "%a %b %d %H:%M:%S %Y", - "%a %b %d %I:%M:%S%p %Y", - "%a, %d %b %Y %H:%M:%S", # GNU coreutils "/bin/date --rfc-2822" - "%b %d %H:%M:%S %Y", - "%b %d %I:%M:%S%p %Y", - "%b %d %H:%M:%S", - "%b %d %I:%M:%S%p", - "%b %d %H:%M", - "%b %d %I:%M%p", - "%b %d %Y", - "%b %d", - "%H:%M:%S", - "%I:%M:%S%p", - "%H:%M", - "%I:%M%p", + b"%Y-%m-%dT%H:%M:%S", # the 'real' ISO8601 + b"%Y-%m-%dT%H:%M", # without seconds + b"%Y-%m-%dT%H%M%S", # another awful but legal variant without : + b"%Y-%m-%dT%H%M", # without seconds + b"%Y-%m-%d %H:%M:%S", # our common legal variant + b"%Y-%m-%d %H:%M", # without seconds + b"%Y-%m-%d %H%M%S", # without : + b"%Y-%m-%d %H%M", # without seconds + b"%Y-%m-%d %I:%M:%S%p", + b"%Y-%m-%d %H:%M", + b"%Y-%m-%d %I:%M%p", + b"%Y-%m-%d", + b"%m-%d", + b"%m/%d", + b"%m/%d/%y", + b"%m/%d/%Y", + b"%a %b %d %H:%M:%S %Y", + b"%a %b %d %I:%M:%S%p %Y", + b"%a, %d %b %Y %H:%M:%S", # GNU coreutils "/bin/date --rfc-2822" + b"%b %d %H:%M:%S %Y", + b"%b %d %I:%M:%S%p %Y", + b"%b %d %H:%M:%S", + b"%b %d %I:%M:%S%p", + b"%b %d %H:%M", + b"%b %d %I:%M%p", + b"%b %d %Y", + b"%b %d", + b"%H:%M:%S", + b"%I:%M:%S%p", + b"%H:%M", + b"%I:%M%p", ) -extendeddateformats = defaultdateformats + ("%Y", "%Y-%m", "%b", "%b %Y",) +extendeddateformats = defaultdateformats + (b"%Y", b"%Y-%m", b"%b", b"%b %Y",) def makedate(timestamp=None): @@ -62,8 +62,8 @@ if timestamp is None: timestamp = time.time() if timestamp < 0: - hint = _("check your clock") - raise error.Abort(_("negative timestamp: %d") % timestamp, hint=hint) + hint = _(b"check your clock") + raise error.Abort(_(b"negative timestamp: %d") % timestamp, hint=hint) delta = datetime.datetime.utcfromtimestamp( timestamp ) - datetime.datetime.fromtimestamp(timestamp) @@ -71,7 +71,7 @@ return timestamp, tz -def datestr(date=None, format="%a %b %d %H:%M:%S %Y %1%2"): +def datestr(date=None, format=b"%a %b %d %H:%M:%S %Y %1%2"): """represent a (unixtime, offset) tuple as a localized time. unixtime is seconds since the epoch, and offset is the time zone's number of seconds away from UTC. @@ -88,13 +88,13 @@ 'Fri Dec 13 20:45:52 1901 +0000' """ t, tz = date or makedate() - if "%1" in format or "%2" in format or "%z" in format: - sign = (tz > 0) and "-" or "+" + if b"%1" in format or b"%2" in format or b"%z" in format: + sign = (tz > 0) and b"-" or b"+" minutes = abs(tz) // 60 q, r = divmod(minutes, 60) - format = format.replace("%z", "%1%2") - format = format.replace("%1", "%c%02d" % (sign, q)) - format = format.replace("%2", "%02d" % r) + format = format.replace(b"%z", b"%1%2") + format = format.replace(b"%1", b"%c%02d" % (sign, q)) + format = format.replace(b"%2", b"%02d" % r) d = t - tz if d > 0x7FFFFFFF: d = 0x7FFFFFFF @@ -110,7 +110,7 @@ def shortdate(date=None): """turn (timestamp, tzoff) tuple into iso 8631 date.""" - return datestr(date, format="%Y-%m-%d") + return datestr(date, format=b"%Y-%m-%d") def parsetimezone(s): @@ -118,29 +118,29 @@ (offset, remainder) pair""" s = pycompat.bytestr(s) - if s.endswith("GMT") or s.endswith("UTC"): + if s.endswith(b"GMT") or s.endswith(b"UTC"): return 0, s[:-3].rstrip() # Unix-style timezones [+-]hhmm - if len(s) >= 5 and s[-5] in "+-" and s[-4:].isdigit(): - sign = (s[-5] == "+") and 1 or -1 + if len(s) >= 5 and s[-5] in b"+-" and s[-4:].isdigit(): + sign = (s[-5] == b"+") and 1 or -1 hours = int(s[-4:-2]) minutes = int(s[-2:]) return -sign * (hours * 60 + minutes) * 60, s[:-5].rstrip() # ISO8601 trailing Z - if s.endswith("Z") and s[-2:-1].isdigit(): + if s.endswith(b"Z") and s[-2:-1].isdigit(): return 0, s[:-1] # ISO8601-style [+-]hh:mm if ( len(s) >= 6 - and s[-6] in "+-" - and s[-3] == ":" + and s[-6] in b"+-" + and s[-3] == b":" and s[-5:-3].isdigit() and s[-2:].isdigit() ): - sign = (s[-6] == "+") and 1 or -1 + sign = (s[-6] == b"+") and 1 or -1 hours = int(s[-5:-3]) minutes = int(s[-2:]) return -sign * (hours * 60 + minutes) * 60, s[:-6] @@ -159,12 +159,19 @@ # add missing elements from defaults usenow = False # default to using biased defaults - for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity + for part in ( + b"S", + b"M", + b"HI", + b"d", + b"mb", + b"yY", + ): # decreasing specificity part = pycompat.bytestr(part) - found = [True for p in part if ("%" + p) in format] + found = [True for p in part if (b"%" + p) in format] if not found: - date += "@" + defaults[part][usenow] - format += "@%" + part[0] + date += b"@" + defaults[part][usenow] + format += b"@%" + part[0] else: # We've found a specific time element, less specific time # elements are relative to today @@ -213,34 +220,34 @@ formats = defaultdateformats date = date.strip() - if date == "now" or date == _("now"): + if date == b"now" or date == _(b"now"): return makedate() - if date == "today" or date == _("today"): + if date == b"today" or date == _(b"today"): date = datetime.date.today().strftime(r"%b %d") date = encoding.strtolocal(date) - elif date == "yesterday" or date == _("yesterday"): + elif date == b"yesterday" or date == _(b"yesterday"): date = (datetime.date.today() - datetime.timedelta(days=1)).strftime( r"%b %d" ) date = encoding.strtolocal(date) try: - when, offset = map(int, date.split(" ")) + when, offset = map(int, date.split(b" ")) except ValueError: # fill out defaults now = makedate() defaults = {} - for part in ("d", "mb", "yY", "HI", "M", "S"): + for part in (b"d", b"mb", b"yY", b"HI", b"M", b"S"): # this piece is for rounding the specific end of unknowns b = bias.get(part) if b is None: - if part[0:1] in "HMS": - b = "00" + if part[0:1] in b"HMS": + b = b"00" else: - b = "0" + b = b"0" # this piece is for matching the generic end to today's date - n = datestr(now, "%" + part[0:1]) + n = datestr(now, b"%" + part[0:1]) defaults[part] = (b, n) @@ -253,16 +260,16 @@ break else: raise error.ParseError( - _("invalid date: %r") % pycompat.bytestr(date) + _(b"invalid date: %r") % pycompat.bytestr(date) ) # validate explicit (probably user-specified) date and # time zone offset. values must fit in signed 32 bits for # current 32-bit linux runtimes. timezones go from UTC-12 # to UTC+14 if when < -0x80000000 or when > 0x7FFFFFFF: - raise error.ParseError(_("date exceeds 32 bits: %d") % when) + raise error.ParseError(_(b"date exceeds 32 bits: %d") % when) if offset < -50400 or offset > 43200: - raise error.ParseError(_("impossible time zone offset: %d") % offset) + raise error.ParseError(_(b"impossible time zone offset: %d") % offset) return when, offset @@ -296,42 +303,42 @@ """ def lower(date): - d = {"mb": "1", "d": "1"} + d = {b"mb": b"1", b"d": b"1"} return parsedate(date, extendeddateformats, d)[0] def upper(date): - d = {"mb": "12", "HI": "23", "M": "59", "S": "59"} - for days in ("31", "30", "29"): + d = {b"mb": b"12", b"HI": b"23", b"M": b"59", b"S": b"59"} + for days in (b"31", b"30", b"29"): try: - d["d"] = days + d[b"d"] = days return parsedate(date, extendeddateformats, d)[0] except error.ParseError: pass - d["d"] = "28" + d[b"d"] = b"28" return parsedate(date, extendeddateformats, d)[0] date = date.strip() if not date: - raise error.Abort(_("dates cannot consist entirely of whitespace")) + raise error.Abort(_(b"dates cannot consist entirely of whitespace")) elif date[0:1] == b"<": if not date[1:]: - raise error.Abort(_("invalid day spec, use '": if not date[1:]: - raise error.Abort(_("invalid day spec, use '>DATE'")) + raise error.Abort(_(b"invalid day spec, use '>DATE'")) when = lower(date[1:]) return lambda x: x >= when elif date[0:1] == b"-": try: days = int(date[1:]) except ValueError: - raise error.Abort(_("invalid day spec: %s") % date[1:]) + raise error.Abort(_(b"invalid day spec: %s") % date[1:]) if days < 0: raise error.Abort( - _("%s must be nonnegative (see 'hg help dates')") % date[1:] + _(b"%s must be nonnegative (see 'hg help dates')") % date[1:] ) when = makedate()[0] - days * 3600 * 24 return lambda x: x >= when diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -91,8 +91,8 @@ """return a message describing a subprocess status (codes from kill are negative - not os.system/wait encoding)""" if code >= 0: - return _("exited with status %d") % code - return _("killed by signal %d") % -code + return _(b"exited with status %d") % code + return _(b"killed by signal %d") % -code class _pfile(object): @@ -120,12 +120,12 @@ self.close() -def popen(cmd, mode="rb", bufsize=-1): - if mode == "rb": +def popen(cmd, mode=b"rb", bufsize=-1): + if mode == b"rb": return _popenreader(cmd, bufsize) - elif mode == "wb": + elif mode == b"wb": return _popenwriter(cmd, bufsize) - raise error.ProgrammingError("unsupported mode: %r" % mode) + raise error.ProgrammingError(b"unsupported mode: %r" % mode) def _popenreader(cmd, bufsize): @@ -205,22 +205,22 @@ the temporary files generated.""" inname, outname = None, None try: - infd, inname = pycompat.mkstemp(prefix="hg-filter-in-") + infd, inname = pycompat.mkstemp(prefix=b"hg-filter-in-") fp = os.fdopen(infd, r"wb") fp.write(s) fp.close() - outfd, outname = pycompat.mkstemp(prefix="hg-filter-out-") + outfd, outname = pycompat.mkstemp(prefix=b"hg-filter-out-") os.close(outfd) - cmd = cmd.replace("INFILE", inname) - cmd = cmd.replace("OUTFILE", outname) + cmd = cmd.replace(b"INFILE", inname) + cmd = cmd.replace(b"OUTFILE", outname) code = system(cmd) - if pycompat.sysplatform == "OpenVMS" and code & 1: + if pycompat.sysplatform == b"OpenVMS" and code & 1: code = 0 if code: raise error.Abort( - _("command '%s' failed: %s") % (cmd, explainexit(code)) + _(b"command '%s' failed: %s") % (cmd, explainexit(code)) ) - with open(outname, "rb") as fp: + with open(outname, b"rb") as fp: return fp.read() finally: try: @@ -236,13 +236,13 @@ _filtertable = { - "tempfile:": tempfilter, - "pipe:": pipefilter, + b"tempfile:": tempfilter, + b"pipe:": pipefilter, } def filter(s, cmd): - "filter a string through a command that transforms its input to its output" + b"filter a string through a command that transforms its input to its output" for name, fn in _filtertable.iteritems(): if cmd.startswith(name): return fn(s, cmd[len(name) :].lstrip()) @@ -256,8 +256,8 @@ (portable, not much used). """ return ( - pycompat.safehasattr(sys, "frozen") - or pycompat.safehasattr(sys, "importers") # new py2exe + pycompat.safehasattr(sys, b"frozen") + or pycompat.safehasattr(sys, b"importers") # new py2exe or imp.is_frozen(r"__main__") # old py2exe ) # tools/freeze @@ -271,27 +271,27 @@ Defaults to $HG or 'hg' in the search path. """ if _hgexecutable is None: - hg = encoding.environ.get("HG") + hg = encoding.environ.get(b"HG") mainmod = sys.modules[r"__main__"] if hg: _sethgexecutable(hg) elif mainfrozen(): - if getattr(sys, "frozen", None) == "macosx_app": + if getattr(sys, "frozen", None) == b"macosx_app": # Env variable set by py2app - _sethgexecutable(encoding.environ["EXECUTABLEPATH"]) + _sethgexecutable(encoding.environ[b"EXECUTABLEPATH"]) else: _sethgexecutable(pycompat.sysexecutable) elif ( not pycompat.iswindows and os.path.basename( - pycompat.fsencode(getattr(mainmod, "__file__", "")) + pycompat.fsencode(getattr(mainmod, "__file__", b"")) ) - == "hg" + == b"hg" ): _sethgexecutable(pycompat.fsencode(mainmod.__file__)) else: _sethgexecutable( - findexe("hg") or os.path.basename(pycompat.sysargv[0]) + findexe(b"hg") or os.path.basename(pycompat.sysargv[0]) ) return _hgexecutable @@ -356,17 +356,17 @@ """return environ with optional override, useful for shelling out""" def py2shell(val): - "convert python object into string that is useful to shell" + b"convert python object into string that is useful to shell" if val is None or val is False: - return "0" + return b"0" if val is True: - return "1" + return b"1" return pycompat.bytestr(val) env = dict(encoding.environ) if environ: env.update((k, py2shell(v)) for k, v in environ.iteritems()) - env["HG"] = hgexecutable() + env[b"HG"] = hgexecutable() return env @@ -420,11 +420,11 @@ stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) - for line in iter(proc.stdout.readline, ""): + for line in iter(proc.stdout.readline, b""): out.write(line) proc.wait() rc = proc.returncode - if pycompat.sysplatform == "OpenVMS" and rc & 1: + if pycompat.sysplatform == b"OpenVMS" and rc & 1: rc = 0 return rc @@ -432,7 +432,7 @@ def gui(): """Are we running in a GUI?""" if pycompat.isdarwin: - if "SSH_CONNECTION" in encoding.environ: + if b"SSH_CONNECTION" in encoding.environ: # handle SSH access to a box where the user is logged in return False elif getattr(osutil, "isgui", None): @@ -442,7 +442,7 @@ # pure build; use a safe default return True else: - return pycompat.iswindows or encoding.environ.get("DISPLAY") + return pycompat.iswindows or encoding.environ.get(b"DISPLAY") def hgcmd(): @@ -453,9 +453,9 @@ get either the python call or current executable. """ if mainfrozen(): - if getattr(sys, "frozen", None) == "macosx_app": + if getattr(sys, "frozen", None) == b"macosx_app": # Env variable set by py2app - return [encoding.environ["EXECUTABLEPATH"]] + return [encoding.environ[b"EXECUTABLEPATH"]] else: return [pycompat.sysexecutable] return _gethgcmd() @@ -589,7 +589,7 @@ returncode = errno.EINVAL raise OSError( returncode, - "error running %r: %s" % (cmd, os.strerror(returncode)), + b"error running %r: %s" % (cmd, os.strerror(returncode)), ) return @@ -598,11 +598,11 @@ # Start a new session os.setsid() - stdin = open(os.devnull, "r") + stdin = open(os.devnull, b"r") if stdout is None: - stdout = open(os.devnull, "w") + stdout = open(os.devnull, b"w") if stderr is None: - stderr = open(os.devnull, "w") + stderr = open(os.devnull, b"w") # connect stdin to devnull to make sure the subprocess can't # muck up that stream for mercurial. diff --git a/mercurial/utils/repoviewutil.py b/mercurial/utils/repoviewutil.py --- a/mercurial/utils/repoviewutil.py +++ b/mercurial/utils/repoviewutil.py @@ -15,10 +15,10 @@ # This create and ordering used for branchmap purpose. # the ordering may be partial subsettable = { - None: "visible", - "visible-hidden": "visible", - "visible": "served", - "served.hidden": "served", - "served": "immutable", - "immutable": "base", + None: b"visible", + b"visible-hidden": b"visible", + b"visible": b"served", + b"served.hidden": b"served", + b"served": b"immutable", + b"immutable": b"base", } diff --git a/mercurial/utils/storageutil.py b/mercurial/utils/storageutil.py --- a/mercurial/utils/storageutil.py +++ b/mercurial/utils/storageutil.py @@ -195,7 +195,7 @@ return store.node(fileid) except IndexError: raise error.LookupError( - "%d" % fileid, identifier, _("no match found") + b"%d" % fileid, identifier, _(b"no match found") ) if len(fileid) == 20: @@ -226,7 +226,7 @@ except (ValueError, OverflowError): pass - raise error.LookupError(fileid, identifier, _("no match found")) + raise error.LookupError(fileid, identifier, _(b"no match found")) def resolvestripinfo(minlinkrev, tiprev, headrevs, linkrevfn, parentrevsfn): @@ -361,9 +361,9 @@ fnode = store.node frev = store.rev - if nodesorder == "nodes": + if nodesorder == b"nodes": revs = [frev(n) for n in nodes] - elif nodesorder == "linear": + elif nodesorder == b"linear": revs = set(frev(n) for n in nodes) revs = dagop.linearize(revs, store.parentrevs) else: # storage and default @@ -498,7 +498,7 @@ # "\1\ncensored:". A delta producing such a censored revision must be a # full-replacement delta, so we inspect the first and only patch in the # delta for this prefix. - hlen = struct.calcsize(">lll") + hlen = struct.calcsize(b">lll") if len(delta) <= hlen: return False @@ -507,6 +507,6 @@ if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): return False - add = "\1\ncensored:" + add = b"\1\ncensored:" addlen = len(add) return newlen >= addlen and delta[hlen : hlen + addlen] == add diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -66,24 +66,24 @@ if isinstance(o, bytes): if bprefix: - yield "b'%s'" % escapestr(o) + yield b"b'%s'" % escapestr(o) else: - yield "'%s'" % escapestr(o) + yield b"'%s'" % escapestr(o) elif isinstance(o, bytearray): # codecs.escape_encode() can't handle bytearray, so escapestr fails # without coercion. - yield "bytearray['%s']" % escapestr(bytes(o)) + yield b"bytearray['%s']" % escapestr(bytes(o)) elif isinstance(o, list): if not o: - yield "[]" + yield b"[]" return - yield "[" + yield b"[" if indent: level += 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) for i, a in enumerate(o): for chunk in pprintgen( @@ -93,28 +93,28 @@ if i + 1 < len(o): if indent: - yield ",\n" - yield " " * (level * indent) + yield b",\n" + yield b" " * (level * indent) else: - yield ", " + yield b", " if indent: level -= 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) - yield "]" + yield b"]" elif isinstance(o, dict): if not o: - yield "{}" + yield b"{}" return - yield "{" + yield b"{" if indent: level += 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) for i, (k, v) in enumerate(sorted(o.items())): for chunk in pprintgen( @@ -122,7 +122,7 @@ ): yield chunk - yield ": " + yield b": " for chunk in pprintgen( v, bprefix=bprefix, indent=indent, level=level @@ -131,28 +131,28 @@ if i + 1 < len(o): if indent: - yield ",\n" - yield " " * (level * indent) + yield b",\n" + yield b" " * (level * indent) else: - yield ", " + yield b", " if indent: level -= 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) - yield "}" + yield b"}" elif isinstance(o, set): if not o: - yield "set([])" + yield b"set([])" return - yield "set([" + yield b"set([" if indent: level += 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) for i, k in enumerate(sorted(o)): for chunk in pprintgen( @@ -162,28 +162,28 @@ if i + 1 < len(o): if indent: - yield ",\n" - yield " " * (level * indent) + yield b",\n" + yield b" " * (level * indent) else: - yield ", " + yield b", " if indent: level -= 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) - yield "])" + yield b"])" elif isinstance(o, tuple): if not o: - yield "()" + yield b"()" return - yield "(" + yield b"(" if indent: level += 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) for i, a in enumerate(o): for chunk in pprintgen( @@ -193,31 +193,31 @@ if i + 1 < len(o): if indent: - yield ",\n" - yield " " * (level * indent) + yield b",\n" + yield b" " * (level * indent) else: - yield ", " + yield b", " if indent: level -= 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) - yield ")" + yield b")" elif isinstance(o, types.GeneratorType): # Special case of empty generator. try: nextitem = next(o) except StopIteration: - yield "gen[]" + yield b"gen[]" return - yield "gen[" + yield b"gen[" if indent: level += 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) last = False @@ -236,17 +236,17 @@ if not last: if indent: - yield ",\n" - yield " " * (level * indent) + yield b",\n" + yield b" " * (level * indent) else: - yield ", " + yield b", " if indent: level -= 1 - yield "\n" - yield " " * (level * indent) + yield b"\n" + yield b" " * (level * indent) - yield "]" + yield b"]" else: yield pycompat.byterepr(o) @@ -261,21 +261,21 @@ # ~~~~~~~~~~~~~~~~ # p0 p1 q0 q1 q0 = -1 - q1 = rs.find("<", p1 + 1) + q1 = rs.find(b"<", p1 + 1) if q1 < 0: q1 = len(rs) - elif q1 > p1 + 1 and rs.startswith("=", q1 - 1): + elif q1 > p1 + 1 and rs.startswith(b"=", q1 - 1): # backtrack for ' field=<' - q0 = rs.rfind(" ", p1 + 1, q1 - 1) + q0 = rs.rfind(b" ", p1 + 1, q1 - 1) if q0 < 0: q0 = q1 else: q0 += 1 # skip ' ' - l = rs.count("<", 0, p0) - rs.count(">", 0, p0) + l = rs.count(b"<", 0, p0) - rs.count(b">", 0, p0) assert l >= 0 lines.append((l, rs[p0:q0].rstrip())) p0, p1 = q0, q1 - return "\n".join(" " * l + s for l, s in lines) + return b"\n".join(b" " * l + s for l, s in lines) def buildrepr(r): @@ -291,7 +291,7 @@ ======== ================================= """ if r is None: - return "" + return b"" elif isinstance(r, tuple): return r[0] % pycompat.rapply(pycompat.maybebytestr, r[1:]) elif isinstance(r, bytes): @@ -304,7 +304,7 @@ def binary(s): """return true if a string is binary data""" - return bool(s and "\0" in s) + return bool(s and b"\0" in s) def stringmatcher(pattern, casesensitive=True): @@ -345,7 +345,7 @@ >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg') ('literal', 'ABCDEFG', [False, False, True]) """ - if pattern.startswith("re:"): + if pattern.startswith(b"re:"): pattern = pattern[3:] try: flags = 0 @@ -353,9 +353,9 @@ flags = remod.I regex = remod.compile(pattern, flags) except remod.error as e: - raise error.ParseError(_("invalid regular expression: %s") % e) - return "re", pattern, regex.search - elif pattern.startswith("literal:"): + raise error.ParseError(_(b"invalid regular expression: %s") % e) + return b"re", pattern, regex.search + elif pattern.startswith(b"literal:"): pattern = pattern[8:] match = pattern.__eq__ @@ -363,21 +363,21 @@ if not casesensitive: ipat = encoding.lower(pattern) match = lambda s: ipat == encoding.lower(s) - return "literal", pattern, match + return b"literal", pattern, match def shortuser(user): """Return a short representation of a user name or email address.""" - f = user.find("@") + f = user.find(b"@") if f >= 0: user = user[:f] - f = user.find("<") + f = user.find(b"<") if f >= 0: user = user[f + 1 :] - f = user.find(" ") + f = user.find(b" ") if f >= 0: user = user[:f] - f = user.find(".") + f = user.find(b".") if f >= 0: user = user[:f] return user @@ -385,10 +385,10 @@ def emailuser(user): """Return the user portion of an email address.""" - f = user.find("@") + f = user.find(b"@") if f >= 0: user = user[:f] - f = user.find("<") + f = user.find(b"<") if f >= 0: user = user[f + 1 :] return user @@ -396,10 +396,10 @@ def email(author): """get email of author.""" - r = author.find(">") + r = author.find(b">") if r == -1: r = None - return author[author.find("<") + 1 : r] + return author[author.find(b"<") + 1 : r] def person(author): @@ -421,13 +421,13 @@ >>> person(b'"Foo Bar ') 'Foo Bar' """ - if "@" not in author: + if b"@" not in author: return author - f = author.find("<") + f = author.find(b"<") if f != -1: - return author[:f].strip(' "').replace('\\"', '"') - f = author.find("@") - return author[:f].replace(".", " ") + return author[:f].strip(b' "').replace(b'\\"', b'"') + f = author.find(b"@") + return author[:f].replace(b".", b" ") @attr.s(hash=True) @@ -497,7 +497,7 @@ # Don't bother checking the line if it is a comment or # is an improperly formed author field - if line.lstrip().startswith("#"): + if line.lstrip().startswith(b"#"): continue # names, emails hold the parsed emails and names for each line @@ -506,17 +506,17 @@ namebuilder = [] for element in line.split(): - if element.startswith("#"): + if element.startswith(b"#"): # If we reach a comment in the mailmap file, move on break - elif element.startswith("<") and element.endswith(">"): + elif element.startswith(b"<") and element.endswith(b">"): # We have found an email. # Parse it, and finalize any names from earlier emails.append(element[1:-1]) # Slice off the "<>" if namebuilder: - names.append(" ".join(namebuilder)) + names.append(b" ".join(namebuilder)) namebuilder = [] # Break if we have found a second email, any other @@ -587,7 +587,7 @@ proper = mailmap.get(commit2, mailmapping(None, None)) # Return the author field with proper values filled in - return "%s <%s>" % ( + return b"%s <%s>" % ( proper.name if proper.name else commit.name, proper.email if proper.email else commit.email, ) @@ -620,7 +620,7 @@ def ellipsis(text, maxlength=400): """Trim string to at most maxlength (default: 400) columns in display.""" - return encoding.trim(text, maxlength, ellipsis="...") + return encoding.trim(text, maxlength, ellipsis=b"...") def escapestr(s): @@ -675,7 +675,7 @@ l += colwidth(ucstr[i]) if space_left < l: return (ucstr[:i], ucstr[i:]) - return ucstr, "" + return ucstr, b"" # overriding of base class def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): @@ -695,7 +695,7 @@ lines = [] if self.width <= 0: - raise ValueError("invalid width %r (must be > 0)" % self.width) + raise ValueError(b"invalid width %r (must be > 0)" % self.width) # Arrange in reverse order so items can be efficiently popped # from a stack of chucks. @@ -759,7 +759,7 @@ return tw(**kwargs) -def wrap(line, width, initindent="", hangindent=""): +def wrap(line, width, initindent=b"", hangindent=b""): maxindent = max(len(hangindent), len(initindent)) if width <= maxindent: # adjust for weird terminal size @@ -783,16 +783,16 @@ _booleans = { - "1": True, - "yes": True, - "true": True, - "on": True, - "always": True, - "0": False, - "no": False, - "false": False, - "off": False, - "never": False, + b"1": True, + b"yes": True, + b"true": True, + b"on": True, + b"always": True, + b"0": False, + b"no": False, + b"false": False, + b"off": False, + b"never": False, } diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -35,8 +35,8 @@ def _normpath(f): # under hg < 2.4, convert didn't sanitize paths properly, so a # converted repo may contain repeated slashes - while "//" in f: - f = f.replace("//", "/") + while b"//" in f: + f = f.replace(b"//", b"/") return f @@ -58,25 +58,25 @@ self.refersmf = False self.fncachewarned = False # developer config: verify.skipflags - self.skipflags = repo.ui.configint("verify", "skipflags") + self.skipflags = repo.ui.configint(b"verify", b"skipflags") self.warnorphanstorefiles = True def _warn(self, msg): """record a "warning" level issue""" - self.ui.warn(msg + "\n") + self.ui.warn(msg + b"\n") self.warnings += 1 def _err(self, linkrev, msg, filename=None): """record a "error" level issue""" if linkrev is not None: self.badrevs.add(linkrev) - linkrev = "%d" % linkrev + linkrev = b"%d" % linkrev else: - linkrev = "?" - msg = "%s: %s" % (linkrev, msg) + linkrev = b"?" + msg = b"%s: %s" % (linkrev, msg) if filename: - msg = "%s@%s" % (filename, msg) - self.ui.warn(" " + msg + "\n") + msg = b"%s@%s" % (filename, msg) + self.ui.warn(b" " + msg + b"\n") self.errors += 1 def _exc(self, linkrev, msg, inst, filename=None): @@ -84,7 +84,7 @@ fmsg = pycompat.bytestr(inst) if not fmsg: fmsg = pycompat.byterepr(inst) - self._err(linkrev, "%s: %s" % (msg, fmsg), filename) + self._err(linkrev, b"%s: %s" % (msg, fmsg), filename) def _checkrevlog(self, obj, name, linkrev): """verify high level property of a revlog @@ -95,20 +95,20 @@ - revlog's format version is correct. """ if not len(obj) and (self.havecl or self.havemf): - self._err(linkrev, _("empty or missing %s") % name) + self._err(linkrev, _(b"empty or missing %s") % name) return d = obj.checksize() if d[0]: - self._err(None, _("data length off by %d bytes") % d[0], name) + self._err(None, _(b"data length off by %d bytes") % d[0], name) if d[1]: - self._err(None, _("index contains %d extra bytes") % d[1], name) + self._err(None, _(b"index contains %d extra bytes") % d[1], name) if obj.version != revlog.REVLOGV0: if not self.revlogv1: - self._warn(_("warning: `%s' uses revlog format 1") % name) + self._warn(_(b"warning: `%s' uses revlog format 1") % name) elif self.revlogv1: - self._warn(_("warning: `%s' uses revlog format 0") % name) + self._warn(_(b"warning: `%s' uses revlog format 0") % name) def _checkentry(self, obj, i, node, seen, linkrevs, f): """verify a single revlog entry @@ -133,9 +133,9 @@ lr = obj.linkrev(obj.rev(node)) if lr < 0 or (self.havecl and lr not in linkrevs): if lr < 0 or lr >= len(self.repo.changelog): - msg = _("rev %d points to nonexistent changeset %d") + msg = _(b"rev %d points to nonexistent changeset %d") else: - msg = _("rev %d points to unexpected changeset %d") + msg = _(b"rev %d points to unexpected changeset %d") self._err(None, msg % (i, lr), f) if linkrevs: if f and len(linkrevs) > 1: @@ -149,8 +149,8 @@ except Exception: pass self._warn( - _(" (expected %s)") - % " ".join(map(pycompat.bytestr, linkrevs)) + _(b" (expected %s)") + % b" ".join(map(pycompat.bytestr, linkrevs)) ) lr = None # can't be trusted @@ -159,20 +159,20 @@ if p1 not in seen and p1 != nullid: self._err( lr, - _("unknown parent 1 %s of %s") % (short(p1), short(node)), + _(b"unknown parent 1 %s of %s") % (short(p1), short(node)), f, ) if p2 not in seen and p2 != nullid: self._err( lr, - _("unknown parent 2 %s of %s") % (short(p2), short(node)), + _(b"unknown parent 2 %s of %s") % (short(p2), short(node)), f, ) except Exception as inst: - self._exc(lr, _("checking parents of %s") % short(node), inst, f) + self._exc(lr, _(b"checking parents of %s") % short(node), inst, f) if node in seen: - self._err(lr, _("duplicate revision %d (%d)") % (i, seen[node]), f) + self._err(lr, _(b"duplicate revision %d (%d)") % (i, seen[node]), f) seen[node] = i return lr @@ -185,15 +185,15 @@ # initial validation and generic report repo = self.repo ui = repo.ui - if not repo.url().startswith("file:"): - raise error.Abort(_("cannot verify bundle or remote repos")) + if not repo.url().startswith(b"file:"): + raise error.Abort(_(b"cannot verify bundle or remote repos")) - if os.path.exists(repo.sjoin("journal")): - ui.warn(_("abandoned transaction found - run hg recover\n")) + if os.path.exists(repo.sjoin(b"journal")): + ui.warn(_(b"abandoned transaction found - run hg recover\n")) if ui.verbose or not self.revlogv1: ui.status( - _("repository uses revlog format %d\n") + _(b"repository uses revlog format %d\n") % (self.revlogv1 and 1 or 0) ) @@ -206,23 +206,23 @@ # final report ui.status( - _("checked %d changesets with %d changes to %d files\n") + _(b"checked %d changesets with %d changes to %d files\n") % (len(repo.changelog), filerevisions, totalfiles) ) if self.warnings: - ui.warn(_("%d warnings encountered!\n") % self.warnings) + ui.warn(_(b"%d warnings encountered!\n") % self.warnings) if self.fncachewarned: ui.warn( _( - 'hint: run "hg debugrebuildfncache" to recover from ' - "corrupt fncache\n" + b'hint: run "hg debugrebuildfncache" to recover from ' + b"corrupt fncache\n" ) ) if self.errors: - ui.warn(_("%d integrity errors encountered!\n") % self.errors) + ui.warn(_(b"%d integrity errors encountered!\n") % self.errors) if self.badrevs: ui.warn( - _("(first damaged changeset appears to be %d)\n") + _(b"(first damaged changeset appears to be %d)\n") % min(self.badrevs) ) return 1 @@ -249,18 +249,18 @@ match = self.match cl = repo.changelog - ui.status(_("checking changesets\n")) + ui.status(_(b"checking changesets\n")) mflinkrevs = {} filelinkrevs = {} seen = {} - self._checkrevlog(cl, "changelog", 0) + self._checkrevlog(cl, b"changelog", 0) progress = ui.makeprogress( - _("checking"), unit=_("changesets"), total=len(repo) + _(b"checking"), unit=_(b"changesets"), total=len(repo) ) for i in repo: progress.update(i) n = cl.node(i) - self._checkentry(cl, i, n, seen, [i], "changelog") + self._checkentry(cl, i, n, seen, [i], b"changelog") try: changes = cl.read(n) @@ -272,12 +272,12 @@ filelinkrevs.setdefault(_normpath(f), []).append(i) except Exception as inst: self.refersmf = True - self._exc(i, _("unpacking changeset %s") % short(n), inst) + self._exc(i, _(b"unpacking changeset %s") % short(n), inst) progress.complete() return mflinkrevs, filelinkrevs def _verifymanifest( - self, mflinkrevs, dir="", storefiles=None, subdirprogress=None + self, mflinkrevs, dir=b"", storefiles=None, subdirprogress=None ): """verify the manifestlog content @@ -313,12 +313,12 @@ mf = mfl.getstorage(dir) if not dir: - self.ui.status(_("checking manifests\n")) + self.ui.status(_(b"checking manifests\n")) filenodes = {} subdirnodes = {} seen = {} - label = "manifest" + label = b"manifest" if dir: label = dir revlogfiles = mf.files() @@ -330,7 +330,7 @@ # null manifests. self._checkrevlog(mf, label, 0) progress = ui.makeprogress( - _("checking"), unit=_("manifests"), total=len(mf) + _(b"checking"), unit=_(b"manifests"), total=len(mf) ) for i in mf: if not dir: @@ -342,24 +342,24 @@ elif dir: self._err( lr, - _("%s not in parent-directory manifest") % short(n), + _(b"%s not in parent-directory manifest") % short(n), label, ) else: - self._err(lr, _("%s not in changesets") % short(n), label) + self._err(lr, _(b"%s not in changesets") % short(n), label) try: mfdelta = mfl.get(dir, n).readdelta(shallow=True) for f, fn, fl in mfdelta.iterentries(): if not f: - self._err(lr, _("entry without name in manifest")) - elif f == "/dev/null": # ignore this in very old repos + self._err(lr, _(b"entry without name in manifest")) + elif f == b"/dev/null": # ignore this in very old repos continue fullpath = dir + _normpath(f) - if fl == "t": + if fl == b"t": if not match.visitdir(fullpath): continue - subdirnodes.setdefault(fullpath + "/", {}).setdefault( + subdirnodes.setdefault(fullpath + b"/", {}).setdefault( fn, [] ).append(lr) else: @@ -367,7 +367,7 @@ continue filenodes.setdefault(fullpath, {}).setdefault(fn, lr) except Exception as inst: - self._exc(lr, _("reading delta %s") % short(n), inst, label) + self._exc(lr, _(b"reading delta %s") % short(n), inst, label) if self._level >= VERIFY_FULL: try: # Various issues can affect manifest. So we read each full @@ -377,7 +377,7 @@ except Exception as inst: self._exc( lr, - _("reading full manifest %s") % short(n), + _(b"reading full manifest %s") % short(n), inst, label, ) @@ -394,8 +394,8 @@ self._err( c, _( - "parent-directory manifest refers to unknown" - " revision %s" + b"parent-directory manifest refers to unknown" + b" revision %s" ) % short(m), label, @@ -403,23 +403,24 @@ else: self._err( c, - _("changeset refers to unknown revision %s") % short(m), + _(b"changeset refers to unknown revision %s") + % short(m), label, ) if not dir and subdirnodes: - self.ui.status(_("checking directory manifests\n")) + self.ui.status(_(b"checking directory manifests\n")) storefiles = set() subdirs = set() revlogv1 = self.revlogv1 for f, f2, size in repo.store.datafiles(): if not f: - self._err(None, _("cannot decode filename '%s'") % f2) - elif (size > 0 or not revlogv1) and f.startswith("meta/"): + self._err(None, _(b"cannot decode filename '%s'") % f2) + elif (size > 0 or not revlogv1) and f.startswith(b"meta/"): storefiles.add(_normpath(f)) subdirs.add(os.path.dirname(f)) subdirprogress = ui.makeprogress( - _("checking"), unit=_("manifests"), total=len(subdirs) + _(b"checking"), unit=_(b"manifests"), total=len(subdirs) ) for subdir, linkrevs in subdirnodes.iteritems(): @@ -433,25 +434,25 @@ subdirprogress.complete() if self.warnorphanstorefiles: for f in sorted(storefiles): - self._warn(_("warning: orphan data file '%s'") % f) + self._warn(_(b"warning: orphan data file '%s'") % f) return filenodes def _crosscheckfiles(self, filelinkrevs, filenodes): repo = self.repo ui = self.ui - ui.status(_("crosschecking files in changesets and manifests\n")) + ui.status(_(b"crosschecking files in changesets and manifests\n")) total = len(filelinkrevs) + len(filenodes) progress = ui.makeprogress( - _("crosschecking"), unit=_("files"), total=total + _(b"crosschecking"), unit=_(b"files"), total=total ) if self.havemf: for f in sorted(filelinkrevs): progress.increment() if f not in filenodes: lr = filelinkrevs[f][0] - self._err(lr, _("in changeset but not in manifest"), f) + self._err(lr, _(b"in changeset but not in manifest"), f) if self.havecl: for f in sorted(filenodes): @@ -462,7 +463,7 @@ lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]]) except Exception: lr = None - self._err(lr, _("in manifest but not in changeset"), f) + self._err(lr, _(b"in manifest but not in changeset"), f) progress.complete() @@ -472,27 +473,27 @@ lrugetctx = self.lrugetctx revlogv1 = self.revlogv1 havemf = self.havemf - ui.status(_("checking files\n")) + ui.status(_(b"checking files\n")) storefiles = set() for f, f2, size in repo.store.datafiles(): if not f: - self._err(None, _("cannot decode filename '%s'") % f2) - elif (size > 0 or not revlogv1) and f.startswith("data/"): + self._err(None, _(b"cannot decode filename '%s'") % f2) + elif (size > 0 or not revlogv1) and f.startswith(b"data/"): storefiles.add(_normpath(f)) state = { # TODO this assumes revlog storage for changelog. - "expectedversion": self.repo.changelog.version & 0xFFFF, - "skipflags": self.skipflags, + b"expectedversion": self.repo.changelog.version & 0xFFFF, + b"skipflags": self.skipflags, # experimental config: censor.policy - "erroroncensored": ui.config("censor", "policy") == "abort", + b"erroroncensored": ui.config(b"censor", b"policy") == b"abort", } files = sorted(set(filenodes) | set(filelinkrevs)) revisions = 0 progress = ui.makeprogress( - _("checking"), unit=_("files"), total=len(files) + _(b"checking"), unit=_(b"files"), total=len(files) ) for i, f in enumerate(files): progress.update(i, item=f) @@ -510,7 +511,7 @@ try: fl = repo.file(f) except error.StorageError as e: - self._err(lr, _("broken revlog! (%s)") % e, f) + self._err(lr, _(b"broken revlog! (%s)") % e, f) continue for ff in fl.files(): @@ -519,15 +520,15 @@ except KeyError: if self.warnorphanstorefiles: self._warn( - _(" warning: revlog '%s' not in fncache!") % ff + _(b" warning: revlog '%s' not in fncache!") % ff ) self.fncachewarned = True if not len(fl) and (self.havecl or self.havemf): - self._err(lr, _("empty or missing %s") % f) + self._err(lr, _(b"empty or missing %s") % f) else: # Guard against implementations not setting this. - state["skipread"] = set() + state[b"skipread"] = set() for problem in fl.verifyintegrity(state): if problem.node is not None: linkrev = fl.linkrev(fl.rev(problem.node)) @@ -544,8 +545,8 @@ ) else: raise error.ProgrammingError( - "problem instance does not set warning or error " - "attribute: %s" % problem.msg + b"problem instance does not set warning or error " + b"attribute: %s" % problem.msg ) seen = {} @@ -555,11 +556,11 @@ lr = self._checkentry(fl, i, n, seen, linkrevs, f) if f in filenodes: if havemf and n not in filenodes[f]: - self._err(lr, _("%s not in manifests") % (short(n)), f) + self._err(lr, _(b"%s not in manifests") % (short(n)), f) else: del filenodes[f][n] - if n in state["skipread"]: + if n in state[b"skipread"]: continue # check renames @@ -574,8 +575,8 @@ if not any(rp[0] in pctx for pctx in ctx.parents()): self._warn( _( - "warning: copy source of '%s' not" - " in parents of %s" + b"warning: copy source of '%s' not" + b" in parents of %s" ) % (f, ctx) ) @@ -584,8 +585,8 @@ self._err( lr, _( - "empty or missing copy source revlog " - "%s:%s" + b"empty or missing copy source revlog " + b"%s:%s" ) % (rp[0], short(rp[1])), f, @@ -593,8 +594,8 @@ elif rp[1] == nullid: ui.note( _( - "warning: %s@%s: copy source" - " revision is nullid %s:%s\n" + b"warning: %s@%s: copy source" + b" revision is nullid %s:%s\n" ) % (f, lr, rp[0], short(rp[1])) ) @@ -602,7 +603,7 @@ fl2.rev(rp[1]) except Exception as inst: self._exc( - lr, _("checking rename of %s") % short(n), inst, f + lr, _(b"checking rename of %s") % short(n), inst, f ) # cross-check @@ -611,7 +612,7 @@ for lr, node in sorted(fns): self._err( lr, - _("manifest refers to unknown revision %s") + _(b"manifest refers to unknown revision %s") % short(node), f, ) @@ -619,6 +620,6 @@ if self.warnorphanstorefiles: for f in sorted(storefiles): - self._warn(_("warning: orphan data file '%s'") % f) + self._warn(_(b"warning: orphan data file '%s'") % f) return len(files), revisions diff --git a/mercurial/vfs.py b/mercurial/vfs.py --- a/mercurial/vfs.py +++ b/mercurial/vfs.py @@ -47,7 +47,7 @@ def __init__(self, *args, **kwargs): """Prevent instantiation; don't call this from subclasses.""" - raise NotImplementedError("attempted instantiating " + str(type(self))) + raise NotImplementedError(b"attempted instantiating " + str(type(self))) def _auditpath(self, path, mode): raise NotImplementedError @@ -59,9 +59,9 @@ except IOError as inst: if inst.errno != errno.ENOENT: raise - return "" + return b"" - def tryreadlines(self, path, mode="rb"): + def tryreadlines(self, path, mode=b"rb"): """gracefully return an empty array for missing files""" try: return self.readlines(path, mode=mode) @@ -81,23 +81,23 @@ return self.__call__ def read(self, path): - with self(path, "rb") as fp: + with self(path, b"rb") as fp: return fp.read() - def readlines(self, path, mode="rb"): + def readlines(self, path, mode=b"rb"): with self(path, mode=mode) as fp: return fp.readlines() def write(self, path, data, backgroundclose=False, **kwargs): - with self(path, "wb", backgroundclose=backgroundclose, **kwargs) as fp: + with self(path, b"wb", backgroundclose=backgroundclose, **kwargs) as fp: return fp.write(data) - def writelines(self, path, data, mode="wb", notindexed=False): + def writelines(self, path, data, mode=b"wb", notindexed=False): with self(path, mode=mode, notindexed=notindexed) as fp: return fp.writelines(data) def append(self, path, data): - with self(path, "ab") as fp: + with self(path, b"ab") as fp: return fp.write(data) def basename(self, path): @@ -175,7 +175,7 @@ def mkdir(self, path=None): return os.mkdir(self.join(path)) - def mkstemp(self, suffix="", prefix="tmp", dir=None): + def mkstemp(self, suffix=b"", prefix=b"tmp", dir=None): fd, name = pycompat.mkstemp( suffix=suffix, prefix=prefix, dir=self.join(dir) ) @@ -203,7 +203,7 @@ checkambig=True only in limited cases (see also issue5418 and issue5584 for detail). """ - self._auditpath(dst, "w") + self._auditpath(dst, b"w") srcpath = self.join(src) dstpath = self.join(dst) oldstat = checkambig and util.filestat.frompath(dstpath) @@ -302,7 +302,7 @@ vfs = getattr(self, "vfs", self) if getattr(vfs, "_backgroundfilecloser", None): raise error.Abort( - _("can only have 1 active background file closer") + _(b"can only have 1 active background file closer") ) with backgroundfilecloser(ui, expectedcount=expectedcount) as bfc: @@ -365,13 +365,13 @@ path = os.path.relpath(path, self.base) r = util.checkosfilename(path) if r: - raise error.Abort("%s: %r" % (r, path)) + raise error.Abort(b"%s: %r" % (r, path)) self.audit(path, mode=mode) def __call__( self, path, - mode="r", + mode=b"r", atomictemp=False, notindexed=False, backgroundclose=False, @@ -413,11 +413,11 @@ self._auditpath(path, mode) f = self.join(path) - if "b" not in mode: - mode += "b" # for that other OS + if b"b" not in mode: + mode += b"b" # for that other OS nlink = -1 - if mode not in ("r", "rb"): + if mode not in (b"r", b"rb"): dirname, basename = util.split(f) # If basename is empty, then the path is malformed because it points # to a directory. Let the posixfile() call below raise IOError. @@ -429,7 +429,7 @@ f, mode, self.createmode, checkambig=checkambig ) try: - if "w" in mode: + if b"w" in mode: util.unlink(f) nlink = 0 else: @@ -455,11 +455,11 @@ self._fixfilemode(f) if checkambig: - if mode in ("r", "rb"): + if mode in (b"r", b"rb"): raise error.Abort( _( - "implementation error: mode %s is not" - " valid for checkambig=True" + b"implementation error: mode %s is not" + b" valid for checkambig=True" ) % mode ) @@ -471,8 +471,8 @@ if not self._backgroundfilecloser: raise error.Abort( _( - "backgroundclose can only be used when a " - "backgroundclosing context manager is active" + b"backgroundclose can only be used when a " + b"backgroundclosing context manager is active" ) ) @@ -493,7 +493,7 @@ except OSError as err: raise OSError( err.errno, - _("could not symlink to %r: %s") + _(b"could not symlink to %r: %s") % (src, encoding.strtolocal(err.strerror)), linkname, ) @@ -552,9 +552,9 @@ def __init__(self, vfs): proxyvfs.__init__(self, vfs) - def __call__(self, path, mode="r", *args, **kw): - if mode not in ("r", "rb"): - raise error.Abort(_("this vfs is read only")) + def __call__(self, path, mode=b"r", *args, **kw): + if mode not in (b"r", b"rb"): + raise error.Abort(_(b"this vfs is read only")) return self.vfs(path, mode, *args, **kw) def join(self, path, *insidef): @@ -584,10 +584,10 @@ return self def __exit__(self, exc_type, exc_value, exc_tb): - raise NotImplementedError("attempted instantiating " + str(type(self))) + raise NotImplementedError(b"attempted instantiating " + str(type(self))) def close(self): - raise NotImplementedError("attempted instantiating " + str(type(self))) + raise NotImplementedError(b"attempted instantiating " + str(type(self))) class delayclosedfile(closewrapbase): @@ -619,7 +619,7 @@ # Only Windows/NTFS has slow file closing. So only enable by default # on that platform. But allow to be enabled elsewhere for testing. defaultenabled = pycompat.iswindows - enabled = ui.configbool("worker", "backgroundclose", defaultenabled) + enabled = ui.configbool(b"worker", b"backgroundclose", defaultenabled) if not enabled: return @@ -627,24 +627,24 @@ # There is overhead to starting and stopping the background threads. # Don't do background processing unless the file count is large enough # to justify it. - minfilecount = ui.configint("worker", "backgroundcloseminfilecount") + minfilecount = ui.configint(b"worker", b"backgroundcloseminfilecount") # FUTURE dynamically start background threads after minfilecount closes. # (We don't currently have any callers that don't know their file count) if expectedcount > 0 and expectedcount < minfilecount: return - maxqueue = ui.configint("worker", "backgroundclosemaxqueue") - threadcount = ui.configint("worker", "backgroundclosethreadcount") + maxqueue = ui.configint(b"worker", b"backgroundclosemaxqueue") + threadcount = ui.configint(b"worker", b"backgroundclosethreadcount") ui.debug( - "starting %d threads for background file closing\n" % threadcount + b"starting %d threads for background file closing\n" % threadcount ) self._queue = pycompat.queue.Queue(maxsize=maxqueue) self._running = True for i in range(threadcount): - t = threading.Thread(target=self._worker, name="backgroundcloser") + t = threading.Thread(target=self._worker, name=b"backgroundcloser") self._threads.append(t) t.start() @@ -680,7 +680,7 @@ """Schedule a file for closing.""" if not self._entered: raise error.Abort( - _("can only call close() when context manager " "active") + _(b"can only call close() when context manager " b"active") ) # If a background thread encountered an exception, raise now so we fail diff --git a/mercurial/win32.py b/mercurial/win32.py --- a/mercurial/win32.py +++ b/mercurial/win32.py @@ -404,7 +404,7 @@ X509_ASN_ENCODING, cert, len(cert) ) if certctx is None: - _raiseoserror("CertCreateCertificateContext") + _raiseoserror(b"CertCreateCertificateContext") flags = 0 @@ -423,7 +423,7 @@ None, # pvReserved ctypes.byref(pchainctx), ): - _raiseoserror("CertGetCertificateChain") + _raiseoserror(b"CertGetCertificateChain") chainctx = pchainctx.contents @@ -543,7 +543,7 @@ t = _kernel32.GetDriveTypeA(volume) if t == _DRIVE_REMOTE: - return "cifs" + return b"cifs" elif t not in ( _DRIVE_REMOVABLE, _DRIVE_FIXED, @@ -663,12 +663,12 @@ pi = _PROCESS_INFORMATION() - env = "" + env = b"" for k in encoding.environ: - env += "%s=%s\0" % (k, encoding.environ[k]) + env += b"%s=%s\0" % (k, encoding.environ[k]) if not env: - env = "\0" - env += "\0" + env = b"\0" + env += b"\0" args = subprocess.list2cmdline(pycompat.rapply(encoding.strfromlocal, args)) @@ -724,7 +724,7 @@ # implicit zombie filename blocking on a temporary name. for tries in pycompat.xrange(10): - temp = "%s-%08x" % (f, random.randint(0, 0xFFFFFFFF)) + temp = b"%s-%08x" % (f, random.randint(0, 0xFFFFFFFF)) try: os.rename(f, temp) # raises OSError EEXIST if temp exists break diff --git a/mercurial/windows.py b/mercurial/windows.py --- a/mercurial/windows.py +++ b/mercurial/windows.py @@ -153,7 +153,7 @@ return getattr(self._fp, name) -def posixfile(name, mode="r", buffering=-1): +def posixfile(name, mode=b"r", buffering=-1): """Open a file with even more POSIX-like semantics""" try: fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError @@ -165,10 +165,10 @@ # The position when opening in append mode is implementation defined, so # make it consistent with other platforms, which position at EOF. - if "a" in mode: + if b"a" in mode: fp.seek(0, os.SEEK_END) - if "+" in mode: + if b"+" in mode: return mixedfilemodewrapper(fp) return fp @@ -230,7 +230,7 @@ try: return sys.getwindowsversion()[3] == 1 except AttributeError: - return "command" in encoding.environ.get("comspec", "") + return b"command" in encoding.environ.get(b"comspec", b"") def openhardlinks(): @@ -240,23 +240,23 @@ def parsepatchoutput(output_line): """parses the output produced by patch and returns the filename""" pf = output_line[14:] - if pf[0] == "`": + if pf[0] == b"`": pf = pf[1:-1] # Remove the quotes return pf def sshargs(sshcmd, host, user, port): """Build argument list for ssh or Plink""" - pflag = "plink" in sshcmd.lower() and "-P" or "-p" - args = user and ("%s@%s" % (user, host)) or host - if args.startswith("-") or args.startswith("/"): + pflag = b"plink" in sshcmd.lower() and b"-P" or b"-p" + args = user and (b"%s@%s" % (user, host)) or host + if args.startswith(b"-") or args.startswith(b"/"): raise error.Abort( - _("illegal ssh hostname or username starting with - or /: %s") + _(b"illegal ssh hostname or username starting with - or /: %s") % args ) args = shellquote(args) if port: - args = "%s %s %s" % (pflag, shellquote(port), args) + args = b"%s %s %s" % (pflag, shellquote(port), args) return args @@ -285,11 +285,11 @@ def pconvert(path): - return path.replace(pycompat.ossep, "/") + return path.replace(pycompat.ossep, b"/") def localpath(path): - return path.replace("/", "\\") + return path.replace(b"/", b"\\") def normpath(path): @@ -407,7 +407,7 @@ and index + 1 < pathlen and path[index + 1 : index + 2] in (b"\\", b"/") ): - res += "%USERPROFILE%" + res += b"%USERPROFILE%" elif ( c == b"\\" and index + 1 < pathlen @@ -483,7 +483,7 @@ """Build a command string suitable for os.popen* calls.""" if sys.version_info < (2, 7, 1): # Python versions since 2.7.1 do this extra quoting themselves - return '"' + cmd + '"' + return b'"' + cmd + b'"' return cmd @@ -499,13 +499,13 @@ PATH isn't searched if command is an absolute or relative path. An extension from PATHEXT is found and added if not present. If command isn't found None is returned.""" - pathext = encoding.environ.get("PATHEXT", ".COM;.EXE;.BAT;.CMD") + pathext = encoding.environ.get(b"PATHEXT", b".COM;.EXE;.BAT;.CMD") pathexts = [ext for ext in pathext.lower().split(pycompat.ospathsep)] if os.path.splitext(command)[1].lower() in pathexts: - pathexts = [""] + pathexts = [b""] def findexisting(pathcommand): - "Will append extension (if needed) and return existing file" + b"Will append extension (if needed) and return existing file" for ext in pathexts: executable = pathcommand + ext if os.path.exists(executable): @@ -515,7 +515,7 @@ if pycompat.ossep in command: return findexisting(command) - for path in encoding.environ.get("PATH", "").split(pycompat.ospathsep): + for path in encoding.environ.get(b"PATH", b"").split(pycompat.ospathsep): executable = findexisting(os.path.join(path, command)) if executable is not None: return executable @@ -536,7 +536,7 @@ nf = normcase(nf) dir, base = os.path.split(nf) if not dir: - dir = "." + dir = b"." cache = dircache.get(dir, None) if cache is None: try: @@ -681,7 +681,7 @@ break chunks.append(s) - return "".join(chunks) + return b"".join(chunks) def bindunixsocket(sock, path): diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py --- a/mercurial/wireprotoframing.py +++ b/mercurial/wireprotoframing.py @@ -127,7 +127,7 @@ val = 1 while value >= val: if value & val: - flags.append(namemap.get(val, "" % val)) + flags.append(namemap.get(val, b"" % val)) val <<= 1 return b"|".join(flags) @@ -158,15 +158,15 @@ @encoding.strmethod def __repr__(self): - typename = "" % self.typeid + typename = b"" % self.typeid for name, value in FRAME_TYPES.iteritems(): if value == self.typeid: typename = name break return ( - "frame(size=%d; request=%d; stream=%d; streamflags=%s; " - "type=%s; flags=%s)" + b"frame(size=%d; request=%d; stream=%d; streamflags=%s; " + b"type=%s; flags=%s)" % ( len(self.payload), self.requestid, @@ -306,7 +306,7 @@ if readcount != FRAME_HEADER_SIZE: raise error.Abort( - _("received incomplete frame: got %d bytes: %s") + _(b"received incomplete frame: got %d bytes: %s") % (readcount, header) ) @@ -315,7 +315,7 @@ payload = fh.read(h.length) if len(payload) != h.length: raise error.Abort( - _("frame length error: expected %d; got %d") + _(b"frame length error: expected %d; got %d") % (h.length, len(payload)) ) @@ -538,13 +538,13 @@ # TODO look for localstr, other types here? if not isinstance(formatting, bytes): - raise ValueError("must use bytes formatting strings") + raise ValueError(b"must use bytes formatting strings") for arg in args: if not isinstance(arg, bytes): - raise ValueError("must use bytes for arguments") + raise ValueError(b"must use bytes for arguments") for label in labels: if not isinstance(label, bytes): - raise ValueError("must use bytes for labels") + raise ValueError(b"must use bytes for labels") # Formatting string must be ASCII. formatting = formatting.decode(r"ascii", r"replace").encode(r"ascii") @@ -568,7 +568,7 @@ payload = b"".join(cborutil.streamencode(atomdicts)) if len(payload) > maxframesize: - raise ValueError("cannot encode data in a single frame") + raise ValueError(b"cannot encode data in a single frame") yield stream.makeframe( requestid=requestid, @@ -710,7 +710,7 @@ def __init__(self, ui, extraobjs): if extraobjs: raise error.Abort( - _("identity decoder received unexpected " "additional values") + _(b"identity decoder received unexpected " b"additional values") ) def decode(self, data): @@ -744,7 +744,7 @@ if extraobjs: raise error.Abort( - _("zlib decoder received unexpected " "additional values") + _(b"zlib decoder received unexpected " b"additional values") ) self._decompressor = zlib.decompressobj() @@ -801,7 +801,7 @@ def __init__(self, ui, extraobjs): if extraobjs: raise error.Abort( - _("zstd8mb decoder received unexpected " "additional values") + _(b"zstd8mb decoder received unexpected " b"additional values") ) super(zstd8mbdecoder, self).__init__(maxwindowsize=8 * 1048576) @@ -872,7 +872,7 @@ decoded from the stream encoding settings frame payloads. """ if name not in STREAM_ENCODERS: - raise error.Abort(_("unknown stream decoder: %s") % name) + raise error.Abort(_(b"unknown stream decoder: %s") % name) self._decoder = STREAM_ENCODERS[name][1](ui, extraobjs) @@ -906,7 +906,7 @@ Receives the stream profile name. """ if name not in STREAM_ENCODERS: - raise error.Abort(_("unknown stream encoder: %s") % name) + raise error.Abort(_(b"unknown stream encoder: %s") % name) self._encoder = STREAM_ENCODERS[name][0](ui) self._encodername = name @@ -979,13 +979,13 @@ def ensureserverstream(stream): if stream.streamid % 2: raise error.ProgrammingError( - "server should only write to even " - "numbered streams; %d is not even" % stream.streamid + b"server should only write to even " + b"numbered streams; %d is not even" % stream.streamid ) DEFAULT_PROTOCOL_SETTINGS = { - "contentencodings": [b"identity"], + b"contentencodings": [b"identity"], } @@ -1066,7 +1066,7 @@ """ self._ui = ui self._deferoutput = deferoutput - self._state = "initial" + self._state = b"initial" self._nextoutgoingstreamid = 2 self._bufferedframegens = [] # stream id -> stream instance for all active streams from the client. @@ -1093,19 +1093,19 @@ if any, the consumer should take next. """ if not frame.streamid % 2: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("received frame with even numbered stream ID: %d") + _(b"received frame with even numbered stream ID: %d") % frame.streamid ) if frame.streamid not in self._incomingstreams: if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "received frame on unknown inactive stream without " - "beginning of stream flag set" + b"received frame on unknown inactive stream without " + b"beginning of stream flag set" ) ) @@ -1113,25 +1113,25 @@ if frame.streamflags & STREAM_FLAG_ENCODING_APPLIED: # TODO handle decoding frames - self._state = "errored" + self._state = b"errored" raise error.ProgrammingError( - "support for decoding stream payloads " "not yet implemented" + b"support for decoding stream payloads " b"not yet implemented" ) if frame.streamflags & STREAM_FLAG_END_STREAM: del self._incomingstreams[frame.streamid] handlers = { - "initial": self._onframeinitial, - "protocol-settings-receiving": self._onframeprotocolsettings, - "idle": self._onframeidle, - "command-receiving": self._onframecommandreceiving, - "errored": self._onframeerrored, + b"initial": self._onframeinitial, + b"protocol-settings-receiving": self._onframeprotocolsettings, + b"idle": self._onframeidle, + b"command-receiving": self._onframecommandreceiving, + b"errored": self._onframeerrored, } meth = handlers.get(self._state) if not meth: - raise error.ProgrammingError("unhandled state: %s" % self._state) + raise error.ProgrammingError(b"unhandled state: %s" % self._state) return meth(frame) @@ -1190,8 +1190,8 @@ for frame in createerrorframe( stream, requestid, - "%s" % stringutil.forcebytestr(e), - errtype="server", + b"%s" % stringutil.forcebytestr(e), + errtype=b"server", ): yield frame @@ -1204,8 +1204,8 @@ if isinstance(o, wireprototypes.alternatelocationresponse): if emitted: raise error.ProgrammingError( - "alternatelocationresponse seen after initial " - "output object" + b"alternatelocationresponse seen after initial " + b"output object" ) frame = stream.makestreamsettingsframe(requestid) @@ -1222,7 +1222,7 @@ if alternatelocationsent: raise error.ProgrammingError( - "object follows alternatelocationresponse" + b"object follows alternatelocationresponse" ) if not emitted: @@ -1266,7 +1266,7 @@ except Exception as e: for frame in createerrorframe( - stream, requestid, "%s" % e, errtype="server" + stream, requestid, b"%s" % e, errtype=b"server" ): yield frame @@ -1285,7 +1285,7 @@ # TODO should we do anything about in-flight commands? if not self._deferoutput or not self._bufferedframegens: - return "noop", {} + return b"noop", {} # If we buffered all our responses, emit those. def makegen(): @@ -1293,21 +1293,21 @@ for frame in gen: yield frame - return "sendframes", {"framegen": makegen(),} + return b"sendframes", {b"framegen": makegen(),} def _handlesendframes(self, framegen): if self._deferoutput: self._bufferedframegens.append(framegen) - return "noop", {} + return b"noop", {} else: - return "sendframes", {"framegen": framegen,} + return b"sendframes", {b"framegen": framegen,} def onservererror(self, stream, requestid, msg): ensureserverstream(stream) def sendframes(): for frame in createerrorframe( - stream, requestid, msg, errtype="server" + stream, requestid, msg, errtype=b"server" ): yield frame @@ -1345,39 +1345,39 @@ # Always use the *server's* preferred encoder over the client's, # as servers have more to lose from sub-optimal encoders being used. for name in STREAM_ENCODERS_ORDER: - if name in self._sendersettings["contentencodings"]: + if name in self._sendersettings[b"contentencodings"]: s.setencoder(self._ui, name) break return s def _makeerrorresult(self, msg): - return "error", {"message": msg,} + return b"error", {b"message": msg,} def _makeruncommandresult(self, requestid): entry = self._receivingcommands[requestid] - if not entry["requestdone"]: - self._state = "errored" + if not entry[b"requestdone"]: + self._state = b"errored" raise error.ProgrammingError( - "should not be called without " "requestdone set" + b"should not be called without " b"requestdone set" ) del self._receivingcommands[requestid] if self._receivingcommands: - self._state = "command-receiving" + self._state = b"command-receiving" else: - self._state = "idle" + self._state = b"idle" # Decode the payloads as CBOR. - entry["payload"].seek(0) - request = cborutil.decodeall(entry["payload"].getvalue())[0] + entry[b"payload"].seek(0) + request = cborutil.decodeall(entry[b"payload"].getvalue())[0] if b"name" not in request: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _('command request missing "name" field') + _(b'command request missing "name" field') ) if b"args" not in request: @@ -1387,70 +1387,70 @@ self._activecommands.add(requestid) return ( - "runcommand", + b"runcommand", { - "requestid": requestid, - "command": request[b"name"], - "args": request[b"args"], - "redirect": request.get(b"redirect"), - "data": entry["data"].getvalue() if entry["data"] else None, + b"requestid": requestid, + b"command": request[b"name"], + b"args": request[b"args"], + b"redirect": request.get(b"redirect"), + b"data": entry[b"data"].getvalue() if entry[b"data"] else None, }, ) def _makewantframeresult(self): - return "wantframe", {"state": self._state,} + return b"wantframe", {b"state": self._state,} def _validatecommandrequestframe(self, frame): new = frame.flags & FLAG_COMMAND_REQUEST_NEW continuation = frame.flags & FLAG_COMMAND_REQUEST_CONTINUATION if new and continuation: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "received command request frame with both new and " - "continuation flags set" + b"received command request frame with both new and " + b"continuation flags set" ) ) if not new and not continuation: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "received command request frame with neither new nor " - "continuation flags set" + b"received command request frame with neither new nor " + b"continuation flags set" ) ) def _onframeinitial(self, frame): # Called when we receive a frame when in the "initial" state. if frame.typeid == FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: - self._state = "protocol-settings-receiving" + self._state = b"protocol-settings-receiving" self._protocolsettingsdecoder = cborutil.bufferingdecoder() return self._onframeprotocolsettings(frame) elif frame.typeid == FRAME_TYPE_COMMAND_REQUEST: - self._state = "idle" + self._state = b"idle" return self._onframeidle(frame) else: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "expected sender protocol settings or command request " - "frame; got %d" + b"expected sender protocol settings or command request " + b"frame; got %d" ) % frame.typeid ) def _onframeprotocolsettings(self, frame): - assert self._state == "protocol-settings-receiving" + assert self._state == b"protocol-settings-receiving" assert self._protocolsettingsdecoder is not None if frame.typeid != FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("expected sender protocol settings frame; got %d") + _(b"expected sender protocol settings frame; got %d") % frame.typeid ) @@ -1458,20 +1458,20 @@ eos = frame.flags & FLAG_SENDER_PROTOCOL_SETTINGS_EOS if more and eos: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "sender protocol settings frame cannot have both " - "continuation and end of stream flags set" + b"sender protocol settings frame cannot have both " + b"continuation and end of stream flags set" ) ) if not more and not eos: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "sender protocol settings frame must have continuation or " - "end of stream flag set" + b"sender protocol settings frame must have continuation or " + b"end of stream flag set" ) ) @@ -1480,9 +1480,11 @@ try: self._protocolsettingsdecoder.decode(frame.payload) except Exception as e: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("error decoding CBOR from sender protocol settings frame: %s") + _( + b"error decoding CBOR from sender protocol settings frame: %s" + ) % stringutil.forcebytestr(e) ) @@ -1495,25 +1497,25 @@ self._protocolsettingsdecoder = None if not decoded: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("sender protocol settings frame did not contain CBOR data") + _(b"sender protocol settings frame did not contain CBOR data") ) elif len(decoded) > 1: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( _( - "sender protocol settings frame contained multiple CBOR " - "values" + b"sender protocol settings frame contained multiple CBOR " + b"values" ) ) d = decoded[0] if b"contentencodings" in d: - self._sendersettings["contentencodings"] = d[b"contentencodings"] + self._sendersettings[b"contentencodings"] = d[b"contentencodings"] - self._state = "idle" + self._state = b"idle" return self._makewantframeresult() @@ -1521,9 +1523,9 @@ # The only frame type that should be received in this state is a # command request. if frame.typeid != FRAME_TYPE_COMMAND_REQUEST: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("expected command request frame; got %d") % frame.typeid + _(b"expected command request frame; got %d") % frame.typeid ) res = self._validatecommandrequestframe(frame) @@ -1531,15 +1533,15 @@ return res if frame.requestid in self._receivingcommands: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("request with ID %d already received") % frame.requestid + _(b"request with ID %d already received") % frame.requestid ) if frame.requestid in self._activecommands: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("request with ID %d is already active") % frame.requestid + _(b"request with ID %d is already active") % frame.requestid ) new = frame.flags & FLAG_COMMAND_REQUEST_NEW @@ -1547,19 +1549,19 @@ expectingdata = frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA if not new: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("received command request frame without new flag set") + _(b"received command request frame without new flag set") ) payload = util.bytesio() payload.write(frame.payload) self._receivingcommands[frame.requestid] = { - "payload": payload, - "data": None, - "requestdone": not moreframes, - "expectingdata": bool(expectingdata), + b"payload": payload, + b"data": None, + b"requestdone": not moreframes, + b"expectingdata": bool(expectingdata), } # This is the final frame for this request. Dispatch it. @@ -1567,7 +1569,7 @@ return self._makeruncommandresult(frame.requestid) assert moreframes or expectingdata - self._state = "command-receiving" + self._state = b"command-receiving" return self._makewantframeresult() def _onframecommandreceiving(self, frame): @@ -1583,16 +1585,16 @@ # All other frames should be related to a command that is currently # receiving but is not active. if frame.requestid in self._activecommands: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("received frame for request that is still active: %d") + _(b"received frame for request that is still active: %d") % frame.requestid ) if frame.requestid not in self._receivingcommands: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("received frame for request that is not receiving: %d") + _(b"received frame for request that is not receiving: %d") % frame.requestid ) @@ -1602,25 +1604,25 @@ moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES expectingdata = bool(frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA) - if entry["requestdone"]: - self._state = "errored" + if entry[b"requestdone"]: + self._state = b"errored" return self._makeerrorresult( _( - "received command request frame when request frames " - "were supposedly done" + b"received command request frame when request frames " + b"were supposedly done" ) ) - if expectingdata != entry["expectingdata"]: - self._state = "errored" + if expectingdata != entry[b"expectingdata"]: + self._state = b"errored" return self._makeerrorresult( - _("mismatch between expect data flag and previous frame") + _(b"mismatch between expect data flag and previous frame") ) - entry["payload"].write(frame.payload) + entry[b"payload"].write(frame.payload) if not moreframes: - entry["requestdone"] = True + entry[b"requestdone"] = True if not moreframes and not expectingdata: return self._makeruncommandresult(frame.requestid) @@ -1628,45 +1630,45 @@ return self._makewantframeresult() elif frame.typeid == FRAME_TYPE_COMMAND_DATA: - if not entry["expectingdata"]: - self._state = "errored" + if not entry[b"expectingdata"]: + self._state = b"errored" return self._makeerrorresult( _( - "received command data frame for request that is not " - "expecting data: %d" + b"received command data frame for request that is not " + b"expecting data: %d" ) % frame.requestid ) - if entry["data"] is None: - entry["data"] = util.bytesio() + if entry[b"data"] is None: + entry[b"data"] = util.bytesio() return self._handlecommanddataframe(frame, entry) else: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("received unexpected frame type: %d") % frame.typeid + _(b"received unexpected frame type: %d") % frame.typeid ) def _handlecommanddataframe(self, frame, entry): assert frame.typeid == FRAME_TYPE_COMMAND_DATA # TODO support streaming data instead of buffering it. - entry["data"].write(frame.payload) + entry[b"data"].write(frame.payload) if frame.flags & FLAG_COMMAND_DATA_CONTINUATION: return self._makewantframeresult() elif frame.flags & FLAG_COMMAND_DATA_EOS: - entry["data"].seek(0) + entry[b"data"].seek(0) return self._makeruncommandresult(frame.requestid) else: - self._state = "errored" + self._state = b"errored" return self._makeerrorresult( - _("command data frame without " "flags") + _(b"command data frame without " b"flags") ) def _onframeerrored(self, frame): - return self._makeerrorresult(_("server already errored")) + return self._makeerrorresult(_(b"server already errored")) class commandrequest(object): @@ -1678,7 +1680,7 @@ self.args = args self.datafh = datafh self.redirect = redirect - self.state = "pending" + self.state = b"pending" class clientreactor(object): @@ -1778,7 +1780,7 @@ Returns a 3-tuple of (request, action, action data). """ if not self._canissuecommands: - raise error.ProgrammingError("cannot issue new commands") + raise error.ProgrammingError(b"cannot issue new commands") requestid = self._nextrequestid self._nextrequestid += 2 @@ -1789,11 +1791,11 @@ if self._buffersends: self._pendingrequests.append(request) - return request, "noop", {} + return request, b"noop", {} else: if not self._cansend: raise error.ProgrammingError( - "sends cannot be performed on " "this instance" + b"sends cannot be performed on " b"this instance" ) if not self._hasmultiplesend: @@ -1802,8 +1804,8 @@ return ( request, - "sendframes", - {"framegen": self._makecommandframes(request),}, + b"sendframes", + {b"framegen": self._makecommandframes(request),}, ) def flushcommands(self): @@ -1817,11 +1819,11 @@ requests are allowed after this is called. """ if not self._pendingrequests: - return "noop", {} + return b"noop", {} if not self._cansend: raise error.ProgrammingError( - "sends cannot be performed on this " "instance" + b"sends cannot be performed on this " b"instance" ) # If the instance only allows sending once, mark that we have fired @@ -1836,7 +1838,7 @@ for frame in self._makecommandframes(request): yield frame - return "sendframes", {"framegen": makeframes(),} + return b"sendframes", {b"framegen": makeframes(),} def _makecommandframes(self, request): """Emit frames to issue a command request. @@ -1845,7 +1847,7 @@ state. """ self._activerequests[request.requestid] = request - request.state = "sending" + request.state = b"sending" if not self._protocolsettingssent and self._clientcontentencoders: self._protocolsettingssent = True @@ -1875,7 +1877,7 @@ for frame in res: yield frame - request.state = "sent" + request.state = b"sent" def onframerecv(self, frame): """Process a frame that has been received off the wire. @@ -1885,10 +1887,10 @@ """ if frame.streamid % 2: return ( - "error", + b"error", { - "message": ( - _("received frame with odd numbered stream ID: %d") + b"message": ( + _(b"received frame with odd numbered stream ID: %d") % frame.streamid ), }, @@ -1897,11 +1899,11 @@ if frame.streamid not in self._incomingstreams: if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: return ( - "error", + b"error", { - "message": _( - "received frame on unknown stream " - "without beginning of stream flag set" + b"message": _( + b"received frame on unknown stream " + b"without beginning of stream flag set" ), }, ) @@ -1924,17 +1926,17 @@ if frame.requestid not in self._activerequests: return ( - "error", + b"error", { - "message": ( - _("received frame for inactive request ID: %d") + b"message": ( + _(b"received frame for inactive request ID: %d") % frame.requestid ), }, ) request = self._activerequests[frame.requestid] - request.state = "receiving" + request.state = b"receiving" handlers = { FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, @@ -1944,7 +1946,7 @@ meth = handlers.get(frame.typeid) if not meth: raise error.ProgrammingError( - "unhandled frame type: %d" % frame.typeid + b"unhandled frame type: %d" % frame.typeid ) return meth(request, frame) @@ -1957,12 +1959,12 @@ if more and eos: return ( - "error", + b"error", { - "message": ( + b"message": ( _( - "stream encoding settings frame cannot have both " - "continuation and end of stream flags set" + b"stream encoding settings frame cannot have both " + b"continuation and end of stream flags set" ) ), }, @@ -1970,11 +1972,11 @@ if not more and not eos: return ( - "error", + b"error", { - "message": _( - "stream encoding settings frame must have " - "continuation or end of stream flag set" + b"message": _( + b"stream encoding settings frame must have " + b"continuation or end of stream flag set" ), }, ) @@ -1989,12 +1991,12 @@ decoder.decode(frame.payload) except Exception as e: return ( - "error", + b"error", { - "message": ( + b"message": ( _( - "error decoding CBOR from stream encoding " - "settings frame: %s" + b"error decoding CBOR from stream encoding " + b"settings frame: %s" ) % stringutil.forcebytestr(e) ), @@ -2002,7 +2004,7 @@ ) if more: - return "noop", {} + return b"noop", {} assert eos @@ -2011,11 +2013,11 @@ if not decoded: return ( - "error", + b"error", { - "message": _( - "stream encoding settings frame did not contain " - "CBOR data" + b"message": _( + b"stream encoding settings frame did not contain " + b"CBOR data" ), }, ) @@ -2026,40 +2028,44 @@ ) except Exception as e: return ( - "error", + b"error", { - "message": ( - _("error setting stream decoder: %s") + b"message": ( + _(b"error setting stream decoder: %s") % stringutil.forcebytestr(e) ), }, ) - return "noop", {} + return b"noop", {} def _oncommandresponseframe(self, request, frame): if frame.flags & FLAG_COMMAND_RESPONSE_EOS: - request.state = "received" + request.state = b"received" del self._activerequests[request.requestid] return ( - "responsedata", + b"responsedata", { - "request": request, - "expectmore": frame.flags & FLAG_COMMAND_RESPONSE_CONTINUATION, - "eos": frame.flags & FLAG_COMMAND_RESPONSE_EOS, - "data": frame.payload, + b"request": request, + b"expectmore": frame.flags & FLAG_COMMAND_RESPONSE_CONTINUATION, + b"eos": frame.flags & FLAG_COMMAND_RESPONSE_EOS, + b"data": frame.payload, }, ) def _onerrorresponseframe(self, request, frame): - request.state = "errored" + request.state = b"errored" del self._activerequests[request.requestid] # The payload should be a CBOR map. m = cborutil.decodeall(frame.payload)[0] return ( - "error", - {"request": request, "type": m["type"], "message": m["message"],}, + b"error", + { + b"request": request, + b"type": m[b"type"], + b"message": m[b"message"], + }, ) diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -34,9 +34,9 @@ HTTP_OK = 200 -HGTYPE = "application/mercurial-0.1" -HGTYPE2 = "application/mercurial-0.2" -HGERRTYPE = "application/hg-error" +HGTYPE = b"application/mercurial-0.1" +HGTYPE2 = b"application/mercurial-0.2" +HGERRTYPE = b"application/hg-error" SSHV1 = wireprototypes.SSHV1 SSHV2 = wireprototypes.SSHV2 @@ -56,7 +56,7 @@ chunks.append(pycompat.bytesurl(v)) i += 1 - return "".join(chunks) + return b"".join(chunks) @interfaceutil.implementer(wireprototypes.baseprotocolhandler) @@ -69,19 +69,19 @@ @property def name(self): - return "http-v1" + return b"http-v1" def getargs(self, args): knownargs = self._args() data = {} keys = args.split() for k in keys: - if k == "*": + if k == b"*": star = {} for key in knownargs.keys(): - if key != "cmd" and key not in keys: + if key != b"cmd" and key not in keys: star[key] = knownargs[key][0] - data["*"] = star + data[b"*"] = star else: data[k] = knownargs[k][0] return [data[k] for k in keys] @@ -104,7 +104,7 @@ def getprotocaps(self): if self._protocaps is None: value = decodevaluefromheaders(self._req, b"X-HgProto") - self._protocaps = set(value.split(" ")) + self._protocaps = set(value.split(b" ")) return self._protocaps def getpayload(self): @@ -132,33 +132,33 @@ self._ui.ferr = olderr def client(self): - return "remote:%s:%s:%s" % ( + return b"remote:%s:%s:%s" % ( self._req.urlscheme, - urlreq.quote(self._req.remotehost or ""), - urlreq.quote(self._req.remoteuser or ""), + urlreq.quote(self._req.remotehost or b""), + urlreq.quote(self._req.remoteuser or b""), ) def addcapabilities(self, repo, caps): caps.append(b"batch") caps.append( - "httpheader=%d" % repo.ui.configint("server", "maxhttpheaderlen") + b"httpheader=%d" % repo.ui.configint(b"server", b"maxhttpheaderlen") ) - if repo.ui.configbool("experimental", "httppostargs"): - caps.append("httppostargs") + if repo.ui.configbool(b"experimental", b"httppostargs"): + caps.append(b"httppostargs") # FUTURE advertise 0.2rx once support is implemented # FUTURE advertise minrx and mintx after consulting config option - caps.append("httpmediatype=0.1rx,0.1tx,0.2tx") + caps.append(b"httpmediatype=0.1rx,0.1tx,0.2tx") compengines = wireprototypes.supportedcompengines( repo.ui, compression.SERVERROLE ) if compengines: - comptypes = ",".join( + comptypes = b",".join( urlreq.quote(e.wireprotosupport().name) for e in compengines ) - caps.append("compression=%s" % comptypes) + caps.append(b"compression=%s" % comptypes) return caps @@ -194,10 +194,10 @@ # HTTP version 1 wire protocol requests are denoted by a "cmd" query # string parameter. If it isn't present, this isn't a wire protocol # request. - if "cmd" not in req.qsparams: + if b"cmd" not in req.qsparams: return False - cmd = req.qsparams["cmd"] + cmd = req.qsparams[b"cmd"] # The "cmd" request parameter is used by both the wire protocol and hgweb. # While not all wire protocol commands are available for all transports, @@ -215,10 +215,10 @@ # in this case. We send an HTTP 404 for backwards compatibility reasons. if req.dispatchpath: res.status = hgwebcommon.statusmessage(404) - res.headers["Content-Type"] = HGTYPE + res.headers[b"Content-Type"] = HGTYPE # TODO This is not a good response to issue for this request. This # is mostly for BC for now. - res.setbodybytes("0\n%s\n" % b"Not Found") + res.setbodybytes(b"0\n%s\n" % b"Not Found") return True proto = httpv1protocolhandler( @@ -237,7 +237,7 @@ res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e)) # TODO This response body assumes the failed command was # "unbundle." That assumption is not always valid. - res.setbodybytes("0\n%s\n" % pycompat.bytestr(e)) + res.setbodybytes(b"0\n%s\n" % pycompat.bytestr(e)) return True @@ -248,7 +248,7 @@ # Registered APIs are made available via config options of the name of # the protocol. for k, v in API_HANDLERS.items(): - section, option = v["config"] + section, option = v[b"config"] if repo.ui.configbool(section, option): apis.add(k) @@ -263,10 +263,10 @@ # This whole URL space is experimental for now. But we want to # reserve the URL space. So, 404 all URLs if the feature isn't enabled. - if not repo.ui.configbool("experimental", "web.apiserver"): + if not repo.ui.configbool(b"experimental", b"web.apiserver"): res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("Experimental API server endpoint not enabled")) + res.setbodybytes(_(b"Experimental API server endpoint not enabled")) return # The URL space is /api//*. The structure of URLs under varies @@ -280,14 +280,14 @@ res.headers[b"Content-Type"] = b"text/plain" lines = [ _( - "APIs can be accessed at /api/, where can be " - "one of the following:\n" + b"APIs can be accessed at /api/, where can be " + b"one of the following:\n" ) ] if availableapis: lines.extend(sorted(availableapis)) else: - lines.append(_("(no available APIs)\n")) + lines.append(_(b"(no available APIs)\n")) res.setbodybytes(b"\n".join(lines)) return @@ -297,7 +297,7 @@ res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("Unknown API: %s\nKnown APIs: %s") + _(b"Unknown API: %s\nKnown APIs: %s") % (proto, b", ".join(sorted(availableapis))) ) return @@ -305,10 +305,10 @@ if proto not in availableapis: res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("API %s not enabled\n") % proto) + res.setbodybytes(_(b"API %s not enabled\n") % proto) return - API_HANDLERS[proto]["handler"]( + API_HANDLERS[proto][b"handler"]( rctx, req, res, checkperm, req.dispatchparts[2:] ) @@ -326,9 +326,9 @@ # descriptor for this service. The response must be serializable to CBOR. API_HANDLERS = { wireprotov2server.HTTP_WIREPROTO_V2: { - "config": ("experimental", "web.api.http-v2"), - "handler": wireprotov2server.handlehttpv2request, - "apidescriptor": wireprotov2server.httpv2apidescriptor, + b"config": (b"experimental", b"web.api.http-v2"), + b"handler": wireprotov2server.handlehttpv2request, + b"apidescriptor": wireprotov2server.httpv2apidescriptor, }, } @@ -341,7 +341,7 @@ # Determine the response media type and compression engine based # on the request parameters. - if "0.2" in proto.getprotocaps(): + if b"0.2" in proto.getprotocaps(): # All clients are expected to support uncompressed data. if prefer_uncompressed: return HGTYPE2, compression._noopengine(), {} @@ -353,9 +353,9 @@ ): if engine.wireprotosupport().name in compformats: opts = {} - level = ui.configint("server", "%slevel" % engine.name()) + level = ui.configint(b"server", b"%slevel" % engine.name()) if level is not None: - opts["level"] = level + opts[b"level"] = level return HGTYPE2, engine, opts @@ -365,8 +365,8 @@ # Don't allow untrusted settings because disabling compression or # setting a very high compression level could lead to flooding # the server's network or CPU. - opts = {"level": ui.configint("server", "zliblevel")} - return HGTYPE, util.compengines["zlib"], opts + opts = {b"level": ui.configint(b"server", b"zliblevel")} + return HGTYPE, util.compengines[b"zlib"], opts def processcapabilitieshandshake(repo, req, res, proto): @@ -377,7 +377,7 @@ advertised services are available, we don't handle the request. """ # Fall back to old behavior unless the API server is enabled. - if not repo.ui.configbool("experimental", "web.apiserver"): + if not repo.ui.configbool(b"experimental", b"web.apiserver"): return False clientapis = decodevaluefromheaders(req, b"X-HgUpgrade") @@ -386,7 +386,7 @@ return False # We currently only support CBOR responses. - protocaps = set(protocaps.split(" ")) + protocaps = set(protocaps.split(b" ")) if b"cbor" not in protocaps: return False @@ -395,20 +395,20 @@ for api in sorted(set(clientapis.split()) & _availableapis(repo)): handler = API_HANDLERS[api] - descriptorfn = handler.get("apidescriptor") + descriptorfn = handler.get(b"apidescriptor") if not descriptorfn: continue descriptors[api] = descriptorfn(req, repo) - v1caps = wireprotov1server.dispatch(repo, proto, "capabilities") + v1caps = wireprotov1server.dispatch(repo, proto, b"capabilities") assert isinstance(v1caps, wireprototypes.bytesresponse) m = { # TODO allow this to be configurable. - "apibase": "api/", - "apis": descriptors, - "v1capabilities": v1caps.data, + b"apibase": b"api/", + b"apis": descriptors, + b"v1capabilities": v1caps.data, } res.status = b"200 OK" @@ -427,7 +427,7 @@ # identifying the compression engine. name = engine.wireprotosupport().name assert 0 < len(name) < 256 - yield struct.pack("B", len(name)) + yield struct.pack(b"B", len(name)) yield name for chunk in gen: @@ -435,11 +435,11 @@ def setresponse(code, contenttype, bodybytes=None, bodygen=None): if code == HTTP_OK: - res.status = "200 Script output follows" + res.status = b"200 Script output follows" else: res.status = hgwebcommon.statusmessage(code) - res.headers["Content-Type"] = contenttype + res.headers[b"Content-Type"] = contenttype if bodybytes is not None: res.setbodybytes(bodybytes) @@ -450,14 +450,17 @@ setresponse( HTTP_OK, HGERRTYPE, - _("requested wire protocol command is not available over " "HTTP"), + _( + b"requested wire protocol command is not available over " + b"HTTP" + ), ) return proto.checkperm(wireprotov1server.commands[cmd].permission) # Possibly handle a modern client wanting to switch protocols. - if cmd == "capabilities" and processcapabilitieshandshake( + if cmd == b"capabilities" and processcapabilitieshandshake( repo, req, res, proto ): @@ -486,21 +489,21 @@ setresponse(HTTP_OK, mediatype, bodygen=gen) elif isinstance(rsp, wireprototypes.pushres): - rsp = "%d\n%s" % (rsp.res, rsp.output) + rsp = b"%d\n%s" % (rsp.res, rsp.output) setresponse(HTTP_OK, HGTYPE, bodybytes=rsp) elif isinstance(rsp, wireprototypes.pusherr): - rsp = "0\n%s\n" % rsp.res + rsp = b"0\n%s\n" % rsp.res res.drain = True setresponse(HTTP_OK, HGTYPE, bodybytes=rsp) elif isinstance(rsp, wireprototypes.ooberror): setresponse(HTTP_OK, HGERRTYPE, bodybytes=rsp.message) else: - raise error.ProgrammingError("hgweb.protocol internal failure", rsp) + raise error.ProgrammingError(b"hgweb.protocol internal failure", rsp) def _sshv1respondbytes(fout, value): """Send a bytes response for protocol version 1.""" - fout.write("%d\n" % len(value)) + fout.write(b"%d\n" % len(value)) fout.write(value) fout.flush() @@ -540,15 +543,15 @@ argline = self._fin.readline()[:-1] arg, l = argline.split() if arg not in keys: - raise error.Abort(_("unexpected parameter %r") % arg) - if arg == "*": + raise error.Abort(_(b"unexpected parameter %r") % arg) + if arg == b"*": star = {} for k in pycompat.xrange(int(l)): argline = self._fin.readline()[:-1] arg, l = argline.split() val = self._fin.read(int(l)) star[arg] = val - data["*"] = star + data[b"*"] = star else: val = self._fin.read(int(l)) data[arg] = val @@ -578,8 +581,8 @@ yield None def client(self): - client = encoding.environ.get("SSH_CLIENT", "").split(" ", 1)[0] - return "remote:ssh:" + client + client = encoding.environ.get(b"SSH_CLIENT", b"").split(b" ", 1)[0] + return b"remote:ssh:" + client def addcapabilities(self, repo, caps): if self.name == wireprototypes.SSHV1: @@ -655,18 +658,18 @@ # Ths happens by default since protocol version 2 is the same as # version 1 except for the handshake. - state = "protov1-serving" + state = b"protov1-serving" proto = sshv1protocolhandler(ui, fin, fout) protoswitched = False while not ev.is_set(): - if state == "protov1-serving": + if state == b"protov1-serving": # Commands are issued on new lines. request = fin.readline()[:-1] # Empty lines signal to terminate the connection. if not request: - state = "shutdown" + state = b"shutdown" continue # It looks like a protocol upgrade request. Transition state to @@ -678,10 +681,10 @@ ui.ferr, b"cannot upgrade protocols multiple " b"times", ) - state = "shutdown" + state = b"shutdown" continue - state = "upgrade-initial" + state = b"upgrade-initial" continue available = wireprotov1server.commands.commandavailable( @@ -715,16 +718,16 @@ _sshv1respondooberror(fout, ui.ferr, rsp.message) else: raise error.ProgrammingError( - "unhandled response type from " - "wire protocol command: %s" % rsp + b"unhandled response type from " + b"wire protocol command: %s" % rsp ) # For now, protocol version 2 serving just goes back to version 1. - elif state == "protov2-serving": - state = "protov1-serving" + elif state == b"protov2-serving": + state = b"protov1-serving" continue - elif state == "upgrade-initial": + elif state == b"upgrade-initial": # We should never transition into this state if we've switched # protocols. assert not protoswitched @@ -738,20 +741,20 @@ token, caps = request.split(b" ")[1:] except ValueError: _sshv1respondbytes(fout, b"") - state = "protov1-serving" + state = b"protov1-serving" continue # Send empty response if we don't support upgrading protocols. - if not ui.configbool("experimental", "sshserver.support-v2"): + if not ui.configbool(b"experimental", b"sshserver.support-v2"): _sshv1respondbytes(fout, b"") - state = "protov1-serving" + state = b"protov1-serving" continue try: caps = urlreq.parseqs(caps) except ValueError: _sshv1respondbytes(fout, b"") - state = "protov1-serving" + state = b"protov1-serving" continue # We don't see an upgrade request to protocol version 2. Ignore @@ -759,15 +762,15 @@ wantedprotos = caps.get(b"proto", [b""])[0] if SSHV2 not in wantedprotos: _sshv1respondbytes(fout, b"") - state = "protov1-serving" + state = b"protov1-serving" continue # It looks like we can honor this upgrade request to protocol 2. # Filter the rest of the handshake protocol request lines. - state = "upgrade-v2-filter-legacy-handshake" + state = b"upgrade-v2-filter-legacy-handshake" continue - elif state == "upgrade-v2-filter-legacy-handshake": + elif state == b"upgrade-v2-filter-legacy-handshake": # Client should have sent legacy handshake after an ``upgrade`` # request. Expected lines: # @@ -787,7 +790,7 @@ b"malformed handshake protocol: " b"missing %s" % line, ) ok = False - state = "shutdown" + state = b"shutdown" break if not ok: @@ -801,13 +804,13 @@ b"malformed handshake protocol: " b"missing between argument value", ) - state = "shutdown" + state = b"shutdown" continue - state = "upgrade-v2-finish" + state = b"upgrade-v2-finish" continue - elif state == "upgrade-v2-finish": + elif state == b"upgrade-v2-finish": # Send the upgrade response. fout.write(b"upgraded %s %s\n" % (token, SSHV2)) servercaps = wireprotov1server.capabilities(repo, proto) @@ -818,15 +821,15 @@ proto = sshv2protocolhandler(ui, fin, fout) protoswitched = True - state = "protov2-serving" + state = b"protov2-serving" continue - elif state == "shutdown": + elif state == b"shutdown": break else: raise error.ProgrammingError( - "unhandled ssh server state: %s" % state + b"unhandled ssh server state: %s" % state ) @@ -839,10 +842,10 @@ # Log write I/O to stdout and stderr if configured. if logfh: self._fout = util.makeloggingfileobject( - logfh, self._fout, "o", logdata=True + logfh, self._fout, b"o", logdata=True ) ui.ferr = util.makeloggingfileobject( - logfh, ui.ferr, "e", logdata=True + logfh, ui.ferr, b"e", logdata=True ) def serve_forever(self): diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py --- a/mercurial/wireprototypes.py +++ b/mercurial/wireprototypes.py @@ -19,27 +19,27 @@ from .utils import compression # Names of the SSH protocol implementations. -SSHV1 = "ssh-v1" +SSHV1 = b"ssh-v1" # These are advertised over the wire. Increment the counters at the end # to reflect BC breakages. -SSHV2 = "exp-ssh-v2-0003" -HTTP_WIREPROTO_V2 = "exp-http-v2-0003" +SSHV2 = b"exp-ssh-v2-0003" +HTTP_WIREPROTO_V2 = b"exp-http-v2-0003" -NARROWCAP = "exp-narrow-1" -ELLIPSESCAP1 = "exp-ellipses-1" -ELLIPSESCAP = "exp-ellipses-2" +NARROWCAP = b"exp-narrow-1" +ELLIPSESCAP1 = b"exp-ellipses-1" +ELLIPSESCAP = b"exp-ellipses-2" SUPPORTED_ELLIPSESCAP = (ELLIPSESCAP1, ELLIPSESCAP) # All available wire protocol transports. TRANSPORTS = { - SSHV1: {"transport": "ssh", "version": 1,}, + SSHV1: {b"transport": b"ssh", b"version": 1,}, SSHV2: { - "transport": "ssh", + b"transport": b"ssh", # TODO mark as version 2 once all commands are implemented. - "version": 1, + b"version": 1, }, - "http-v1": {"transport": "http", "version": 1,}, - HTTP_WIREPROTO_V2: {"transport": "http", "version": 2,}, + b"http-v1": {b"transport": b"http", b"version": 1,}, + HTTP_WIREPROTO_V2: {b"transport": b"http", b"version": 2,}, } @@ -116,13 +116,13 @@ # list of nodes encoding / decoding -def decodelist(l, sep=" "): +def decodelist(l, sep=b" "): if l: return [bin(v) for v in l.split(sep)] return [] -def encodelist(l, sep=" "): +def encodelist(l, sep=b" "): try: return sep.join(map(hex, l)) except TypeError: @@ -134,19 +134,19 @@ def escapebatcharg(plain): return ( - plain.replace(":", ":c") - .replace(",", ":o") - .replace(";", ":s") - .replace("=", ":e") + plain.replace(b":", b":c") + .replace(b",", b":o") + .replace(b";", b":s") + .replace(b"=", b":e") ) def unescapebatcharg(escaped): return ( - escaped.replace(":e", "=") - .replace(":s", ";") - .replace(":o", ",") - .replace(":c", ":") + escaped.replace(b":e", b"=") + .replace(b":s", b";") + .replace(b":o", b",") + .replace(b":c", b":") ) @@ -162,18 +162,18 @@ # :scsv: set of values, transmitted as comma-separated values # :plain: string with no transformation needed. GETBUNDLE_ARGUMENTS = { - "heads": "nodes", - "bookmarks": "boolean", - "common": "nodes", - "obsmarkers": "boolean", - "phases": "boolean", - "bundlecaps": "scsv", - "listkeys": "csv", - "cg": "boolean", - "cbattempted": "boolean", - "stream": "boolean", - "includepats": "csv", - "excludepats": "csv", + b"heads": b"nodes", + b"bookmarks": b"boolean", + b"common": b"nodes", + b"obsmarkers": b"boolean", + b"phases": b"boolean", + b"bundlecaps": b"scsv", + b"listkeys": b"csv", + b"cg": b"boolean", + b"cbattempted": b"boolean", + b"stream": b"boolean", + b"includepats": b"csv", + b"excludepats": b"csv", } @@ -253,9 +253,9 @@ def __init__( self, func, - args="", + args=b"", transports=None, - permission="push", + permission=b"push", cachekeyfn=None, extracapabilitiesfn=None, ): @@ -292,7 +292,7 @@ elif i == 1: return self.args else: - raise IndexError("can only access elements 0 and 1") + raise IndexError(b"can only access elements 0 and 1") class commanddict(dict): @@ -308,7 +308,7 @@ # Cast 2-tuples to commandentry instances. elif isinstance(v, tuple): if len(v) != 2: - raise ValueError("command tuples must have exactly 2 elements") + raise ValueError(b"command tuples must have exactly 2 elements") # It is common for extensions to wrap wire protocol commands via # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers @@ -322,11 +322,12 @@ v[0], args=v[1], transports=set(TRANSPORTS), - permission="push", + permission=b"push", ) else: raise ValueError( - "command entries must be commandentry instances " "or 2-tuples" + b"command entries must be commandentry instances " + b"or 2-tuples" ) return super(commanddict, self).__setitem__(k, v) @@ -354,8 +355,8 @@ # Allow config to override default list and ordering. if role == compression.SERVERROLE: - configengines = ui.configlist("server", "compressionengines") - config = "server.compressionengines" + configengines = ui.configlist(b"server", b"compressionengines") + config = b"server.compressionengines" else: # This is currently implemented mainly to facilitate testing. In most # cases, the server should be in charge of choosing a compression engine @@ -363,14 +364,16 @@ # CPU DoS due to an expensive engine or a network DoS due to poor # compression ratio). configengines = ui.configlist( - "experimental", "clientcompressionengines" + b"experimental", b"clientcompressionengines" ) - config = "experimental.clientcompressionengines" + config = b"experimental.clientcompressionengines" # No explicit config. Filter out the ones that aren't supposed to be # advertised and return default ordering. if not configengines: - attr = "serverpriority" if role == util.SERVERROLE else "clientpriority" + attr = ( + b"serverpriority" if role == util.SERVERROLE else b"clientpriority" + ) return [ e for e in compengines if getattr(e.wireprotosupport(), attr) > 0 ] @@ -383,8 +386,8 @@ invalidnames = set(e for e in configengines if e not in validnames) if invalidnames: raise error.Abort( - _("invalid compression engine defined in %s: %s") - % (config, ", ".join(sorted(invalidnames))) + _(b"invalid compression engine defined in %s: %s") + % (config, b", ".join(sorted(invalidnames))) ) compengines = [e for e in compengines if e.name() in configengines] @@ -395,11 +398,12 @@ if not compengines: raise error.Abort( _( - "%s config option does not specify any known " - "compression engines" + b"%s config option does not specify any known " + b"compression engines" ) % config, - hint=_("usable compression engines: %s") % ", ".sorted(validnames), + hint=_(b"usable compression engines: %s") + % b", ".sorted(validnames), ) return compengines diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py --- a/mercurial/wireprotov1peer.py +++ b/mercurial/wireprotov1peer.py @@ -73,8 +73,8 @@ """placeholder for a value to be set later""" def set(self, value): - if util.safehasattr(self, "value"): - raise error.RepoError("future is already set") + if util.safehasattr(self, b"value"): + raise error.RepoError(b"future is already set") self.value = value @@ -89,13 +89,13 @@ # servers. assert all(escapearg(k) == k for k in argsdict) - args = ",".join( - "%s=%s" % (escapearg(k), escapearg(v)) + args = b",".join( + b"%s=%s" % (escapearg(k), escapearg(v)) for k, v in argsdict.iteritems() ) - cmds.append("%s %s" % (op, args)) + cmds.append(b"%s %s" % (op, args)) - return ";".join(cmds) + return b";".join(cmds) class unsentfuture(pycompat.futures.Future): @@ -139,12 +139,12 @@ def callcommand(self, command, args): if self._sent: raise error.ProgrammingError( - "callcommand() cannot be used " "after commands are sent" + b"callcommand() cannot be used " b"after commands are sent" ) if self._closed: raise error.ProgrammingError( - "callcommand() cannot be used " "after close()" + b"callcommand() cannot be used " b"after close()" ) # Commands are dispatched through methods on the peer. @@ -152,8 +152,8 @@ if not fn: raise error.ProgrammingError( - "cannot call command %s: method of same name not available " - "on peer" % command + b"cannot call command %s: method of same name not available " + b"on peer" % command ) # Commands are either batchable or they aren't. If a command @@ -179,8 +179,8 @@ else: if self._calls: raise error.ProgrammingError( - "%s is not batchable and cannot be called on a command " - "executor along with other commands" % command + b"%s is not batchable and cannot be called on a command " + b"executor along with other commands" % command ) f = addcall() @@ -306,7 +306,7 @@ if not f.done(): f.set_exception( error.ResponseError( - _("unfulfilled batch command response") + _(b"unfulfilled batch command response") ) ) @@ -348,16 +348,16 @@ # Begin of ipeercommands interface. def clonebundles(self): - self.requirecap("clonebundles", _("clone bundles")) - return self._call("clonebundles") + self.requirecap(b"clonebundles", _(b"clone bundles")) + return self._call(b"clonebundles") @batchable def lookup(self, key): - self.requirecap("lookup", _("look up remote revision")) + self.requirecap(b"lookup", _(b"look up remote revision")) f = future() - yield {"key": encoding.fromlocal(key)}, f + yield {b"key": encoding.fromlocal(key)}, f d = f.value - success, data = d[:-1].split(" ", 1) + success, data = d[:-1].split(b" ", 1) if int(success): yield bin(data) else: @@ -371,17 +371,17 @@ try: yield wireprototypes.decodelist(d[:-1]) except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), d)) + self._abort(error.ResponseError(_(b"unexpected response:"), d)) @batchable def known(self, nodes): f = future() - yield {"nodes": wireprototypes.encodelist(nodes)}, f + yield {b"nodes": wireprototypes.encodelist(nodes)}, f d = f.value try: yield [bool(int(b)) for b in pycompat.iterbytestr(d)] except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), d)) + self._abort(error.ResponseError(_(b"unexpected response:"), d)) @batchable def branchmap(self): @@ -391,83 +391,83 @@ try: branchmap = {} for branchpart in d.splitlines(): - branchname, branchheads = branchpart.split(" ", 1) + branchname, branchheads = branchpart.split(b" ", 1) branchname = encoding.tolocal(urlreq.unquote(branchname)) branchheads = wireprototypes.decodelist(branchheads) branchmap[branchname] = branchheads yield branchmap except TypeError: - self._abort(error.ResponseError(_("unexpected response:"), d)) + self._abort(error.ResponseError(_(b"unexpected response:"), d)) @batchable def listkeys(self, namespace): - if not self.capable("pushkey"): + if not self.capable(b"pushkey"): yield {}, None f = future() - self.ui.debug('preparing listkeys for "%s"\n' % namespace) - yield {"namespace": encoding.fromlocal(namespace)}, f + self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) + yield {b"namespace": encoding.fromlocal(namespace)}, f d = f.value self.ui.debug( - 'received listkey for "%s": %i bytes\n' % (namespace, len(d)) + b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) ) yield pushkeymod.decodekeys(d) @batchable def pushkey(self, namespace, key, old, new): - if not self.capable("pushkey"): + if not self.capable(b"pushkey"): yield False, None f = future() - self.ui.debug('preparing pushkey for "%s:%s"\n' % (namespace, key)) + self.ui.debug(b'preparing pushkey for "%s:%s"\n' % (namespace, key)) yield { - "namespace": encoding.fromlocal(namespace), - "key": encoding.fromlocal(key), - "old": encoding.fromlocal(old), - "new": encoding.fromlocal(new), + b"namespace": encoding.fromlocal(namespace), + b"key": encoding.fromlocal(key), + b"old": encoding.fromlocal(old), + b"new": encoding.fromlocal(new), }, f d = f.value - d, output = d.split("\n", 1) + d, output = d.split(b"\n", 1) try: d = bool(int(d)) except ValueError: raise error.ResponseError( - _("push failed (unexpected response):"), d + _(b"push failed (unexpected response):"), d ) for l in output.splitlines(True): - self.ui.status(_("remote: "), l) + self.ui.status(_(b"remote: "), l) yield d def stream_out(self): - return self._callstream("stream_out") + return self._callstream(b"stream_out") def getbundle(self, source, **kwargs): kwargs = pycompat.byteskwargs(kwargs) - self.requirecap("getbundle", _("look up remote changes")) + self.requirecap(b"getbundle", _(b"look up remote changes")) opts = {} - bundlecaps = kwargs.get("bundlecaps") or set() + bundlecaps = kwargs.get(b"bundlecaps") or set() for key, value in kwargs.iteritems(): if value is None: continue keytype = wireprototypes.GETBUNDLE_ARGUMENTS.get(key) if keytype is None: raise error.ProgrammingError( - "Unexpectedly None keytype for key %s" % key + b"Unexpectedly None keytype for key %s" % key ) - elif keytype == "nodes": + elif keytype == b"nodes": value = wireprototypes.encodelist(value) - elif keytype == "csv": - value = ",".join(value) - elif keytype == "scsv": - value = ",".join(sorted(value)) - elif keytype == "boolean": - value = "%i" % bool(value) - elif keytype != "plain": - raise KeyError("unknown getbundle option type %s" % keytype) + elif keytype == b"csv": + value = b",".join(value) + elif keytype == b"scsv": + value = b",".join(sorted(value)) + elif keytype == b"boolean": + value = b"%i" % bool(value) + elif keytype != b"plain": + raise KeyError(b"unknown getbundle option type %s" % keytype) opts[key] = value - f = self._callcompressable("getbundle", **pycompat.strkwargs(opts)) - if any((cap.startswith("HG2") for cap in bundlecaps)): + f = self._callcompressable(b"getbundle", **pycompat.strkwargs(opts)) + if any((cap.startswith(b"HG2") for cap in bundlecaps)): return bundle2.getunbundler(self.ui, f) else: - return changegroupmod.cg1unpacker(f, "UN") + return changegroupmod.cg1unpacker(f, b"UN") def unbundle(self, bundle, heads, url): """Send cg (a readable file-like object representing the @@ -483,30 +483,30 @@ visible to hooks. """ - if heads != ["force"] and self.capable("unbundlehash"): + if heads != [b"force"] and self.capable(b"unbundlehash"): heads = wireprototypes.encodelist( - ["hashed", hashlib.sha1("".join(sorted(heads))).digest()] + [b"hashed", hashlib.sha1(b"".join(sorted(heads))).digest()] ) else: heads = wireprototypes.encodelist(heads) - if util.safehasattr(bundle, "deltaheader"): + if util.safehasattr(bundle, b"deltaheader"): # this a bundle10, do the old style call sequence - ret, output = self._callpush("unbundle", bundle, heads=heads) - if ret == "": - raise error.ResponseError(_("push failed:"), output) + ret, output = self._callpush(b"unbundle", bundle, heads=heads) + if ret == b"": + raise error.ResponseError(_(b"push failed:"), output) try: ret = int(ret) except ValueError: raise error.ResponseError( - _("push failed (unexpected response):"), ret + _(b"push failed (unexpected response):"), ret ) for l in output.splitlines(True): - self.ui.status(_("remote: "), l) + self.ui.status(_(b"remote: "), l) else: # bundle2 push. Send a stream, fetch a stream. - stream = self._calltwowaystream("unbundle", bundle, heads=heads) + stream = self._calltwowaystream(b"unbundle", bundle, heads=heads) ret = bundle2.getunbundler(self.ui, stream) return ret @@ -516,46 +516,46 @@ def branches(self, nodes): n = wireprototypes.encodelist(nodes) - d = self._call("branches", nodes=n) + d = self._call(b"branches", nodes=n) try: br = [tuple(wireprototypes.decodelist(b)) for b in d.splitlines()] return br except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), d)) + self._abort(error.ResponseError(_(b"unexpected response:"), d)) def between(self, pairs): batch = 8 # avoid giant requests r = [] for i in pycompat.xrange(0, len(pairs), batch): - n = " ".join( + n = b" ".join( [ - wireprototypes.encodelist(p, "-") + wireprototypes.encodelist(p, b"-") for p in pairs[i : i + batch] ] ) - d = self._call("between", pairs=n) + d = self._call(b"between", pairs=n) try: r.extend( l and wireprototypes.decodelist(l) or [] for l in d.splitlines() ) except ValueError: - self._abort(error.ResponseError(_("unexpected response:"), d)) + self._abort(error.ResponseError(_(b"unexpected response:"), d)) return r def changegroup(self, nodes, source): n = wireprototypes.encodelist(nodes) - f = self._callcompressable("changegroup", roots=n) - return changegroupmod.cg1unpacker(f, "UN") + f = self._callcompressable(b"changegroup", roots=n) + return changegroupmod.cg1unpacker(f, b"UN") def changegroupsubset(self, bases, heads, source): - self.requirecap("changegroupsubset", _("look up remote changes")) + self.requirecap(b"changegroupsubset", _(b"look up remote changes")) bases = wireprototypes.encodelist(bases) heads = wireprototypes.encodelist(heads) f = self._callcompressable( - "changegroupsubset", bases=bases, heads=heads + b"changegroupsubset", bases=bases, heads=heads ) - return changegroupmod.cg1unpacker(f, "UN") + return changegroupmod.cg1unpacker(f, b"UN") # End of ipeerlegacycommands interface. @@ -565,28 +565,28 @@ Returns an iterator of the raw responses from the server. """ ui = self.ui - if ui.debugflag and ui.configbool("devel", "debug.peer-request"): - ui.debug("devel-peer-request: batched-content\n") + if ui.debugflag and ui.configbool(b"devel", b"debug.peer-request"): + ui.debug(b"devel-peer-request: batched-content\n") for op, args in req: - msg = "devel-peer-request: - %s (%d arguments)\n" + msg = b"devel-peer-request: - %s (%d arguments)\n" ui.debug(msg % (op, len(args))) unescapearg = wireprototypes.unescapebatcharg - rsp = self._callstream("batch", cmds=encodebatchcmds(req)) + rsp = self._callstream(b"batch", cmds=encodebatchcmds(req)) chunk = rsp.read(1024) work = [chunk] while chunk: - while ";" not in chunk and chunk: + while b";" not in chunk and chunk: chunk = rsp.read(1024) work.append(chunk) - merged = "".join(work) - while ";" in merged: - one, merged = merged.split(";", 1) + merged = b"".join(work) + while b";" in merged: + one, merged = merged.split(b";", 1) yield unescapearg(one) chunk = rsp.read(1024) work = [merged, chunk] - yield unescapearg("".join(work)) + yield unescapearg(b"".join(work)) def _submitone(self, op, args): return self._call(op, **pycompat.strkwargs(args)) @@ -598,7 +598,7 @@ opts[r"three"] = three if four is not None: opts[r"four"] = four - return self._call("debugwireargs", one=one, two=two, **opts) + return self._call(b"debugwireargs", one=one, two=two, **opts) def _call(self, cmd, **args): """execute on the server diff --git a/mercurial/wireprotov1server.py b/mercurial/wireprotov1server.py --- a/mercurial/wireprotov1server.py +++ b/mercurial/wireprotov1server.py @@ -38,11 +38,11 @@ urlerr = util.urlerr urlreq = util.urlreq -bundle2requiredmain = _("incompatible Mercurial client; bundle2 required") +bundle2requiredmain = _(b"incompatible Mercurial client; bundle2 required") bundle2requiredhint = _( - "see https://www.mercurial-scm.org/wiki/" "IncompatibleClient" + b"see https://www.mercurial-scm.org/wiki/" b"IncompatibleClient" ) -bundle2required = "%s\n(%s)\n" % (bundle2requiredmain, bundle2requiredhint) +bundle2required = b"%s\n(%s)\n" % (bundle2requiredmain, bundle2requiredhint) def clientcompressionsupport(proto): @@ -53,9 +53,9 @@ been announced, fallback to the default of zlib and uncompressed. """ for cap in proto.getprotocaps(): - if cap.startswith("comp="): - return cap[5:].split(",") - return ["zlib", "none"] + if cap.startswith(b"comp="): + return cap[5:].split(b",") + return [b"zlib", b"none"] # wire protocol command can either return a string or one of these classes. @@ -68,7 +68,7 @@ extensions that need commands to operate on different repo views under specialized circumstances. """ - viewconfig = repo.ui.config("server", "view") + viewconfig = repo.ui.config(b"server", b"view") return repo.filtered(viewconfig) @@ -89,8 +89,8 @@ del others[k] if others: procutil.stderr.write( - "warning: %s ignored unexpected arguments %s\n" - % (cmd, ",".join(others)) + b"warning: %s ignored unexpected arguments %s\n" + % (cmd, b",".join(others)) ) return opts @@ -106,29 +106,29 @@ 4. server.bundle1 """ ui = repo.ui - gd = "generaldelta" in repo.requirements + gd = b"generaldelta" in repo.requirements if gd: - v = ui.configbool("server", "bundle1gd.%s" % action) + v = ui.configbool(b"server", b"bundle1gd.%s" % action) if v is not None: return v - v = ui.configbool("server", "bundle1.%s" % action) + v = ui.configbool(b"server", b"bundle1.%s" % action) if v is not None: return v if gd: - v = ui.configbool("server", "bundle1gd") + v = ui.configbool(b"server", b"bundle1gd") if v is not None: return v - return ui.configbool("server", "bundle1") + return ui.configbool(b"server", b"bundle1") commands = wireprototypes.commanddict() -def wireprotocommand(name, args=None, permission="push"): +def wireprotocommand(name, args=None, permission=b"push"): """Decorator to declare a wire protocol command. ``name`` is the name of the wire protocol command being provided. @@ -144,7 +144,7 @@ a repository that is supposed to be read-only. """ transports = { - k for k, v in wireprototypes.TRANSPORTS.items() if v["version"] == 1 + k for k, v in wireprototypes.TRANSPORTS.items() if v[b"version"] == 1 } # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to @@ -153,24 +153,24 @@ if name == b"batch": transports.add(wireprototypes.SSHV2) - if permission not in ("push", "pull"): + if permission not in (b"push", b"pull"): raise error.ProgrammingError( - "invalid wire protocol permission; " - 'got %s; expected "push" or "pull"' % permission + b"invalid wire protocol permission; " + b'got %s; expected "push" or "pull"' % permission ) if args is None: - args = "" + args = b"" if not isinstance(args, bytes): raise error.ProgrammingError( - "arguments for version 1 commands " "must be declared as bytes" + b"arguments for version 1 commands " b"must be declared as bytes" ) def register(func): if name in commands: raise error.ProgrammingError( - "%s command already registered " "for version 1" % name + b"%s command already registered " b"for version 1" % name ) commands[name] = wireprototypes.commandentry( func, args=args, transports=transports, permission=permission @@ -182,34 +182,34 @@ # TODO define a more appropriate permissions type to use for this. -@wireprotocommand("batch", "cmds *", permission="pull") +@wireprotocommand(b"batch", b"cmds *", permission=b"pull") def batch(repo, proto, cmds, others): unescapearg = wireprototypes.unescapebatcharg res = [] - for pair in cmds.split(";"): - op, args = pair.split(" ", 1) + for pair in cmds.split(b";"): + op, args = pair.split(b" ", 1) vals = {} - for a in args.split(","): + for a in args.split(b","): if a: - n, v = a.split("=") + n, v = a.split(b"=") vals[unescapearg(n)] = unescapearg(v) func, spec = commands[op] # Validate that client has permissions to perform this command. perm = commands[op].permission - assert perm in ("push", "pull") + assert perm in (b"push", b"pull") proto.checkperm(perm) if spec: keys = spec.split() data = {} for k in keys: - if k == "*": + if k == b"*": star = {} for key in vals.keys(): if key not in keys: star[key] = vals[key] - data["*"] = star + data[b"*"] = star else: data[k] = vals[k] result = func(repo, proto, *[data[k] for k in keys]) @@ -225,42 +225,42 @@ result = result.data res.append(wireprototypes.escapebatcharg(result)) - return wireprototypes.bytesresponse(";".join(res)) + return wireprototypes.bytesresponse(b";".join(res)) -@wireprotocommand("between", "pairs", permission="pull") +@wireprotocommand(b"between", b"pairs", permission=b"pull") def between(repo, proto, pairs): - pairs = [wireprototypes.decodelist(p, "-") for p in pairs.split(" ")] + pairs = [wireprototypes.decodelist(p, b"-") for p in pairs.split(b" ")] r = [] for b in repo.between(pairs): - r.append(wireprototypes.encodelist(b) + "\n") + r.append(wireprototypes.encodelist(b) + b"\n") - return wireprototypes.bytesresponse("".join(r)) + return wireprototypes.bytesresponse(b"".join(r)) -@wireprotocommand("branchmap", permission="pull") +@wireprotocommand(b"branchmap", permission=b"pull") def branchmap(repo, proto): branchmap = repo.branchmap() heads = [] for branch, nodes in branchmap.iteritems(): branchname = urlreq.quote(encoding.fromlocal(branch)) branchnodes = wireprototypes.encodelist(nodes) - heads.append("%s %s" % (branchname, branchnodes)) + heads.append(b"%s %s" % (branchname, branchnodes)) - return wireprototypes.bytesresponse("\n".join(heads)) + return wireprototypes.bytesresponse(b"\n".join(heads)) -@wireprotocommand("branches", "nodes", permission="pull") +@wireprotocommand(b"branches", b"nodes", permission=b"pull") def branches(repo, proto, nodes): nodes = wireprototypes.decodelist(nodes) r = [] for b in repo.branches(nodes): - r.append(wireprototypes.encodelist(b) + "\n") + r.append(wireprototypes.encodelist(b) + b"\n") - return wireprototypes.bytesresponse("".join(r)) + return wireprototypes.bytesresponse(b"".join(r)) -@wireprotocommand("clonebundles", "", permission="pull") +@wireprotocommand(b"clonebundles", b"", permission=b"pull") def clonebundles(repo, proto): """Server command for returning info for available bundles to seed clones. @@ -271,17 +271,17 @@ data center given the client's IP address. """ return wireprototypes.bytesresponse( - repo.vfs.tryread("clonebundles.manifest") + repo.vfs.tryread(b"clonebundles.manifest") ) wireprotocaps = [ - "lookup", - "branchmap", - "pushkey", - "known", - "getbundle", - "unbundlehash", + b"lookup", + b"branchmap", + b"pushkey", + b"known", + b"getbundle", + b"unbundlehash", ] @@ -300,27 +300,27 @@ # Command of same name as capability isn't exposed to version 1 of # transports. So conditionally add it. - if commands.commandavailable("changegroupsubset", proto): - caps.append("changegroupsubset") + if commands.commandavailable(b"changegroupsubset", proto): + caps.append(b"changegroupsubset") if streamclone.allowservergeneration(repo): - if repo.ui.configbool("server", "preferuncompressed"): - caps.append("stream-preferred") + if repo.ui.configbool(b"server", b"preferuncompressed"): + caps.append(b"stream-preferred") requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap - if not requiredformats - {"revlogv1"}: - caps.append("stream") + if not requiredformats - {b"revlogv1"}: + caps.append(b"stream") # otherwise, add 'streamreqs' detailing our local revlog format else: - caps.append("streamreqs=%s" % ",".join(sorted(requiredformats))) - if repo.ui.configbool("experimental", "bundle2-advertise"): - capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role="server")) - caps.append("bundle2=" + urlreq.quote(capsblob)) - caps.append("unbundle=%s" % ",".join(bundle2.bundlepriority)) + caps.append(b"streamreqs=%s" % b",".join(sorted(requiredformats))) + if repo.ui.configbool(b"experimental", b"bundle2-advertise"): + capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role=b"server")) + caps.append(b"bundle2=" + urlreq.quote(capsblob)) + caps.append(b"unbundle=%s" % b",".join(bundle2.bundlepriority)) - if repo.ui.configbool("experimental", "narrow"): + if repo.ui.configbool(b"experimental", b"narrow"): caps.append(wireprototypes.NARROWCAP) - if repo.ui.configbool("experimental", "narrowservebrokenellipses"): + if repo.ui.configbool(b"experimental", b"narrowservebrokenellipses"): caps.append(wireprototypes.ELLIPSESCAP) return proto.addcapabilities(repo, caps) @@ -328,37 +328,37 @@ # If you are writing an extension and consider wrapping this function. Wrap # `_capabilities` instead. -@wireprotocommand("capabilities", permission="pull") +@wireprotocommand(b"capabilities", permission=b"pull") def capabilities(repo, proto): caps = _capabilities(repo, proto) - return wireprototypes.bytesresponse(" ".join(sorted(caps))) + return wireprototypes.bytesresponse(b" ".join(sorted(caps))) -@wireprotocommand("changegroup", "roots", permission="pull") +@wireprotocommand(b"changegroup", b"roots", permission=b"pull") def changegroup(repo, proto, roots): nodes = wireprototypes.decodelist(roots) outgoing = discovery.outgoing( repo, missingroots=nodes, missingheads=repo.heads() ) - cg = changegroupmod.makechangegroup(repo, outgoing, "01", "serve") - gen = iter(lambda: cg.read(32768), "") + cg = changegroupmod.makechangegroup(repo, outgoing, b"01", b"serve") + gen = iter(lambda: cg.read(32768), b"") return wireprototypes.streamres(gen=gen) -@wireprotocommand("changegroupsubset", "bases heads", permission="pull") +@wireprotocommand(b"changegroupsubset", b"bases heads", permission=b"pull") def changegroupsubset(repo, proto, bases, heads): bases = wireprototypes.decodelist(bases) heads = wireprototypes.decodelist(heads) outgoing = discovery.outgoing(repo, missingroots=bases, missingheads=heads) - cg = changegroupmod.makechangegroup(repo, outgoing, "01", "serve") - gen = iter(lambda: cg.read(32768), "") + cg = changegroupmod.makechangegroup(repo, outgoing, b"01", b"serve") + gen = iter(lambda: cg.read(32768), b"") return wireprototypes.streamres(gen=gen) -@wireprotocommand("debugwireargs", "one two *", permission="pull") +@wireprotocommand(b"debugwireargs", b"one two *", permission=b"pull") def debugwireargs(repo, proto, one, two, others): # only accept optional args from the known set - opts = options("debugwireargs", ["three", "four"], others) + opts = options(b"debugwireargs", [b"three", b"four"], others) return wireprototypes.bytesresponse( repo.debugwireargs(one, two, **pycompat.strkwargs(opts)) ) @@ -381,9 +381,9 @@ """ def decodehexstring(s): - return {binascii.unhexlify(h) for h in s.split(";")} + return {binascii.unhexlify(h) for h in s.split(b";")} - manifest = repo.vfs.tryread("pullbundles.manifest") + manifest = repo.vfs.tryread(b"pullbundles.manifest") if not manifest: return None res = exchange.parseclonebundlesmanifest(repo, manifest) @@ -395,15 +395,15 @@ common_anc = cl.ancestors([cl.rev(rev) for rev in common], inclusive=True) compformats = clientcompressionsupport(proto) for entry in res: - comp = entry.get("COMPRESSION") + comp = entry.get(b"COMPRESSION") altcomp = util.compengines._bundlenames.get(comp) if comp and comp not in compformats and altcomp not in compformats: continue # No test yet for VERSION, since V2 is supported by any client # that advertises partial pulls - if "heads" in entry: + if b"heads" in entry: try: - bundle_heads = decodehexstring(entry["heads"]) + bundle_heads = decodehexstring(entry[b"heads"]) except TypeError: # Bad heads entry continue @@ -416,61 +416,61 @@ for rev in bundle_heads ): continue - if "bases" in entry: + if b"bases" in entry: try: - bundle_bases = decodehexstring(entry["bases"]) + bundle_bases = decodehexstring(entry[b"bases"]) except TypeError: # Bad bases entry continue if not all(cl.rev(rev) in common_anc for rev in bundle_bases): continue - path = entry["URL"] - repo.ui.debug('sending pullbundle "%s"\n' % path) + path = entry[b"URL"] + repo.ui.debug(b'sending pullbundle "%s"\n' % path) try: return repo.vfs.open(path) except IOError: - repo.ui.debug('pullbundle "%s" not accessible\n' % path) + repo.ui.debug(b'pullbundle "%s" not accessible\n' % path) continue return None -@wireprotocommand("getbundle", "*", permission="pull") +@wireprotocommand(b"getbundle", b"*", permission=b"pull") def getbundle(repo, proto, others): opts = options( - "getbundle", wireprototypes.GETBUNDLE_ARGUMENTS.keys(), others + b"getbundle", wireprototypes.GETBUNDLE_ARGUMENTS.keys(), others ) for k, v in opts.iteritems(): keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k] - if keytype == "nodes": + if keytype == b"nodes": opts[k] = wireprototypes.decodelist(v) - elif keytype == "csv": - opts[k] = list(v.split(",")) - elif keytype == "scsv": - opts[k] = set(v.split(",")) - elif keytype == "boolean": + elif keytype == b"csv": + opts[k] = list(v.split(b",")) + elif keytype == b"scsv": + opts[k] = set(v.split(b",")) + elif keytype == b"boolean": # Client should serialize False as '0', which is a non-empty string # so it evaluates as a True bool. - if v == "0": + if v == b"0": opts[k] = False else: opts[k] = bool(v) - elif keytype != "plain": - raise KeyError("unknown getbundle option type %s" % keytype) + elif keytype != b"plain": + raise KeyError(b"unknown getbundle option type %s" % keytype) - if not bundle1allowed(repo, "pull"): - if not exchange.bundle2requested(opts.get("bundlecaps")): - if proto.name == "http-v1": + if not bundle1allowed(repo, b"pull"): + if not exchange.bundle2requested(opts.get(b"bundlecaps")): + if proto.name == b"http-v1": return wireprototypes.ooberror(bundle2required) raise error.Abort(bundle2requiredmain, hint=bundle2requiredhint) try: clheads = set(repo.changelog.heads()) - heads = set(opts.get("heads", set())) - common = set(opts.get("common", set())) + heads = set(opts.get(b"heads", set())) + common = set(opts.get(b"common", set())) common.discard(nullid) if ( - repo.ui.configbool("server", "pullbundle") - and "partial-pull" in proto.getprotocaps() + repo.ui.configbool(b"server", b"pullbundle") + and b"partial-pull" in proto.getprotocaps() ): # Check if a pre-built bundle covers this request. bundle = find_pullbundle(repo, proto, opts, clheads, heads, common) @@ -479,32 +479,32 @@ gen=util.filechunkiter(bundle), prefer_uncompressed=True ) - if repo.ui.configbool("server", "disablefullbundle"): + if repo.ui.configbool(b"server", b"disablefullbundle"): # Check to see if this is a full clone. - changegroup = opts.get("cg", True) + changegroup = opts.get(b"cg", True) if changegroup and not common and clheads == heads: raise error.Abort( - _("server has pull-based clones disabled"), - hint=_("remove --pull if specified or upgrade Mercurial"), + _(b"server has pull-based clones disabled"), + hint=_(b"remove --pull if specified or upgrade Mercurial"), ) info, chunks = exchange.getbundlechunks( - repo, "serve", **pycompat.strkwargs(opts) + repo, b"serve", **pycompat.strkwargs(opts) ) - prefercompressed = info.get("prefercompressed", True) + prefercompressed = info.get(b"prefercompressed", True) except error.Abort as exc: # cleanly forward Abort error to the client - if not exchange.bundle2requested(opts.get("bundlecaps")): - if proto.name == "http-v1": - return wireprototypes.ooberror(pycompat.bytestr(exc) + "\n") + if not exchange.bundle2requested(opts.get(b"bundlecaps")): + if proto.name == b"http-v1": + return wireprototypes.ooberror(pycompat.bytestr(exc) + b"\n") raise # cannot do better for bundle1 + ssh # bundle2 request expect a bundle2 reply bundler = bundle2.bundle20(repo.ui) - manargs = [("message", pycompat.bytestr(exc))] + manargs = [(b"message", pycompat.bytestr(exc))] advargs = [] if exc.hint is not None: - advargs.append(("hint", exc.hint)) - bundler.addpart(bundle2.bundlepart("error:abort", manargs, advargs)) + advargs.append((b"hint", exc.hint)) + bundler.addpart(bundle2.bundlepart(b"error:abort", manargs, advargs)) chunks = bundler.getchunks() prefercompressed = False @@ -513,13 +513,13 @@ ) -@wireprotocommand("heads", permission="pull") +@wireprotocommand(b"heads", permission=b"pull") def heads(repo, proto): h = repo.heads() - return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + "\n") + return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b"\n") -@wireprotocommand("hello", permission="pull") +@wireprotocommand(b"hello", permission=b"pull") def hello(repo, proto): """Called as part of SSH handshake to obtain server info. @@ -532,16 +532,16 @@ capabilities: """ caps = capabilities(repo, proto).data - return wireprototypes.bytesresponse("capabilities: %s\n" % caps) + return wireprototypes.bytesresponse(b"capabilities: %s\n" % caps) -@wireprotocommand("listkeys", "namespace", permission="pull") +@wireprotocommand(b"listkeys", b"namespace", permission=b"pull") def listkeys(repo, proto, namespace): d = sorted(repo.listkeys(encoding.tolocal(namespace)).items()) return wireprototypes.bytesresponse(pushkeymod.encodekeys(d)) -@wireprotocommand("lookup", "key", permission="pull") +@wireprotocommand(b"lookup", b"key", permission=b"pull") def lookup(repo, proto, key): try: k = encoding.tolocal(key) @@ -551,25 +551,25 @@ except Exception as inst: r = stringutil.forcebytestr(inst) success = 0 - return wireprototypes.bytesresponse("%d %s\n" % (success, r)) + return wireprototypes.bytesresponse(b"%d %s\n" % (success, r)) -@wireprotocommand("known", "nodes *", permission="pull") +@wireprotocommand(b"known", b"nodes *", permission=b"pull") def known(repo, proto, nodes, others): - v = "".join( - b and "1" or "0" for b in repo.known(wireprototypes.decodelist(nodes)) + v = b"".join( + b and b"1" or b"0" for b in repo.known(wireprototypes.decodelist(nodes)) ) return wireprototypes.bytesresponse(v) -@wireprotocommand("protocaps", "caps", permission="pull") +@wireprotocommand(b"protocaps", b"caps", permission=b"pull") def protocaps(repo, proto, caps): if proto.name == wireprototypes.SSHV1: - proto._protocaps = set(caps.split(" ")) - return wireprototypes.bytesresponse("OK") + proto._protocaps = set(caps.split(b" ")) + return wireprototypes.bytesresponse(b"OK") -@wireprotocommand("pushkey", "namespace key old new", permission="push") +@wireprotocommand(b"pushkey", b"namespace key old new", permission=b"push") def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally # sending raw binary nodes rather than utf-8-encoded hex @@ -594,11 +594,11 @@ or False ) - output = output.getvalue() if output else "" - return wireprototypes.bytesresponse("%d\n%s" % (int(r), output)) + output = output.getvalue() if output else b"" + return wireprototypes.bytesresponse(b"%d\n%s" % (int(r), output)) -@wireprotocommand("stream_out", permission="pull") +@wireprotocommand(b"stream_out", permission=b"pull") def stream(repo, proto): """If the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo @@ -607,17 +607,17 @@ return wireprototypes.streamreslegacy(streamclone.generatev1wireproto(repo)) -@wireprotocommand("unbundle", "heads", permission="push") +@wireprotocommand(b"unbundle", b"heads", permission=b"push") def unbundle(repo, proto, heads): their_heads = wireprototypes.decodelist(heads) with proto.mayberedirectstdio() as output: try: - exchange.check_heads(repo, their_heads, "preparing changes") + exchange.check_heads(repo, their_heads, b"preparing changes") cleanup = lambda: None try: payload = proto.getpayload() - if repo.ui.configbool("server", "streamunbundle"): + if repo.ui.configbool(b"server", b"streamunbundle"): def cleanup(): # Ensure that the full payload is consumed, so @@ -636,11 +636,11 @@ if tempname: os.unlink(tempname) - fd, tempname = pycompat.mkstemp(prefix="hg-unbundle-") + fd, tempname = pycompat.mkstemp(prefix=b"hg-unbundle-") repo.ui.debug( - "redirecting incoming bundle to %s\n" % tempname + b"redirecting incoming bundle to %s\n" % tempname ) - fp = os.fdopen(fd, pycompat.sysstr("wb+")) + fp = os.fdopen(fd, pycompat.sysstr(b"wb+")) for p in payload: fp.write(p) fp.seek(0) @@ -648,8 +648,8 @@ gen = exchange.readbundle(repo.ui, fp, None) if isinstance( gen, changegroupmod.cg1unpacker - ) and not bundle1allowed(repo, "push"): - if proto.name == "http-v1": + ) and not bundle1allowed(repo, b"push"): + if proto.name == b"http-v1": # need to special case http because stderr do not get to # the http client on failed push so we need to abuse # some other error type to make sure the message get to @@ -660,14 +660,14 @@ ) r = exchange.unbundle( - repo, gen, their_heads, "serve", proto.client() + repo, gen, their_heads, b"serve", proto.client() ) - if util.safehasattr(r, "addpart"): + if util.safehasattr(r, b"addpart"): # The return looks streamable, we are in the bundle2 case # and should return a stream. return wireprototypes.streamreslegacy(gen=r.getchunks()) return wireprototypes.pushres( - r, output.getvalue() if output else "" + r, output.getvalue() if output else b"" ) finally: @@ -683,17 +683,17 @@ # We did not change it to minimise code change. # This need to be moved to something proper. # Feel free to do it. - procutil.stderr.write("abort: %s\n" % exc) + procutil.stderr.write(b"abort: %s\n" % exc) if exc.hint is not None: - procutil.stderr.write("(%s)\n" % exc.hint) + procutil.stderr.write(b"(%s)\n" % exc.hint) procutil.stderr.flush() return wireprototypes.pushres( - 0, output.getvalue() if output else "" + 0, output.getvalue() if output else b"" ) except error.PushRaced: return wireprototypes.pusherr( pycompat.bytestr(exc), - output.getvalue() if output else "", + output.getvalue() if output else b"", ) bundler = bundle2.bundle20(repo.ui) @@ -707,41 +707,41 @@ remotecaps = getattr(exc, "_replycaps", None) if ( remotecaps is not None - and "pushkey" not in remotecaps.get("error", ()) + and b"pushkey" not in remotecaps.get(b"error", ()) ): # no support remote side, fallback to Abort handler. raise - part = bundler.newpart("error:pushkey") - part.addparam("in-reply-to", exc.partid) + part = bundler.newpart(b"error:pushkey") + part.addparam(b"in-reply-to", exc.partid) if exc.namespace is not None: part.addparam( - "namespace", exc.namespace, mandatory=False + b"namespace", exc.namespace, mandatory=False ) if exc.key is not None: - part.addparam("key", exc.key, mandatory=False) + part.addparam(b"key", exc.key, mandatory=False) if exc.new is not None: - part.addparam("new", exc.new, mandatory=False) + part.addparam(b"new", exc.new, mandatory=False) if exc.old is not None: - part.addparam("old", exc.old, mandatory=False) + part.addparam(b"old", exc.old, mandatory=False) if exc.ret is not None: - part.addparam("ret", exc.ret, mandatory=False) + part.addparam(b"ret", exc.ret, mandatory=False) except error.BundleValueError as exc: - errpart = bundler.newpart("error:unsupportedcontent") + errpart = bundler.newpart(b"error:unsupportedcontent") if exc.parttype is not None: - errpart.addparam("parttype", exc.parttype) + errpart.addparam(b"parttype", exc.parttype) if exc.params: - errpart.addparam("params", "\0".join(exc.params)) + errpart.addparam(b"params", b"\0".join(exc.params)) except error.Abort as exc: - manargs = [("message", stringutil.forcebytestr(exc))] + manargs = [(b"message", stringutil.forcebytestr(exc))] advargs = [] if exc.hint is not None: - advargs.append(("hint", exc.hint)) + advargs.append((b"hint", exc.hint)) bundler.addpart( - bundle2.bundlepart("error:abort", manargs, advargs) + bundle2.bundlepart(b"error:abort", manargs, advargs) ) except error.PushRaced as exc: bundler.newpart( - "error:pushraced", - [("message", stringutil.forcebytestr(exc))], + b"error:pushraced", + [(b"message", stringutil.forcebytestr(exc))], ) return wireprototypes.streamreslegacy(gen=bundler.getchunks()) diff --git a/mercurial/wireprotov2peer.py b/mercurial/wireprotov2peer.py --- a/mercurial/wireprotov2peer.py +++ b/mercurial/wireprotov2peer.py @@ -58,14 +58,14 @@ """ if target.get(b"protocol") not in SUPPORTED_REDIRECT_PROTOCOLS: ui.note( - _("(remote redirect target %s uses unsupported protocol: %s)\n") + _(b"(remote redirect target %s uses unsupported protocol: %s)\n") % (target[b"name"], target.get(b"protocol", b"")) ) return False if target.get(b"snirequired") and not sslutil.hassni: ui.note( - _("(redirect target %s requires SNI, which is unsupported)\n") + _(b"(redirect target %s requires SNI, which is unsupported)\n") % target[b"name"] ) return False @@ -81,14 +81,14 @@ if not tlsversions & supported: ui.note( _( - "(remote redirect target %s requires unsupported TLS " - "versions: %s)\n" + b"(remote redirect target %s requires unsupported TLS " + b"versions: %s)\n" ) % (target[b"name"], b", ".join(sorted(tlsversions))) ) return False - ui.note(_("(remote redirect target %s is compatible)\n") % target[b"name"]) + ui.note(_(b"(remote redirect target %s is compatible)\n") % target[b"name"]) return True @@ -181,9 +181,9 @@ if self._redirect: raise error.Abort( _( - "received unexpected response data " - "after content redirect; the remote is " - "buggy" + b"received unexpected response data " + b"after content redirect; the remote is " + b"buggy" ) ) @@ -215,9 +215,9 @@ ) return - atoms = [{"msg": o[b"error"][b"message"]}] + atoms = [{b"msg": o[b"error"][b"message"]}] if b"args" in o[b"error"]: - atoms[0]["args"] = o[b"error"][b"args"] + atoms[0][b"args"] = o[b"error"][b"args"] raise error.RepoError(formatrichmessage(atoms)) @@ -293,8 +293,8 @@ command, args, redirect=redirect ) - if action != "noop": - raise error.ProgrammingError("%s not yet supported" % action) + if action != b"noop": + raise error.ProgrammingError(b"%s not yet supported" % action) rid = request.requestid self._requests[rid] = request @@ -312,10 +312,10 @@ """ action, meta = self._reactor.flushcommands() - if action != "sendframes": - raise error.ProgrammingError("%s not yet supported" % action) + if action != b"sendframes": + raise error.ProgrammingError(b"%s not yet supported" % action) - return meta["framegen"] + return meta[b"framegen"] def readdata(self, framefh): """Attempt to read data and do work. @@ -329,7 +329,7 @@ # TODO tell reactor? self._frameseof = True else: - self._ui.debug("received %r\n" % frame) + self._ui.debug(b"received %r\n" % frame) self._processframe(frame) # Also try to read the first redirect. @@ -347,8 +347,8 @@ action, meta = self._reactor.onframerecv(frame) - if action == "error": - e = error.RepoError(meta["message"]) + if action == b"error": + e = error.RepoError(meta[b"message"]) if frame.requestid in self._responses: self._responses[frame.requestid]._oninputcomplete() @@ -360,24 +360,24 @@ raise e return - elif action == "noop": + elif action == b"noop": return - elif action == "responsedata": + elif action == b"responsedata": # Handled below. pass else: - raise error.ProgrammingError("action not handled: %s" % action) + raise error.ProgrammingError(b"action not handled: %s" % action) if frame.requestid not in self._requests: raise error.ProgrammingError( - "received frame for unknown request; this is either a bug in " - "the clientreactor not screening for this or this instance was " - "never told about this request: %r" % frame + b"received frame for unknown request; this is either a bug in " + b"the clientreactor not screening for this or this instance was " + b"never told about this request: %r" % frame ) response = self._responses[frame.requestid] - if action == "responsedata": + if action == b"responsedata": # Any failures processing this frame should bubble up to the # future tracking the request. try: @@ -397,12 +397,12 @@ response._onerror(e) else: raise error.ProgrammingError( - "unhandled action from clientreactor: %s" % action + b"unhandled action from clientreactor: %s" % action ) def _processresponsedata(self, frame, meta, response): # This can raise. The caller can handle it. - response._onresponsedata(meta["data"]) + response._onresponsedata(meta[b"data"]) # We need to be careful about resolving futures prematurely. If a # response is a redirect response, resolving the future before the @@ -414,7 +414,7 @@ # EOS occurs or until the initial response object is fully received. # Always react to eos. - if meta["eos"]: + if meta[b"eos"]: response._oninputcomplete() del self._requests[frame.requestid] @@ -446,28 +446,28 @@ def _followredirect(self, requestid, redirect): """Called to initiate redirect following for a request.""" - self._ui.note(_("(following redirect to %s)\n") % redirect.url) + self._ui.note(_(b"(following redirect to %s)\n") % redirect.url) # TODO handle framed responses. if redirect.mediatype != b"application/mercurial-cbor": raise error.Abort( - _("cannot handle redirects for the %s media type") + _(b"cannot handle redirects for the %s media type") % redirect.mediatype ) if redirect.fullhashes: self._ui.warn( _( - "(support for validating hashes on content " - "redirects not supported)\n" + b"(support for validating hashes on content " + b"redirects not supported)\n" ) ) if redirect.serverdercerts or redirect.servercadercerts: self._ui.warn( _( - "(support for pinning server certificates on " - "content redirects not supported)\n" + b"(support for pinning server certificates on " + b"content redirects not supported)\n" ) ) @@ -481,10 +481,10 @@ res = self._opener.open(req) except util.urlerr.httperror as e: if e.code == 401: - raise error.Abort(_("authorization failed")) + raise error.Abort(_(b"authorization failed")) raise except util.httplib.HTTPException as e: - self._ui.debug("http error requesting %s\n" % req.get_full_url()) + self._ui.debug(b"http error requesting %s\n" % req.get_full_url()) self._ui.traceback() raise IOError(None, e) @@ -567,10 +567,10 @@ COMMAND_DECODERS = { - "branchmap": decodebranchmap, - "heads": decodeheads, - "known": decodeknown, - "listkeys": decodelistkeys, - "lookup": decodelookup, - "pushkey": decodepushkey, + b"branchmap": decodebranchmap, + b"heads": decodeheads, + b"known": decodeknown, + b"listkeys": decodelistkeys, + b"lookup": decodelookup, + b"pushkey": decodepushkey, } diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py --- a/mercurial/wireprotov2server.py +++ b/mercurial/wireprotov2server.py @@ -56,14 +56,14 @@ if not urlparts: res.status = b"200 OK" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("HTTP version 2 API handler")) + res.setbodybytes(_(b"HTTP version 2 API handler")) return if len(urlparts) == 1: res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("do not know how to process %s\n") % req.dispatchpath + _(b"do not know how to process %s\n") % req.dispatchpath ) return @@ -72,13 +72,13 @@ if permission not in (b"ro", b"rw"): res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("unknown permission: %s") % permission) + res.setbodybytes(_(b"unknown permission: %s") % permission) return - if req.method != "POST": + if req.method != b"POST": res.status = b"405 Method Not Allowed" res.headers[b"Allow"] = b"POST" - res.setbodybytes(_("commands require POST requests")) + res.setbodybytes(_(b"commands require POST requests")) return # At some point we'll want to use our own API instead of recycling the @@ -86,12 +86,12 @@ # TODO return reasonable responses - not responses that overload the # HTTP status line message for error reporting. try: - checkperm(rctx, req, "pull" if permission == b"ro" else "push") + checkperm(rctx, req, b"pull" if permission == b"ro" else b"push") except hgwebcommon.ErrorResponse as e: res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e)) for k, v in e.headers: res.headers[k] = v - res.setbodybytes("permission denied") + res.setbodybytes(b"permission denied") return # We have a special endpoint to reflect the request back at the client. @@ -102,12 +102,12 @@ # Extra commands that we handle that aren't really wire protocol # commands. Think extra hard before making this hackery available to # extension. - extracommands = {"multirequest"} + extracommands = {b"multirequest"} if command not in COMMANDS and command not in extracommands: res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("unknown wire protocol command: %s\n") % command) + res.setbodybytes(_(b"unknown wire protocol command: %s\n") % command) return repo = rctx.repo @@ -121,7 +121,7 @@ ): res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("invalid wire protocol command: %s") % command) + res.setbodybytes(_(b"invalid wire protocol command: %s") % command) return # TODO consider cases where proxies may add additional Accept headers. @@ -129,7 +129,7 @@ res.status = b"406 Not Acceptable" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("client MUST specify Accept header with value: %s\n") + _(b"client MUST specify Accept header with value: %s\n") % FRAMINGTYPE ) return @@ -140,7 +140,7 @@ # since client does Accept it. res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("client MUST send Content-Type header with " "value: %s\n") + _(b"client MUST send Content-Type header with " b"value: %s\n") % FRAMINGTYPE ) return @@ -160,10 +160,10 @@ """ # Reflection APIs have a history of being abused, accidentally disclosing # sensitive data, etc. So we have a config knob. - if not ui.configbool("experimental", "web.api.debugreflect"): + if not ui.configbool(b"experimental", b"web.api.debugreflect"): res.status = b"404 Not Found" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("debugreflect service not available")) + res.setbodybytes(_(b"debugreflect service not available")) return # We assume we have a unified framing protocol request body. @@ -187,7 +187,7 @@ states.append(templatefilters.json((action, meta))) action, meta = reactor.oninputeof() - meta["action"] = action + meta[b"action"] = action states.append(templatefilters.json(meta)) res.status = b"200 OK" @@ -216,10 +216,10 @@ action, meta = reactor.onframerecv(frame) - if action == "wantframe": + if action == b"wantframe": # Need more data before we can do anything. continue - elif action == "runcommand": + elif action == b"runcommand": # Defer creating output stream because we need to wait for # protocol settings frames so proper encoding can be applied. if not outstream: @@ -243,29 +243,29 @@ seencommand = True - elif action == "error": + elif action == b"error": # TODO define proper error mechanism. res.status = b"200 OK" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(meta["message"] + b"\n") + res.setbodybytes(meta[b"message"] + b"\n") return else: raise error.ProgrammingError( - "unhandled action from frame processor: %s" % action + b"unhandled action from frame processor: %s" % action ) action, meta = reactor.oninputeof() - if action == "sendframes": + if action == b"sendframes": # We assume we haven't started sending the response yet. If we're # wrong, the response type will raise an exception. res.status = b"200 OK" res.headers[b"Content-Type"] = FRAMINGTYPE - res.setbodygen(meta["framegen"]) - elif action == "noop": + res.setbodygen(meta[b"framegen"]) + elif action == b"noop": pass else: raise error.ProgrammingError( - "unhandled action from frame processor: %s" % action + b"unhandled action from frame processor: %s" % action ) @@ -301,31 +301,31 @@ # TODO consider allowing multiple commands to regular command URLs # iff each command is the same. - proto = httpv2protocolhandler(req, ui, args=command["args"]) + proto = httpv2protocolhandler(req, ui, args=command[b"args"]) if reqcommand == b"multirequest": - if not COMMANDS.commandavailable(command["command"], proto): + if not COMMANDS.commandavailable(command[b"command"], proto): # TODO proper error mechanism res.status = b"200 OK" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("wire protocol command not available: %s") - % command["command"] + _(b"wire protocol command not available: %s") + % command[b"command"] ) return True # TODO don't use assert here, since it may be elided by -O. assert authedperm in (b"ro", b"rw") - wirecommand = COMMANDS[command["command"]] - assert wirecommand.permission in ("push", "pull") + wirecommand = COMMANDS[command[b"command"]] + assert wirecommand.permission in (b"push", b"pull") - if authedperm == b"ro" and wirecommand.permission != "pull": + if authedperm == b"ro" and wirecommand.permission != b"pull": # TODO proper error mechanism res.status = b"403 Forbidden" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("insufficient permissions to execute " "command: %s") - % command["command"] + _(b"insufficient permissions to execute " b"command: %s") + % command[b"command"] ) return True @@ -340,53 +340,53 @@ res.status = b"200 OK" res.headers[b"Content-Type"] = b"text/plain" res.setbodybytes( - _("multiple commands cannot be issued to this " "URL") + _(b"multiple commands cannot be issued to this " b"URL") ) return True - if reqcommand != command["command"]: + if reqcommand != command[b"command"]: # TODO define proper error mechanism res.status = b"200 OK" res.headers[b"Content-Type"] = b"text/plain" - res.setbodybytes(_("command in frame must match command in URL")) + res.setbodybytes(_(b"command in frame must match command in URL")) return True res.status = b"200 OK" res.headers[b"Content-Type"] = FRAMINGTYPE try: - objs = dispatch(repo, proto, command["command"], command["redirect"]) + objs = dispatch(repo, proto, command[b"command"], command[b"redirect"]) action, meta = reactor.oncommandresponsereadyobjects( - outstream, command["requestid"], objs + outstream, command[b"requestid"], objs ) except error.WireprotoCommandError as e: action, meta = reactor.oncommanderror( - outstream, command["requestid"], e.message, e.messageargs + outstream, command[b"requestid"], e.message, e.messageargs ) except Exception as e: action, meta = reactor.onservererror( outstream, - command["requestid"], - _("exception when invoking command: %s") + command[b"requestid"], + _(b"exception when invoking command: %s") % stringutil.forcebytestr(e), ) - if action == "sendframes": - res.setbodygen(meta["framegen"]) + if action == b"sendframes": + res.setbodygen(meta[b"framegen"]) return True - elif action == "noop": + elif action == b"noop": return False else: raise error.ProgrammingError( - "unhandled event from reactor: %s" % action + b"unhandled event from reactor: %s" % action ) def getdispatchrepo(repo, proto, command): - viewconfig = repo.ui.config("server", "view") + viewconfig = repo.ui.config(b"server", b"view") return repo.filtered(viewconfig) @@ -453,7 +453,7 @@ cached = cacher.lookup() if cached: - for o in cached["objs"]: + for o in cached[b"objs"]: yield o return @@ -484,15 +484,16 @@ extra = set(self._args) - set(args) if extra: raise error.WireprotoCommandError( - "unsupported argument to command: %s" % ", ".join(sorted(extra)) + b"unsupported argument to command: %s" + % b", ".join(sorted(extra)) ) # And look for required arguments that are missing. - missing = {a for a in args if args[a]["required"]} - set(self._args) + missing = {a for a in args if args[a][b"required"]} - set(self._args) if missing: raise error.WireprotoCommandError( - "missing required arguments: %s" % ", ".join(sorted(missing)) + b"missing required arguments: %s" % b", ".join(sorted(missing)) ) # Now derive the arguments to pass to the command, taking into @@ -501,13 +502,13 @@ for k, meta in sorted(args.items()): # This argument wasn't passed by the client. if k not in self._args: - data[k] = meta["default"]() + data[k] = meta[b"default"]() continue v = self._args[k] # Sets may be expressed as lists. Silently normalize. - if meta["type"] == "set" and isinstance(v, list): + if meta[b"type"] == b"set" and isinstance(v, list): v = set(v) # TODO consider more/stronger type validation. @@ -550,9 +551,9 @@ transports. """ caps = { - "commands": {}, - "framingmediatypes": [FRAMINGTYPE], - "pathfilterprefixes": set(narrowspec.VALID_PREFIXES), + b"commands": {}, + b"framingmediatypes": [FRAMINGTYPE], + b"pathfilterprefixes": set(narrowspec.VALID_PREFIXES), } for command, entry in COMMANDS.items(): @@ -562,15 +563,15 @@ args[arg] = { # TODO should this be a normalized type using CBOR's # terminology? - b"type": meta["type"], - b"required": meta["required"], + b"type": meta[b"type"], + b"required": meta[b"required"], } - if not meta["required"]: - args[arg][b"default"] = meta["default"]() + if not meta[b"required"]: + args[arg][b"default"] = meta[b"default"]() - if meta["validvalues"]: - args[arg][b"validvalues"] = meta["validvalues"] + if meta[b"validvalues"]: + args[arg][b"validvalues"] = meta[b"validvalues"] # TODO this type of check should be defined in a per-command callback. if ( @@ -579,16 +580,16 @@ ): continue - caps["commands"][command] = { - "args": args, - "permissions": [entry.permission], + caps[b"commands"][command] = { + b"args": args, + b"permissions": [entry.permission], } if entry.extracapabilitiesfn: extracaps = entry.extracapabilitiesfn(repo, proto) - caps["commands"][command].update(extracaps) + caps[b"commands"][command].update(extracaps) - caps["rawrepoformats"] = sorted(repo.requirements & repo.supportedformats) + caps[b"rawrepoformats"] = sorted(repo.requirements & repo.supportedformats) targets = getadvertisedredirecttargets(repo, proto) if targets: @@ -599,12 +600,12 @@ for target in targets: entry = { - b"name": target["name"], - b"protocol": target["protocol"], - b"uris": target["uris"], + b"name": target[b"name"], + b"protocol": target[b"protocol"], + b"uris": target[b"uris"], } - for key in ("snirequired", "tlsversions"): + for key in (b"snirequired", b"tlsversions"): if key in target: entry[key] = target[key] @@ -655,7 +656,7 @@ def wireprotocommand( name, args=None, - permission="push", + permission=b"push", cachekeyfn=None, extracapabilitiesfn=None, ): @@ -710,13 +711,13 @@ under. """ transports = { - k for k, v in wireprototypes.TRANSPORTS.items() if v["version"] == 2 + k for k, v in wireprototypes.TRANSPORTS.items() if v[b"version"] == 2 } - if permission not in ("push", "pull"): + if permission not in (b"push", b"pull"): raise error.ProgrammingError( - "invalid wire protocol permission; " - 'got %s; expected "push" or "pull"' % permission + b"invalid wire protocol permission; " + b'got %s; expected "push" or "pull"' % permission ) if args is None: @@ -724,48 +725,55 @@ if not isinstance(args, dict): raise error.ProgrammingError( - "arguments for version 2 commands " "must be declared as dicts" + b"arguments for version 2 commands " b"must be declared as dicts" ) for arg, meta in args.items(): - if arg == "*": + if arg == b"*": raise error.ProgrammingError( - "* argument name not allowed on " "version 2 commands" + b"* argument name not allowed on " b"version 2 commands" ) if not isinstance(meta, dict): raise error.ProgrammingError( - "arguments for version 2 commands " - "must declare metadata as a dict" + b"arguments for version 2 commands " + b"must declare metadata as a dict" ) - if "type" not in meta: + if b"type" not in meta: raise error.ProgrammingError( - "%s argument for command %s does not " - "declare type field" % (arg, name) + b"%s argument for command %s does not " + b"declare type field" % (arg, name) ) - if meta["type"] not in ("bytes", "int", "list", "dict", "set", "bool"): + if meta[b"type"] not in ( + b"bytes", + b"int", + b"list", + b"dict", + b"set", + b"bool", + ): raise error.ProgrammingError( - "%s argument for command %s has " - "illegal type: %s" % (arg, name, meta["type"]) + b"%s argument for command %s has " + b"illegal type: %s" % (arg, name, meta[b"type"]) ) - if "example" not in meta: + if b"example" not in meta: raise error.ProgrammingError( - "%s argument for command %s does not " - "declare example field" % (arg, name) + b"%s argument for command %s does not " + b"declare example field" % (arg, name) ) - meta["required"] = "default" not in meta + meta[b"required"] = b"default" not in meta - meta.setdefault("default", lambda: None) - meta.setdefault("validvalues", None) + meta.setdefault(b"default", lambda: None) + meta.setdefault(b"validvalues", None) def register(func): if name in COMMANDS: raise error.ProgrammingError( - "%s command already registered " "for version 2" % name + b"%s command already registered " b"for version 2" % name ) COMMANDS[name] = wireprototypes.commandentry( @@ -796,16 +804,18 @@ * The repository path. """ if not allargs: - raise error.ProgrammingError("only allargs=True is currently supported") + raise error.ProgrammingError( + b"only allargs=True is currently supported" + ) if localversion is None: - raise error.ProgrammingError("must set localversion argument value") + raise error.ProgrammingError(b"must set localversion argument value") def cachekeyfn(repo, proto, cacher, **args): spec = COMMANDS[command] # Commands that mutate the repo can not be cached. - if spec.permission == "push": + if spec.permission == b"push": return None # TODO config option to disable caching. @@ -880,13 +890,13 @@ if not isinstance(revisions, list): raise error.WireprotoCommandError( - "revisions must be defined as an " "array" + b"revisions must be defined as an " b"array" ) for spec in revisions: if b"type" not in spec: raise error.WireprotoCommandError( - "type key not present in revision specifier" + b"type key not present in revision specifier" ) typ = spec[b"type"] @@ -894,8 +904,8 @@ if typ == b"changesetexplicit": if b"nodes" not in spec: raise error.WireprotoCommandError( - "nodes key not present in changesetexplicit revision " - "specifier" + b"nodes key not present in changesetexplicit revision " + b"specifier" ) for node in spec[b"nodes"]: @@ -907,8 +917,8 @@ for key in (b"nodes", b"depth"): if key not in spec: raise error.WireprotoCommandError( - "%s key not present in changesetexplicitdepth revision " - "specifier", + b"%s key not present in changesetexplicitdepth revision " + b"specifier", (key,), ) @@ -925,14 +935,14 @@ for key in (b"roots", b"heads"): if key not in spec: raise error.WireprotoCommandError( - "%s key not present in changesetdagrange revision " - "specifier", + b"%s key not present in changesetdagrange revision " + b"specifier", (key,), ) if not spec[b"heads"]: raise error.WireprotoCommandError( - "heads key in changesetdagrange cannot be empty" + b"heads key in changesetdagrange cannot be empty" ) if spec[b"roots"]: @@ -947,39 +957,39 @@ else: raise error.WireprotoCommandError( - "unknown revision specifier type: %s", (typ,) + b"unknown revision specifier type: %s", (typ,) ) return nodes -@wireprotocommand("branchmap", permission="pull") +@wireprotocommand(b"branchmap", permission=b"pull") def branchmapv2(repo, proto): yield {encoding.fromlocal(k): v for k, v in repo.branchmap().iteritems()} -@wireprotocommand("capabilities", permission="pull") +@wireprotocommand(b"capabilities", permission=b"pull") def capabilitiesv2(repo, proto): yield _capabilitiesv2(repo, proto) @wireprotocommand( - "changesetdata", + b"changesetdata", args={ - "revisions": { - "type": "list", - "example": [ + b"revisions": { + b"type": b"list", + b"example": [ {b"type": b"changesetexplicit", b"nodes": [b"abcdef..."],} ], }, - "fields": { - "type": "set", - "default": set, - "example": {b"parents", b"revision"}, - "validvalues": {b"bookmarks", b"parents", b"phase", b"revision"}, + b"fields": { + b"type": b"set", + b"default": set, + b"example": {b"parents", b"revision"}, + b"validvalues": {b"bookmarks", b"parents", b"phase", b"revision"}, }, }, - permission="pull", + permission=b"pull", ) def changesetdata(repo, proto, revisions, fields): # TODO look for unknown fields and abort when they can't be serviced. @@ -990,7 +1000,7 @@ publishing = repo.publishing() if outgoing: - repo.hook("preoutgoing", throw=True, source="serve") + repo.hook(b"preoutgoing", throw=True, source=b"serve") yield { b"totalitems": len(outgoing), @@ -1078,7 +1088,7 @@ fl = repo.file(path) if not len(fl): - raise FileAccessError(path, "unknown file: %s", (path,)) + raise FileAccessError(path, b"unknown file: %s", (path,)) return fl @@ -1125,8 +1135,8 @@ for pattern in pathfilter.get(key, []): if not pattern.startswith((b"path:", b"rootfilesin:")): raise error.WireprotoCommandError( - "%s pattern must begin with `path:` or `rootfilesin:`; " - "got %s", + b"%s pattern must begin with `path:` or `rootfilesin:`; " + b"got %s", (key, pattern), ) @@ -1146,27 +1156,27 @@ @wireprotocommand( - "filedata", + b"filedata", args={ - "haveparents": { - "type": "bool", - "default": lambda: False, - "example": True, + b"haveparents": { + b"type": b"bool", + b"default": lambda: False, + b"example": True, }, - "nodes": {"type": "list", "example": [b"0123456..."],}, - "fields": { - "type": "set", - "default": set, - "example": {b"parents", b"revision"}, - "validvalues": {b"parents", b"revision", b"linknode"}, + b"nodes": {b"type": b"list", b"example": [b"0123456..."],}, + b"fields": { + b"type": b"set", + b"default": set, + b"example": {b"parents", b"revision"}, + b"validvalues": {b"parents", b"revision", b"linknode"}, }, - "path": {"type": "bytes", "example": b"foo.txt",}, + b"path": {b"type": b"bytes", b"example": b"foo.txt",}, }, - permission="pull", + permission=b"pull", # TODO censoring a file revision won't invalidate the cache. # Figure out a way to take censoring into account when deriving # the cache key. - cachekeyfn=makecommandcachekeyfn("filedata", 1, allargs=True), + cachekeyfn=makecommandcachekeyfn(b"filedata", 1, allargs=True), ) def filedata(repo, proto, haveparents, nodes, fields, path): # TODO this API allows access to file revisions that are attached to @@ -1188,7 +1198,7 @@ store.rev(node) except error.LookupError: raise error.WireprotoCommandError( - "unknown file node: %s", (hex(node),) + b"unknown file node: %s", (hex(node),) ) # TODO by creating the filectx against a specific file revision @@ -1223,41 +1233,41 @@ @wireprotocommand( - "filesdata", + b"filesdata", args={ - "haveparents": { - "type": "bool", - "default": lambda: False, - "example": True, + b"haveparents": { + b"type": b"bool", + b"default": lambda: False, + b"example": True, }, - "fields": { - "type": "set", - "default": set, - "example": {b"parents", b"revision"}, - "validvalues": { + b"fields": { + b"type": b"set", + b"default": set, + b"example": {b"parents", b"revision"}, + b"validvalues": { b"firstchangeset", b"linknode", b"parents", b"revision", }, }, - "pathfilter": { - "type": "dict", - "default": lambda: None, - "example": {b"include": [b"path:tests"]}, + b"pathfilter": { + b"type": b"dict", + b"default": lambda: None, + b"example": {b"include": [b"path:tests"]}, }, - "revisions": { - "type": "list", - "example": [ + b"revisions": { + b"type": b"list", + b"example": [ {b"type": b"changesetexplicit", b"nodes": [b"abcdef..."],} ], }, }, - permission="pull", + permission=b"pull", # TODO censoring a file revision won't invalidate the cache. # Figure out a way to take censoring into account when deriving # the cache key. - cachekeyfn=makecommandcachekeyfn("filesdata", 1, allargs=True), + cachekeyfn=makecommandcachekeyfn(b"filesdata", 1, allargs=True), extracapabilitiesfn=filesdatacapabilities, ) def filesdata(repo, proto, haveparents, fields, pathfilter, revisions): @@ -1327,29 +1337,33 @@ @wireprotocommand( - "heads", + b"heads", args={ - "publiconly": { - "type": "bool", - "default": lambda: False, - "example": False, + b"publiconly": { + b"type": b"bool", + b"default": lambda: False, + b"example": False, }, }, - permission="pull", + permission=b"pull", ) def headsv2(repo, proto, publiconly): if publiconly: - repo = repo.filtered("immutable") + repo = repo.filtered(b"immutable") yield repo.heads() @wireprotocommand( - "known", + b"known", args={ - "nodes": {"type": "list", "default": list, "example": [b"deadbeef"],}, + b"nodes": { + b"type": b"list", + b"default": list, + b"example": [b"deadbeef"], + }, }, - permission="pull", + permission=b"pull", ) def knownv2(repo, proto, nodes): result = b"".join(b"1" if n else b"0" for n in repo.known(nodes)) @@ -1357,9 +1371,9 @@ @wireprotocommand( - "listkeys", - args={"namespace": {"type": "bytes", "example": b"ns",},}, - permission="pull", + b"listkeys", + args={b"namespace": {b"type": b"bytes", b"example": b"ns",},}, + permission=b"pull", ) def listkeysv2(repo, proto, namespace): keys = repo.listkeys(encoding.tolocal(namespace)) @@ -1372,9 +1386,9 @@ @wireprotocommand( - "lookup", - args={"key": {"type": "bytes", "example": b"foo",},}, - permission="pull", + b"lookup", + args={b"key": {b"type": b"bytes", b"example": b"foo",},}, + permission=b"pull", ) def lookupv2(repo, proto, key): key = encoding.tolocal(key) @@ -1396,24 +1410,24 @@ @wireprotocommand( - "manifestdata", + b"manifestdata", args={ - "nodes": {"type": "list", "example": [b"0123456..."],}, - "haveparents": { - "type": "bool", - "default": lambda: False, - "example": True, + b"nodes": {b"type": b"list", b"example": [b"0123456..."],}, + b"haveparents": { + b"type": b"bool", + b"default": lambda: False, + b"example": True, }, - "fields": { - "type": "set", - "default": set, - "example": {b"parents", b"revision"}, - "validvalues": {b"parents", b"revision"}, + b"fields": { + b"type": b"set", + b"default": set, + b"example": {b"parents", b"revision"}, + b"validvalues": {b"parents", b"revision"}, }, - "tree": {"type": "bytes", "example": b"",}, + b"tree": {b"type": b"bytes", b"example": b"",}, }, - permission="pull", - cachekeyfn=makecommandcachekeyfn("manifestdata", 1, allargs=True), + permission=b"pull", + cachekeyfn=makecommandcachekeyfn(b"manifestdata", 1, allargs=True), extracapabilitiesfn=manifestdatacapabilities, ) def manifestdata(repo, proto, haveparents, nodes, fields, tree): @@ -1424,7 +1438,7 @@ try: store.rev(node) except error.LookupError: - raise error.WireprotoCommandError("unknown node: %s", (node,)) + raise error.WireprotoCommandError(b"unknown node: %s", (node,)) revisions = store.emitrevisions( nodes, @@ -1466,14 +1480,14 @@ @wireprotocommand( - "pushkey", + b"pushkey", args={ - "namespace": {"type": "bytes", "example": b"ns",}, - "key": {"type": "bytes", "example": b"key",}, - "old": {"type": "bytes", "example": b"old",}, - "new": {"type": "bytes", "example": "new",}, + b"namespace": {b"type": b"bytes", b"example": b"ns",}, + b"key": {b"type": b"bytes", b"example": b"key",}, + b"old": {b"type": b"bytes", b"example": b"old",}, + b"new": {b"type": b"bytes", b"example": b"new",}, }, - permission="push", + permission=b"push", ) def pushkeyv2(repo, proto, namespace, key, old, new): # TODO handle ui output redirection @@ -1486,16 +1500,19 @@ @wireprotocommand( - "rawstorefiledata", + b"rawstorefiledata", args={ - "files": {"type": "list", "example": [b"changelog", b"manifestlog"],}, - "pathfilter": { - "type": "list", - "default": lambda: None, - "example": {b"include": [b"path:tests"]}, + b"files": { + b"type": b"list", + b"example": [b"changelog", b"manifestlog"], + }, + b"pathfilter": { + b"type": b"list", + b"default": lambda: None, + b"example": {b"include": [b"path:tests"]}, }, }, - permission="pull", + permission=b"pull", ) def rawstorefiledata(repo, proto, files, pathfilter): if not streamclone.allowservergeneration(repo): @@ -1546,7 +1563,7 @@ # We have to use a closure for this to ensure the context manager is # closed only after sending the final chunk. def getfiledata(): - with repo.svfs(name, "rb", auditpath=False) as fh: + with repo.svfs(name, b"rb", auditpath=False) as fh: for chunk in util.filechunkiter(fh, limit=size): yield chunk diff --git a/mercurial/worker.py b/mercurial/worker.py --- a/mercurial/worker.py +++ b/mercurial/worker.py @@ -44,7 +44,7 @@ # windows try: - n = int(encoding.environ["NUMBER_OF_PROCESSORS"]) + n = int(encoding.environ[b"NUMBER_OF_PROCESSORS"]) if n > 0: return n except (KeyError, ValueError): @@ -54,14 +54,14 @@ def _numworkers(ui): - s = ui.config("worker", "numcpus") + s = ui.config(b"worker", b"numcpus") if s: try: n = int(s) if n >= 1: return n except ValueError: - raise error.Abort(_("number of cpus must be an integer")) + raise error.Abort(_(b"number of cpus must be an integer")) return min(max(countcpus(), 4), 32) @@ -115,7 +115,7 @@ a thread-based worker. Should be disabled for CPU heavy tasks that don't release the GIL. """ - enabled = ui.configbool("worker", "enabled") + enabled = ui.configbool(b"worker", b"enabled") if enabled and worthwhile(ui, costperarg, len(args), threadsafe=threadsafe): return _platformworker(ui, func, staticargs, args, hasretval) return func(*staticargs + (args,)) @@ -331,8 +331,8 @@ # task and does not get to handle the interruption. ui.warn( _( - "failed to kill worker threads while " - "handling an exception\n" + b"failed to kill worker threads while " + b"handling an exception\n" ) ) return