diff options
author | James Cowgill <jcowgill@debian.org> | 2018-12-22 10:47:29 +0000 |
---|---|---|
committer | James Cowgill <jcowgill@debian.org> | 2018-12-22 10:47:29 +0000 |
commit | 41c422dff219468b00c2ed7e42c831863e2b06a1 (patch) | |
tree | ba55ecc48268a60ca3523bad2d3207dca13eeaf0 | |
parent | 82d8a5ac948a5d558bf51e418fd845c30ac80995 (diff) |
New upstream version 4.8.1
42 files changed, 266 insertions, 143 deletions
@@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: tortoisehg -Version: 4.7 +Version: 4.8.1 Summary: TortoiseHg dialogs for Mercurial VCS Home-page: https://tortoisehg.bitbucket.io Author: Steve Borho diff --git a/doc/source-cs/preface.txt b/doc/source-cs/preface.txt index 0b532f3..d783afd 100644 --- a/doc/source-cs/preface.txt +++ b/doc/source-cs/preface.txt @@ -45,12 +45,6 @@ na neomezené množství počítačů a šířit ve shodě s licencí GPLv2. Komunita ======== -Adresy: - -* `Uživatelé <https://lists.sourceforge.net/lists/listinfo/tortoisehg-discuss>`_ - Oznámení, otázky-odpovědi a diskuze o vlastnostech -* `Vývojáři <https://lists.sourceforge.net/lists/listinfo/tortoisehg-develop>`_ - Oprávky, zprávy o chybách a diskuze o vývoji programu. -* `Problémy <https://lists.sourceforge.net/lists/listinfo/tortoisehg-issues>`_ - Přehled zaznamenávaných problémů. - Naše Wiki na stránkách Bitbucket je `zde <https://bitbucket.org/tortoisehg/thg/wiki/Home>`_ . Poděkování diff --git a/doc/source-ja/preface.txt b/doc/source-ja/preface.txt index f94cc05..6873433 100644 --- a/doc/source-ja/preface.txt +++ b/doc/source-ja/preface.txt @@ -57,12 +57,6 @@ GPLv2 ライセンスに従う限り再配布も可能です。 コミュニティ ============ -メーリングリスト: - -* `利用者 ML <https://lists.sourceforge.net/lists/listinfo/tortoisehg-discuss>`_ - アナウンス、使い方などの質問、機能の議論など。 -* `開発者 ML <https://lists.sourceforge.net/lists/listinfo/tortoisehg-develop>`_ - パッチ投稿、バグ報告、開発関連の議論など。 -* `バグ通知 ML <https://lists.sourceforge.net/lists/listinfo/tortoisehg-issues>`_ - バグ管理システムからの自動通知メール。 - Bitbucket には `公式 Wiki <https://bitbucket.org/tortoisehg/thg/wiki/Home>`_ もあります。 日本語 Wiki は `こちら <https://bitbucket.org/kuy/thg-ja/wiki/Home>`_ になります。 diff --git a/doc/source/conf.py b/doc/source/conf.py index c47ba5c..601d765 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -49,9 +49,9 @@ copyright = u'2010-2018, Steve Borho and others' # built documents. # # The short X.Y version. -version = '3.8' +version = '4.7' # The full version, including alpha/beta/rc tags. -release = '3.8.0' +release = '4.7.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/preface.txt b/doc/source/preface.txt index 546856c..d0a11b4 100644 --- a/doc/source/preface.txt +++ b/doc/source/preface.txt @@ -52,11 +52,9 @@ according to the GPLv2 license. Community ========= -Mailing Lists: +Mailing List:: -* `Users <https://lists.sourceforge.net/lists/listinfo/tortoisehg-discuss>`_ - Announcements, user Q&A, and feature discussions. -* `Developers <thg-dev@googlegroups.com>`_ - Patches, bug reports, development discussions. -* `Issues <https://lists.sourceforge.net/lists/listinfo/tortoisehg-issues>`_ - Notifications from the issue tracker. + `Developers <thg-dev@googlegroups.com>`_ - Patches, bug reports, development discussions. And our `wiki <https://bitbucket.org/tortoisehg/thg/wiki/Home>`_ on Bitbucket. diff --git a/hgext3rd/thg.py b/hgext3rd/thg.py index a5f8bf6..c3be94c 100644 --- a/hgext3rd/thg.py +++ b/hgext3rd/thg.py @@ -54,12 +54,7 @@ else: import threading from mercurial import demandimport -try: - _updateignores = demandimport.IGNORES.update -except AttributeError: - # hg<4.7 (670eb4fa1b86) - _updateignores = demandimport.ignore.extend -_updateignores([ +demandimport.IGNORES.update([ 'win32com.shell', 'numpy', # comtypes.npsupport does try-import 'tortoisehg.util.config', @@ -59,12 +59,7 @@ else: import threading from mercurial import demandimport -try: - _updateignores = demandimport.IGNORES.update -except AttributeError: - # hg<4.7 (670eb4fa1b86) - _updateignores = demandimport.ignore.extend -_updateignores([ +demandimport.IGNORES.update([ 'win32com.shell', 'numpy', # comtypes.npsupport does try-import 'tortoisehg.util.config', diff --git a/tortoisehg/hgqt/about.py b/tortoisehg/hgqt/about.py index 032c0bf..ef374c6 100644 --- a/tortoisehg/hgqt/about.py +++ b/tortoisehg/hgqt/about.py @@ -169,9 +169,7 @@ class AboutDialog(QDialog): except (IndexError, ImportError, ValueError): pass try: - thgv = version.version() - if '+' in thgv: - thgv = thgv[:thgv.index('+')] + thgv = version.package_version() curver = tuple([int(p) for p in thgv.split('.')]) except ValueError: curver = (0,0,0) diff --git a/tortoisehg/hgqt/bisect.py b/tortoisehg/hgqt/bisect.py index ae4f67e..bd41641 100644 --- a/tortoisehg/hgqt/bisect.py +++ b/tortoisehg/hgqt/bisect.py @@ -26,6 +26,7 @@ from .qtgui import ( from mercurial import ( error, + scmutil, ) from ..util import hglib @@ -157,7 +158,7 @@ class BisectDialog(QDialog): def _lookupRevision(self, changeid): try: - ctx = self.repo[hglib.fromunicode(changeid)] + ctx = scmutil.revsymbol(self.repo, hglib.fromunicode(changeid)) return ctx.rev() except (error.LookupError, error.RepoLookupError), e: self._stbar.showMessage(hglib.tounicode(str(e))) diff --git a/tortoisehg/hgqt/clone.py b/tortoisehg/hgqt/clone.py index 5663a32..b286317 100644 --- a/tortoisehg/hgqt/clone.py +++ b/tortoisehg/hgqt/clone.py @@ -76,7 +76,8 @@ class CloneWidget(cmdui.AbstractCmdWidget): self._cmdagent = cmdagent self.ui = ui - dest = src = os.getcwd() + dest = src = (self.ui.config('tortoisehg', 'defaultclonedest') + or os.getcwd()) if args: if len(args) > 1: src = args[0] diff --git a/tortoisehg/hgqt/commit.py b/tortoisehg/hgqt/commit.py index 0fe9deb..4228e82 100644 --- a/tortoisehg/hgqt/commit.py +++ b/tortoisehg/hgqt/commit.py @@ -56,6 +56,7 @@ from mercurial import ( error, obsolete, # delete if obsolete becomes enabled by default phases, + scmutil, ) from mercurial.utils import ( dateutil, @@ -569,7 +570,8 @@ class CommitWidget(QWidget, qtlib.TaskWidget): if branch in [p.branch() for p in repo[None].parents()]: resp = 0 else: - rev = repo[branch].rev() + # TODO: should look up only in branch namespace + rev = scmutil.revsymbol(repo, branch).rev() resp = qtlib.CustomPrompt(_('Confirm Branch Change'), _('Named branch "%s" already exists, ' 'last used in revision %d\n' diff --git a/tortoisehg/hgqt/docklog.py b/tortoisehg/hgqt/docklog.py index 6106ad3..fdf6b66 100644 --- a/tortoisehg/hgqt/docklog.py +++ b/tortoisehg/hgqt/docklog.py @@ -336,6 +336,7 @@ class ConsoleWidget(QWidget, qtlib.TaskWidget): matchinfo = {} for cmdspec in cmdtable: for cmdname in cmdspec.split('|'): + # TODO: switch to hg>=4.8 (fa88170c10bb) syntax if cmdname[0] == '^': cmdname = cmdname[1:] if cmdname.startswith(cmdstart): diff --git a/tortoisehg/hgqt/filedata.py b/tortoisehg/hgqt/filedata.py index 89163cf..08ae24a 100644 --- a/tortoisehg/hgqt/filedata.py +++ b/tortoisehg/hgqt/filedata.py @@ -226,13 +226,7 @@ class FileData(_AbstractFileData): def _checkMaxDiff(self, ctx, wfile, maxdiff, force): self.error = None fctx = ctx.filectx(wfile) - if ctx.rev() is None: - size = fctx.size() - else: - # fctx.size() can read all data into memory in rename cases so - # we read the size directly from the filelog, this is deeper - # under the API than I prefer to go, but seems necessary - size = fctx._filelog.rawsize(fctx.filerev()) + size = hglib.getestimatedsize(fctx) if not force and size > maxdiff: raise _BadContent(_('File is larger than the specified max size.\n' 'maxdiff = %s KB') % (maxdiff // 1024)) @@ -312,7 +306,7 @@ class FileData(_AbstractFileData): if status in ('R', '!'): if wfile in ctx.p1(): fctx = ctx.p1()[wfile] - if fctx._filelog.rawsize(fctx.filerev()) > maxdiff: + if hglib.getestimatedsize(fctx) > maxdiff: self.error = mde else: olddata = fctx.data() @@ -380,7 +374,7 @@ class FileData(_AbstractFileData): self.olddata = olddata if changeselect: - diffopts = patch.diffopts(repo.ui, {}) + diffopts = patch.difffeatureopts(repo.ui) diffopts.git = True m = match.exact(repo.root, repo.root, [wfile]) fp = cStringIO.StringIO() diff --git a/tortoisehg/hgqt/filedialogs.py b/tortoisehg/hgqt/filedialogs.py index 2f64cd3..81475b7 100644 --- a/tortoisehg/hgqt/filedialogs.py +++ b/tortoisehg/hgqt/filedialogs.py @@ -52,6 +52,10 @@ from .qtgui import ( QWidget, ) +from mercurial import ( + scmutil, +) + from ..util import hglib from ..util.i18n import _ from . import ( @@ -366,7 +370,8 @@ class FileLogDialog(_AbstractFileDialog): if ':' in link: scheme, param = link.split(':', 1) if scheme == 'cset': - rev = self.repo[hglib.fromunicode(param)].rev() + rev = scmutil.revsymbol(self.repo, + hglib.fromunicode(param)).rev() return self.goto(rev) QDesktopServices.openUrl(QUrl(link)) diff --git a/tortoisehg/hgqt/fileview.py b/tortoisehg/hgqt/fileview.py index 524e94b..cf8e6ef 100644 --- a/tortoisehg/hgqt/fileview.py +++ b/tortoisehg/hgqt/fileview.py @@ -1118,12 +1118,16 @@ class _AnnotateViewControl(_AbstractViewControl): links = [] fctxcache = {} # (path, rev): fctx for l in data[0]['lines']: - path, rev = l['file'], l['rev'] + try: + path, rev, lineno = l['path'], l['rev'], l['lineno'] + except KeyError: + # hg<4.8 (34ba47117164, 47cb6750dea3) + path, rev, lineno = l['file'], l['rev'], l['line_number'] try: fctx = fctxcache[path, rev] except KeyError: fctx = fctxcache[path, rev] = repo[rev][path] - links.append((fctx, l['line_number'])) + links.append((fctx, lineno)) self._links = links self._updateView() diff --git a/tortoisehg/hgqt/graft.py b/tortoisehg/hgqt/graft.py index 6ccfee0..323f4e5 100644 --- a/tortoisehg/hgqt/graft.py +++ b/tortoisehg/hgqt/graft.py @@ -24,6 +24,8 @@ from .qtgui import ( QVBoxLayout, ) +from mercurial import scmutil + from ..util import hglib from ..util.i18n import _ from . import ( @@ -53,7 +55,7 @@ class GraftDialog(QDialog): self.valid = True def cleanrevlist(revlist): - return [self.repo[rev].rev() for rev in revlist] + return [scmutil.revsymbol(self.repo, rev).rev() for rev in revlist] self.sourcelist = cleanrevlist(opts.get('source', ['.'])) currgraftrevs = self.graftstate() if currgraftrevs: @@ -220,17 +222,7 @@ class GraftDialog(QDialog): sess.commandFinished.connect(self._abortFinished) def graftstate(self): - graftstatefile = self.repo.vfs.join('graftstate') - if os.path.exists(graftstatefile): - f = open(graftstatefile, 'r') - info = f.readlines() - f.close() - if len(info): - revlist = [rev.strip() for rev in info] - revlist = [rev for rev in revlist if rev != ''] - if revlist: - return revlist - return None + return hglib.readgraftstate(self.repo) def _runCommand(self, cmdline): assert self._cmdsession.isFinished() diff --git a/tortoisehg/hgqt/grep.py b/tortoisehg/hgqt/grep.py index f33e62c..a689786 100644 --- a/tortoisehg/hgqt/grep.py +++ b/tortoisehg/hgqt/grep.py @@ -51,6 +51,7 @@ from mercurial import ( match, subrepo, ui, + scmutil, ) from mercurial.utils import ( stringutil, @@ -357,7 +358,7 @@ class SearchWidget(QWidget, qtlib.TaskWidget): if inc: inc = map(str.strip, inc.split(',')) exc = hglib.fromunicode(self.excle.text()) if exc: exc = map(str.strip, exc.split(',')) - rev = hglib.fromunicode(self.revle.text()).strip() + revstr = hglib.fromunicode(self.revle.text()).strip() self.addHistory(pattern, inc or [], exc or []) if self.wctxradio.isChecked(): @@ -371,7 +372,8 @@ class SearchWidget(QWidget, qtlib.TaskWidget): self.tv.setColumnHidden(COL_REVISION, True) self.tv.setColumnHidden(COL_USER, True) try: - ctx = self.repo[rev or '.'] + rev = scmutil.revsymbol(self.repo, revstr or '.').rev() + ctx = self.repo[rev] except error.RepoError, e: msg = _('grep: %s\n') % hglib.tounicode(str(e)) self.showMessage.emit(msg) diff --git a/tortoisehg/hgqt/hgemail_ui.py b/tortoisehg/hgqt/hgemail_ui.py index 1fb8bd4..b572d6e 100644 --- a/tortoisehg/hgqt/hgemail_ui.py +++ b/tortoisehg/hgqt/hgemail_ui.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '/Users/sborho/repos/thg/tortoisehg/hgqt/hgemail.ui' +# Form implementation generated from reading ui file '/home/sborho/repos/thg/tortoisehg/hgqt/hgemail.ui' # -# Created by: PyQt5 UI code generator 5.10.1 +# Created by: PyQt5 UI code generator 5.11.2 # # WARNING! All changes made in this file will be lost! diff --git a/tortoisehg/hgqt/matching.py b/tortoisehg/hgqt/matching.py index d47ba36..e36c04f 100644 --- a/tortoisehg/hgqt/matching.py +++ b/tortoisehg/hgqt/matching.py @@ -26,7 +26,10 @@ from .qtgui import ( QVBoxLayout, ) -from mercurial import error +from mercurial import ( + error, + scmutil, +) from ..util import hglib from ..util.i18n import _ @@ -230,7 +233,7 @@ class MatchDialog(QDialog): self.match_btn.setEnabled(True) return try: - csinfo_update(self.repo[new_rev]) + csinfo_update(scmutil.revsymbol(self.repo, new_rev)) return except (error.LookupError, error.RepoLookupError, error.RepoError): pass diff --git a/tortoisehg/hgqt/merge.py b/tortoisehg/hgqt/merge.py index 907e44e..5fe0a4f 100644 --- a/tortoisehg/hgqt/merge.py +++ b/tortoisehg/hgqt/merge.py @@ -599,10 +599,13 @@ class CommitPage(BasePage): self.wizard().close() return True - user = hglib.tounicode(qtlib.getCurrentUsername(self, self.repo, - self.opts)) - if not user: - return False + # username will be prompted as necessary by hg if ui.askusername + user = self.opts.get('user') + if not self.repo.ui.configbool('ui', 'askusername'): + user = hglib.tounicode(qtlib.getCurrentUsername(self, self.repo, + self.opts)) + if not user: + return False self.setTitle(_('Committing...')) self.setSubTitle(_('Please wait while committing merged files.')) diff --git a/tortoisehg/hgqt/mq.py b/tortoisehg/hgqt/mq.py index 373c8e3..5f056c6 100644 --- a/tortoisehg/hgqt/mq.py +++ b/tortoisehg/hgqt/mq.py @@ -45,7 +45,10 @@ from .qtgui import ( QWidget, ) -from mercurial import error +from mercurial import ( + error, + scmutil, +) from ..util import hglib from ..util.i18n import _ @@ -522,7 +525,10 @@ class PatchQueueModel(QAbstractListModel): repo = self._repoagent.rawRepo() patch = self._series[index.row()] try: - ctx = repo[patch] + if patch in repo.thgmqunappliedpatches: + ctx = repo[patch] + else: + ctx = scmutil.revsymbol(repo, patch) except error.RepoLookupError: # cache not updated after qdelete or qfinish return diff --git a/tortoisehg/hgqt/postreview_ui.py b/tortoisehg/hgqt/postreview_ui.py index 70c7e67..16b770c 100644 --- a/tortoisehg/hgqt/postreview_ui.py +++ b/tortoisehg/hgqt/postreview_ui.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '/Users/sborho/repos/thg/tortoisehg/hgqt/postreview.ui' +# Form implementation generated from reading ui file '/home/sborho/repos/thg/tortoisehg/hgqt/postreview.ui' # -# Created by: PyQt5 UI code generator 5.10.1 +# Created by: PyQt5 UI code generator 5.11.2 # # WARNING! All changes made in this file will be lost! diff --git a/tortoisehg/hgqt/qfold.py b/tortoisehg/hgqt/qfold.py index 962a079..41cf894 100644 --- a/tortoisehg/hgqt/qfold.py +++ b/tortoisehg/hgqt/qfold.py @@ -28,6 +28,9 @@ from .qtgui import ( ) from hgext import mq +from mercurial import ( + scmutil, +) from ..util import hglib from ..util.i18n import _ @@ -135,9 +138,10 @@ class QFoldDialog(QDialog): self.summ.setText(hglib.tounicode(txt)) def composeMsg(self, patches): - return u'\n* * *\n'.join( - [hglib.tounicode(self.repo[p].description()) - for p in ['qtip'] + patches]) + descs = [scmutil.revsymbol(self.repo, 'qtip').description()] + # lookup of unapplied patches is handled by thgrepo hack + descs.extend(self.repo[p].description() for p in patches) + return u'\n* * *\n'.join(map(hglib.tounicode, descs)) @pyqtSlot() def configChanged(self): diff --git a/tortoisehg/hgqt/qscilib.py b/tortoisehg/hgqt/qscilib.py index 579f21e..d0f94dc 100644 --- a/tortoisehg/hgqt/qscilib.py +++ b/tortoisehg/hgqt/qscilib.py @@ -34,6 +34,7 @@ from .qtgui import ( QCheckBox, QDialog, QDialogButtonBox, + QFont, QInputMethodEvent, QKeyEvent, QKeySequence, @@ -820,7 +821,12 @@ def fileEditor(filename, **opts): editor.installEventFilter(KeyPressInterceptor(dialog)) editor.setMarginLineNumbers(1, True) editor.setMarginWidth(1, '000') - editor.setLexer(QsciLexerProperties()) + + lexer = QsciLexerProperties() + lexer.setFont(QFont('Monospace', 10), -1) + + editor.setLexer(lexer) + if opts.get('foldable'): editor.setFolding(QsciScintilla.BoxedTreeFoldStyle) dialog.layout().addWidget(editor) diff --git a/tortoisehg/hgqt/qtlib.py b/tortoisehg/hgqt/qtlib.py index 9cf73db..c2bf940 100644 --- a/tortoisehg/hgqt/qtlib.py +++ b/tortoisehg/hgqt/qtlib.py @@ -22,6 +22,7 @@ import tempfile import weakref from .qtcore import ( + PYQT_VERSION, QByteArray, QDir, QEvent, @@ -1470,5 +1471,5 @@ class PaletteSwitcher(object): def setContextMenuShortcut(action, shortcut): """Set shortcut for a context menu action, making sure it's visible""" action.setShortcut(shortcut) - if QT_VERSION >= 0x50a00: + if QT_VERSION >= 0x50a00 and PYQT_VERSION >= 0x50a00: action.setShortcutVisibleInContextMenu(True) diff --git a/tortoisehg/hgqt/repofilter.py b/tortoisehg/hgqt/repofilter.py index 35266ea..4f35255 100644 --- a/tortoisehg/hgqt/repofilter.py +++ b/tortoisehg/hgqt/repofilter.py @@ -35,6 +35,7 @@ from .qtgui import ( from mercurial import ( error, repoview, + scmutil, util, ) @@ -60,6 +61,9 @@ def _firstword(query): def _querytype(repo, query): r""" + >>> # TODO: maybe replace with real repo + >>> origisrevsymbol = scmutil.isrevsymbol + >>> scmutil.isrevsymbol = lambda repo, changeid: changeid in repo >>> repo = set('0 1 2 3 . stable'.split()) >>> _querytype(repo, u'') is None True @@ -79,6 +83,7 @@ def _querytype(repo, query): 'revset' >>> _querytype(repo, u'\u3000') # UnicodeEncodeError 'revset' + >>> scmutil.isrevsymbol = origisrevsymbol """ if not query: return @@ -91,7 +96,7 @@ def _querytype(repo, query): if not changeid: return 'keyword' try: - if changeid in repo: + if scmutil.isrevsymbol(repo, changeid): return 'revset' except error.LookupError: # ambiguous changeid pass diff --git a/tortoisehg/hgqt/repoview.py b/tortoisehg/hgqt/repoview.py index 702e33c..b97c250 100644 --- a/tortoisehg/hgqt/repoview.py +++ b/tortoisehg/hgqt/repoview.py @@ -366,20 +366,23 @@ class HgRepoView(QTableView): """ if isinstance(rev, unicode): rev = hglib.fromunicode(rev) - try: - rev = scmutil.revsymbol(self.repo, rev).rev() - except error.RepoError: - self.showMessage.emit(_("Can't find revision '%s'") - % hglib.tounicode(str(rev))) - except LookupError as e: - self.showMessage.emit(hglib.tounicode(str(e))) - else: - idx = self.model().indexFromRev(rev) - if idx.isValid(): - flags = (QItemSelectionModel.ClearAndSelect - | QItemSelectionModel.Rows) - self.selectionModel().setCurrentIndex(idx, flags) - self.scrollTo(idx) + if not isinstance(rev, int): + try: + rev = scmutil.revsymbol(self.repo, rev).rev() + except error.RepoError: + self.showMessage.emit(_("Can't find revision '%s'") + % hglib.tounicode(str(rev))) + return + except LookupError as e: + self.showMessage.emit(hglib.tounicode(str(e))) + return + + idx = self.model().indexFromRev(rev) + if idx.isValid(): + flags = (QItemSelectionModel.ClearAndSelect + | QItemSelectionModel.Rows) + self.selectionModel().setCurrentIndex(idx, flags) + self.scrollTo(idx) def saveSettings(self, s = None): if not s: diff --git a/tortoisehg/hgqt/repowidget.py b/tortoisehg/hgqt/repowidget.py index 857f7d4..b4e04f6 100644 --- a/tortoisehg/hgqt/repowidget.py +++ b/tortoisehg/hgqt/repowidget.py @@ -45,6 +45,7 @@ from .qtgui import ( from mercurial import ( error, phases, + scmutil, ) from mercurial.utils import ( procutil, @@ -637,7 +638,7 @@ class RepoWidget(QWidget): """Select and scroll to the specified revision""" try: # try instant look up - if hglib.fromunicode(revspec) in self.repo: + if scmutil.isrevsymbol(self.repo, hglib.fromunicode(revspec)): self.repoview.goto(revspec) return except error.LookupError: @@ -1287,7 +1288,8 @@ class RepoWidget(QWidget): submenu = menu.addMenu(_('Change &Phase to')) submenu.triggered.connect(self._changePhaseByMenu) - for pnum, pname in enumerate(phases.phasenames): + # TODO: filter out hidden names better + for pnum, pname in enumerate(phases.phasenames[:3]): a = entry(items, submenu, None, enablefuncs['isrev'], pname) a.setData(pnum) entry(items, menu) @@ -1411,9 +1413,9 @@ class RepoWidget(QWidget): dlg.restart(str(revB), str(revA)) def compressDlg(): ctxa, ctxb = map(self.repo.hgchangectx, self.menuselection) - if ctxa.ancestor(ctxb) == ctxb: + if ctxa.ancestor(ctxb).rev() == ctxb.rev(): revs = self.menuselection[:] - elif ctxa.ancestor(ctxb) == ctxa: + elif ctxa.ancestor(ctxb).rev() == ctxa.rev(): revs = [self.menuselection[1], self.menuselection[0]] else: InfoMsgBox(_('Unable to compress history'), @@ -1803,13 +1805,27 @@ class RepoWidget(QWidget): @pyqtSlot() def mergeWithRevision(self): + # Don't use self.rev (i.e. the current revision.) This is a context + # menu handler, and the menu is open for the selected rows, not for + # the current row. + revisions = self.repoview.selectedRevisions() + if len(revisions) != 1: + QMessageBox.warning(self, _('Unable to merge'), + _('Please select a revision to merge.')) + return + rev = revisions[0] + if not isinstance(rev, int): + QMessageBox.warning(self, _('Unable to merge'), + _('Cannot merge with a pseudo revision %r.') + % rev) + return pctx = self.repo['.'] - octx = self.repo[self.rev] + octx = self.repo[rev] if pctx == octx: QMessageBox.warning(self, _('Unable to merge'), _('You cannot merge a revision with itself')) return - self._dialogs.open(RepoWidget._createMergeDialog, self.rev) + self._dialogs.open(RepoWidget._createMergeDialog, rev) def _createMergeDialog(self, rev): return merge.MergeDialog(self._repoagent, rev, self) @@ -2035,7 +2051,7 @@ class RepoWidget(QWidget): QMessageBox.warning(self, _('Cannot import selected revision'), _('The selected revision (rev #%d) cannot be imported ' 'because it is not a descendant of ''qparent'' (rev #%d)') \ - % (self.rev, self.repo['qparent'].rev())) + % (self.rev, scmutil.revsymbol(self.repo, 'qparent').rev())) return patchdir = self.repo.vfs.join('patches') diff --git a/tortoisehg/hgqt/revpanel.py b/tortoisehg/hgqt/revpanel.py index 2450283..a9cc3d6 100644 --- a/tortoisehg/hgqt/revpanel.py +++ b/tortoisehg/hgqt/revpanel.py @@ -8,7 +8,10 @@ from __future__ import absolute_import -from mercurial import error +from mercurial import ( + error, + scmutil, +) from ..util import hglib, obsoleteutil from ..util.i18n import _ @@ -81,7 +84,7 @@ def data_func(widget, item, ctx): if not ts: return None try: - tctx = ctx._repo[ts] + tctx = scmutil.revsymbol(ctx.repo(), ts) return revline_data(tctx) except (error.LookupError, error.RepoLookupError, error.RepoError): return ts diff --git a/tortoisehg/hgqt/run.py b/tortoisehg/hgqt/run.py index d8c70a2..0da6c48 100644 --- a/tortoisehg/hgqt/run.py +++ b/tortoisehg/hgqt/run.py @@ -227,7 +227,9 @@ def _parse(ui, args): sys.exit() else: alias, args = 'workbench', [] - aliases, i = cmdutil.findcmd(alias, table, ui.config("ui", "strict")) + # copies hg<4.8 (fa88170c10bb) behavior + stable = {k.lstrip('^'): e for k, e in table.items()} + aliases, i = cmdutil.findcmd(alias, stable, ui.config("ui", "strict")) for a in aliases: if a.startswith(alias): alias = a @@ -732,8 +734,10 @@ def help_(ui, name=None, with_version=False, **opts): version(ui) ui.write('\n') + # copies hg<4.8 (fa88170c10bb) behavior + stable = {k.lstrip('^'): e for k, e in table.items()} try: - aliases, i = cmdutil.findcmd(name, table, False) + aliases, i = cmdutil.findcmd(name, stable, False) except error.AmbiguousCommand, inst: select = lambda c: c.lstrip('^').startswith(inst.args[0]) helplist(_('list of commands:\n\n'), select) @@ -771,6 +775,7 @@ def help_(ui, name=None, with_version=False, **opts): if (not select and name != 'shortlist' and e[0].__module__ != __name__): continue + # TODO: switch to hg>=4.8 (fa88170c10bb) syntax if name == "shortlist" and not f.startswith("^"): continue f = f.lstrip("^") diff --git a/tortoisehg/hgqt/rupdate.py b/tortoisehg/hgqt/rupdate.py index 6ed0166..e949f62 100644 --- a/tortoisehg/hgqt/rupdate.py +++ b/tortoisehg/hgqt/rupdate.py @@ -34,7 +34,10 @@ from .qtgui import ( QVBoxLayout, ) -from mercurial import error +from mercurial import ( + error, + scmutil, +) from ..util import hglib from ..util.i18n import _ @@ -145,7 +148,7 @@ class RemoteUpdateWidget(cmdui.AbstractCmdWidget): self.commandChanged.emit() return try: - self.target_info.update(self.repo[new_rev]) + self.target_info.update(scmutil.revsymbol(self.repo, new_rev)) except (error.LookupError, error.RepoLookupError, error.RepoError): self.target_info.setText(_('unknown revision!')) self.commandChanged.emit() @@ -153,8 +156,8 @@ class RemoteUpdateWidget(cmdui.AbstractCmdWidget): def canRunCommand(self): rev = hglib.fromunicode(self.rev_combo.currentText()) try: - return rev in self.repo - except error.LookupError: + return scmutil.isrevsymbol(self.repo, rev) + except error.AmbiguousPrefixLookupError: # ambiguous changeid return False diff --git a/tortoisehg/hgqt/serve_ui.py b/tortoisehg/hgqt/serve_ui.py index 672445f..1676cc8 100644 --- a/tortoisehg/hgqt/serve_ui.py +++ b/tortoisehg/hgqt/serve_ui.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '/Users/sborho/repos/thg/tortoisehg/hgqt/serve.ui' +# Form implementation generated from reading ui file '/home/sborho/repos/thg/tortoisehg/hgqt/serve.ui' # -# Created by: PyQt5 UI code generator 5.10.1 +# Created by: PyQt5 UI code generator 5.11.2 # # WARNING! All changes made in this file will be lost! diff --git a/tortoisehg/hgqt/settings.py b/tortoisehg/hgqt/settings.py index 7ab201b..4e26b9b 100644 --- a/tortoisehg/hgqt/settings.py +++ b/tortoisehg/hgqt/settings.py @@ -694,6 +694,12 @@ INFO = ( _('If specified, files in the directory, e.g. .hgignore, are copied ' 'to the newly-created repository.'), globalonly=True), + _fi(_('Default Clone Destination'), 'tortoisehg.defaultclonedest', + genPathBrowser, + _('If specified, the destination field in the clone widget will be ' + 'pre-filled with this path. Otherwise, it will be pre-filled with ' + 'the current working directory.'), + globalonly=True), )), ({'name': 'log', 'label': _('Workbench'), 'icon': 'hg-log'}, ( @@ -826,7 +832,7 @@ INFO = ( 'This setting is used by the Merge, Tag and Backout dialogs. ' 'Default: False')), _fi(_('New Commit Phase'), 'phases.new-commit', - (genDefaultCombo, phases.phasenames), + (genDefaultCombo, phases.phasenames[:3]), _('The phase of new commits. Default: draft')), _fi(_('Secret MQ Patches'), 'mq.secret', genBoolRBGroup, _('Make MQ patches secret (instead of draft). ' @@ -1155,7 +1161,8 @@ INFO = ( )), )), -({'name': 'reviewboard', 'label': _('Review Board'), 'icon': 'reviewboard'}, ( +({'name': 'reviewboard', 'label': _('Review Board'), 'icon': 'reviewboard', + 'extension': 'reviewboard'}, ( _fi(_('Server'), 'reviewboard.server', genEditCombo, _('Path to review board ' 'example "http://demo.reviewboard.org"')), diff --git a/tortoisehg/hgqt/thgstrip.py b/tortoisehg/hgqt/thgstrip.py index f1b9341..62d0dbd 100644 --- a/tortoisehg/hgqt/thgstrip.py +++ b/tortoisehg/hgqt/thgstrip.py @@ -21,7 +21,10 @@ from .qtgui import ( QVBoxLayout, ) -from mercurial import error +from mercurial import ( + error, + scmutil, +) from ..util import hglib from ..util.i18n import _, ngettext @@ -114,7 +117,7 @@ class StripWidget(cmdui.AbstractCmdWidget): if not revstr: return None try: - rev = self.repo[revstr].rev() + rev = scmutil.revsymbol(self.repo, revstr).rev() except (error.RepoError, error.LookupError): return None return rev diff --git a/tortoisehg/hgqt/update.py b/tortoisehg/hgqt/update.py index aa74614..0ecc801 100644 --- a/tortoisehg/hgqt/update.py +++ b/tortoisehg/hgqt/update.py @@ -180,7 +180,7 @@ class UpdateWidget(cmdui.AbstractCmdWidget): self.p1_info.update(self.ctxs[0].node()) merge = len(self.ctxs) == 2 if merge: - self.p2_info.update(self.ctxs[1]) + self.p2_info.update(self.ctxs[1].node()) new_rev = hglib.fromunicode(self.rev_combo.currentText()) if new_rev == 'null': self.target_info.setText(_('remove working directory')) @@ -324,7 +324,8 @@ class UpdateWidget(cmdui.AbstractCmdWidget): if clean is None: clean = isclean() pa = p1.ancestor(p2) - return not clean and (p1 == pa or p2 == pa) + return not clean \ + and (p1.rev() == pa.rev() or p2.rev() == pa.rev()) def confirmupdate(clean=None): if clean is None: clean = isclean() diff --git a/tortoisehg/hgqt/visdiff.py b/tortoisehg/hgqt/visdiff.py index cd07e42..494143a 100644 --- a/tortoisehg/hgqt/visdiff.py +++ b/tortoisehg/hgqt/visdiff.py @@ -213,7 +213,11 @@ def visualdiff(ui, repo, pats, opts): try: ctx1b = None if change: - ctx2 = repo[change] + # TODO: figure out what's the expect type + if isinstance(change, str): + ctx2 = scmutil.revsymbol(repo, change) + else: + ctx2 = repo[change] p = ctx2.parents() if len(p) > 1: ctx1a, ctx1b = p diff --git a/tortoisehg/hgqt/webconf_ui.py b/tortoisehg/hgqt/webconf_ui.py index ef47812..876a854 100644 --- a/tortoisehg/hgqt/webconf_ui.py +++ b/tortoisehg/hgqt/webconf_ui.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file '/Users/sborho/repos/thg/tortoisehg/hgqt/webconf.ui' +# Form implementation generated from reading ui file '/home/sborho/repos/thg/tortoisehg/hgqt/webconf.ui' # -# Created by: PyQt5 UI code generator 5.10.1 +# Created by: PyQt5 UI code generator 5.11.2 # # WARNING! All changes made in this file will be lost! diff --git a/tortoisehg/util/__version__.py b/tortoisehg/util/__version__.py index 93d182a..7b797e2 100644 --- a/tortoisehg/util/__version__.py +++ b/tortoisehg/util/__version__.py @@ -1,2 +1,2 @@ # this file is autogenerated by setup.py -version = "4.7" +version = "4.8.1" diff --git a/tortoisehg/util/hglib.py b/tortoisehg/util/hglib.py index c3f89bf..97e3d09 100644 --- a/tortoisehg/util/hglib.py +++ b/tortoisehg/util/hglib.py @@ -32,6 +32,7 @@ from mercurial import ( revset as revsetmod, revsetlang, scmutil, + state as statemod, subrepoutil, ui as uimod, util, @@ -250,6 +251,22 @@ def getqqueues(repo): qqueues = [] return qqueues +def readgraftstate(repo): + """Read a list of nodes from graftstate; or None if nothing in progress""" + graftstatefile = repo.vfs.join('graftstate') + if not os.path.exists(graftstatefile): + return + with open(graftstatefile, 'r') as f: + info = f.readlines() + if info and info[0] == '1\n': + # doesn't look like a list of nodes + return statemod.cmdstate(repo, 'graftstate').read()['nodes'] + if len(info): + revlist = [rev.strip() for rev in info] + revlist = [rev for rev in revlist if rev != ''] + if revlist: + return revlist + readmergestate = mergemod.mergestate.read def readundodesc(repo): @@ -290,11 +307,13 @@ def allextensions(): disabledexts = disabledextensions() exts = (disabledexts or {}).copy() exts.update(enabledexts) + exts.pop('configitems') # tortoisehg.util.configitems if hasattr(sys, "frozen"): if 'hgsubversion' not in exts: exts['hgsubversion'] = _('hgsubversion packaged with thg') if 'hggit' not in exts: exts['hggit'] = _('hggit packaged with thg') + exts.pop('mercurial_extension_utils', None) # Part of keyring extension return exts def validateextensions(enabledexts): @@ -316,7 +335,7 @@ def validateextensions(enabledexts): exts['perfarce'] = _('perfarce is incompatible with hgsubversion') return exts -def _loadextensionwithblacklist(orig, ui, name, path): +def _loadextensionwithblacklist(orig, ui, name, path, *args, **kwargs): if name.startswith('hgext.') or name.startswith('hgext/'): shortname = name[6:] else: @@ -324,7 +343,7 @@ def _loadextensionwithblacklist(orig, ui, name, path): if shortname in _extensions_blacklist and not path: # only bundled ext return - return orig(ui, name, path) + return orig(ui, name, path, *args, **kwargs) def _wrapextensionsloader(): """Wrap extensions.load(ui, name) for blacklist to take effect""" @@ -719,6 +738,16 @@ def user(ctx): user = '' return user +def getestimatedsize(fctx): + """Return the size of the given fctx without loading the revision text""" + if fctx.rev() is None: + return fctx.size() + else: + # fctx.size() can read all data into memory in rename cases so + # we read the size directly from the filelog, this is deeper + # under the API than I prefer to go, but seems necessary + return fctx._filelog._revlog.rawsize(fctx.filerev()) + def get_revision_desc(fctx, curpath=None): """return the revision description as a string""" author = tounicode(username(fctx.user())) diff --git a/tortoisehg/util/hgversion.py b/tortoisehg/util/hgversion.py index 93d57a1..ea5063e 100644 --- a/tortoisehg/util/hgversion.py +++ b/tortoisehg/util/hgversion.py @@ -16,7 +16,7 @@ except AttributeError: from mercurial import version hgversion = version.get_version() -testedwith = '4.6 4.7' +testedwith = '4.7 4.8' def checkhgversion(v): """range check the Mercurial version""" diff --git a/tortoisehg/util/patchctx.py b/tortoisehg/util/patchctx.py index 751497a..37cff32 100644 --- a/tortoisehg/util/patchctx.py +++ b/tortoisehg/util/patchctx.py @@ -110,6 +110,7 @@ class patchctx(object): def description(self): return self._desc def branch(self): return self._branch def parents(self): return () + def repo(self): return self._repo def tags(self): return () def bookmarks(self): return () def children(self): return () diff --git a/tortoisehg/util/version.py b/tortoisehg/util/version.py index 3c0a127..395fc1d 100644 --- a/tortoisehg/util/version.py +++ b/tortoisehg/util/version.py @@ -56,25 +56,69 @@ def version(): def package_version(): try: branch, version = liveversion() + return _build_package_version(branch, version) + except: + pass + try: + import __version__ + return _build_package_version('stable', __version__.version) + except ImportError: + return _('unknown') - extra = None - if '+' in version: - version, extra = version.split('+', 1) +def _build_package_version(branch, version): + """ + >>> _build_package_version('default', '4.8+10') + '4.8.5010' + >>> _build_package_version('stable', '4.8.2+5') + '4.8.21005' + >>> _build_package_version('stable', '4.8') + '4.8.0' + >>> _build_package_version('stable', '4.8.3') + '4.8.3' + >>> _build_package_version('stable', '4.8rc1') + '4.7.91000' + >>> _build_package_version('stable', '4.8rc1+2') + '4.7.91002' + >>> _build_package_version('stable', '1.0rc0') + '0.9.90000' + >>> _build_package_version('stable', '0.1rc0') + '0.0.90000' + """ + extra = rc = None + if '+' in version: + version, extra = version.split('+', 1) + if 'rc' in version: + version, rc = version.split('rc', 1) + if extra is None: + extra = '0' # rc should be a development release - v = [int(x) for x in version.split('.')] - while len(v) < 3: - v.append(0) - major, minor, periodic = v + v = [int(x) for x in version.split('.')] + if rc: + v = _decrement_version(v) + while len(v) < 3: + v.append(0) + major, minor, periodic = v - if extra != None: - tagdistance = int(extra.split('-', 1)[0]) - periodic *= 10000 - if branch == 'default': - periodic += tagdistance + 5000 - else: - periodic += tagdistance + 1000 + if extra != None: + tagdistance = int(extra.split('-', 1)[0]) + periodic *= 10000 + if rc: + periodic += tagdistance + int(rc) * 1000 + 90000 + elif branch == 'default': + periodic += tagdistance + 5000 + else: + periodic += tagdistance + 1000 - return '.'.join([str(x) for x in (major, minor, periodic)]) - except: - pass - return _('unknown') + return '.'.join([str(x) for x in (major, minor, periodic)]) + +def _decrement_version(v): + if not v: + return v + v = v[:] + p = len(v) - 1 + v[p] -= 1 + while p > 0 and v[p] < 0: + v[p] = 9 + v[p - 1] -= 1 + p -= 1 + return v |