by
Changes to 75 files · Browse files at 3860b6414a48 Showing diff from parent 7c9a7be0c881 150c1ecb3d0f Diff from another changeset...
|
@@ -0,0 +1,25 @@ + ** Please do not run setup.py **
+
+On Linux, the suggested methods for using TortoiseHg are to either
+install a package built for your distribution, or run directly out of a
+cloned repository. For details, see:
+
+http://bitbucket.org/tortoisehg/stable/wiki/download
+
+http://bitbucket.org/tortoisehg/stable/wiki/hgtk
+
+http://bitbucket.org/tortoisehg/stable/wiki/nautilus
+
+
+On Windows, we prefer you use the more recent stable release, which
+can always be found at http://tortoisehg.org
+
+
+If you ran setup.py and are now having troubles with icons, you have two
+choices:
+
+1) Find the tortoisehg/util/config.py file that was installed and
+manually edit it to fixup the paths.
+
+2) Delete the installation and use one of the preferred install methods.
+
|
@@ -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
|
@@ -25,7 +25,7 @@ import subprocess
import urllib
-from mercurial import hg, ui, match, util
+from mercurial import hg, ui, match, util, error
from mercurial.node import short
def _thg_path():
@@ -40,7 +40,7 @@ sys.path.insert(0, thgpath)
_thg_path()
-from tortoisehg.util import paths, debugthg, hglib, cachethg
+from tortoisehg.util import paths, debugthg, cachethg
from tortoisehg.hgtk import gtklib
if debugthg.debug('N'):
@@ -107,7 +107,7 @@ return None
try:
return hg.repository(ui.ui(), path=p)
- except hglib.RepoError:
+ except error.RepoError:
return None
except StandardError, e:
debugf(e)
|
Change 1 of 9
Show Entire File
contrib/win32/hgtk.iss
Stacked
copied from contrib/win32/mercurial.iss
|
||
---|---|---|
|
@@ -6,24 +6,24 @@ #endif
[Setup]
-AppCopyright=Copyright 2005-2009 Matt Mackall and others
-AppName=TortoiseHg
-AppVerName=TortoiseHg {#VERSION}
+AppCopyright=Copyright 2005-2009 Steve Borho and others
+AppName=hgtk
+AppVerName=hgtk {#VERSION}
InfoAfterFile=contrib/win32/postinstall.txt
LicenseFile=COPYING.txt
ShowLanguageDialog=yes
-AppPublisher=Steve Borho and others
+AppPublisher=Steve Borho
AppPublisherURL=http://tortoisehg.org/
AppSupportURL=http://tortoisehg.org/
AppUpdatesURL=http://tortoisehg.org/
AppID=TortoiseHg
AppContact=Steve Borho <steve@borho.org>
-OutputBaseFilename=TortoiseHg-{#VERSION}
+OutputBaseFilename=Hgtk-{#VERSION}
DefaultDirName={pf}\TortoiseHg
SourceDir=..\..
-VersionInfoDescription=Mercurial distributed SCM
-VersionInfoCopyright=Copyright 2005-2009 Matt Mackall and others
-VersionInfoCompany=Matt Mackall and others
+VersionInfoDescription=TortoiseHg Dialogs for Mercurial SCM
+VersionInfoCopyright=Copyright 2005-2009 Steve Borho and others
+VersionInfoCompany=Steve Borho and others
InternalCompressLevel=max
SolidCompression=true
SetupIconFile=icons\thg_logo.ico
@@ -34,10 +34,7 @@WizardSmallImageFile=..\misc\install-wizard-small.bmp
AllowNoIcons=true
DefaultGroupName=TortoiseHg
-PrivilegesRequired=poweruser
-AlwaysRestart=no
SetupLogging=yes
-ArchitecturesInstallIn64BitMode=x64
[Types]
Name: full; Description: Full installation
@@ -47,17 +44,11 @@Name: main; Description: Main Files (includes 'hg' and 'hgtk' commands); Types: full custom; Flags: fixed
Name: help; Description: Help Files; Types: full
Name: hgbook; Description: The book 'Mercurial: The Definitive Guide' (PDF); Types: full
-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\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\locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs
-Source: ..\build-hg\help\*.*; DestDir: {app}\help
+Source: ..\build-hg\mercurial\help\*.txt; DestDir: {app}\help
+Source: ..\build-hg\mercurial\templates\*.*; DestDir: {app}\templates; Flags: recursesubdirs createallsubdirs
+Source: ..\build-hg\mercurial\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
Source: ..\build-hg\doc\style.css; DestDir: {app}\docs; Flags: ignoreversion; Components: help
@@ -67,10 +58,6 @@Source: ReleaseNotes.txt; DestDir: {app}; DestName: ReleaseNotes.txt
Source: ..\contrib\*.exe; DestDir: {app}
Source: ..\contrib\*.dll; DestDir: {app}
-Source: ..\contrib\TortoiseOverlays\*.*; DestDir: {app}/TortoiseOverlays
-Source: contrib\refreshicons.cmd; DestDir: {app}/contrib
-Source: dist\*.exe; Excludes: thgtaskbar.exe; DestDir: {app}; Flags: ignoreversion
-Source: dist\thgtaskbar.exe; DestDir: {app}; Flags: ignoreversion; Components: shell
Source: dist\*.dll; DestDir: {app}; Flags: ignoreversion
Source: dist\library.zip; DestDir: {app}
Source: doc\build\pdf\*.pdf; DestDir: {app}/docs; Flags: ignoreversion; Components: help
@@ -79,20 +66,15 @@Source: dist\gtk\*; DestDir: {app}\gtk; Flags: ignoreversion recursesubdirs createallsubdirs
Source: locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs
Source: i18n\*.*; DestDir: {app}\i18n; Flags: recursesubdirs createallsubdirs
-Source: win32\*.reg; DestDir: {app}\cmenu_i18n
Source: COPYING.txt; DestDir: {app}; DestName: Copying.txt
Source: icons\thg_logo.ico; DestDir: {app}
Source: ..\misc\hgbook.pdf; DestDir: {app}/docs; Flags: ignoreversion; Components: hgbook
-Source: ..\misc\ThgShellx86.dll; DestDir: {app}; DestName: ThgShell.dll; Check: not Is64BitInstallMode; Flags: ignoreversion restartreplace uninsrestartdelete; Components: shell
-Source: ..\misc\ThgShellx86.dll; DestDir: {app}; DestName: ThgShellx86.dll; Check: Is64BitInstallMode; Flags: ignoreversion restartreplace uninsrestartdelete; Components: shell
-Source: ..\misc\ThgShellx64.dll; DestDir: {app}; DestName: ThgShell.dll; Check: Is64BitInstallMode; Flags: ignoreversion restartreplace uninsrestartdelete; Components: shell
[INI]
Filename: {app}\Mercurial.url; Section: InternetShortcut; Key: URL; String: http://mercurial.selenic.com/
Filename: {app}\TortoiseHg.url; Section: InternetShortcut; Key: URL; String: http://tortoisehg.org/
[Icons]
-Name: {group}\Start Taskbar App; Filename: {app}\thgtaskbar.exe; Components: shell
Name: {group}\TortoiseHg Book (chm); Filename: {app}\docs\TortoiseHg.chm; Components: help
Name: {group}\TortoiseHg Book (pdf); Filename: {app}\docs\TortoiseHg.pdf; Components: help
Name: {group}\TortoiseHg Web Site; Filename: {app}\TortoiseHg.url
@@ -104,8 +86,6 @@
[Run]
Filename: {app}\add_path.exe; Parameters: {app}; StatusMsg: Adding the installation path to the search path...
-Filename: msiexec.exe; Parameters: "/i ""{app}\TortoiseOverlays\TortoiseOverlays-1.0.6.16523-win32.msi"" /qn /norestart ALLUSERS=1"; Components: shell; StatusMsg: Installing TortoiseOverlays.dll ...
-Filename: msiexec.exe; Parameters: "/i ""{app}\TortoiseOverlays\TortoiseOverlays-1.0.6.16523-x64.msi"" /qn /norestart ALLUSERS=1"; Check: Is64BitInstallMode; Components: shell; StatusMsg: Installing TortoiseOverlays.dll ...
[UninstallRun]
Filename: {app}\add_path.exe; Parameters: /del {app}
@@ -119,8 +99,9 @@Root: HKLM; Subkey: Software\Mercurial; Flags: uninsdeletekey; ValueData: {app}\Mercurial.ini
[Code]
-const
- wm_Close = $0010;
+
+var UserInfoPage: TInputQueryWizardPage;
+var GetUserName: Boolean;
procedure FileExpandString(fn: String);
var
@@ -135,38 +116,6 @@ SaveStringsToFile(InFile, InFileLines, False);
end;
-var IsUpgrade: Boolean;
-
-function InitializeSetup(): Boolean;
-var
- ThgSwReg: String;
- msg: String;
- CRLF: String;
-begin
- CRLF := Chr(10) + Chr(13);
- Result := True;
-
- {abort installation if TortoiseHg 0.7 or earlier is installed}
- if RegQueryStringValue(HKLM, 'Software\TortoiseHg', '', ThgSwReg) then
- begin
- IsUpgrade := True;
- {hgproc was removed after 0.7, so it's a good guess}
- if (FileExists(ThgSwReg + '\hgproc.exe')) then
- begin
- msg := 'TortoiseHg Setup Error:' + CRLF + CRLF +
- 'The version of TortoiseHg installed is too old to upgrade in place.' + CRLF +
- 'You must uninstall it before installing this version.' + CRLF + CRLF +
- 'Please uninstall the existing versions of TortoiseHg and TortoiseOverlays,' + CRLF +
- 'then run the installer again to continue.';
- MsgBox(msg, mbError, MB_OK);
- Result := False; {quit and abort installation}
- end;
- end;
-end;
-
-var UserInfoPage: TInputQueryWizardPage;
-var GetUserName: Boolean;
-
procedure InitializeWizard();
begin
if (not(FileExists(ExpandConstant('{%USERPROFILE}\Mercurial.ini')))) then
@@ -207,60 +156,3 @@ SaveStringsToFile(InFile, InFileLines, False);
end;
end;
-
-function ShouldSkipPage(PageID: Integer): Boolean;
-begin
- { Skip wpSelectDir page if upgrading; show all others }
- case PageID of
- wpSelectDir:
- Result := IsUpgrade;
- else
- Result := False;
- end;
-end;
-
-function TerminateThgTaskbar(): Boolean;
-var
- TaskbarWindow: HWND;
- TaskbarMutex: String;
- tries: Integer;
-begin
- { Terminate thgtaskbar.exe if it is running. Returns True, if successful }
- TaskbarMutex := 'thgtaskbar,Global\thgtaskbar';
- tries := 0;
- while (tries < 4) and CheckForMutexes(TaskbarMutex) do begin
- TaskbarWindow := FindWindowByWindowName('TortoiseHg RPC server');
- if TaskbarWindow <> 0 then
- SendMessage(TaskbarWindow, wm_Close, 0, 0);
- Sleep(3000 { ms });
- tries := tries + 1;
- end;
- Result := not CheckForMutexes(TaskbarMutex);
-end;
-
-function PrepareToInstall: String;
-begin
- if TerminateThgTaskbar() then
- Result := ''
- else
- Result := 'The installer failed to shut down thgtaskbar.exe, and will now close.';
-end;
-
-procedure CurUninstallStepChanged(step: TUninstallStep);
-begin
- if step = usAppMutexCheck then
- TerminateThgTaskbar();
-end;
-
-function ShellInstallPossible(): Boolean;
-begin
- if not IsAdminLoggedOn then begin
- SuppressibleMsgBox(
- 'The shell integration install option (overlay icons, context menu) is unavailable (Administrator required)',
- mbInformation, MB_OK, 0
- );
- Result := False;
- end else Result := True;
-end;
-
-#include "registry.iss"
|
@@ -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,9 @@;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"
-
-[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
|
Change 1 of 2
Show Entire File
contrib/win32/tortoisehg.iss
Stacked
renamed from contrib/win32/mercurial.iss
|
||
---|---|---|
@@ -50,14 +50,9 @@ 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\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\locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs
-Source: ..\build-hg\help\*.*; DestDir: {app}\help
+Source: ..\build-hg\mercurial\help\*.txt; DestDir: {app}\help
+Source: ..\build-hg\mercurial\templates\*.*; DestDir: {app}\templates; Flags: recursesubdirs createallsubdirs
+Source: ..\build-hg\mercurial\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
Source: ..\build-hg\doc\style.css; DestDir: {app}\docs; Flags: ignoreversion; Components: help
@@ -229,6 +224,9 @@ TaskbarMutex := 'thgtaskbar,Global\thgtaskbar';
tries := 0;
while (tries < 4) and CheckForMutexes(TaskbarMutex) do begin
+ TaskbarWindow := FindWindowByWindowName('TortoiseHg Overlay Icon Server');
+ if TaskbarWindow <> 0 then
+ SendMessage(TaskbarWindow, wm_Close, 0, 0);
TaskbarWindow := FindWindowByWindowName('TortoiseHg RPC server');
if TaskbarWindow <> 0 then
SendMessage(TaskbarWindow, wm_Close, 0, 0);
|
@@ -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.
|
@@ -83,12 +83,12 @@ `download <http://bitbucket.org/tortoisehg/stable/wiki/download/>`_
page of the wiki.
-Deb packages for Ubuntu can be found at
-`that <https://launchpad.net/~tortoisehg-ppa>`_.
+Packages for Ubuntu can be found at the TortoiseHg
+`PPA <https://launchpad.net/~tortoisehg-ppa>`_ web site.
-For MacOSX, no packages are available but you can run hgtk and all the
+For Mac OS X, no packages are available but you can run hgtk and all the
dialogs via the source install method. For details, see
-`MacOSX <http://bitbucket.org/tortoisehg/stable/wiki/MacOSX>`_.
+`Mac OS X <http://bitbucket.org/tortoisehg/stable/wiki/MacOSX>`_.
Language settings
^^^^^^^^^^^^^^^^^
|
|
|
|
|
@@ -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,
|
|
|
@@ -1,5 +1,6 @@ # Creates a task-bar icon. Run from Python.exe to see the
-# messages printed.
+# messages printed. Takes an optional logfile as first command
+# line parameter
import gc
import os
@@ -28,16 +29,12 @@from tortoisehg.util import thread2, paths, shlib
if hasattr(sys, "frozen"):
- # Insert PATH to binary installer gtk directory
- gtkpath = os.path.join(paths.bin_path, 'gtk')
- os.environ['PATH'] = os.pathsep.join([gtkpath, os.environ['PATH']])
# Give stdout/stderr closed attributes to prevent ui.py errors
sys.stdout.closed = True
sys.stderr.closed = True
-APP_TITLE = _('TortoiseHg RPC server')
+APP_TITLE = _('TortoiseHg Overlay Icon Server')
-SHOWLOG_CMD = 1023
EXIT_CMD = 1025
def SetIcon(hwnd, name, add=False):
@@ -93,11 +90,12 @@ 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \
0, 0, hinst, None)
UpdateWindow(self.hwnd)
- self.guithread = None
self._DoCreateIcons()
def _DoCreateIcons(self):
- SetIcon(self.hwnd, "hg.ico", add=True)
+ show, highlight = get_config()
+ if show:
+ SetIcon(self.hwnd, "hg.ico", add=True)
# start namepipe server for hg status
self.start_pipe_server()
@@ -115,8 +113,7 @@ def OnTaskbarNotify(self, hwnd, msg, wparam, lparam):
if lparam==win32con.WM_RBUTTONUP or lparam==win32con.WM_LBUTTONUP:
menu = CreatePopupMenu()
- AppendMenu(menu, win32con.MF_STRING, SHOWLOG_CMD, _('Options...'))
- AppendMenu(menu, win32con.MF_SEPARATOR, 0, '')
+ # AppendMenu(menu, win32con.MF_SEPARATOR, 0, '')
AppendMenu(menu, win32con.MF_STRING, EXIT_CMD, _('Exit'))
pos = GetCursorPos()
# See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/menus_0hdi.asp
@@ -130,12 +127,7 @@
def OnCommand(self, hwnd, msg, wparam, lparam):
id = LOWORD(wparam)
- if id == SHOWLOG_CMD:
- if not self.guithread or not self.guithread.isAlive():
- self.launchgui()
- else:
- print "TortoiseHG options dialog already running"
- elif id == EXIT_CMD:
+ if id == EXIT_CMD:
self.exit_application()
else:
print "Unknown command -", id
@@ -143,11 +135,8 @@ def exit_application(self):
if self.stop_pipe_server():
DestroyWindow(self.hwnd)
- if self.guithread and self.guithread.isAlive():
- import gobject
- gobject.idle_add(self.dialog.destroy)
print "Goodbye"
-
+
def stop_pipe_server(self):
print "Stopping pipe server..."
if not self.pipethread.isAlive():
@@ -173,25 +162,6 @@ else:
return True
- def launchgui(self):
- def launch():
- import gtk
- # Import hgtk for signal setup side-effects
- from tortoisehg.hgtk import hgtk
- from tortoisehg.hgtk import taskbarui
- dlg = taskbarui.TaskBarUI(logger.getqueue(), requests)
- dlg.show_all()
- dlg.connect('destroy', gtk.main_quit)
- self.dialog = dlg
- gtk.gdk.threads_init()
- gtk.gdk.threads_enter()
- gtk.main()
- gtk.gdk.threads_leave()
- logger.reset()
-
- self.guithread = thread2.Thread(target=launch)
- self.guithread.start()
-
def start_pipe_server(self):
def servepipe():
self.svc = PipeServer(self.hwnd)
@@ -208,19 +178,19 @@
class Logger():
def __init__(self):
- self.q = None
+ self.file = None
- def getqueue(self):
- self.q = Queue.Queue()
- return self.q
-
- def reset(self):
- self.q = None
+ def setfile(self, name):
+ self.file = open(name, 'wb')
+ self.msg('Logging to file started')
def msg(self, msg):
ts = '[%s] ' % time.strftime('%c')
- if self.q:
- self.q.put(ts + msg)
+ f = self.file
+ if f:
+ f.write(ts + msg + '\n')
+ f.flush()
+ os.fsync(f.fileno())
print 'L' + ts + msg
else:
print ts + msg
@@ -279,16 +249,19 @@requests = Queue.Queue(0)
def get_config():
+ show_taskbaricon = True
hgighlight_taskbaricon = True
try:
from _winreg import HKEY_CURRENT_USER, OpenKey, QueryValueEx
hkey = OpenKey(HKEY_CURRENT_USER, r'Software\TortoiseHg')
t = ('1', 'True')
+ try: show_taskbaricon = QueryValueEx(hkey, 'ShowTaskbarIcon')[0] in t
+ except EnvironmentError: pass
try: hgighlight_taskbaricon = QueryValueEx(hkey, 'HighlightTaskbarIcon')[0] in t
except EnvironmentError: pass
except (ImportError, WindowsError):
pass
- return hgighlight_taskbaricon
+ return (show_taskbaricon, hgighlight_taskbaricon)
def update(args, hwnd):
batch = []
@@ -296,8 +269,8 @@ print "got update request %s (first in batch)" % r
batch.append(r)
print "wait a bit for additional requests..."
- highlight = get_config()
- if highlight:
+ show, highlight = get_config()
+ if show and highlight:
SetIcon(hwnd, "hgB.ico")
time.sleep(0.2)
deferred_requests = []
@@ -318,7 +291,7 @@ msg = "processing batch with %i update requests"
print msg % len(batch)
update_batch(batch)
- if highlight:
+ if show and highlight:
SetIcon(hwnd, "hg.ico")
def remove(args):
@@ -462,6 +435,7 @@RUNMUTEXNAME = 'thgtaskbar-' + GetUserName()
def main():
+ args = sys.argv[1:]
sa = win32security.SECURITY_ATTRIBUTES()
sa.SetSecurityDescriptorDacl(1, None, 0) # allow full access
runmutex = win32event.CreateMutex(sa, 1, RUNMUTEXNAME)
@@ -471,6 +445,16 @@ # see http://www.jrsoftware.org/iskb.php?mutexsessions
installmutex1 = win32event.CreateMutex(sa, 1, INSTALLMUTEXNAME)
installmutex2 = win32event.CreateMutex(sa, 1, 'Global\\' + INSTALLMUTEXNAME)
+
+ logfilename = None
+ for arg in args:
+ if arg[0] == '-':
+ pass
+ else:
+ logfilename = arg
+ if logfilename:
+ logger.setfile(logfilename)
+
w=MainWindow()
PumpMessages()
|
@@ -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)
@@ -65,7 +42,7 @@ self.set_name("TortoiseHg")
self.set_version(_("(version %s)") % version.version())
if hasattr(self, 'set_wrap_license'):
- self.set_wrap_license(True)
+ self.set_wrap_license(False)
self.set_copyright(_("Copyright 2009 Steve Borho and others"))
thg_logo = paths.get_tortoise_icon('thg_logo_92x50.png')
@@ -83,8 +60,10 @@ self.set_license('\n'.join(license))
self.set_comments(_("with %s") % lib_versions + "\n\n" + comment)
- self.set_logo(gtk.gdk.pixbuf_new_from_file(thg_logo))
- self.set_icon_from_file(thg_icon)
+ if thg_logo:
+ self.set_logo(gtk.gdk.pixbuf_new_from_file(thg_logo))
+ if thg_icon:
+ self.set_icon_from_file(thg_icon)
self.connect('response', self.response)
def response(self, widget, respid):
|
@@ -10,7 +10,7 @@ import gobject
import pango
-from mercurial import hg, ui
+from mercurial import hg, ui, error
from tortoisehg.util.i18n import _
from tortoisehg.util import hglib, paths
@@ -39,7 +39,7 @@
try:
repo = hg.repository(ui.ui(), path=paths.find_root())
- except hglib.RepoError:
+ except error.RepoError:
gtklib.idle_add_single_call(self.destroy)
return
self.repo = repo
@@ -176,7 +176,7 @@ else:
try:
self.repo[text]
- except (hglib.RepoError, hglib.LookupError):
+ except (error.RepoError, error.LookupError):
return
if path is None:
path = self.destentry.get_text()
|
@@ -10,7 +10,7 @@ import gobject
import pango
-from mercurial import hg, ui
+from mercurial import hg, ui, error
from tortoisehg.util.i18n import _
from tortoisehg.util import hglib, paths, i18n, settings
@@ -43,7 +43,7 @@
try:
repo = hg.repository(ui.ui(), path=paths.find_root())
- except hglib.RepoError:
+ except error.RepoError:
gtklib.idle_add_single_call(self.destroy)
return
|
|
|
@@ -0,0 +1,385 @@ + # bookmark.py - TortoiseHg dialog to add/remove/rename bookmarks
+#
+# 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 gtk
+import traceback
+
+from mercurial import ui, util
+from hgext import bookmarks
+
+from tortoisehg.util.i18n import _
+from tortoisehg.util import hglib, i18n, settings
+
+from tortoisehg.hgtk import dialog, gtklib
+
+TYPE_ADDREMOVE = 1
+TYPE_RENAME = 2
+TYPE_CURRENT = 3
+
+RESPONSE_ADD = 1
+RESPONSE_REMOVE = 2
+RESPONSE_RENAME = 3
+RESPONSE_CURRENT = 4
+RESPONSE_MOVE = 5
+
+class BookmarkDialog(gtk.Dialog):
+ """ Dialog to add bookmark to Mercurial repo """
+ def __init__(self, repo, type, bookmark='', rev=''):
+ """ Initialize the Dialog """
+ gtk.Dialog.__init__(self)
+ gtklib.set_tortoise_keys(self)
+ self.set_title(_('Bookmark - %s') % hglib.get_reponame(repo))
+ self.set_resizable(False)
+ self.set_has_separator(False)
+
+ self.repo = repo
+
+ # persistent settings
+ self.settings = settings.Settings('bookmark')
+
+ # add buttons
+ if type == TYPE_ADDREMOVE:
+ self._button_add = self.add_button(_('Add'), RESPONSE_ADD)
+ self._button_move = self.add_button(_('Move'), RESPONSE_MOVE)
+ self.add_button(_('Remove'), RESPONSE_REMOVE)
+ elif type == TYPE_RENAME:
+ self.add_button(_('Rename'), RESPONSE_RENAME)
+ elif type == TYPE_CURRENT:
+ self.add_button(_('Set Current'), RESPONSE_CURRENT)
+ else:
+ raise _('unexpected type: %s') % type
+ self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
+
+ # 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.set_text(bookmark)
+ if type == TYPE_RENAME:
+ label = _('Old name:')
+ else:
+ label = _('Bookmark:')
+ table.add_row(label, self._bookmarklistbox, padding=False)
+
+ ## add entry
+ if type == TYPE_CURRENT:
+ entry = None
+ else:
+ entry = gtk.Entry()
+ if type == TYPE_ADDREMOVE:
+ self._rev_input = entry
+ entry.set_width_chars(12)
+ entry.set_text(rev)
+ label = _('Revision:')
+ elif type == TYPE_RENAME:
+ self._name_input = entry
+ label = _('New Name:')
+ table.add_row(label, entry, padding=False)
+
+ # Option to make new bookmark the active one
+ trackcurrent = self.repo.ui.configbool('bookmarks', 'track.current')
+ if type == TYPE_ADDREMOVE and trackcurrent:
+ check = gtk.CheckButton(_('Make new/moved bookmark current'))
+ self.opt_newcurrent = check
+ check.set_sensitive(hglib.is_rev_current(self.repo, rev))
+ table.add_row(None, check)
+
+ # signal handlers
+ self.connect('response', self.dialog_response)
+ self._bookmark_input.connect('activate', self.entry_activated, type)
+ if entry:
+ entry.connect('activate', self.entry_activated, type)
+ if type == TYPE_ADDREMOVE:
+ self._bookmark_input.connect('changed', self.bookmark_changed)
+ if trackcurrent:
+ self._rev_input.connect('changed', self.rev_changed)
+
+ # prepare to show
+ self.load_settings()
+ if type == TYPE_ADDREMOVE:
+ self.set_add_move_button_sensitivity()
+ self._refresh(clear=False)
+ if type == TYPE_RENAME:
+ self._name_input.grab_focus()
+ else:
+ self._bookmarklistbox.grab_focus()
+
+ def _refresh(self, clear=True):
+ """ update display on dialog with recent repo data """
+ self.repo.invalidate()
+ self._bookmarkslist.clear()
+
+ # 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])
+
+ # clear bookmark name input
+ if clear:
+ self._bookmark_input.set_text('')
+
+ def load_settings(self):
+ if hasattr(self, 'opt_newcurrent'):
+ newcurrent = self.settings.get_value('newcurrent', False)
+ self.opt_newcurrent.set_active(newcurrent)
+
+ def store_settings(self):
+ if hasattr(self, 'opt_newcurrent'):
+ newcurrent = self.opt_newcurrent.get_active()
+ self.settings.set_value('newcurrent', newcurrent)
+
+ self.settings.write()
+
+ def dialog_response(self, dialog, response_id):
+ # Add button
+ if response_id == RESPONSE_ADD:
+ self._do_add_bookmark()
+ # Move button
+ elif response_id == RESPONSE_MOVE:
+ self._do_move_bookmark()
+ # Remove button
+ elif response_id == RESPONSE_REMOVE:
+ self._do_remove_bookmark()
+ # Rename button
+ elif response_id == RESPONSE_RENAME:
+ self._do_rename_bookmark()
+ # Set Current button
+ elif response_id == RESPONSE_CURRENT:
+ self._do_current_bookmark()
+ # Close button or closed by the user
+ elif response_id in (gtk.RESPONSE_CLOSE, gtk.RESPONSE_DELETE_EVENT):
+ self.store_settings()
+ self.destroy()
+ return # close dialog
+ else:
+ raise _('unexpected response id: %s') % response_id
+
+ self.run() # don't close dialog
+
+ def entry_activated(self, entry, type):
+ if type == TYPE_ADDREMOVE:
+ if self._button_add.get_property('sensitive'):
+ self.response(RESPONSE_ADD)
+ else:
+ self.response(RESPONSE_MOVE)
+ elif type == TYPE_RENAME:
+ self.response(RESPONSE_RENAME)
+ elif type == TYPE_CURRENT:
+ self.response(RESPONSE_CURRENT)
+ else:
+ raise _('unexpected type: %s') % type
+
+ def rev_changed(self, rev_input):
+ rev = rev_input.get_text()
+ self.opt_newcurrent.set_sensitive(hglib.is_rev_current(self.repo, rev))
+
+ def bookmark_changed(self, bookmark_widget):
+ self.set_add_move_button_sensitivity()
+
+ def set_add_move_button_sensitivity(self):
+ mark = self._bookmark_input.get_text()
+ if mark in hglib.get_repo_bookmarks(self.repo):
+ self._button_add.set_sensitive(False)
+ self._button_move.set_sensitive(True)
+ else:
+ self._button_add.set_sensitive(True)
+ self._button_move.set_sensitive(False)
+
+
+ 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)
+ if (hasattr(self, 'opt_newcurrent') and
+ self.opt_newcurrent.get_property('sensitive') and
+ self.opt_newcurrent.get_active()):
+ self._current_hg_bookmark(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_move_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
+
+ # move bookmark
+ try:
+ self._move_hg_bookmark(name, rev)
+ dialog.info_dialog(self, _('Bookmarking completed'),
+ _('Bookmark "%s" has been moved') % name)
+ if (hasattr(self, 'opt_newcurrent') and
+ self.opt_newcurrent.get_property('sensitive') and
+ self.opt_newcurrent.get_active()):
+ self._current_hg_bookmark(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_remove_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._remove_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 _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 _do_current_bookmark(self):
+ # gather input data
+ name = self._bookmark_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
+
+ # set current bookmark
+ try:
+ self._current_hg_bookmark(name)
+ dialog.info_dialog(self, _('Bookmarking completed'),
+ _('Bookmark "%s" has been made current') %
+ 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 _move_hg_bookmark(self, name, revision):
+ if name not in hglib.get_repo_bookmarks(self.repo):
+ raise util.Abort(_('No bookmark named "%s" exists') % name)
+
+ bookmarks.bookmark(ui=ui.ui(),
+ repo=self.repo,
+ rev=revision,
+ mark=name,
+ force=True)
+
+ def _remove_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)
+
+ 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)
+
+ def _current_hg_bookmark(self, name):
+ if name not in hglib.get_repo_bookmarks(self.repo):
+ raise util.Abort(_('no bookmark named "%s" exists') %
+ name)
+ bookmarks.setcurrent(self.repo, name)
|
|
|
@@ -0,0 +1,364 @@ + # browse.py - TortoiseHg's repository browser
+#
+# Copyright 2009 Steve Borho <steve@borho.org>
+#
+# 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 gobject
+import pango
+
+from mercurial import hg, ui, cmdutil
+
+from tortoisehg.util.i18n import _
+from tortoisehg.util import hglib, paths, shlib, menuthg
+
+from tortoisehg.hgtk import hgcmd, gtklib, gdialog
+
+folderxpm = [
+ "17 16 7 1",
+ " c #000000",
+ ". c #808000",
+ "X c yellow",
+ "o c #808080",
+ "O c #c0c0c0",
+ "+ c white",
+ "@ c None",
+ "@@@@@@@@@@@@@@@@@",
+ "@@@@@@@@@@@@@@@@@",
+ "@@+XXXX.@@@@@@@@@",
+ "@+OOOOOO.@@@@@@@@",
+ "@+OXOXOXOXOXOXO. ",
+ "@+XOXOXOXOXOXOX. ",
+ "@+OXOXOXOXOXOXO. ",
+ "@+XOXOXOXOXOXOX. ",
+ "@+OXOXOXOXOXOXO. ",
+ "@+XOXOXOXOXOXOX. ",
+ "@+OXOXOXOXOXOXO. ",
+ "@+XOXOXOXOXOXOX. ",
+ "@+OOOOOOOOOOOOO. ",
+ "@ ",
+ "@@@@@@@@@@@@@@@@@",
+ "@@@@@@@@@@@@@@@@@"
+ ]
+folderpb = gtk.gdk.pixbuf_new_from_xpm_data(folderxpm)
+
+filexpm = [
+ "12 12 3 1",
+ " c #000000",
+ ". c #ffff04",
+ "X c #b2c0dc",
+ "X XXX",
+ "X ...... XXX",
+ "X ...... X",
+ "X . ... X",
+ "X ........ X",
+ "X . .... X",
+ "X ........ X",
+ "X . .. X",
+ "X ........ X",
+ "X . .. X",
+ "X ........ X",
+ "X X"
+ ]
+filepb = gtk.gdk.pixbuf_new_from_xpm_data(filexpm)
+
+class dirnode(object):
+ def __init__(self):
+ self.subdirs = {}
+ self.files = []
+ self.statuses = set()
+ def addfile(self, filename, st):
+ self.files.append((filename, st))
+ self.addstatus(st)
+ def addsubdir(self, dirname):
+ self.subdirs[dirname] = dirnode()
+ def addstatus(self, st):
+ self.statuses.add(st)
+
+class BrowsePane(gtk.TreeView):
+ 'Dialog for browsing repo.status() output'
+ def __init__(self, callback):
+ gtk.TreeView.__init__(self)
+ self.callback = callback
+ self.cachedroot = None
+ self.menu = menuthg.menuThg()
+ fm = gtk.ListStore(str, # canonical path
+ bool, # Checked
+ str, # basename-UTF8
+ bool, # M
+ bool, # A
+ bool, # R
+ bool, # !
+ bool, # ?
+ bool, # I
+ bool, # C
+ bool) # isfile
+ self.set_model(fm)
+
+ self.set_headers_visible(False)
+ self.set_reorderable(True)
+ self.connect('popup-menu', self.popupmenu)
+ self.connect('button-release-event', self.buttonrelease)
+ self.connect('row-activated', self.rowactivated)
+ self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+ self.set_reorderable(False)
+ self.set_enable_search(True)
+ if hasattr(self, 'set_rubber_banding'):
+ self.set_rubber_banding(True)
+
+ col = gtk.TreeViewColumn(_('status'))
+ self.append_column(col)
+
+ iconw, iconh = gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR)
+ def packpixmap(ico, id):
+ iconpath = paths.get_tortoise_icon(ico)
+ if iconpath == None:
+ raise (_("could not open icon file '%s' (check install)") % ico)
+ pm = gtk.gdk.pixbuf_new_from_file_at_size(iconpath, iconw, iconh)
+ cell = gtk.CellRendererPixbuf()
+ cell.set_property('pixbuf', pm)
+ col.pack_start(cell, expand=False)
+ col.add_attribute(cell, 'visible', id)
+
+ #packpixmap('filemodify.ico', 3) # this icon does not load for me
+ packpixmap('menucommit.ico', 3) # M
+ packpixmap('fileadd.ico', 4) # A
+ packpixmap('filedelete.ico', 5) # R
+ packpixmap('detect_rename.ico', 6) # missing
+ packpixmap('menublame.ico', 7) # unknown
+ #packpixmap('ignore.ico', 8) # ignored
+ #packpixmap('hg.ico', 9) # clean
+
+ def cell_seticon(column, cell, model, iter):
+ isfile = model.get_value(iter, 10)
+ pixbuf = isfile and filepb or folderpb
+ cell.set_property('pixbuf', pixbuf)
+
+ col = gtk.TreeViewColumn(_('type'))
+ cell = gtk.CellRendererPixbuf()
+ col.pack_start(cell, expand=False)
+ col.set_cell_data_func(cell, cell_seticon)
+ self.append_column(col)
+
+ col = gtk.TreeViewColumn(_('path'), gtk.CellRendererText(), text=2)
+ self.append_column(col)
+
+ def split(self, filename):
+ 'Split a filename into a list of directories and the basename'
+ dirs = []
+ path, basename = os.path.split(filename)
+ while path:
+ path, piece = os.path.split(path)
+ dirs.append(piece)
+ dirs.reverse()
+ return dirs, basename
+
+ def chdir(self, cwd):
+ 'change to a new directory'
+ # disable updates while we refill the model
+ self.cwd = cwd
+ model = self.get_model()
+ self.set_model(None)
+ model.clear()
+ try:
+ self._chdir(model, cwd)
+ except Exception, e:
+ # report to status bar
+ pass
+ self.set_model(model)
+
+ def _chdir(self, model, cwd):
+ def buildrow(name, stset, isfile):
+ dirs, basename = self.split(name)
+ row = [ name, False, hglib.toutf(basename),
+ 'M' in stset, 'A' in stset, 'R' in stset,
+ '!' in stset, '?' in stset, 'I' in stset,
+ 'C' in stset, isfile ]
+ return row
+
+ def adddir(node):
+ for dname, dirnode in node.subdirs.iteritems():
+ model.append(buildrow(dname, dirnode.statuses, False))
+ for fname, st in node.files:
+ model.append(buildrow(fname, st, True))
+
+ drive, tail = os.path.splitdrive(cwd)
+ if cwd != '/' or (drive and tail):
+ model.append(buildrow('..', '', False))
+
+ root = paths.find_root(cwd)
+ if root and self.cachedroot != root:
+ self.cacherepo(root)
+
+ if root:
+ node = self.cachedmodel
+ relpath = cwd[len(root)+len(os.sep):]
+ dirs, basename = self.split(relpath)
+ for dname in dirs:
+ node = node.subdirs[dname]
+ if basename:
+ node = node.subdirs[basename]
+ adddir(node)
+ self.currepo = self.cachedrepo
+ else:
+ try:
+ for name in os.listdir(cwd):
+ isfile = os.path.isfile(os.path.join(cwd, name))
+ model.append(buildrow(name, '', isfile))
+ except OSError:
+ # report to status bar
+ pass
+ self.currepo = None
+
+
+ def cacherepo(self, root, pats=[], filetypes='CI?'):
+ status = ([],)*7
+ try:
+ repo = hg.repository(ui.ui(), path=root)
+ matcher = cmdutil.match(repo, pats)
+ st = repo.status(match=matcher,
+ clean='C' in filetypes,
+ ignored='I' in filetypes,
+ unknown='?' in filetypes)
+ except IOError:
+ pass
+ filelist = []
+ # concatenate status output into a single list, then sort on filename
+ for l, s in ( (st[0], 'M'), (st[1], 'A'), (st[2], 'R'), (st[3], '!'),
+ (st[4], '?'), (st[5], 'I'), (st[6], 'C') ):
+ for m in l:
+ filelist.append([ m, s ])
+ filelist.sort()
+
+ # Build tree data structure
+ modelroot = dirnode()
+ for name, filestatus in filelist:
+ dirs, basename = self.split(name)
+ curdir = modelroot
+ for dir in dirs:
+ if dir not in curdir.subdirs:
+ curdir.addsubdir(dir)
+ curdir.addstatus(filestatus)
+ curdir = curdir.subdirs[dir]
+ curdir.addfile(name, filestatus)
+
+ self.cachedmodel = modelroot
+ self.cachedroot = root
+ self.cachedrepo = repo
+
+ def popupmenu(self, browse):
+ model, tpaths = browse.get_selection().get_selected_rows()
+ if not tpaths:
+ return
+ cpaths = [model[p][0] for p in tpaths]
+ files = []
+ if self.currepo:
+ repo = self.currepo
+ files = [os.path.join(self.cwd, p) for p in cpaths]
+ menus = self.menu.get_commands(repo, self.cwd, files)
+ else:
+ menus = self.menu.get_norepo_commands(None, cpaths)
+
+ def rundialog(item, hgcmd):
+ print 'rundialog', hgcmd, cpaths
+
+ def create_menu(label, hgcmd=None):
+ menuitem = gtk.MenuItem(label, True)
+ if hgcmd:
+ menuitem.connect('activate', rundialog, hgcmd)
+ menuitem.set_border_width(1)
+ return menuitem
+
+ def create_submenu(label, menu):
+ m = create_menu(label)
+ m.set_submenu(menu)
+ return m
+
+ def buildmenus(menus):
+ m = gtklib.MenuItems()
+ for menu_info in menus:
+ if menu_info.isSep():
+ m.append_sep()
+ elif menu_info.isSubmenu():
+ item = create_submenu(menu_info.menutext,
+ buildmenus(menu_info.get_menus()))
+ m.append(item)
+ elif menu_info.state:
+ # TODO: do something with menu_info.helptext, .icon
+ item = create_menu(menu_info.menutext, menu_info.hgcmd)
+ m.append(item)
+ return m.create_menu()
+
+ menu = buildmenus(menus)
+ menu.show_all()
+ menu.popup(None, None, None, 0, 0)
+
+
+ def buttonrelease(self, browse, event):
+ if event.button != 3:
+ return False
+ self.popupmenu(browse)
+ return True
+
+ def rowactivated(self, browse, path, column):
+ model, tpaths = browse.get_selection().get_selected_rows()
+ if not tpaths:
+ return
+ if len(tpaths) == 1 and not model[tpaths[0]][10]:
+ self.callback(model[tpaths[0]][0])
+ else:
+ files = [model[p][0] for p in tpaths if model[p][10]]
+ print files, 'activated'
+
+class BrowseDialog(gtk.Dialog):
+ 'Wrapper application for BrowsePane'
+ def __init__(self, command, pats):
+ gtk.Dialog.__init__(self)
+ gtklib.set_tortoise_icon(self, 'hg.ico')
+ gtklib.set_tortoise_keys(self)
+ self.set_has_separator(False)
+ self.set_default_size(400, 500)
+ self.connect('response', self.dialog_response)
+
+ entry = gtk.Entry()
+ self.vbox.pack_start(entry, False, True)
+
+ def newfolder_notify(newfolder):
+ curpath = entry.get_text()
+ newpath = os.path.join(curpath, newfolder)
+ newpath = hglib.toutf(os.path.abspath(newpath))
+ root = paths.find_root(newpath)
+ if root:
+ self.set_title(root + ' - ' + _('browser'))
+ else:
+ self.set_title(_('browser'))
+ entry.set_text(newpath)
+ browse.chdir(newpath)
+
+ browse = BrowsePane(newfolder_notify)
+ scroller = gtk.ScrolledWindow()
+ scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scroller.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ scroller.add(browse)
+ self.vbox.pack_start(scroller, True, True)
+ self.show_all()
+
+ cwd = hglib.toutf(os.getcwd())
+ entry.connect('activate', self.entry_activated, browse)
+ entry.set_text(cwd)
+ browse.chdir(cwd)
+
+ def entry_activated(self, entry, browse):
+ browse.chdir(entry.get_text())
+
+ def dialog_response(self, dialog, response):
+ return True
+
+def run(ui, *pats, **opts):
+ pats = hglib.canonpaths(pats)
+ if opts.get('canonpats'):
+ pats = list(pats) + opts['canonpats']
+ return BrowseDialog(opts.get('alias'), pats)
|
|
|
@@ -6,15 +6,16 @@ # GNU General Public License version 2, incorporated herein by reference.
import os
+import re
import gtk
import gobject
import pango
import Queue
-from mercurial import cmdutil, util, patch, mdiff
+from mercurial import cmdutil, util, patch, mdiff, error
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:
@@ -274,7 +303,7 @@
try:
fctx = self.repo[rev].filectx(wfile)
- except hglib.LookupError:
+ except error.LookupError:
fctx = None
if fctx and fctx.size() > hglib.getmaxdiffsize(self.repo.ui):
lines = ['diff',
@@ -286,7 +315,7 @@ try:
for s in patch.diff(self.repo, n1, n2, match=m, opts=opts):
lines.extend(s.splitlines())
- except (hglib.RepoLookupError, hglib.RepoError, hglib.LookupError), e:
+ except (error.RepoLookupError, error.RepoError, error.LookupError), e:
err = _('Repository Error: %s, refresh suggested') % str(e)
lines = ['diff', '', err]
tags, lines = self.prepare_diff(lines, offset, 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'
@@ -485,7 +514,16 @@ try:
tctx = self.repo[ts]
return revline_data(tctx)
- except (hglib.LookupError, hglib.RepoLookupError, hglib.RepoError):
+ except (error.LookupError, error.RepoLookupError, error.RepoError):
+ return ts
+ elif item == 'p4':
+ ts = widget.get_data('p4', usepreset=True)
+ if not ts:
+ return None
+ try:
+ tctx = self.repo[ts]
+ return revline_data(tctx)
+ except (error.LookupError, error.RepoLookupError, error.RepoError):
return ts
elif item == 'patch':
if hasattr(ctx, '_patchname'):
@@ -516,7 +554,7 @@ if branch:
return '%s - %s %s' % (revnum, branch, summary)
return '%s - %s' % (revnum, summary)
- if item in ('cset', 'transplant', 'patch'):
+ if item in ('cset', 'transplant', 'patch', 'p4'):
if isinstance(value, basestring):
return revid_markup(value)
return revline_markup(*value)
@@ -572,7 +610,7 @@ markup=markup_func, widget=widget_func)
self.csetstyle = csinfo.panelstyle(contents=('cset', 'branch',
'user', 'dateage', 'parents', 'children',
- 'tags', 'transplant'), selectable=True)
+ 'tags', 'transplant', 'p4'), selectable=True)
self.patchstyle = csinfo.panelstyle(contents=('patch', 'branch',
'user', 'dateage', 'parents'),
selectable=True)
@@ -608,6 +646,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 +674,43 @@ 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)
+ if iconpath == None:
+ raise (_("could not open icon file '%s' (check install)")
+ % 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 +718,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 +781,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 error.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)):
@@ -730,7 +851,7 @@ try:
fctx = ctx.filectx(self.curfile)
has_filelog = fctx.filelog().linkrev(fctx.filerev()) == ctx.rev()
- except hglib.LookupError:
+ except error.LookupError:
has_filelog = False
self.ann_menu.set_sensitive(has_filelog)
self.save_menu.set_sensitive(has_filelog)
|
@@ -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()
|
@@ -26,7 +26,7 @@ from tortoisehg.hgtk import csinfo, gtklib, thgconfig, gdialog, hgcmd
class BranchOperationDialog(gtk.Dialog):
- def __init__(self, branch, close, mergebranches):
+ def __init__(self, branch, close, repo):
gtk.Dialog.__init__(self, parent=None, flags=gtk.DIALOG_MODAL,
buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
@@ -39,11 +39,11 @@ self.newbranch = None
self.closebranch = False
- if mergebranches:
+ if len(repo.parents()) == 2:
lbl = gtk.Label(_('Select branch of merge commit'))
branchcombo = gtk.combo_box_new_text()
- for name in mergebranches:
- branchcombo.append_text(name)
+ for p in repo.parents():
+ branchcombo.append_text(p.branch())
branchcombo.set_active(0)
self.vbox.pack_start(lbl, True, True, 2)
self.vbox.pack_start(branchcombo, True, True, 2)
@@ -56,7 +56,15 @@ self.newbranchradio = gtk.RadioButton(nochanges,
_('Open a new named branch'))
self.newbranchradio.set_active(True)
- self.branchentry = gtk.Entry()
+ branchcombo = gtk.combo_box_entry_new_text()
+ self.branchentry = branchcombo.child
+
+ dblist = repo.ui.config('tortoisehg', 'deadbranch', '')
+ deadbranches = [ x.strip() for x in dblist.split(',') ]
+ for name in repo.branchtags().keys():
+ if name not in deadbranches:
+ branchcombo.append_text(name)
+
self.closebranchradio = gtk.RadioButton(nochanges,
_('Close current named branch'))
@@ -68,7 +76,7 @@ lbl.set_markup(gtklib.markup(_('Changes take effect on next commit'),
weight='bold'))
table.add_row(lbl, padding=False, ypad=6)
- table.add_row(self.newbranchradio, self.branchentry)
+ table.add_row(self.newbranchradio, branchcombo)
table.add_row(self.closebranchradio)
table.add_row(nochanges)
@@ -390,17 +398,17 @@ # parent changeset info
parents_vbox = gtk.VBox(spacing=1)
self.parents_frame = parents_vbox
- style = csinfo.labelstyle(contents=(_('Parent: %(rev)s'),
- ' %(athead)s', ' %(branch)s', ' %(tags)s',
+ style = csinfo.labelstyle(contents=('%(athead)s ',
+ _('Parent: %(rev)s'), ' %(branch)s', ' %(tags)s',
' %(summary)s'), selectable=True)
def data_func(widget, item, ctx):
if item == 'athead':
- return widget.get_data('ishead') or self.mqmode
+ return widget.get_data('ishead') or bool(self.mqmode)
raise csinfo.UnknownItem(item)
def markup_func(widget, item, value):
if item == 'athead' and value is False:
- text = '[%s]' % _('not at head revision')
- return gtklib.markup(text, weight='bold')
+ text = '[%s]' % _('Not at head')
+ return gtklib.markup(text, weight='bold', color='#880000')
raise csinfo.UnknownItem(item)
custom = csinfo.custom(data=data_func, markup=markup_func)
factory = csinfo.factory(self.repo, custom, style)
@@ -477,11 +485,8 @@ liststore.append([sumline, msg])
def branch_clicked(self, button):
- if self.is_merge():
- mb = [p.branch() for p in self.repo.parents()]
- else:
- mb = None
- dialog = BranchOperationDialog(self.nextbranch, self.closebranch, mb)
+ dialog = BranchOperationDialog(self.nextbranch,
+ self.closebranch, self.repo)
dialog.run()
self.nextbranch = None
self.closebranch = False
@@ -733,7 +738,7 @@ self.commit_selected(commit_list)
elif self.qheader is not None:
self.commit_selected([])
- elif self.closebranch:
+ elif self.closebranch or self.nextbranch:
self.commit_selected([])
else:
gdialog.Prompt(_('Nothing Commited'),
@@ -860,13 +865,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
|
|
|
@@ -12,15 +12,15 @@ import gtk
import binascii
-from mercurial import patch, util
-from mercurial.node import short, hex
+from mercurial import patch, util, error
+from mercurial.node import hex
from tortoisehg.util.i18n import _
from tortoisehg.util import hglib, paths
from tortoisehg.hgtk import gtklib
-PANEL_DEFAULT = ('rev', 'summary', 'user', 'dateage', 'branch', 'tags', 'transplant')
+PANEL_DEFAULT = ('rev', 'summary', 'user', 'dateage', 'branch', 'tags', 'transplant', 'p4')
def create(repo, target=None, style=None, custom=None, **kargs):
return Factory(repo, custom, style, target, **kargs)()
@@ -113,7 +113,7 @@ return None
try:
ctx = repo[rev]
- except (hglib.LookupError, hglib.RepoLookupError, hglib.RepoError):
+ except (error.LookupError, error.RepoLookupError, error.RepoError):
ctx = None
return ctx
@@ -165,13 +165,13 @@ continue
try:
self._parents.append(repo[p])
- except (hglib.LookupError, hglib.RepoLookupError, hglib.RepoError):
+ except (error.LookupError, error.RepoLookupError, error.RepoError):
self._parents.append(p)
def __str__(self):
node = self.node()
if node:
- return short(node)
+ return node[:12]
return ''
def __int__(self):
@@ -191,6 +191,7 @@ def tags(self): return ()
def parents(self): return self._parents
def children(self): return ()
+ def extra(self): return {}
class SummaryInfo(object):
@@ -199,7 +200,8 @@ 'user': _('User:'), 'date': _('Date:'),'age': _('Age:'),
'dateage': _('Date:'), 'branch': _('Branch:'),
'tags': _('Tags:'), 'rawbranch': _('Branch:'),
- 'rawtags': _('Tags:'), 'transplant': _('Transplant:')}
+ 'rawtags': _('Tags:'), 'transplant': _('Transplant:'),
+ 'p4': _('Perforce:')}
def __init__(self):
pass
@@ -212,7 +214,9 @@ if item == 'rev':
revnum = self.get_data('revnum', *args)
revid = self.get_data('revid', *args)
- return (revnum, revid)
+ if revid:
+ return (revnum, revid)
+ return None
elif item == 'revnum':
return ctx.rev()
elif item == 'revid':
@@ -254,7 +258,7 @@ if dblist and value in [hglib.toutf(b.strip()) \
for b in dblist.split(',')]:
return None
- return value
+ return None
elif item == 'rawtags':
value = [hglib.toutf(tag) for tag in ctx.tags()]
if len(value) == 0:
@@ -269,7 +273,7 @@ value = [tag for tag in value if tag not in htags]
if len(value) == 0:
return None
- return value
+ return None
elif item == 'transplant':
extra = ctx.extra()
try:
@@ -279,6 +283,9 @@ except KeyError:
pass
return None
+ elif item == 'p4':
+ extra = ctx.extra()
+ return extra.get('p4', None)
elif item == 'ishead':
return len(ctx.children()) == 0
raise UnknownItem(item)
@@ -321,10 +328,12 @@ if item == 'rev':
revnum, revid = value
revid = gtklib.markup(revid, **mono)
- return '%s (%s)' % (revnum, revid)
+ if revnum is not None and revid is not None:
+ return '%s (%s)' % (revnum, revid)
+ return '%s' % revid
elif item in ('revid', 'transplant'):
return gtklib.markup(value, **mono)
- elif item == 'revnum':
+ elif item in ('revnum', 'p4'):
return str(value)
elif item in ('rawbranch', 'branch'):
return gtklib.markup(' %s ' % value, color='black',
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
@@ -13,7 +13,7 @@ import threading
import re
-from mercurial import util
+from mercurial import util, error
from tortoisehg.util.i18n import _
from tortoisehg.util import hglib, thread2
@@ -191,7 +191,7 @@ parent_ctx = self.repo[parent_revid]
try:
parent_ctx.filectx(filepath)
- except LookupError:
+ except error.LookupError:
# file was renamed/moved, try to find previous file path
end_iter = iter
path = graphview.get_path_at_revid(int(anotrev))
@@ -208,7 +208,7 @@ if renamed:
filepath = renamed[0]
break
- except LookupError:
+ except error.LookupError:
# break iteration, but don't use 'break' statement
# so that execute 'else' block for showing prompt.
iter = end_iter
@@ -453,7 +453,7 @@ def threadfunc(q, *args):
try:
hglib.hgcmd_toq(q, *args)
- except (util.Abort, hglib.LookupError), e:
+ except (util.Abort, error.LookupError), e:
self.stbar.set_status_text(_('Abort: %s') % str(e))
thread = thread2.Thread(target=threadfunc, args=args)
@@ -580,7 +580,7 @@ ctx = self.repo.parents()[0]
try:
fctx = ctx.filectx(path)
- except LookupError:
+ except error.LookupError:
gdialog.Prompt(_('File is unrevisioned'),
_('Unable to annotate ') + path, self).run()
return
@@ -752,7 +752,7 @@ def threadfunc(q, *args):
try:
hglib.hgcmd_toq(q, *args)
- except (util.Abort, hglib.LookupError), e:
+ except (util.Abort, error.LookupError), e:
self.stbar.set_status_text(_('Abort: %s') % str(e))
(frame, treeview, origpath, graphview) = objs
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
@@ -9,7 +9,8 @@ import os
import gtk
import gobject
-import mercurial
+
+from mercurial import error
from tortoisehg.util.i18n import _
from tortoisehg.hgtk import gtklib, gdialog
@@ -54,11 +55,11 @@ self.gotofunc(revision)
self.revEntry.set_text('')
self.hide()
- except mercurial.error.LookupError, e:
+ except error.LookupError, e:
gdialog.Prompt(_('Ambiguous Revision'), str(e), self).run()
self.revEntry.grab_focus()
return
- except mercurial.error.RepoError, e:
+ except error.RepoError, e:
gdialog.Prompt(_('Invalid Revision'), str(e), self).run()
self.revEntry.grab_focus()
return
|
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... |
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... |
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... |
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... |
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... |
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... |
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... |
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... |
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... |
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... |
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... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
Loading...