by
Changes to 11 files · Browse files at 99441bb0669a Showing diff from parent 2ebd7cabe28b cc0ea6747a17 Diff from another changeset...
@@ -6,7 +6,25 @@ what bugs have been fixed, and what features have been added in the current
version.
-New features and improvements since 0.6:
+The ReleaseNotes page on the TortosieHg Wiki is usually kept up to date.
+http://bitbucket.org/tortoisehg/wiki/ReleaseNotes
+
+Bug fixes since 0.7:
+
+* thgutil: UNC paths should be filtered by 'localdisks' config
+* serve: direct web browser at loopback address
+* shlib: moved app data to %APPDATA%\TortoiseHg on Windows
+* thgconfig: UTF-8 fixes
+* thgconfig: show description of selected item
+* thgconfig: move 'bottom diffs' to tortoisehg page
+* datamine: fix markup problem in status bar
+* sync: allow bundles without .hg extension
+* sync: handle non-ascii paths and aliases
+* status: prevent traceback caused by toggling rename diffs
+* update: fix update to rev 0 from changelog viewer
+* hgtK: follow 'hg version' convention for 'hgtk version'
+
+New features and improvements in 0.7:
* Status window now supports shelving of selected changes.
Unknown files are now displayed by default, hg status convention.
|
@@ -75,6 +75,7 @@ vbox.pack_start(self.notebook, True, True, 2)
self.stbar = gtklib.StatusBar()
+ self.stbar.sttext.set_property('use-markup', True)
vbox.pack_start(self.stbar, False, False, 2)
self.stop_button.set_sensitive(False)
return vbox
|
@@ -13,7 +13,7 @@ from tempfile import mkstemp
from dialog import *
from mercurial import hg, ui, extensions
-from hglib import RepoError
+from hglib import RepoError, fromutf, toutf
from thgconfig import ConfigDialog
from hgcmd import CmdDialog
@@ -195,10 +195,10 @@
if initial:
# Only zap these fields at startup
- self._tobox.child.set_text(repo.ui.config('email', 'to', ''))
- self._ccbox.child.set_text(repo.ui.config('email', 'cc', ''))
- self._frombox.child.set_text(repo.ui.config('email', 'from', ''))
- self._subjbox.child.set_text(repo.ui.config('email', 'subject', ''))
+ self._tobox.child.set_text(fromutf(repo.ui.config('email', 'to', '')))
+ self._ccbox.child.set_text(fromutf(repo.ui.config('email', 'cc', '')))
+ self._frombox.child.set_text(fromutf(repo.ui.config('email', 'from', '')))
+ self._subjbox.child.set_text(fromutf(repo.ui.config('email', 'subject', '')))
fill_history(history, self._tolist, 'email.to')
fill_history(history, self._cclist, 'email.cc')
fill_history(history, self._fromlist, 'email.from')
@@ -237,10 +237,10 @@ history.get_value(cpath).remove(newvalue)
history.get_value(cpath).insert(0, newvalue)
- totext = self._tobox.child.get_text()
- cctext = self._ccbox.child.get_text()
- fromtext = self._frombox.child.get_text()
- subjtext = self._subjbox.child.get_text()
+ totext = fromutf(self._tobox.child.get_text())
+ cctext = fromutf(self._ccbox.child.get_text())
+ fromtext = fromutf(self._frombox.child.get_text())
+ subjtext = fromutf(self._subjbox.child.get_text())
if not totext:
info_dialog(self, 'Info required', 'You must specify a recipient')
|
@@ -5,7 +5,7 @@ # Copyright (C) 2008-9 Steve Borho <steve@borho.org>
# Copyright (C) 2008 TK Soh <teekaysoh@gmail.com>
-shortlicense = '''\
+shortlicense = '''
Copyright (C) 2009 Steve Borho <steve@borho.org>.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -510,8 +510,9 @@def version(ui, **opts):
"""output version and copyright information"""
import hggtk.shlib
- ui.write("%s\n" % hggtk.shlib.version())
- if ui.verbose: ui.write(shortlicense)
+ ui.write("TortoiseHg Dialogs (version %s)\n" % hggtk.shlib.version())
+ if not ui.quiet:
+ ui.write(shortlicense)
globalopts = [
('R', 'repository', '',
|
@@ -232,7 +232,9 @@
while not gservice or not hasattr(gservice, 'httpd'):
time.sleep(0.1)
- self._url = 'http://%s:%d/' % (gservice.httpd.fqaddr, port)
+ # gservice.httpd.fqaddr turned out to be unreliable, so use
+ # loopback addr directly
+ self._url = 'http://127.0.0.1:%d/' % (port)
gobject.timeout_add(10, self.process_queue)
def _stop_server(self):
|
@@ -103,24 +103,43 @@ dbase.close()
def _get_path(self, appname):
- return os.path.join(os.path.expanduser('~'), '.tortoisehg',
- 'settings', appname)
+ if os.name == 'nt':
+ return os.path.join(os.environ.get('APPDATA'), 'TortoiseHg', appname)
+ else:
+ return os.path.join(os.path.expanduser('~'), '.tortoisehg',
+ 'settings', appname)
def _audit(self):
if os.path.exists(os.path.dirname(self._path)):
return
- os.makedirs(os.path.dirname(self._path))
- self._import()
+ try:
+ os.makedirs(os.path.dirname(self._path))
+ self._import()
+ except:
+ pass
def _import(self):
- # import old settings data (TortoiseHg <= 0.3)
- old_path = os.path.join(os.path.expanduser('~'), '.hgext', 'tortoisehg')
- if os.path.isfile(old_path):
- print "converting old history..."
- olddb = shelve.open(old_path)
+ # import old settings data dir (TortoiseHg <= 0.7)
+ home = os.path.expanduser('~')
+ if os.name == 'nt':
+ olddir = os.path.join(home, '.tortoisehg', 'settings')
+ newdir = os.path.join(os.environ.get('APPDATA'), 'TortoiseHg')
+ if os.path.isdir(olddir):
+ for f in os.listdir(olddir):
+ src = os.path.join(olddir, f)
+ dst = os.path.join(newdir, f)
+ os.rename(src, dst)
+ os.removedirs(olddir)
+
+ # import old settings data file (TortoiseHg <= 0.3)
+ oldpath = os.path.join(home, '.hgext', 'tortoisehg')
+ if os.path.isfile(oldpath):
+ olddb = shelve.open(oldpath)
for key in olddb.keys():
self._write(key, olddb[key])
olddb.close()
+ os.unlink(oldpath)
+ os.removedirs(os.path.dirname(oldpath))
def get_system_times():
t = os.times()
|
@@ -643,10 +643,11 @@ row[DM_DISPLAYED] = row[DM_MARKUP]
def _update_diff_header(self, dmodel, wfile, selected):
- hc = self._filechunks[wfile][0]
+ fc = self._filechunks[wfile]
+ hc = fc[0]
+ lasthunk = len(fc)-1
row = dmodel[hc]
- displayed = row[DM_DISPLAYED]
- sel = lambda x: not dmodel[hc+x+1][DM_REJECTED]
+ sel = lambda x: x >= lasthunk or not dmodel[hc+x+1][DM_REJECTED]
newtext = self._shelve_chunks[row[DM_CHUNK_ID]].selpretty(sel)
if not selected:
newtext = "<span foreground='#888888'>" + newtext + "</span>"
|
@@ -130,13 +130,13 @@ defpushrow = i
if repos:
- self._pathtext.set_text(repos[0])
+ self._pathtext.set_text(toutf(repos[0]))
elif defpushrow is not None and pushmode:
self._pathbox.set_active(defpushrow)
elif defrow is not None:
self._pathbox.set_active(defrow)
else:
- if len(self.pathlist) > 1 and not self.pathlist[3]:
+ if len(self.pathlist) > 1 and not self.pathlist[0][3]:
self._pathbox.set_active(0)
# support dropping of repos or bundle files
@@ -222,7 +222,7 @@ sympaths = []
for name, path in self.paths:
sympaths.append(path)
- self.pathlist.append([path, name, False])
+ self.pathlist.append([toutf(path), name, False])
separator = False
for p in self._recent_src:
if p in sympaths:
@@ -230,7 +230,7 @@ if not separator:
self.pathlist.append(['-'*20, '', True])
separator = True
- self.pathlist.append([p, '', False])
+ self.pathlist.append([toutf(p), '', False])
def _drag_receive(self, widget, context, x, y, selection, targetType, time):
if time != self._last_drop_time:
@@ -243,9 +243,9 @@ return
path = urllib.unquote(uri[7:])
if rootpath(path) == path:
- self._pathtext.set_text(path)
+ self._pathtext.set_text(toutf(path))
elif not os.path.isdir(path) and path.endswith('.hg'):
- self._pathtext.set_text(path)
+ self._pathtext.set_text(toutf(path))
def update_buttons(self, *args):
self.buttonhbox.hide()
@@ -359,6 +359,10 @@ filefilter.set_name("Bundle (*.hg)")
filefilter.add_pattern("*.hg")
dialog.add_filter(filefilter)
+ filefilter = gtk.FileFilter()
+ filefilter.set_name("Bundle (*)")
+ filefilter.add_pattern("*")
+ dialog.add_filter(filefilter)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self._pathtext.set_text(dialog.get_filename())
@@ -433,7 +437,7 @@ self._exec_cmd(cmd)
def _conf_clicked(self, toolbutton, data=None):
- newpath = self._pathtext.get_text().strip()
+ newpath = fromutf(self._pathtext.get_text()).strip()
for name, path in self.paths:
if path == newpath:
newpath = None
@@ -451,7 +455,7 @@ self.fill_path_combo()
def _email_clicked(self, toolbutton, data=None):
- path = self._pathtext.get_text().strip()
+ path = fromutf(self._pathtext.get_text()).strip()
if not path:
info_dialog(self, 'No repository selected',
'Select a peer repository to compare with')
@@ -500,7 +504,7 @@ proxy_host = ui.ui().config('http_proxy', 'host', '')
use_proxy = self._use_proxy.get_active()
text_entry = self._pathbox.get_child()
- remote_path = fromutf(text_entry.get_text().strip())
+ remote_path = fromutf(text_entry.get_text()).strip()
cmdline = cmd[:]
cmdline += ['--verbose', '--repository', self.root]
|
|
|
@@ -1,7 +1,7 @@ #_
# Configuration dialog for TortoiseHg and Mercurial
#
-# Copyright (C) 2008 Steve Borho <steve@borho.org>
+# Copyright (C) 2008-9 Steve Borho <steve@borho.org>
# Copyright (C) 2007 TK Soh <teekaysoh@gmail.com>
#
@@ -11,7 +11,7 @@import pango
from mercurial import hg, ui, cmdutil, util
from dialog import error_dialog, question_dialog
-from hglib import RepoError
+from hglib import RepoError, toutf, fromutf
import shlib
import shelve
import iniparse
@@ -35,6 +35,9 @@ ('Tab Width', 'tortoisehg.tabwidth', [],
'Specify the number of spaces to expand tabs.'
' Default: Not expanded'),
+ ('Bottom Diffs', 'gtools.diffbottom', ['False', 'True'],
+ 'Show the diff panel below the file list in status, shelve, and'
+ ' commit dialogs. Default: False'),
('Overlay Icons', 'tortoisehg.overlayicons',
['False', 'True', 'localdisks'],
'Display overlay icons in Explorer windows.'
@@ -45,10 +48,7 @@ 'Name associated with commits'),
('External Commit Tool', 'tortoisehg.extcommit', ['None', 'qct'],
'Select commit tool launched by TortoiseHg. Qct must must be'
- ' installed separately. Default: None'),
- ('Bottom Diffs', 'gtools.diffbottom', ['False', 'True'],
- 'Move diff panel below file list in status and'
- ' commit dialogs. Default: False'))
+ ' installed separately. Default: None'))
_log_info = (
('Author Coloring', 'tortoisehg.authorcolor', ['False', 'True'],
@@ -216,11 +216,21 @@ # 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)
+ self.vbox.pack_start(notebook, False, False)
notebook.show()
self.show_tabs = True
self.show_border = True
+ descframe = gtk.Frame('Description')
+ vbox = gtk.VBox()
+ self.desctext = gtk.TextView()
+ self.desctext.set_wrap_mode(gtk.WRAP_WORD)
+ self.desctext.set_editable(False)
+ vbox.pack_start(self.desctext, False, False)
+ vbox.set_border_width(10)
+ descframe.add(vbox)
+ self.vbox.pack_start(descframe, True, True)
+
self._btn_apply = gtk.Button("Apply")
self._btn_apply.connect('clicked', self._apply_clicked)
self.action_area.pack_end(self._btn_apply)
@@ -252,8 +262,8 @@ if name in ('default', 'default-push'): continue
path = self.ini['paths'][name]
i = self.pathdata.insert_before(None, None)
- self.pathdata.set_value(i, 0, "%s" % name)
- self.pathdata.set_value(i, 1, "%s" % path)
+ self.pathdata.set_value(i, 0, "%s" % toutf(name))
+ self.pathdata.set_value(i, 1, "%s" % toutf(path))
# Define view model for 'Paths' tab
self.pathtree = gtk.TreeView()
@@ -263,15 +273,13 @@ renderer = gtk.CellRendererText()
renderer.set_property('editable', True)
renderer.connect('edited', self.on_alias_edit)
- column = gtk.TreeViewColumn('Alias',
- renderer, text=0)
+ column = gtk.TreeViewColumn('Alias', renderer, text=0)
self.pathtree.append_column(column)
renderer = gtk.CellRendererText()
renderer.set_property('editable', True)
renderer.connect('edited', self.on_path_edit)
- column = gtk.TreeViewColumn('Repository Path',
- renderer, text=1)
+ column = gtk.TreeViewColumn('Repository Path', renderer, text=1)
self.pathtree.append_column(column)
scrolledwindow = gtk.ScrolledWindow()
@@ -349,7 +357,7 @@ '''Add a new path to [paths], give default name, focus'''
i = self.pathdata.insert_before(None, None)
self.pathdata.set_value(i, 0, 'new')
- self.pathdata.set_value(i, 1, '%s' % newpath)
+ self.pathdata.set_value(i, 1, '%s' % toutf(newpath))
self.pathtree.get_selection().select_iter(i)
self.pathtree.set_cursor(
self.pathdata.get_path(i),
@@ -391,7 +399,7 @@ 'Path testing cannot work without a repository')
return
model, path = selection.get_selected()
- testpath = model[path][1]
+ testpath = fromutf(model[path][1])
if not testpath:
return
if testpath[0] == '~':
@@ -414,6 +422,9 @@ self._delpathbutton.set_sensitive(path_selected)
self._testpathbutton.set_sensitive(repo_available and path_selected)
+ def set_help(self, widget, event, tooltip):
+ self.desctext.get_buffer().set_text(tooltip)
+
def fill_frame(self, frame, info):
widgets = []
table = gtk.Table(len(info), 2, False)
@@ -425,6 +436,7 @@ vlist = gtk.ListStore(str, bool)
combo = gtk.ComboBoxEntry(vlist, 0)
combo.connect("changed", self.dirty_event)
+ combo.child.connect("focus-in-event", self.set_help, tooltip)
combo.set_row_separator_func(lambda model, path: model[path][1])
widgets.append(combo)
@@ -476,7 +488,7 @@ if values:
vlist.append(['Suggested', True])
for v in values:
- vlist.append([v, False])
+ vlist.append([toutf(v), False])
if v == curvalue:
currow = len(vlist) - 1
if cpath in self.history.get_keys():
@@ -486,14 +498,14 @@ if not separator:
vlist.append(['History', True])
separator = True
- vlist.append([v, False])
+ vlist.append([toutf(v), False])
if v == curvalue:
currow = len(vlist) - 1
if curvalue is None:
combo.set_active(0)
elif currow is None:
- combo.child.set_text(curvalue)
+ combo.child.set_text(toutf(curvalue))
else:
combo.set_active(currow)
@@ -555,8 +567,8 @@ if len(self.pathdata):
refreshlist = []
for row in self.pathdata:
- name = row[0]
- path = row[1]
+ name = fromutf(row[0])
+ path = fromutf(row[1])
cpath = '.'.join(['paths', name])
self.record_new_value(cpath, path, False)
refreshlist.append(name)
@@ -573,7 +585,7 @@ # Flush changes on all pages
for vbox, info, widgets in self.pages:
for w, (label, cpath, values, tip) in enumerate(info):
- newvalue = widgets[w].child.get_text()
+ newvalue = fromutf(widgets[w].child.get_text())
self.record_new_value(cpath, newvalue)
self.history.write()
|
@@ -18,7 +18,7 @@
class UpdateDialog(gtk.Window):
""" Dialog to update Mercurial repo """
- def __init__(self, cwd='', rev=''):
+ def __init__(self, cwd='', rev=None):
""" Initialize the Dialog """
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
set_tortoise_icon(self, 'menucheckout.ico')
@@ -141,7 +141,7 @@ if node == tip:
status += ", tip"
self._revlist.append([short(node), "(%s)" %status])
- if self.rev:
+ if self.rev is not None:
self._revbox.get_child().set_text(str(self.rev))
else:
self._revbox.set_active(0)
@@ -182,7 +182,7 @@ self._refresh()
shell_notify([self.cwd])
-def run(cwd='', rev='', **opts):
+def run(cwd='', rev=None, **opts):
dialog = UpdateDialog(cwd, rev)
dialog.connect('destroy', gtk.main_quit)
dialog.show_all()
|
@@ -81,6 +81,10 @@ return True if a network drive is accessible (connected, ...),
or None if <drive> is not a network drive
"""
+ if hasattr(os.path, 'splitunc'):
+ unc, rest = os.path.splitunc(drive)
+ if unc: # All UNC paths (\\host\mount) are considered nonlocal
+ return True
letter = os.path.splitdrive(drive)[0]
_drives, total, _ = win32net.NetUseEnum(None, 1, 0)
for drv in _drives:
|
Loading...