by
Changes to 34 files · Browse files at f27f08cac337 Showing diff from parent 86ad2e9d9583 1f3219626658 Diff from another changeset...
@@ -1,14 +1,41 @@ + #
+# hgtk
+#
+# contrib/bash_completion
+#
+# Copyright 2009 Andreas Tscharner <andy@vis.ethz.ch>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+# as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
_hgtk()
{
- local cur prev opts
+ local cur prev opts cmds
- COMPREPLY=()
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
- opts="about add annotate archive blame checkout clone commit datamine diff filter email forget grep guess hgignore history ignore init incoming log merge outgoing pull push recovery remove rename repoconfig revert rollback serve shelve status strip synch unshelve update userconfig vdiff verify version"
+ cmds="about add annotate archive blame checkout clone commit datamine diff email explorer filter forget grep guess hgignore history ignore init incoming log merge outgoing pull push recovery remove rename repoconfig revert rollback serve shelve status strip synch unshelve update userconfig vdiff verify version"
- COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ opts="-R --repository -v --verbose -q --quiet -h --help --debugger --nofork --fork --listfile"
+
+ if [[ ${cur} == -* ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ else
+ COMPREPLY=( $(compgen -W "${cmds}" -- ${cur}) )
+ fi
+ return 0
}
-
complete -F _hgtk hgtk
|
@@ -58,6 +58,10 @@ winmergeu.args=/e /ub /dl other /dr local $other $local $output
winmergeu.fixeol=True
winmergeu.gui=True
+araxis.executable=C:\Program Files\Araxis\Araxis Merge v6.5\AraxisP4WinMrg.exe
+araxis.priority=1
+araxis.args=$base $other $local $output
+araxis.gui=True
;
; For more information about mercurial extensions, start here
@@ -147,17 +151,21 @@;cmd.vdiff = C:\Progra~1\TortoiseSVN\bin\TortoiseMerge.exe
;cmd.vimdiff = gvim.exe
;opts.vimdiff = -f '+next' '+execute "DirDiff ".argv(0)." ".argv(1)'
+;cmd.araxis=C:\Program Files\Araxis\Araxis Merge v6.5\compare.exe
+;opts.araxis=/wait
-[qct]
-;See http://bitbucket.org/tortoisehg/stable/wiki/FAQ for details
-;path="C:\Program Files\qct\qct.exe"
+[tortoisehg]
+; These templates will typically be applied to a repository's .hg/hgrc
+; file. They are included them here for reference.
+;
+; Template for linking BitBucket style bug report IDs (#412)
+;issue.regex = #(\d+)\b
+;issue.link = http://bitbucket.org/<your project and repo>/issue/{1}/
+;
+; Template for linking Mercurial style bug report IDs (issue1200)
+;issue.regex = \bissue\d+\b
+;issue.link = http://mercurial.selenic.com/bts/
-[hgk]
-;See http://bitbucket.org/tortoisehg/stable/wiki/FAQ for details
-;path={app}\scripts\hgk.cmd
-;vdiff=vdiff
-
-;
; The git extended diff format will properly store binary files,
; file permission changes, and rename information that the normal
; patch format cannot cover. However it is also not 100% compatible
|
@@ -50,12 +50,14 @@ Name: shell; Description: Shell integration (overlay icons, context menu) [admin required]; Types: full; Flags: restart; Check: ShellInstallPossible
[Files]
-Source: ..\build-hg\contrib\mercurial.el; DestDir: {app}/contrib
-Source: ..\build-hg\contrib\vim\*.*; DestDir: {app}/contrib/vim
-Source: ..\build-hg\contrib\zsh_completion; DestDir: {app}/contrib
+Source: ..\build-hg\contrib\mercurial.el; DestDir: {app}\contrib
+Source: ..\build-hg\contrib\vim\*.*; DestDir: {app}\contrib\vim
+Source: ..\build-hg\contrib\zsh\*.*; DestDir: {app}\contrib\zsh
+Source: ..\build-hg\contrib\bash\*.*; DestDir: {app}\contrib\bash
Source: ..\build-hg\contrib\hgk; DestDir: {app}/contrib
Source: ..\build-hg\contrib\win32\ReadMe.html; DestDir: {app}; Flags: isreadme
-Source: ..\build-hg\templates\*.*; DestDir: {app}\templates; Flags: recursesubdirs createallsubdirs
+Source: ..\build-hg\mercurial\templates\*.*; DestDir: {app}\templates; Flags: recursesubdirs createallsubdirs
+Source: ..\build-hg\mercurial\help\*.txt; DestDir: {app}\help; Components: help
Source: ..\build-hg\locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs
Source: ..\build-hg\i18n\*.*; DestDir: {app}\i18n
Source: ..\build-hg\doc\*.html; DestDir: {app}\docs; Flags: ignoreversion; Components: help
|
@@ -332,6 +332,40 @@ patches into a repository, so this must be done on the command line with
the :command:`hg import` command.
+Message Parsing
+---------------
+
+New in TortoiseHg 0.10, the repository browser will detect and underline
+changeset hashes and bug report identifiers inside changeset messages. These
+underlined phrases are clickable links.
+
+Every word-boundary delimited string of 12 or 40 characters from the
+range [0-9a-f] is considered a changeset link. Clicking on it in the
+repository explorer will jump to the given changeset if possible.
+
+Issue tracker links are enabled when configured in the tortoisehg
+section of the configuration files. There are two keys: issue.regex
+and issue.link. The first defines the regex to match when picking up
+issue numbers, while the second defines the command to run when an
+issue number is recognized.
+
+You may include groups in issue.regex, and corresponding {n} tokens
+in issue.link (where n is a non-negative integer). {0} refers to the
+entire string matched by issue.regex, while {1} refers to the first
+group and so on. If no {n} tokens are found in issue.link, the entire
+matched string is appended instead.
+
+Examples::
+
+ BitBucket:
+ issue.regex = #(\d+)\b
+ issue.link = http://bitbucket.org/<your project and repo>/issue/{1}/
+
+ Mercurial:
+ issue.regex = \bissue\d+\b
+ issue.link = http://mercurial.selenic.com/bts/
+
+
Keyboard navigation
-------------------
@@ -341,6 +375,8 @@ Display visual diffs for selected changeset or file
:kbd:`Ctrl-R`
Refresh repository contents
+:kbd:`Ctrl-G`
+ Go to a specific revision
Configurables
|
@@ -49,9 +49,9 @@ # built documents.
#
# The short X.Y version.
-version = '0.9'
+version = '0.10'
# The full version, including alpha/beta/rc tags.
-release = '0.9.1'
+release = '0.10.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
|
|
|
|
@@ -191,7 +191,7 @@ version=version,
author='Steve Borho',
author_email='steve@borho.org',
- url='http://tortoisehg.bitbucket.org',
+ url='http://tortoisehg.org',
description=desc,
license='GNU GPL2',
scripts=scripts,
|
@@ -9,37 +9,14 @@ import os
import sys
import gtk
-import threading
from tortoisehg.util.i18n import _
-from tortoisehg.util import version, paths, hglib
+from tortoisehg.util import version, paths, hglib, shlib
from tortoisehg.hgtk import gtklib, hgtk
-def browse_url(url):
- def start_browser():
- if os.name == 'nt':
- import win32api, win32con
- win32api.ShellExecute(0, "open", url, None, "",
- win32con.SW_SHOW)
- elif sys.platform == 'darwin':
- # use Mac OS X internet config module (removed in Python 3.0)
- import ic
- ic.launchurl(url)
- else:
- try:
- import gconf
- client = gconf.client_get_default()
- browser = client.get_string(
- '/desktop/gnome/url-handlers/http/command') + '&'
- os.system(browser % url)
- except ImportError:
- # If gconf is not found, fall back to old standard
- os.system('firefox ' + url)
- threading.Thread(target=start_browser).start()
-
def url_handler(dialog, link, user_data):
- browse_url(link)
+ shlib.browse_url(link)
gtk.about_dialog_set_url_hook(url_handler, None)
|
|
|
@@ -0,0 +1,260 @@ + # bookmarkadd.py - TortoiseHg dialog to add bookmark
+#
+# Copyright 2007 TK Soh <teekaysoh@gmail.com>
+# Copyright 2007 Steve Borho <steve@borho.org>
+# Copyright 2009 Emmanuel Rosa <goaway1000@gmail.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+import os
+import gtk
+import traceback
+
+from mercurial import hg, ui, util
+from hgext import bookmarks
+
+from tortoisehg.util.i18n import _
+from tortoisehg.util import hglib, i18n
+
+from tortoisehg.hgtk import dialog, gtklib
+
+keep = i18n.keepgettext()
+
+class BookmarkAddDialog(gtk.Dialog):
+ """ Dialog to add bookmark to Mercurial repo """
+ def __init__(self, repo, bookmark='', rev=''):
+ """ Initialize the Dialog """
+ gtk.Dialog.__init__(self,
+ buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+ gtklib.set_tortoise_keys(self)
+ self.set_title(_('Bookmark - %s') % hglib.get_reponame(repo))
+ self.set_resizable(False)
+ self.set_has_separator(False)
+ self.connect('response', self.dialog_response)
+
+ self.repo = repo
+
+ # add Add button
+ addbutton = gtk.Button(_('Add'))
+ addbutton.connect('clicked', lambda b: self._do_add_bookmark())
+ self.action_area.pack_end(addbutton)
+
+ # add Remove button
+ removebutton = gtk.Button(_('Remove'))
+ removebutton.connect('clicked', lambda b: self._do_rm_bookmark())
+ self.action_area.pack_end(removebutton)
+
+ # top layout table
+ table = gtklib.LayoutTable()
+ self.vbox.pack_start(table, True, True, 2)
+
+ ## bookmark name input
+ self._bookmarkslist = gtk.ListStore(str)
+ self._bookmarklistbox = gtk.ComboBoxEntry(self._bookmarkslist, 0)
+ self._bookmark_input = self._bookmarklistbox.get_child()
+ self._bookmark_input.connect('activate', self._bookmarkinput_activated)
+ self._bookmark_input.set_text(bookmark)
+ table.add_row(_('Bookmark:'), self._bookmarklistbox, padding=False)
+
+ ## revision input
+ self._rev_input = gtk.Entry()
+ self._rev_input.set_width_chars(12)
+ self._rev_input.set_text(rev)
+ table.add_row(_('Revision:'), self._rev_input)
+
+ # prepare to show
+ self._refresh()
+ self._bookmarklistbox.grab_focus()
+
+ def _refresh(self):
+ """ update display on dialog with recent repo data """
+ self.repo.invalidate()
+ self._bookmarkslist.clear()
+ self._bookmark_input.set_text("")
+
+ # add bookmarks to drop-down list
+ bookmarks = hglib.get_repo_bookmarks(self.repo)
+ bookmarks.sort()
+ for bookmarkname in bookmarks:
+ if bookmarkname != "tip":
+ self._bookmarkslist.append([bookmarkname])
+
+ def dialog_response(self, dialog, response_id):
+ if response_id == gtk.RESPONSE_CLOSE \
+ or response_id == gtk.RESPONSE_DELETE_EVENT:
+ self.destroy()
+
+ def _bookmarkinput_activated(self, bookmarkinput):
+ self._do_add_bookmark()
+
+ def _do_add_bookmark(self):
+ # gather input data
+ name = self._bookmark_input.get_text()
+ rev = self._rev_input.get_text()
+
+ # verify input
+ if name == '':
+ dialog.error_dialog(self, _('Bookmark input is empty'),
+ _('Please enter bookmark name'))
+ self._bookmark_input.grab_focus()
+ return False
+
+ # add bookmark to repo
+ try:
+ self._add_hg_bookmark(name, rev)
+ dialog.info_dialog(self, _('Bookmarking completed'),
+ _('Bookmark "%s" has been added') % name)
+ self._refresh()
+ except util.Abort, inst:
+ dialog.error_dialog(self, _('Error in bookmarking'), str(inst))
+ return False
+ except:
+ dialog.error_dialog(self, _('Error in bookmarking'),
+ traceback.format_exc())
+ return False
+
+ def _do_rm_bookmark(self):
+ # gather input data
+ name = self._bookmark_input.get_text()
+
+ # verify input
+ if name == '':
+ dialog.error_dialog(self, _('Bookmark name is empty'),
+ _('Please select bookmark name to remove'))
+ self._bookmark_input.grab_focus()
+ return False
+
+ try:
+ self._rm_hg_bookmark(name)
+ dialog.info_dialog(self, _('Bookmarking completed'),
+ _('Bookmark "%s" has been removed') % name)
+ self._refresh()
+ except util.Abort, inst:
+ dialog.error_dialog(self, _('Error in bookmarking'), str(inst))
+ return False
+ except:
+ dialog.error_dialog(self, _('Error in bookmarking'),
+ traceback.format_exc())
+ return False
+
+ def _add_hg_bookmark(self, name, revision):
+ if name in hglib.get_repo_bookmarks(self.repo):
+ raise util.Abort(_('a bookmark named "%s" already exists') % name)
+
+ bookmarks.bookmark(ui=ui.ui(),
+ repo=self.repo,
+ rev=revision,
+ mark=name)
+
+ def _rm_hg_bookmark(self, name):
+ if not name in hglib.get_repo_bookmarks(self.repo):
+ raise util.Abort(_("Bookmark '%s' does not exist") % name)
+
+ bookmarks.bookmark(ui=ui.ui(),
+ repo=self.repo,
+ mark=name,
+ delete=True)
+
+class BookmarkRenameDialog(gtk.Dialog):
+ """ Dialog to rename a bookmark """
+ def __init__(self, repo, bookmark='', rev=''):
+ """ Initialize the Dialog """
+ gtk.Dialog.__init__(self,
+ buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+ gtklib.set_tortoise_keys(self)
+ self.set_title(_('Bookmark - %s') % hglib.get_reponame(repo))
+ self.set_resizable(False)
+ self.set_has_separator(False)
+ self.connect('response', self.dialog_response)
+
+ self.repo = repo
+
+ # add Rename button
+ renamebutton = gtk.Button(_('Rename'))
+ renamebutton.connect('clicked', lambda b: self._do_rename_bookmark())
+ self.action_area.pack_end(renamebutton)
+
+ # top layout table
+ table = gtklib.LayoutTable()
+ self.vbox.pack_start(table, True, True, 2)
+
+ ## bookmark name input
+ self._bookmarkslist = gtk.ListStore(str)
+ self._bookmarklistbox = gtk.ComboBoxEntry(self._bookmarkslist, 0)
+ self._bookmark_input = self._bookmarklistbox.get_child()
+ self._bookmark_input.connect('activate', self._bookmarkinput_activated)
+ self._bookmark_input.set_text(bookmark)
+ table.add_row(_('Bookmark:'), self._bookmarklistbox, padding=False)
+
+ ## revision input
+ self._name_input = gtk.Entry()
+ table.add_row(_('New name:'), self._name_input)
+
+ # prepare to show
+ self._refresh()
+ self._bookmarklistbox.grab_focus()
+
+ def _refresh(self):
+ """ update display on dialog with recent repo data """
+ self.repo.invalidate()
+ self._bookmarkslist.clear()
+ self._bookmark_input.set_text("")
+
+ # add bookmarks to drop-down list
+ bookmarks = hglib.get_repo_bookmarks(self.repo)
+ bookmarks.sort()
+ for bookmarkname in bookmarks:
+ if bookmarkname == "tip":
+ continue
+ self._bookmarkslist.append([bookmarkname])
+
+ def dialog_response(self, dialog, response_id):
+ if response_id == gtk.RESPONSE_CLOSE \
+ or response_id == gtk.RESPONSE_DELETE_EVENT:
+ self.destroy()
+
+ def _bookmarkinput_activated(self, bookmarkinput):
+ self._do_rename_bookmark()
+
+ def _do_rename_bookmark(self):
+ # gather input data
+ name = self._bookmark_input.get_text()
+ new_name = self._name_input.get_text()
+
+ # verify input
+ if name == '':
+ dialog.error_dialog(self, _('Bookmark input is empty'),
+ _('Please enter bookmark name'))
+ self._bookmark_input.grab_focus()
+ return False
+
+ if new_name == '':
+ dialog.error_dialog(self, _('Bookmark new name input is empty'),
+ _('Please enter new bookmark name'))
+ self._bookmark_input.grab_focus()
+ return False
+
+ # rename bookmark
+ try:
+ self._rename_hg_bookmark(name, new_name)
+ dialog.info_dialog(self, _('Bookmarking completed'),
+ _('Bookmark "%s" has been renamed to "%s"') %
+ (name, new_name))
+ self._refresh()
+ except util.Abort, inst:
+ dialog.error_dialog(self, _('Error in bookmarking'), str(inst))
+ return False
+ except:
+ dialog.error_dialog(self, _('Error in bookmarking'),
+ traceback.format_exc())
+ return False
+
+ def _rename_hg_bookmark(self, name, new_name):
+ if new_name in hglib.get_repo_bookmarks(self.repo):
+ raise util.Abort(_('a bookmark named "%s" already exists') % new_name)
+ bookmarks.bookmark(ui=ui.ui(),
+ repo=self.repo,
+ mark=new_name,
+ rename=name)
+
|
|
@@ -6,6 +6,7 @@ # GNU General Public License version 2, incorporated herein by reference.
import os
+import re
import gtk
import gobject
import pango
@@ -14,7 +15,7 @@from mercurial import cmdutil, util, patch, mdiff
from tortoisehg.util.i18n import _
-from tortoisehg.util import shlib, hglib
+from tortoisehg.util import shlib, hglib, paths
from tortoisehg.hgtk import csinfo, gdialog, gtklib, hgcmd, statusbar
@@ -26,6 +27,14 @@ self.glog_parent = None
self.bfile = None
+ # initialize changeset/issue tracker link regex and dict
+ match = r'(\b[0-9a-f]{12}(?:[0-9a-f]{28})?\b)'
+ issue = repo.ui.config('tortoisehg', 'issue.regex')
+ if issue:
+ match = r'%s|(%s)' % (match, issue)
+ self.bodyre = re.compile(match)
+ self.issuedict = dict()
+
def get_title(self):
title = _('%s changeset ') % self.get_reponame()
rev = self.opts['rev']
@@ -92,8 +101,8 @@ if len(parents) == 2:
# deferred adding of parent check button
if not self.parent_button.parent:
+ self.parent_box.pack_start(self.parent_button, False, False)
self.parent_box.pack_start(gtk.HSeparator(), False, False)
- self.parent_box.pack_start(self.parent_button, False, False)
self.parent_box.show_all()
# show parent box
@@ -261,7 +270,27 @@ buf = self._buffer
buf.set_text('')
eob = buf.get_end_iter()
- buf.insert(eob, desc.rstrip('\n\r') + '\n\n')
+ desc = desc.rstrip('\n\r')
+
+ pos = 0
+ self.issuedict.clear()
+ for m in self.bodyre.finditer(desc):
+ a, b = m.span()
+ if a > pos:
+ buf.insert(eob, desc[pos:a])
+ pos = b
+ groups = m.groups()
+ link = groups[0]
+ if link:
+ buf.insert_with_tags_by_name(eob, link, 'csetlink')
+ else:
+ link = groups[1]
+ if len(groups) > 2:
+ self.issuedict[link] = groups[1:]
+ buf.insert_with_tags_by_name(eob, link, 'issuelink')
+ if pos < len(desc):
+ buf.insert(eob, desc[pos:])
+ buf.insert(eob, '\n\n')
def append_diff(self, wfile):
if not wfile:
@@ -358,9 +387,9 @@ offset += len(txt.decode('utf-8'))
for l1 in difflines[1:]:
l = hglib.toutf(l1)
- if l.startswith('+++'):
+ if l.startswith('--- '):
continue
- if l.startswith('---'):
+ if l.startswith('+++ '):
continue
if l.startswith('@@'):
tag = 'blue'
@@ -608,6 +637,7 @@
## file list
filelist_tree = gtk.TreeView()
+ filelist_tree.set_headers_visible(False)
filesel = filelist_tree.get_selection()
filesel.connect('changed', self.filelist_rowchanged)
self._filesel = filesel
@@ -635,10 +665,40 @@ gobject.TYPE_STRING, # filename
)
filelist_tree.set_model(self._filelist)
- column = gtk.TreeViewColumn(_('Stat'), gtk.CellRendererText(), text=0)
+
+ column = gtk.TreeViewColumn()
filelist_tree.append_column(column)
- column = gtk.TreeViewColumn(_('Files'), gtk.CellRendererText(), text=1)
- filelist_tree.append_column(column)
+
+ iconcell = gtk.CellRendererPixbuf()
+ filecell = gtk.CellRendererText()
+
+ column.pack_start(iconcell, expand=False)
+ column.pack_start(filecell, expand=False)
+ column.add_attribute(filecell, 'text', 1)
+
+ iconw, iconh = gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR)
+
+ def get_pixbuf(iconfilename):
+ iconpath = paths.get_tortoise_icon(iconfilename)
+ return gtk.gdk.pixbuf_new_from_file_at_size(
+ iconpath, iconw, iconh)
+
+ addedpixbuf = get_pixbuf('fileadd.ico')
+ removedpixbuf = get_pixbuf('filedelete.ico')
+ modifiedpixbuf = get_pixbuf('filemodify.ico')
+
+ def cell_seticon(column, cell, model, iter):
+ state = model.get_value(iter, 0)
+ pixbuf = None
+ if state == 'A':
+ pixbuf = addedpixbuf
+ elif state == 'R':
+ pixbuf = removedpixbuf
+ elif state == 'M':
+ pixbuf = modifiedpixbuf
+ cell.set_property('pixbuf', pixbuf)
+
+ column.set_cell_data_func(iconcell, cell_seticon)
list_frame = gtk.Frame()
list_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
@@ -646,11 +706,10 @@ scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scroller.add(filelist_tree)
flbox = gtk.VBox()
- flbox.pack_start(scroller)
list_frame.add(flbox)
-
self.parent_box = gtk.VBox()
flbox.pack_start(self.parent_box, False, False)
+ flbox.pack_start(scroller)
btn = gtk.CheckButton(_('Diff to second Parent'))
btn.connect('toggled', self.parent_toggled)
@@ -710,6 +769,56 @@ weight=pango.WEIGHT_BOLD))
tag_table.add(make_texttag('yellowbg', background='yellow'))
+ issuelink_tag = make_texttag('issuelink', foreground='blue',
+ underline=pango.UNDERLINE_SINGLE)
+ issuelink_tag.connect('event', self.issuelink_event)
+ tag_table.add(issuelink_tag)
+ csetlink_tag = make_texttag('csetlink', foreground='blue',
+ underline=pango.UNDERLINE_SINGLE)
+ csetlink_tag.connect('event', self.csetlink_event)
+ tag_table.add(csetlink_tag)
+
+ def issuelink_event(self, tag, widget, event, liter):
+ if event.type != gtk.gdk.BUTTON_RELEASE:
+ return
+ text = self.get_link_text(tag, widget, liter)
+ if not text:
+ return
+ link = self.repo.ui.config('tortoisehg', 'issue.link')
+ if link:
+ groups = self.issuedict.get(text, [text])
+ link, num = re.subn(r'\{(\d+)\}', lambda m:
+ groups[int(m.group(1))], link)
+ if not num:
+ link += text
+ shlib.browse_url(link)
+
+ def csetlink_event(self, tag, widget, event, liter):
+ if event.type != gtk.gdk.BUTTON_RELEASE:
+ return
+ text = self.get_link_text(tag, widget, liter)
+ if not text:
+ return
+ try:
+ rev = self.repo[text].rev()
+ if self.graphview:
+ self.graphview.set_revision_id(rev, load=True)
+ else:
+ self.load_details(rev)
+ except RepoError:
+ pass
+
+ def get_link_text(self, tag, widget, liter):
+ text_buffer = widget.get_buffer()
+ beg = liter.copy()
+ while not beg.begins_tag(tag):
+ beg.backward_char()
+ end = liter.copy()
+ while not end.ends_tag(tag):
+ end.forward_char()
+ text = text_buffer.get_text(beg, end)
+ return text
+
def file_button_release(self, widget, event):
if event.button == 3 and not (event.state & (gtk.gdk.SHIFT_MASK |
gtk.gdk.CONTROL_MASK)):
|
@@ -51,7 +51,7 @@ elif len(repos):
srcpath = repos[0]
- def createcombo(path, label, title):
+ def createcombo(path, label, title, bundle=False):
# comboentry
model = gtk.ListStore(str)
combo = gtk.ComboBoxEntry(model, 0)
@@ -74,7 +74,14 @@ browse = gtk.Button(_('Browse...'))
browse.connect('clicked', self.browse_clicked, title, entry)
- table.add_row(label, combo, 0, browse)
+ if bundle:
+ # bundle button
+ bundlebtn = gtk.Button(_('Bundle...'))
+ bundlebtn.connect('clicked', self.bundle_clicked,
+ _('Select a Mercurial Bundle'), entry)
+ table.add_row(label, combo, 0, browse, bundlebtn)
+ else:
+ table.add_row(label, combo, 0, browse)
return model, combo
@@ -85,7 +92,7 @@ ## comboentry for source paths
self.srclist, srccombo = createcombo(srcpath,
_('Source path:'),
- _('Select Source Folder'))
+ _('Select Source Folder'), True)
self.srcentry = srccombo.get_child()
## add pre-defined src paths to pull-down list
@@ -206,6 +213,21 @@ if res:
entry.set_text(res)
+ def bundle_clicked(self, button, title, entry):
+ path = entry.get_text()
+ if os.path.isdir(path):
+ initial = path
+ else:
+ initial = os.path.dirname(path)
+
+ res = gtklib.NativeSaveFileDialogWrapper(
+ initial=initial,
+ title=title,
+ filter= ((_('Mercurial bundles'), '*.hg'),),
+ open=True).run()
+ if res:
+ entry.set_text(res)
+
def checkbutton_toggled(self, checkbutton, entry):
state = checkbutton.get_active()
entry.set_sensitive(state)
@@ -266,7 +288,7 @@
def clone(self):
# gather input data
- src = self.srcentry.get_text()
+ src = self.srcentry.get_text().strip()
dest = self.destentry.get_text() or os.path.basename(src)
remotecmd = self.remotecmdentry.get_text()
rev = self.reventry.get_text()
|
@@ -858,13 +858,6 @@ _('Errors during rollback!'), self).run()
- def changelog_clicked(self, toolbutton, data=None):
- from tortoisehg.hgtk import history
- dlg = history.run(self.ui)
- dlg.display()
- return True
-
-
def should_addremove(self, files):
if self.test_opt('addremove'):
return True
|
@@ -18,7 +18,7 @@ from mercurial import cmdutil, util, ui, hg, commands
from tortoisehg.util.i18n import _
-from tortoisehg.util import settings, hglib, paths
+from tortoisehg.util import settings, hglib, paths, shlib
from tortoisehg.hgtk import gtklib
@@ -387,8 +387,7 @@ return
if not url.startswith('http'):
url = 'http://tortoisehg.org/manual/0.9/' + url
- from tortoisehg.hgtk import about
- about.browse_url(url)
+ shlib.browse_url(url)
def launch(self, item, app):
import sys
|
@@ -68,6 +68,8 @@ window.connect('thg-close', thgclose)
window.connect('thg-exit', thgexit)
+ return accelgroup, mod
+
def thgexit(window):
if thgclose(window):
gobject.idle_add(hgtk.thgexit, window)
@@ -318,7 +320,7 @@ return fname
def runCompatible(self):
- dialog = gtk.FileChooserDialog(title=None,
+ dialog = gtk.FileChooserDialog(title=self.title,
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
|
|
@@ -222,17 +222,17 @@
def __init__(self, style=STYLE_NORMAL, tooltips=None, logsize=None):
"""
- style: String. Predefined constans of CmdWidget style. Two styles;
- STYLE_NORMAL (progress bar + popup log viewer) and
- STYLE_COMPACT (progress bar + embedded log viewer) are
- availabled. Default: STYLE_NORMAL.
+ style: String. Predefined constans of CmdWidget style. Two styles,
+ STYLE_NORMAL (progress bar + popup log viewer) and
+ STYLE_COMPACT (progress bar + embedded log viewer) are
+ available. Default: STYLE_NORMAL.
tooltips: Reference. gtk.Tooltips instance to show tooltips of several
- buttons. If you omit, it will create a new instance of
- gtk.Tooltips. Default: None.
- logsize: Tuple or list contains 2 numbers. Specify the size of
- embedded log viewer. size[0] = width, size[1] = height.
- If you pass -1 as width or height size, it will be change to
- *natual* size of the widget. Default: tuple(-1, 180).
+ buttons. If omitted, a new instance of gtk.Tooltips will be
+ created. Default: None.
+ logsize: Tuple or list containing two numbers. Specify the size of the
+ embedded log viewer. size[0] = width, size[1] = height.
+ If you pass -1 as width or height size, it will be set to
+ the natural size of the widget. Default: tuple(-1, 180).
"""
gtk.VBox.__init__(self)
@@ -324,16 +324,16 @@ def execute(self, cmdline, callback, *args, **kargs):
"""
Execute passed command line using 'hgthread'.
- When the command terminated, callback function is called
- with return code.
+ When the command terminates, the callback function is invoked
+ with its return code.
cmdline: command line string.
- callback: function called after terminated the thread.
+ callback: function invoked after the command terminates.
def callback(returncode, useraborted, ...)
returncode: See the description of 'hgthread'.
- useraborted: Indicates whether the thread is aborted by user.
+ useraborted: Whether the command was aborted by the user.
"""
if self.hgthread:
return
@@ -376,12 +376,11 @@
def set_result(self, text, style=None):
"""
- Put text message and icon to the progress bar.
+ Put text message and icon in the progress bar.
style: String. If passed 'succeed', 'green' or 'ok', green
text and succeed icon will be shown. If passed 'error',
- 'failed', 'fail' or 'red' are passed, red text and error
- icon will be shown.
+ 'failed', 'fail' or 'red', red text and error icon will be shown.
"""
markup = '<span foreground="%s" weight="%s">%%s</span>'
if style in ('succeed', 'green', 'ok'):
@@ -409,7 +408,7 @@ def get_pbar(self):
"""
Return 'visible' property of the progress bar box.
- If not exists progress bar, it always returns False.
+ If there is no progress bar, it returns False.
"""
if hasattr(self, 'progbox'):
return self.progbox.get_property('visible')
@@ -418,7 +417,7 @@ def set_buttons(self, log=None, stop=None, close=None):
"""
Set visible properties of buttons on the progress bar box.
- If omitted all argments, it does nothing.
+ If all arguments are omitted, it does nothing.
log: if True, log button is shown. (default: None)
stop: if True, stop button is shown. (default: None)
@@ -573,7 +572,7 @@
def append(self, text, error=False):
"""
- Insert the text to the end of TextView.
+ Insert text at the end of the TextView.
text: string you want to append.
error: if True, append text with 'error' tag. (default: False)
@@ -587,7 +586,7 @@
def clear(self):
"""
- Clear all text in TextView.
+ Clear all text in the TextView.
"""
self.buffer.delete(self.buffer.get_start_iter(),
self.buffer.get_end_iter())
@@ -597,20 +596,17 @@ def __init__(self, title=_('Command Log')):
gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
gtklib.set_tortoise_icon(self, 'hg.ico')
+ accelgroup, mod = gtklib.set_tortoise_keys(self)
self.set_title(title)
self.set_default_size(320, 240)
- self.connect('delete-event', self.delete_event)
+ self.connect('delete-event', self.should_live)
# accelerators
- accelgroup = gtk.AccelGroup()
- self.add_accel_group(accelgroup)
- mod = gtklib.get_thg_modifier()
- for key, modifier in (gtk.accelerator_parse(mod+'w'),
- gtk.accelerator_parse(mod+'q'),
- gtk.accelerator_parse('Escape')):
- self.add_accelerator('thg-close', accelgroup, key,
- modifier, gtk.ACCEL_VISIBLE)
- self.connect('thg-close', self.delete_event)
+ key, modifier = gtk.accelerator_parse('Escape')
+ self.add_accelerator('thg-close', accelgroup, key, modifier,
+ gtk.ACCEL_VISIBLE)
+ self.connect('thg-close', self.should_live)
+ self.connect('thg-exit', self.should_live)
# log viewer
self.log = CmdLogWidget()
@@ -637,20 +633,183 @@ """
Set hook function.
- hook: the function called on closing this dialog.
+ hook: the function called when this dialog is closed.
def close_hook(dialog)
- where 'dialog' is the instance of CmdLogDialog class.
+ where 'dialog' is an instance of the CmdLogDialog class.
The hook function should return True or False.
- By returning True, you can prevent closing/hiding the dialog.
+ If True is returned, closing the dialog is prevented.
"""
self.close_hook = hook
### signal handlers ###
- def delete_event(self, *args):
+ def should_live(self, *args):
if hasattr(self, 'close_hook'):
if self.close_hook(self):
self.hide()
return True
+
+# Structured log types for CmdRunner
+LOG_NORMAL = 0
+LOG_ERROR = 1
+
+class CmdRunner(object):
+ """
+ Interactive command runner without GUI.
+
+ By default, there is no GUI (as opposed to CmdDialog).
+ If user interaction is needed (e.g. HTTPS auth), a simple
+ input dialog will be shown.
+ """
+ def __init__(self):
+ self.hgthread = None
+
+ self.dlg = CmdLogDialog()
+ def close_hook(dialog):
+ self.show_log(False)
+ return False
+ self.dlg.set_close_hook(close_hook)
+
+ self.clear_buffers()
+
+ ### public functions ###
+
+ def execute(self, cmdline, callback, *args, **kargs):
+ """
+ Execute passed command line using 'hgthread'.
+ When the command terminates, the callback function is invoked
+ with its return code.
+
+ cmdline: command line string.
+ callback: function invoked after the command terminates.
+
+ def callback(returncode, useraborted, ...)
+
+ returncode: See the description of 'hgthread'.
+ useraborted: Whether the command was aborted by the user.
+
+ return: True if the command was started,
+ False if a command is already running.
+ """
+ if self.hgthread:
+ return False
+
+ # clear previous logs
+ self.clear_buffers()
+
+ # thread start
+ self.hgthread = hgthread.HgThread(cmdline[1:])
+ self.hgthread.start()
+ gobject.timeout_add(10, self.process_queue, callback, args, kargs)
+
+ return True
+
+ def is_alive(self):
+ """
+ Return whether the thread is alive.
+ """
+ return self.hgthread and self.hgthread.isAlive()
+
+ def stop(self):
+ """
+ Terminate the thread forcibly.
+ """
+ if self.hgthread:
+ self.hgthread.terminate()
+
+ def get_buffer(self):
+ """
+ Return buffer containing all messages.
+
+ Note that the buffer will be cleared when the 'execute' method
+ is called, so you need to store this before next execution.
+ """
+ return ''.join([chunk[0] for chunk in self.buffer])
+
+ def get_raw_buffer(self):
+ """
+ Return structured buffer.
+
+ Note that the buffer will be cleared when the 'execute' method
+ is called, so you need to store this before next execution.
+ """
+ return self.buffer
+
+ def get_msg_buffer(self):
+ """
+ Return buffer with regular messages.
+
+ Note that the buffer will be cleared when the 'execute' method
+ is called, so you need to store this before next execution.
+ """
+ return ''.join([chunk[0] for chunk in self.buffer \
+ if chunk[1] == LOG_NORMAL])
+
+ def get_err_buffer(self):
+ """
+ Return buffer with error messages.
+
+ Note that the buffer will be cleared when the 'execute' method
+ is called, so you need to store this before next execution.
+ """
+ return ''.join([chunk[0] for chunk in self.buffer \
+ if chunk[1] == LOG_ERROR])
+
+ def set_title(self, title):
+ """
+ Set the title of the command log window.
+ """
+ self.dlg.set_title(title)
+
+ ### internal use functions ###
+
+ def clear_buffers(self):
+ """
+ Clear both message and error buffers.
+ """
+ self.buffer = []
+ self.dlg.log.clear()
+
+ def show_log(self, visible=True):
+ if visible:
+ if self.dlg.get_property('visible'):
+ self.dlg.present()
+ else:
+ self.dlg.show_all()
+ else:
+ self.dlg.hide()
+
+ def process_queue(self, callback, args, kargs):
+ # process queue
+ self.hgthread.process_dialogs()
+
+ # receive messages from queue
+ while self.hgthread.getqueue().qsize():
+ try:
+ msg = hglib.toutf(self.hgthread.getqueue().get(0))
+ self.buffer.append((msg, LOG_NORMAL))
+ self.dlg.log.append(msg)
+ except Queue.Empty:
+ pass
+ while self.hgthread.geterrqueue().qsize():
+ try:
+ msg = hglib.toutf(self.hgthread.geterrqueue().get(0))
+ self.buffer.append((msg, LOG_ERROR))
+ self.dlg.log.append(msg, error=True)
+ except Queue.Empty:
+ pass
+
+ # check thread state
+ if not self.hgthread.isAlive():
+ returncode = self.hgthread.return_code()
+ self.hgthread = None
+ if len(self.get_err_buffer()) > 0:
+ self.show_log(True)
+ def call_callback():
+ callback(returncode, self.get_buffer(), *args, **kargs)
+ gtklib.idle_add_single_call(call_callback)
+ return False # Stop polling this function
+ else:
+ return True # Continue polling
|
|
|
@@ -15,6 +15,7 @@ import atexit
from mercurial import ui, hg, cmdutil, commands, extensions, util, match, url
+from mercurial import hbisect
from tortoisehg.util.i18n import _
from tortoisehg.util import hglib
@@ -24,14 +25,97 @@from tortoisehg.hgtk import gdialog, gtklib, hgcmd, gorev, thgstrip
from tortoisehg.hgtk import backout, status, hgemail, tagadd, update, merge
from tortoisehg.hgtk import archive, changeset, thgconfig, thgmq, histdetails
-from tortoisehg.hgtk import statusbar
+from tortoisehg.hgtk import statusbar, bookmark
-def create_menu(label, callback):
+def create_menu(label, callback=None):
menuitem = gtk.MenuItem(label, True)
- menuitem.connect('activate', callback)
+ if callback:
+ menuitem.connect('activate', callback)
menuitem.set_border_width(1)
return menuitem
+def create_submenu(label, menu):
+ m = create_menu(label)
+ m.set_submenu(menu)
+ return m
+
+class FilterBox(gtklib.SlimToolbar):
+ 'Filter Toolbar for repository log'
+
+ def __init__(self, tooltips, filter_mode, branch_names):
+ gtklib.SlimToolbar.__init__(self, tooltips)
+ self.filter_mode = filter_mode
+
+ self.all = gtk.RadioButton(None, _('All'))
+ self.all.set_active(True)
+ self.append_widget(self.all, padding=0)
+
+ self.tagged = gtk.RadioButton(self.all, _('Tagged'))
+ self.append_widget(self.tagged, padding=0)
+
+ self.ancestry = gtk.RadioButton(self.all, _('Ancestry'))
+ self.append_widget(self.ancestry, padding=0)
+
+ self.parents = gtk.RadioButton(self.all, _('Parents'))
+ self.append_widget(self.parents, padding=0)
+
+ self.heads = gtk.RadioButton(self.all, _('Heads'))
+ self.append_widget(self.heads, padding=0)
+
+ self.merges = gtk.RadioButton(self.all, _('Merges'))
+ self.append_widget(self.merges, padding=0)
+
+ self.hidemerges = gtk.CheckButton(_('Hide Merges'))
+ self.append_widget(self.hidemerges, padding=0)
+
+ self.branches = gtk.RadioButton(self.all)
+ tooltips.set_tip(self.branches, _('Branch Filter'))
+ self.branches.set_sensitive(False)
+ self.append_widget(self.branches, padding=0)
+
+ self.branchcombo = gtk.combo_box_new_text()
+ self.branchcombo.append_text(_('Branches...'))
+ for name in branch_names:
+ self.branchcombo.append_text(hglib.toutf(name))
+ self.branchcombo.set_active(0)
+ self.append_widget(self.branchcombo, padding=0)
+
+ self.custombutton = gtk.RadioButton(self.all)
+ tooltips.set_tip(self.custombutton, _('Custom Filter'))
+ self.custombutton.set_sensitive(False)
+ self.append_widget(self.custombutton, padding=0)
+
+ self.filtercombo = gtk.combo_box_new_text()
+ self.filtercombo_entries = (_('Rev Range'), _('File Patterns'),
+ _('Keywords'), _('Date'), _('User'))
+ for f in self.filtercombo_entries:
+ self.filtercombo.append_text(f)
+ if (self.filter_mode >= len(self.filtercombo_entries) or
+ self.filter_mode < 0):
+ self.filter_mode = 1
+ self.filtercombo.set_active(self.filter_mode)
+ self.append_widget(self.filtercombo, padding=0)
+
+ searchlist = gtk.ListStore(int, # filtercombo value
+ str, # search string (utf-8)
+ str) # mode string (utf-8)
+ entrycombo = gtk.ComboBoxEntry(searchlist, 1)
+ cell = gtk.CellRendererText()
+ entrycombo.pack_end(cell, False)
+ entrycombo.add_attribute(cell, 'text', 2)
+ entry = entrycombo.child
+ self.entrycombo = entrycombo
+ self.entry = entry
+ self.append_widget(entrycombo, expand=True, padding=0)
+
+
+ def connect(self, detailed_signal, handler, *opts):
+ '''Connect an external signal handler to an internal widget
+ Signal format is '[widget_name]_[signal]'.'''
+ widget_name, signal = detailed_signal.split('_')
+ widget = self.__dict__[widget_name]
+ widget.connect(signal, handler, *opts)
+
class GLog(gdialog.GDialog):
'GTK+ based dialog for displaying repository logs'
def init(self):
@@ -53,6 +137,7 @@ self.revrange = None
self.forcepush = False
self.bundle_autoreject = False
+ self.runner = hgcmd.CmdRunner()
os.chdir(self.repo.root)
# Load extension support for commands which need it
@@ -216,6 +301,8 @@ func=self.push_clicked, icon=gtk.STOCK_GOTO_TOP),
dict(text=_('Email...'), name='email',
func=self.email_clicked, icon=gtk.STOCK_GOTO_LAST),
+ dict(text=_('Stop'), name='stop', sensitive=False,
+ func=self.stop_clicked, icon=gtk.STOCK_STOP),
dict(text='----'),
dict(text=_('Add Bundle...'), name='add-bundle',
sensitive=not bool(self.bfile),
@@ -227,7 +314,7 @@ sensitive=bool(self.bfile),
func=self.reject_clicked, icon=gtk.STOCK_DIALOG_ERROR),
dict(text='----'),
- dict(name='use-proxy-server', text=_('Use proxy server'),
+ dict(text=_('Use proxy server'), name='use-proxy-server',
ascheck=True, func=toggle_proxy),
dict(text=_('Force push'), ascheck=True, func=toggle_force),
])
@@ -368,7 +455,7 @@ text = entry.get_text()
if not text:
return
- row = [mode, text, combo.get_active_text()]
+ row = [mode, text, combo.get_active_text()]
model = self.entrycombo.get_model()
for r in model:
if r[0] == row[0] and r[1] == row[1]:
@@ -462,24 +549,21 @@ self.pats = []
opts = self.opts
- if 'bundle' in opts:
- self.set_bundlefile(opts['bundle'])
- self.bundle_autoreject = True
if opts['filehist']:
- file = opts['filehist']
- opts['pats'] = [file]
self.custombutton.set_active(True)
self.filter = 'custom'
self.filtercombo.set_active(1)
- self.filterentry.set_text(file)
- self.filter_entry_activated(self.filterentry, self.filtercombo)
+ self.filterentry.set_text(opts['filehist'])
+ opts['pats'] = [opts['filehist']]
elif self.pats:
self.custombutton.set_active(True)
self.filter = 'custom'
self.filtercombo.set_active(1)
self.filterentry.set_text(', '.join(self.pats))
opts['pats'] = self.pats
- self.filter_entry_activated(self.filterentry, self.filtercombo)
+ if 'bundle' in opts:
+ self.set_bundlefile(opts['bundle'])
+ self.bundle_autoreject = True
else:
self.reload_log(**opts)
@@ -734,16 +818,16 @@ m.append(create_menu(_('_Update...'), self.checkout))
cmenu_merge = create_menu(_('_Merge with...'), self.domerge)
m.append(cmenu_merge)
- m.append_sep()
- m.append(create_menu(_('_Export Patch...'), self.export_patch))
- m.append(create_menu(_('E_mail Patch...'), self.email_patch))
- m.append(create_menu(_('_Bundle rev:tip...'), self.bundle_rev_to_tip))
- m.append_sep()
- m.append(create_menu(_('Add/Remove _Tag...'), self.add_tag))
- cmenu_backout = create_menu(_('Backout Revision...'), self.backout_rev)
+ cmenu_backout = create_menu(_('Backout...'), self.backout_rev)
m.append(cmenu_backout)
m.append(create_menu(_('_Revert'), self.revert))
- m.append(create_menu(_('_Archive...'), self.archive))
+ m.append_sep()
+ m.append(create_submenu(_('Export'),
+ self.export_context_menu()))
+ m.append_sep()
+ m.append(create_submenu(_('Tag'),
+ self.tags_context_menu()))
+ m.append_sep()
# disable/enable menus as required
parents = self.repo.parents()
@@ -759,39 +843,74 @@ cmenu_merge.set_sensitive(can_merge)
cmenu_backout.set_sensitive(can_backout)
+ # need mq extension for strip command
+ if 'mq' in self.exs:
+ m.append(create_submenu(_('Mercurial Queues'),
+ self.mq_context_menu()))
+
# need transplant extension for transplant command
if 'transplant' in self.exs:
m.append(create_menu(_('Transp_lant to local'),
self.transplant_rev))
- # need mq extension for strip command
- if 'mq' in self.exs:
- cmenu_qimport = create_menu(_('QImport Revision'), self.qimport_rev)
- cmenu_strip = create_menu(_('Strip Revision...'), self.strip_rev)
-
- try:
- ctx = self.repo[self.currevid]
- qbase = self.repo['qbase']
- actx = ctx.ancestor(qbase)
- if self.repo['qparent'] == ctx:
- cmenu_qimport.set_sensitive(True)
- cmenu_strip.set_sensitive(False)
- elif actx == qbase or actx == ctx:
- # we're in the mq revision range or the mq
- # is a descendant of us
- cmenu_qimport.set_sensitive(False)
- cmenu_strip.set_sensitive(False)
- except:
- pass
-
- m.append_sep()
- m.append(cmenu_qimport)
- m.append(cmenu_strip)
-
+ m.append_sep()
+ m.append(create_submenu(_('Bisect'),
+ self.bisect_context_menu()))
menu = m.create_menu()
menu.show_all()
return menu
+ def export_context_menu(self):
+ m = gtklib.MenuItems()
+ m.append(create_menu(_('_Export Patch...'), self.export_patch))
+ m.append(create_menu(_('E_mail Patch...'), self.email_patch))
+ m.append(create_menu(_('_Bundle rev:tip...'), self.bundle_rev_to_tip))
+ m.append(create_menu(_('_Archive...'), self.archive))
+ return m.create_menu()
+
+ def tags_context_menu(self):
+ m = gtklib.MenuItems()
+ m.append(create_menu(_('Add/Remove _Tag...'), self.add_tag))
+ if 'bookmarks' in self.exs:
+ m.append(create_menu(_('Add/Remove B_ookmark...'),
+ self.add_bookmark))
+ m.append(create_menu(_('Rename Bookmark...'),
+ self.rename_bookmark))
+ return m.create_menu()
+
+ def mq_context_menu(self):
+ m = gtklib.MenuItems()
+ cmenu_qimport = create_menu(_('QImport Revision'), self.qimport_rev)
+ cmenu_strip = create_menu(_('Strip Revision...'), self.strip_rev)
+
+ try:
+ ctx = self.repo[self.currevid]
+ qbase = self.repo['qbase']
+ actx = ctx.ancestor(qbase)
+ if self.repo['qparent'] == ctx:
+ cmenu_qimport.set_sensitive(True)
+ cmenu_strip.set_sensitive(False)
+ elif actx == qbase or actx == ctx:
+ # we're in the mq revision range or the mq
+ # is a descendant of us
+ cmenu_qimport.set_sensitive(False)
+ cmenu_strip.set_sensitive(False)
+ except:
+ pass
+
+ m.append_sep()
+ m.append(cmenu_qimport)
+ m.append(cmenu_strip)
+ return m.create_menu()
+
+ def bisect_context_menu(self):
+ m = gtklib.MenuItems()
+ m.append(create_menu(_('Reset'), self.bisect_reset))
+ m.append(create_menu(_('Mark as good'), self.bisect_good))
+ m.append(create_menu(_('Mark as bad'), self.bisect_bad))
+ m.append(create_menu(_('Skip testing'), self.bisect_skip))
+ return m.create_menu()
+
def restore_single_sel(self, widget, *args):
self.tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
if self.origsel:
@@ -843,7 +962,7 @@
# need MQ extension for qimport command
if 'mq' in self.exs:
- m.append(create_menu(_('QImport from here to selected'),
+ m.append(create_menu(_('qimport from here to selected'),
self.qimport_revs))
m.append_sep()
@@ -937,9 +1056,14 @@ _('Push outgoing changesets'))
email = syncbox.append_stock(gtk.STOCK_GOTO_LAST,
_('Email outgoing changesets'))
+ syncbox.append_widget(gtk.VSeparator())
+ stop = syncbox.append_stock(gtk.STOCK_STOP,
+ _('Stop current transaction'))
+ stop.set_sensitive(False)
apply.set_sensitive(False)
reject.set_sensitive(False)
+ self.stop_button = stop
self.syncbar_apply = apply
self.syncbar_reject = reject
@@ -995,89 +1119,37 @@ reject.connect('clicked', self.reject_clicked)
conf.connect('clicked', self.conf_clicked, urlcombo)
email.connect('clicked', self.email_clicked)
+ stop.connect('clicked', self.stop_clicked)
# filter bar
- self.filterbox = gtklib.SlimToolbar()
+ self.filterbox = FilterBox(self.tooltips,
+ self.filter_mode,
+ self.get_live_branches())
filterbox = self.filterbox
+ self.ancestrybutton = filterbox.ancestry
+ self.hidemerges = filterbox.hidemerges
+ self.branchbutton = filterbox.branches
+ self.lastbranchrow = None
+ self.branchcombo = filterbox.branchcombo
+ self.custombutton = filterbox.custombutton
+ self.filter_mode = filterbox.filter_mode
+ self.filtercombo = filterbox.filtercombo
+ self.filterentry = filterbox.entry
+ self.entrycombo = filterbox.entrycombo
- all = gtk.RadioButton(None, _('All'))
- all.set_active(True)
- all.connect('toggled', self.filter_selected, 'all')
- filterbox.append_widget(all, padding=0)
-
- tagged = gtk.RadioButton(all, _('Tagged'))
- tagged.connect('toggled', self.filter_selected, 'tagged')
- filterbox.append_widget(tagged, padding=0)
-
- ancestry = gtk.RadioButton(all, _('Ancestry'))
- ancestry.connect('toggled', self.filter_selected, 'ancestry')
- filterbox.append_widget(ancestry, padding=0)
- self.ancestrybutton = ancestry
-
- parents = gtk.RadioButton(all, _('Parents'))
- parents.connect('toggled', self.filter_selected, 'parents')
- filterbox.append_widget(parents, padding=0)
-
- heads = gtk.RadioButton(all, _('Heads'))
- heads.connect('toggled', self.filter_selected, 'heads')
- filterbox.append_widget(heads, padding=0)
-
- merges = gtk.RadioButton(all, _('Merges'))
- merges.connect('toggled', self.filter_selected, 'only_merges')
- filterbox.append_widget(merges, padding=0)
-
- hidemerges = gtk.CheckButton(_('Hide Merges'))
- hidemerges.connect('toggled', self.filter_selected, 'no_merges')
- filterbox.append_widget(hidemerges, padding=0)
- self.hidemerges = hidemerges
-
- branches = gtk.RadioButton(all)
- branches.connect('toggled', self.filter_selected, 'branch')
- self.tooltips.set_tip(branches, _('Branch Filter'))
- branches.set_sensitive(False)
- filterbox.append_widget(branches, padding=0)
- self.branchbutton = branches
-
- branchcombo = gtk.combo_box_new_text()
- branchcombo.append_text(_('Branches...'))
- for name in self.get_live_branches():
- branchcombo.append_text(hglib.toutf(name))
- branchcombo.set_active(0)
- branchcombo.connect('changed', self.select_branch)
- self.lastbranchrow = None
- filterbox.append_widget(branchcombo, padding=0)
- self.branchcombo = branchcombo
-
- self.custombutton = gtk.RadioButton(all)
- self.tooltips.set_tip(self.custombutton, _('Custom Filter'))
- self.custombutton.set_sensitive(False)
- filterbox.append_widget(self.custombutton, padding=0)
-
- filtercombo = gtk.combo_box_new_text()
- filtercombo_entries = (_('Rev Range'), _('File Patterns'),
- _('Keywords'), _('Date'), _('User'))
- for f in filtercombo_entries:
- filtercombo.append_text(f)
- if (self.filter_mode >= len(filtercombo_entries) or
- self.filter_mode < 0):
- self.filter_mode = 1
- filtercombo.set_active(self.filter_mode)
- self.filtercombo = filtercombo
- filterbox.append_widget(filtercombo, padding=0)
-
- searchlist = gtk.ListStore(int, # filtercombo value
- str, # search string (utf-8)
- str) # mode string (utf-8)
- entrycombo = gtk.ComboBoxEntry(searchlist, 1)
- cell = gtk.CellRendererText()
- entrycombo.pack_end(cell, False)
- entrycombo.add_attribute(cell, 'text', 2)
- entry = entrycombo.child
- entry.connect('activate', self.filter_entry_activated, filtercombo)
- entrycombo.connect('changed', self.filter_entry_changed, filtercombo)
- self.entrycombo = entrycombo
- self.filterentry = entry
- filterbox.append_widget(entrycombo, expand=True, padding=0)
+ fcon = self.filterbox.connect
+ fsel = self.filter_selected
+ fcon('all_toggled', fsel, 'all')
+ fcon('tagged_toggled', fsel, 'tagged')
+ fcon('ancestry_toggled', fsel, 'ancestry')
+ fcon('parents_toggled', fsel, 'parents')
+ fcon('heads_toggled', fsel, 'heads')
+ fcon('merges_toggled', fsel, 'only_merges')
+ fcon('hidemerges_toggled', fsel, 'no_merges')
+ fcon('branches_toggled', fsel, 'branch')
+ fcon('branchcombo_changed', self.select_branch)
+ fcon('entry_activate', self.filter_entry_activated, self.filtercombo)
+ fcon('entrycombo_changed', self.filter_entry_changed, self.filtercombo)
midpane = gtk.VBox()
midpane.pack_start(syncbox, False)
@@ -1134,6 +1206,15 @@ def get_extras(self):
return self.stbar
+ def refresh_on_marker_change(self, oldlen, oldmarkers, newmarkers):
+ self.repo.invalidate()
+ self.changeview.clear_cache()
+ if len(self.repo) != oldlen:
+ self.reload_log()
+ else:
+ if newmarkers != oldmarkers:
+ self.refresh_model()
+
def apply_clicked(self, button):
combo = self.ppullcombo
list, iter = combo.get_model(), combo.get_active_iter()
@@ -1209,22 +1290,35 @@ atexit.register(cleanup)
bfile = path
- path = hglib.validate_synch_path(path, self.repo)
-
-
for badchar in (':', '*', '\\', '?', '#'):
bfile = bfile.replace(badchar, '')
bfile = bfile.replace('/', '_')
bfile = os.path.join(self.bundledir, bfile) + '.hg'
cmdline = ['hg', 'incoming', '--bundle', bfile]
cmdline += self.get_proxy_args()
- cmdline += [path]
- dlg = hgcmd.CmdDialog(cmdline, text='hg incoming')
- dlg.show_all()
- dlg.run()
- dlg.hide()
- if dlg.return_code() == 0 and os.path.isfile(bfile):
- self.set_bundlefile(bfile)
+ cmdline += [hglib.validate_synch_path(path, self.repo)]
+
+ def callback(return_code, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0 and os.path.isfile(bfile):
+ self.set_bundlefile(bfile)
+ text = _('%d incoming changesets') % self.npreviews
+ elif return_code is None:
+ text = _('Aborted incoming')
+ else:
+ text = _('No incoming changesets')
+ self.stbar.set_idle_text(text)
+ if self.runner.execute(cmdline, callback):
+ self.runner.set_title(_('Incoming'))
+ self.stbar.begin(_('Checking incoming changesets...'))
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
+ else:
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def set_bundlefile(self, bfile, **kwopts):
self.origurl = self.urlcombo.get_active()
@@ -1254,14 +1348,15 @@ self.cmd_set_sensitive('accept', True)
self.cmd_set_sensitive('reject', True)
- cmds = ('incoming', 'outgoing', 'push', 'pull', 'email', 'refresh',
- 'synchronize', 'mq', 'add-bundle')
+ cmds = ('incoming', 'outgoing', 'push', 'pull', 'email', 'refresh',
+ 'synchronize', 'mq', 'add-bundle')
self.incoming_disabled_cmds = []
for cmd in cmds:
self.cmd_set_sensitive(cmd, False)
self.incoming_disabled_cmds.append(cmd)
- ignore = (self.syncbar_apply, self.syncbar_reject, self.ppullbox)
+ ignore = (self.syncbar_apply, self.syncbar_reject, self.ppullbox,
+ self.stop_button)
self.incoming_disabled = []
def disable_child(w):
if (w not in ignore) and w.get_property('sensitive'):
@@ -1318,18 +1413,35 @@ self.pathentry.grab_focus()
return
cmdline = ['hg'] + cmd + self.get_proxy_args() + [remote_path]
- dlg = hgcmd.CmdDialog(cmdline, text=' '.join(['hg'] + cmd))
- dlg.show_all()
- dlg.run()
- dlg.hide()
- if dlg.return_code() == 0:
- self.repo.invalidate()
- self.changeview.clear_cache()
- if '--rebase' in cmd:
- self.origtip = len(self.repo)
- self.reload_log()
- elif len(self.repo) > self.origtip:
- self.reload_log()
+
+ def callback(return_code, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0:
+ self.repo.invalidate()
+ self.changeview.clear_cache()
+ if '--rebase' in cmd:
+ self.origtip = len(self.repo)
+ self.reload_log()
+ text = _('Finished pull with rebase')
+ elif len(self.repo) > self.origtip:
+ self.reload_log()
+ text = _('Finished pull')
+ else:
+ text = _('No changesets to pull')
+ else:
+ text = _('Aborted pull')
+ self.stbar.set_idle_text(text)
+ if self.runner.execute(cmdline, callback):
+ self.runner.set_title(_('Pull'))
+ self.stbar.begin(_('Pulling changesets...'))
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
+ else:
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def outgoing_clicked(self, toolbutton):
path = hglib.fromutf(self.pathentry.get_text()).strip()
@@ -1343,24 +1455,35 @@ cmd += self.get_proxy_args()
cmd += [hglib.validate_synch_path(path, self.repo)]
- dlg = hgcmd.CmdDialog(cmd, text='hg outgoing')
- dlg.show_all()
- dlg.run()
- dlg.hide()
- if dlg.return_code() == 0:
- outgoing = []
- buf = dlg.textbuffer
- begin, end = buf.get_bounds()
- for line in buf.get_text(begin, end).splitlines()[:-1]:
- try:
- node = self.repo[line].node()
- outgoing.append(node)
- except:
- pass
- self.outgoing = outgoing
- self.reload_log()
- text = _('%d outgoing changesets') % len(outgoing)
+ def callback(return_code, buffer, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0:
+ outgoing = []
+ for line in buffer.splitlines()[:-1]:
+ try:
+ node = self.repo[line].node()
+ outgoing.append(node)
+ except:
+ pass
+ self.outgoing = outgoing
+ self.reload_log()
+ text = _('%d outgoing changesets') % len(outgoing)
+ elif return_code is None:
+ text = _('Aborted outgoing')
+ else:
+ text = _('No outgoing changesets')
self.stbar.set_idle_text(text)
+ if self.runner.execute(cmd, callback):
+ self.runner.set_title(_('Outgoing'))
+ self.stbar.begin(_('Checking outgoing changesets...'))
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
+ else:
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def email_clicked(self, toolbutton):
path = hglib.fromutf(self.pathentry.get_text()).strip()
@@ -1412,13 +1535,28 @@ if self.forcepush:
cmdline += ['--force']
cmdline += [remote_path]
- dlg = hgcmd.CmdDialog(cmdline, text=' '.join(cmdline[:-1]))
- dlg.show_all()
- dlg.run()
- dlg.hide()
- if dlg.return_code() == 0 and self.outgoing:
- self.outgoing = []
- self.reload_log()
+
+ def callback(return_code, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0:
+ if self.outgoing:
+ self.outgoing = []
+ self.reload_log()
+ text = _('Finished push')
+ else:
+ text = _('Aborted push')
+ self.stbar.set_idle_text(text)
+ if self.runner.execute(cmdline, callback):
+ self.runner.set_title(_('Push'))
+ self.stbar.begin(_('Pushing changesets...'))
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
+ else:
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def conf_clicked(self, toolbutton, combo):
newpath = hglib.fromutf(self.pathentry.get_text()).strip()
@@ -1439,6 +1577,9 @@ self.update_urllist()
self.update_postpull()
+ def stop_clicked(self, toolbutton):
+ self.runner.stop()
+
def update_urllist(self):
urllist = self.urlcombo.get_model()
urllist.clear()
@@ -1723,19 +1864,74 @@ tag = ''
def refresh(*args):
- self.repo.invalidate()
- self.changeview.clear_cache()
- if len(self.repo) != oldlen:
- self.reload_log()
- else:
- newtags = self.repo.tagslist()
- if newtags != oldtags:
- self.refresh_model()
+ self.refresh_on_marker_change(oldlen, oldtags, self.repo.tagslist())
dialog = tagadd.TagAddDialog(self.repo, tag, rev)
dialog.connect('destroy', refresh)
self.show_dialog(dialog)
+ def add_bookmark(self, menuitem):
+ # save bookmark info for detecting new bookmarks added
+ oldbookmarks = hglib.get_repo_bookmarks(self.repo)
+ oldlen = len(self.repo)
+ rev = self.currevid
+
+ def refresh(*args):
+ self.refresh_on_marker_change(oldlen,
+ oldbookmarks,
+ hglib.get_repo_bookmarks(self.repo))
+
+ dialog = bookmark.BookmarkAddDialog(self.repo, rev=str(rev))
+ dialog.connect('destroy', refresh)
+ self.show_dialog(dialog)
+
+ def rename_bookmark(self, menuitem):
+ # save bookmark info for detecting new bookmarks added
+ oldbookmarks = hglib.get_repo_bookmarks(self.repo)
+ oldlen = len(self.repo)
+ rev = self.currevid
+
+ def refresh(*args):
+ self.refresh_on_marker_change(oldlen,
+ oldbookmarks,
+ hglib.get_repo_bookmarks(self.repo))
+
+ dialog = bookmark.BookmarkRenameDialog(self.repo, rev=str(rev))
+ dialog.connect('destroy', refresh)
+ self.show_dialog(dialog)
+
+ def bisect_reset(self, menuitem):
+ commands.bisect(ui=self.ui,
+ repo=self.repo,
+ good=False,
+ bad=False,
+ skip=False,
+ reset=True)
+
+ def bisect_good(self, menuitem):
+ cmd = ['hg', 'bisect', '--good', str(self.currevid)]
+ dlg = hgcmd.CmdDialog(cmd)
+ dlg.show_all()
+ dlg.run()
+ dlg.hide()
+ self.refresh_model()
+
+ def bisect_bad(self, menuitem):
+ cmd = ['hg', 'bisect', '--bad', str(self.currevid)]
+ dlg = hgcmd.CmdDialog(cmd)
+ dlg.show_all()
+ dlg.run()
+ dlg.hide()
+ self.refresh_model()
+
+ def bisect_skip(self, menuitem):
+ cmd = ['hg', 'bisect', '--skip', str(self.currevid)]
+ dlg = hgcmd.CmdDialog(cmd)
+ dlg.show_all()
+ dlg.run()
+ dlg.hide()
+ self.refresh_model()
+
def show_status(self, menuitem):
rev = self.currevid
statopts = self.merge_opts(commands.table['^status|st'][1],
@@ -1766,33 +1962,65 @@ self.pathentry.grab_focus()
return
node = self.repo[self.currevid].node()
- cmdline = ['hg', 'push', '--rev', str(self.currevid), remote_path]
- dlg = hgcmd.CmdDialog(cmdline, text='hg push')
- dlg.show_all()
- dlg.run()
- dlg.hide()
- if dlg.return_code() == 0 and self.outgoing:
- d = self.outgoing.index(node)
- self.outgoing = self.outgoing[d+1:]
- self.reload_log()
+ rev = str(self.currevid)
+ cmdline = ['hg', 'push', '--rev', rev, remote_path]
+
+ def callback(return_code, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0:
+ if self.outgoing:
+ d = self.outgoing.index(node)
+ self.outgoing = self.outgoing[d + 1:]
+ self.reload_log()
+ text = _('Finished push to revision %s') % rev
+ else:
+ text = _('Aborted push')
+ self.stbar.set_idle_text(text)
+ if self.runner.execute(cmdline, callback):
+ self.runner.set_title(_('Push to %s') % rev)
+ self.stbar.begin(_('Pushing changesets to revision %s...') % rev)
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
+ else:
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def pull_to(self, menuitem):
- cmdline = ['hg', 'pull', '--rev', str(self.currevid), self.bfile]
- dlg = hgcmd.CmdDialog(cmdline)
- dlg.show_all()
- dlg.run()
- dlg.hide()
- curtip = len(hg.repository(self.ui, self.repo.root))
- self.repo = hg.repository(self.ui, path=self.bfile)
- self.graphview.set_repo(self.repo, self.stbar)
- self.changeview.set_repo(self.repo)
- if hasattr(self, 'mqwidget'):
- self.mqwidget.set_repo(self.repo)
- self.npreviews = len(self.repo) - curtip
- if self.npreviews == 0:
- self.remove_overlay(False)
+ rev = str(self.currevid)
+ cmdline = ['hg', 'pull', '--rev', rev, self.bfile]
+
+ def callback(return_code, *args):
+ self.stbar.end()
+ self.stop_button.set_sensitive(False)
+ self.cmd_set_sensitive('stop', False)
+ if return_code == 0:
+ curtip = len(hg.repository(self.ui, self.repo.root))
+ self.repo = hg.repository(self.ui, path=self.bfile)
+ self.graphview.set_repo(self.repo, self.stbar)
+ self.changeview.set_repo(self.repo)
+ if hasattr(self, 'mqwidget'):
+ self.mqwidget.set_repo(self.repo)
+ self.npreviews = len(self.repo) - curtip
+ if self.npreviews == 0:
+ self.remove_overlay(False)
+ else:
+ self.reload_log()
+ text = _('Finished pull to revision %s') % rev
+ else:
+ text = _('Aborted pull')
+ self.stbar.set_idle_text(text)
+ if self.runner.execute(cmdline, callback):
+ self.runner.set_title(_('Pull to %s') % rev)
+ self.stbar.begin(_('Pulling changesets to revision %s...') % rev)
+ self.stop_button.set_sensitive(True)
+ self.cmd_set_sensitive('stop', True)
else:
- self.reload_log()
+ gdialog.Prompt(_('Cannot run now'),
+ _('Please try again after running '
+ 'operation is completed'), self).run()
def copy_hash(self, menuitem):
hash = self.repo[self.currevid].hex()
|
@@ -159,13 +159,29 @@ escape = gtklib.markup_escape_text
summary = escape(hglib.toutf(summary))
node = ctx.node()
+
+ # Check if we're using bookmarks, and have the
+ # 'track.current' option set; if so,
+ # find what the 'current' bookmark is
+ currentBookmark = None
+ bookmarks = None
+ try:
+ bookmarks = hglib.extensions.find('bookmarks')
+ except KeyError:
+ pass
+ if bookmarks:
+ if self.repo.ui.configbool('bookmarks', 'track.current'):
+ currentBookmark = bookmarks.current(self.repo)
+
tags = self.repo.nodetags(node)
taglist = hglib.toutf(', '.join(tags))
tstr = ''
for tag in tags:
if tag not in self.hidetags:
- tstr += gtklib.markup(' %s ' % tag, color='black',
- background='#ffffaa') + ' '
+ style = {'color':'black', 'background':'#ffffaa'}
+ if tag == currentBookmark:
+ style['background'] = '#ffcc99'
+ tstr += gtklib.markup(' %s ' % tag, **style) + ' '
branch = ctx.branch()
bstr = ''
|
@@ -392,6 +392,7 @@ cell = gtk.CellRendererText()
cell.set_property("width-chars", 8)
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
+ cell.set_property("xalign", 1.0)
col = self.tvcolumns['rev'] = gtk.TreeViewColumn(_('Rev'))
col.set_visible(False)
col.set_resizable(True)
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
@@ -26,7 +26,7 @@ fname = util.canonpath(root, cwd, pats[0])
target = util.canonpath(root, cwd, pats[1])
except util.Abort, e:
- return gdialog.Prompt("invalid path", str(e), None)
+ return gdialog.Prompt(_('Invalid path'), str(e), None)
except IndexError:
pass
os.chdir(root)
|
@@ -42,7 +42,7 @@ self.pbar.pulse()
return True
- def begin(self, msg=_('Running'), timeout=100):
+ def begin(self, msg=_('Running...'), timeout=100):
self.pbox.set_child_visible(True)
self.pbox.map()
self.set_status_text(msg)
|
@@ -559,6 +559,12 @@ self.connect('thg-accept', self.thgaccept)
self.connect('delete-event', self.delete_event)
+ # wrapper box for padding
+ wrapbox = gtk.VBox()
+ wrapbox.set_border_width(5)
+ self.vbox.pack_start(wrapbox, False, False)
+
+ # create combo to select the target
combo = gtk.combo_box_new_text()
combo.append_text(_('User global settings'))
if repo:
@@ -570,12 +576,15 @@ edit = gtk.Button(_('Edit File'))
hbox.pack_start(edit, False, False, 2)
edit.connect('clicked', self.edit_clicked)
- self.vbox.pack_start(hbox, False, False, 4)
+ wrapbox.pack_start(hbox, False, False, 1)
+
+ # insert padding of between combo and notebook
+ wrapbox.pack_start(gtk.VBox(), False, False, 3)
# Create a new notebook, place the position of the tabs
self.notebook = notebook = gtk.Notebook()
notebook.set_tab_pos(gtk.POS_TOP)
- self.vbox.pack_start(notebook, True, True)
+ wrapbox.pack_start(notebook, True, True)
notebook.show()
self.show_tabs = True
self.show_border = True
@@ -1064,6 +1073,14 @@ break
except (IOError, OSError):
pass
+ else:
+ gdialog.Prompt(_('Unable to create a Mercurial.ini file'),
+ _('Insufficient access rights, reverting to read-only'
+ 'mode.'), self).run()
+ from mercurial import config
+ self.fn = rcpath[0]
+ cfg = config.config()
+ return cfg
self.fn = fn
try:
import iniparse
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
@@ -236,3 +236,5 @@ return_path = path_aux
return return_path
+def get_repo_bookmarks(repo):
+ return repo._bookmarks.keys()
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
Loading...