[PATCH] docklog: avoid a crash on tab completion with py3 (fixes #5906)

7 views
Skip to first unread message

Matt Harbison

unread,
Jun 22, 2023, 2:01:49 PM6/22/23
to thg...@googlegroups.com
# HG changeset patch
# User Matt Harbison <matt_h...@yahoo.com>
# Date 1687448549 14400
# Thu Jun 22 11:42:29 2023 -0400
# Branch stable
# Node ID 701d61540dda76d92b3701ffe63eb19bba0558c7
# Parent c3ee78109fde3ebebcf5601169046e6a4fb3b99d
# EXP-Topic docklog-fix
docklog: avoid a crash on tab completion with py3 (fixes #5906)

diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
--- a/tortoisehg/hgqt/docklog.py
+++ b/tortoisehg/hgqt/docklog.py
@@ -8,6 +8,11 @@


import os
+from typing import (
+ Dict,
+ List,
+ Tuple,
+)

from .qsci import (
QsciScintilla,
@@ -323,7 +328,7 @@
else:
self._logwidget.flash()

- def _commandComplete(self, cmdtype, cmdline):
+ def _commandComplete(self, cmdtype: str, cmdline: str) -> List[str]:
from tortoisehg.hgqt import run
matches = []
cmd = cmdline.split()
@@ -334,12 +339,12 @@
subcmd = ''
if len(cmd) >= 2:
subcmd = cmd[1].lower()
- def findhgcmd(cmdstart):
+ def findhgcmd(cmdstart: str) -> Dict[str, str]:
matchinfo = {}
for cmdspec in cmdtable:
- for cmdname in cmdspec.split('|'):
- if cmdname.startswith(cmdstart):
- matchinfo[cmdname] = cmdspec
+ for cmdname in cmdspec.split(b'|'):
+ if cmdname.startswith(hglib.fromunicode(cmdstart)):
+ matchinfo[hglib.tounicode(cmdname)] = hglib.tounicode(cmdspec)
return matchinfo
matchingcmds = findhgcmd(subcmd)
if not matchingcmds:
@@ -349,21 +354,21 @@
matches = [basecmdline % c for c in matchingcmds]
else:
scmdtype = list(matchingcmds)[0]
- cmdspec = matchingcmds[scmdtype]
- opts = cmdtable[cmdspec][1]
- def findcmdopt(cmdopt):
+ cmdspec = hglib.fromunicode(matchingcmds[scmdtype])
+ opts: List[Tuple[bytes]] = cmdtable[cmdspec][1]
+ def findcmdopt(cmdopt: str) -> List[Tuple[str]]:
cmdopt = cmdopt.lower()
while cmdopt.startswith('-'):
cmdopt = cmdopt[1:]
matchingopts = []
for opt in opts:
- if opt[1].startswith(cmdopt):
- matchingopts.append(opt)
+ if opt[1].startswith(hglib.fromunicode(cmdopt)):
+ matchingopts.append(tuple(hglib.tounicode(o) for o in opt))
return matchingopts
basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
if len(cmd) == 2:
matches = ['%s %s ' % (cmdtype, scmdtype)]
- matches += [basecmdline % opt[1] for opt in opts]
+ matches += [basecmdline % hglib.tounicode(opt[1]) for opt in opts]
else:
cmdopt = cmd[-1]
if cmdopt.startswith('-'):

Yuya Nishihara

unread,
Jun 22, 2023, 10:26:33 PM6/22/23
to Matt Harbison, thg...@googlegroups.com
Mercurial's cmdtable may contain arbitrary value types, so better to not
apply unicode conversion here.

> return matchingopts
> basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
> if len(cmd) == 2:
> matches = ['%s %s ' % (cmdtype, scmdtype)]
> - matches += [basecmdline % opt[1] for opt in opts]
> + matches += [basecmdline % hglib.tounicode(opt[1]) for opt in opts]
> else:
> cmdopt = cmd[-1]
> if cmdopt.startswith('-'):

So do hglib.tounicode(opt[1]) here? (or rewrite findcmdopt() to only return opt[1].)

Matt Harbison

unread,
Jun 23, 2023, 10:58:57 AM6/23/23
to thg...@googlegroups.com
# HG changeset patch
# User Matt Harbison <matt_h...@yahoo.com>
# Date 1687448549 14400
# Thu Jun 22 11:42:29 2023 -0400
# Branch stable
# Node ID 63c1c62862793a9bda7036b821bdfc7afe4fbdb3
@@ -349,28 +354,29 @@
matches = [basecmdline % c for c in matchingcmds]
else:
scmdtype = list(matchingcmds)[0]
- cmdspec = matchingcmds[scmdtype]
- opts = cmdtable[cmdspec][1]
- def findcmdopt(cmdopt):
+ cmdspec = hglib.fromunicode(matchingcmds[scmdtype])
+ opts: List[Tuple[bytes]] = cmdtable[cmdspec][1]
+ def findcmdopt(cmdopt: str) -> List[str]:
cmdopt = cmdopt.lower()
while cmdopt.startswith('-'):
cmdopt = cmdopt[1:]
matchingopts = []
for opt in opts:
- if opt[1].startswith(cmdopt):
- matchingopts.append(opt)
+ uopt = hglib.tounicode(opt[1])
+ if uopt.startswith(cmdopt):
+ matchingopts.append(uopt)
return matchingopts
basecmdline = '%s %s --%%s' % (cmdtype, scmdtype)
if len(cmd) == 2:
matches = ['%s %s ' % (cmdtype, scmdtype)]
- matches += [basecmdline % opt[1] for opt in opts]
+ matches += [basecmdline % hglib.tounicode(opt[1]) for opt in opts]
else:
cmdopt = cmd[-1]
if cmdopt.startswith('-'):
# find the matching options
basecmdline = ' '.join(cmd[:-1]) + ' --%s'
cmdopts = findcmdopt(cmdopt)
- matches = [basecmdline % opt[1] for opt in cmdopts]
+ matches = [basecmdline % opt for opt in cmdopts]
return sorted(matches)

@pyqtSlot(str)

Yuya Nishihara

unread,
Jun 23, 2023, 11:18:52 PM6/23/23
to Matt Harbison, thg...@googlegroups.com
On Fri, 23 Jun 2023 10:58:50 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_h...@yahoo.com>
> # Date 1687448549 14400
> # Thu Jun 22 11:42:29 2023 -0400
> # Branch stable
> # Node ID 63c1c62862793a9bda7036b821bdfc7afe4fbdb3
> # Parent c3ee78109fde3ebebcf5601169046e6a4fb3b99d
> # EXP-Topic docklog-fix
> docklog: avoid a crash on tab completion with py3 (fixes #5906)

> @@ -349,28 +354,29 @@
> matches = [basecmdline % c for c in matchingcmds]
> else:
> scmdtype = list(matchingcmds)[0]
> - cmdspec = matchingcmds[scmdtype]
> - opts = cmdtable[cmdspec][1]
> - def findcmdopt(cmdopt):
> + cmdspec = hglib.fromunicode(matchingcmds[scmdtype])
> + opts: List[Tuple[bytes]] = cmdtable[cmdspec][1]

As you might notice, this type annotation is wrong. It's something like
List[Tuple[bytes, bytes, Any, ...]] but I don't remember the exact guarantee
provided by registrar.command() API.

Other than that, the patch looks good to me.

Matt Harbison

unread,
Jun 26, 2023, 11:16:18 AM6/26/23
to thg...@googlegroups.com
# HG changeset patch
# User Matt Harbison <matt_h...@yahoo.com>
# Date 1687448549 14400
# Thu Jun 22 11:42:29 2023 -0400
# Branch stable
# Node ID 7482046464a0d42ba30bf52c1912d6f99a123fd7
# Parent c3ee78109fde3ebebcf5601169046e6a4fb3b99d
# EXP-Topic docklog-fix
docklog: avoid a crash on tab completion with py3 (fixes #5906)

diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py
--- a/tortoisehg/hgqt/docklog.py
+++ b/tortoisehg/hgqt/docklog.py
@@ -8,6 +8,10 @@


import os
+from typing import (
+ Dict,
+ List,
+)

from .qsci import (
QsciScintilla,
@@ -323,7 +327,7 @@
else:
self._logwidget.flash()

- def _commandComplete(self, cmdtype, cmdline):
+ def _commandComplete(self, cmdtype: str, cmdline: str) -> List[str]:
from tortoisehg.hgqt import run
matches = []
cmd = cmdline.split()
@@ -334,12 +338,12 @@
subcmd = ''
if len(cmd) >= 2:
subcmd = cmd[1].lower()
- def findhgcmd(cmdstart):
+ def findhgcmd(cmdstart: str) -> Dict[str, str]:
matchinfo = {}
for cmdspec in cmdtable:
- for cmdname in cmdspec.split('|'):
- if cmdname.startswith(cmdstart):
- matchinfo[cmdname] = cmdspec
+ for cmdname in cmdspec.split(b'|'):
+ if cmdname.startswith(hglib.fromunicode(cmdstart)):
+ matchinfo[hglib.tounicode(cmdname)] = hglib.tounicode(cmdspec)
return matchinfo
matchingcmds = findhgcmd(subcmd)
if not matchingcmds:
@@ -349,28 +353,29 @@
matches = [basecmdline % c for c in matchingcmds]
else:
scmdtype = list(matchingcmds)[0]
- cmdspec = matchingcmds[scmdtype]
+ cmdspec = hglib.fromunicode(matchingcmds[scmdtype])
opts = cmdtable[cmdspec][1]
- def findcmdopt(cmdopt):

Yuya Nishihara

unread,
Jun 26, 2023, 9:31:24 PM6/26/23
to Matt Harbison, thg...@googlegroups.com
On Mon, 26 Jun 2023 11:16:12 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_h...@yahoo.com>
> # Date 1687448549 14400
> # Thu Jun 22 11:42:29 2023 -0400
> # Branch stable
> # Node ID 7482046464a0d42ba30bf52c1912d6f99a123fd7
> # Parent c3ee78109fde3ebebcf5601169046e6a4fb3b99d
> # EXP-Topic docklog-fix
> docklog: avoid a crash on tab completion with py3 (fixes #5906)

Queued for stable, thanks.
Reply all
Reply to author
Forward
0 new messages