Commits

Peter Arrenbrecht  committed 8dfdb81 Merge

merge with crew

  • Participants
  • Parent commits a6dcece, 8ccb624
  • Branches hg-crew-tip

Comments (0)

Files changed (11)

 864497951b6b801cfacbac16eec5b7edb4f1be3c 0.4rc4
 f627244263631682216716cde477d05bebc0d934 0.4
 491a94666fc3498827066b8aa65aab34d3a3e623 0.4.1
+93df004457accaba3651c6534115aa4b98d94ce7 0.5

File ReleaseNotes.txt

 what bugs have been fixed, and what features have been added in the current
 version.
 
-New features and improvement in 0.4.1
+New features and improvement in 0.5:
+
+  * Explorer shell extensions:
+    - share overlay icons with TortoiseSVN 1.5.x via TortoiseSVN's 
+	  TortoiseOverlays project (by Peer Sommerlund)
+
+  * New mercurial-like command line syntax for hgtk, with help support.
+
+  * The gPyFm merge-tool is not longer bundled (see bug 2119067)
+  
+  * Interal commit dialog:
+	- show number of files selected (also apply to Status dialog)
+	- add 'Undo' button to rollback last commit.
+	- do not clear commit message window if commit fails
+    - accept commit message in multi-byte charset (fix bug 2116362)
+	
+  * Synchronize dialog:
+    - load patchbomb extension automatically (by Peer Sommerlund)
+
+  
+Bug fixes in 0.5:
+  
+  * [ 2119138 ] Merge-tool priority fix (by Mads Kiilerich)
+  * [ 2116362 ] Internal commit tool not support gbk comment
+  * [ 2113989 ] Can't create repository via Explorer context menu (when 
+                a file is selected)	
+  * [ 2103749 ] Changelog viewer doesn't refresh after making local tag
+  
+  * nautilus: fix error when there is no repo in the current directory
+    (by Germ�n P�o-Caama�o)
+
+
+New features and improvement in 0.4.1:
 
   * Installer-only release to link with Mercurial 1.0.2
 
-New features and improvement in 0.4
+New features and improvement in 0.4:
 
   * Updated to work, and link, with Mercurial 1.0.1
 

File hggtk/commit.py

 from gtools import cmdtable
 from status import GStatus
 from hgcmd import CmdDialog
+from hglib import fromutf
 
 class GCommit(GStatus):
     """GTK+ based dialog for displaying repository status and committing changes.
         cmdline  = ["hg", "commit", "--verbose", "--repository", self.repo.root]
         if self.opts['addremove']:
             cmdline += ['--addremove']
-        cmdline += ['--message', self.opts['message']]
+        cmdline += ['--message', fromutf(self.opts['message'])]
         cmdline += [self.repo.wjoin(x) for x in files]
         dialog = CmdDialog(cmdline, True)
         dialog.set_transient_for(self)
         dialog.hide()
 
         # refresh overlay icons and commit dialog
-        self.text.set_buffer(gtk.TextBuffer())
-        self._update_recent_messages(self.opts['message'])
-        shell_notify([self.cwd] + files)
-        self._last_commit_id = self._get_tip_rev(True)
-        self.reload_status()
+        if dialog.return_code() == 0:
+            self.text.set_buffer(gtk.TextBuffer())
+            self._update_recent_messages(self.opts['message'])
+            shell_notify([self.cwd] + files)
+            self._last_commit_id = self._get_tip_rev(True)
+            self.reload_status()
 
     def _get_tip_rev(self, refresh=False):
         if refresh:

File hggtk/hgcmd.py

             self.last_pbar_update = tm
             self.pbar.pulse()
 
+    def return_code(self):
+        return self.hgthread.return_code()
+
 def run(cmdline=[], gui=True, **opts):
     if not gui:
         q = Queue.Queue()

File hggtk/hgemail.py

             self.repo = None
             return
 
-        for name, module in extensions.extensions():
-            if name == 'patchbomb':
-                break
-        else:
-            error_dialog(self, 'Email not enabled',
-                    'You must enable the patchbomb extension to use this tool')
-            self.response(gtk.RESPONSE_CANCEL)
+        extensions.load(self.repo.ui, 'patchbomb', None)
 
         if initial:
             # Only zap these fields at startup

File hggtk/history.py

         # save tag info for detecting new tags added
         oldtags = self.repo.tagslist()
         
+        def refresh(*args):
+            self.repo.invalidate()
+            newtags = self.repo.tagslist()
+            if newtags != oldtags:
+                self.reload_log()
+
         dialog = TagAddDialog(self.repo.root, rev=str(rev))
         dialog.set_transient_for(self)
+        dialog.connect('destroy', refresh)
         dialog.show_all()
         dialog.present()
         dialog.set_transient_for(None)
-        
-        # refresh if new tags added
-        self.repo.invalidate()
-        newtags = self.repo.tagslist()
-        if newtags != oldtags:
-            self.reload_log()
 
     def _show_status(self, menuitem):
         rev = self.currow[treemodel.REVID]

File hggtk/vis/treeview.py

     def refresh(self, graphcol, pats, opts):
         self.repo.invalidate()
         self.repo.dirstate.invalidate()
-        self.create_log_generator(graphcol, pats, opts)
-        self.pbar.begin()
-        gobject.idle_add(self.populate, self.get_revision())
+        if self.repo.changelog.count() > 0:
+            self.create_log_generator(graphcol, pats, opts)
+            self.pbar.begin()
+            gobject.idle_add(self.populate, self.get_revision())
+        else:
+            self.pbar.set_status_text('Repository is empty')
 
     def construct_treeview(self):
         self.treeview = gtk.TreeView()
                         "icon_resources": [(1, "icons/tortoise/python.ico")]}
             ]
     extra['com_server'] = ["tortoisehg"]
-    extra['console'] = ["contrib/hg"]
+    extra['console'] = ["contrib/hg", "contrib/hgtk"]
 
 opts = {
    "py2exe" : {

File tortoise/contextmenu.py

         ]
 
     registry_keys = [
-        (_winreg.HKEY_CLASSES_ROOT, r"*\shellex\ContextMenuHandlers\TortoiseHg"),
-        (_winreg.HKEY_CLASSES_ROOT, r"Directory\Background\shellex\ContextMenuHandlers\TortoiseHg"),
-        (_winreg.HKEY_CLASSES_ROOT, r"Directory\shellex\ContextMenuHandlers\TortoiseHg"),
-        (_winreg.HKEY_CLASSES_ROOT, r"Folder\shellex\ContextMenuHandlers\TortoiseHg"),
-        (_winreg.HKEY_CLASSES_ROOT, r"Directory\shellex\DragDropHandlers\TortoiseHg"),
-        (_winreg.HKEY_CLASSES_ROOT, r"Folder\shellex\DragDropHandlers\TortoiseHg"),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"*\shellex\ContextMenuHandlers\TortoiseHg", 
+         [(None, _reg_clsid_)]),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"Directory\Background\shellex\ContextMenuHandlers\TortoiseHg",
+         [(None, _reg_clsid_)]),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"Directory\shellex\ContextMenuHandlers\TortoiseHg",
+         [(None, _reg_clsid_)]),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"Folder\shellex\ContextMenuHandlers\TortoiseHg",
+         [(None, _reg_clsid_)]),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"Directory\shellex\DragDropHandlers\TortoiseHg",
+         [(None, _reg_clsid_)]),
+        (_winreg.HKEY_CLASSES_ROOT,
+         r"Folder\shellex\DragDropHandlers\TortoiseHg",
+         [(None, _reg_clsid_)]),
         ]
 
     def __init__(self):
 
     def _init(self, parent_window):
         dest = self._folder or self._filenames[0]
+        if os.path.isfile(dest):
+            dest = os.path.dirname(dest)
+
         msg = "Create Hg repository in %s?" % (dest)
         title = "Mercurial: init"
         rv = win32ui.MessageBox(msg, title, win32con.MB_OKCANCEL)

File tortoise/iconoverlay.py

 class IconOverlayExtension(object):
     """
     Class to implement icon overlays for source controlled files.
+    Specialized classes are created for each overlay icon.
 
     Displays a different icon based on version control status.
 
     NOTE: The system allocates only 15 slots in _total_ for all
         icon overlays; we (will) use 6, tortoisecvs uses 7... not a good
-        recipe for a happy system.
+        recipe for a happy system. By utilizing the TortoiseOverlay.dll
+        we can share overlay slots with the other tortoises.
     """
     
     counter = 0
     _reg_threading_ = 'Apartment'
 
     def GetOverlayInfo(self): 
-        icon = thgutil.get_icon_path("status", self.icon)
-        print "icon = ", icon
-
-        if icon:
-            return (icon, 0, shellcon.ISIOI_ICONFILE)
-        else:
-            return ("", 0, 0) 
+        return ("", 0, 0) 
 
     def GetPriority(self):
         return 0
-
-    def _get_installed_overlays():
-        key = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
-                                    "Software\\Microsoft\\Windows\\" +
-                                        "CurrentVersion\\Explorer\\" +
-                                        "ShellIconOverlayIdentifiers",
-                                    0,
-                                    win32con.KEY_READ)
-        keys = win32api.RegEnumKeyEx(key)
-        handlercount = len(keys)
-        print "number of overlay handlers installed = %d" % handlercount
-        for i, k in enumerate(keys):
-            print i, k
-        win32api.RegCloseKey(key)
-        return handlercount
         
     def _get_state(self, upath):
         """
             print "IsMemberOf: _get_state() took %d ticks" % \
                     (win32api.GetTickCount() - tc)
             
-def make_icon_overlay(name, icon, state, clsid):
+def make_icon_overlay(name, icon_type, state, clsid):
     """
     Make an icon overlay COM class.
 
     prog_id = "Mercurial.ShellExtension.%s" % classname
     desc = "Mercurial icon overlay shell extension for %s files" % name.lower()
     reg = [
-        (_winreg.HKEY_LOCAL_MACHINE, r"Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\%s" % name) ]
+            (_winreg.HKEY_LOCAL_MACHINE,
+             r"Software\TortoiseOverlays\%s" % icon_type,
+             [("TortoiseHg", clsid)])
+        ]
     cls = type(
             classname,
             (IconOverlayExtension, ),
-            dict(_reg_clsid_=clsid, _reg_progid_=prog_id, _reg_desc_=desc, registry_keys=reg, icon=icon, state=state))
+            dict(_reg_clsid_=clsid, _reg_progid_=prog_id, _reg_desc_=desc, registry_keys=reg, stringKey="HG", state=state))
 
     _overlay_classes.append(cls)
     # We need to register the class as global, as pythoncom will
     globals()[classname] = cls
 
 _overlay_classes = []
-make_icon_overlay("Changed", "changed.ico", MODIFIED, "{102C6A24-5F38-4186-B64A-237011809FAB}")
-make_icon_overlay("Unchanged", "unchanged.ico", UNCHANGED, "{00FEE959-5773-424B-88AC-A01BFC8E4555}")
-make_icon_overlay("Added", "added.ico", ADDED, "{8447DB75-5875-4BA8-9F38-A727DAA484A0}")
-
-def get_overlay_classes():
-    """
-    Get a list of all registerable icon overlay classes
-    """
-    return _overlay_classes
+make_icon_overlay("Changed", "Modified", MODIFIED, "{4D0F33E1-654C-4A1B-9BE8-E47A98752BAB}")
+make_icon_overlay("Unchanged", "Normal", UNCHANGED, "{4D0F33E2-654C-4A1B-9BE8-E47A98752BAB}")
+make_icon_overlay("Added", "Added", ADDED, "{4D0F33E3-654C-4A1B-9BE8-E47A98752BAB}")

File tortoisehg.py

 bin_path = os.path.dirname(os.path.join(os.getcwd(), sys.argv[0]))
 print "bin path = ", bin_path
 
+def check_tortoise_overlays():
+    # TortoiseOverlays must be installed, and we must be able to write there.
+    try:
+        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
+                               r"Software\TortoiseOverlays", 0,
+                               _winreg.KEY_ALL_ACCESS)
+    except WindowsError:
+        print "TortoiseOverlays is not installed."
+        sys.exit(1)
+
 # TortoiseHg registry setup
 def register_tortoise_path(unregister=False):
     key = r"Software\TortoiseHg"
 
 # for COM registration via py2exe
 def DllRegisterServer():
+    check_tortoise_overlays()
     RegisterServer(ContextMenuExtension)
     RegisterServer(ChangedOverlay)
     RegisterServer(AddedOverlay)
         pass
         
     # Add the appropriate shell extension registry keys
-    for category, keyname in cls.registry_keys: 
-        _winreg.SetValue(category, keyname, _winreg.REG_SZ, cls._reg_clsid_)
+    for category, keyname, values in cls.registry_keys:
+        hkey = _winreg.CreateKey(category, keyname)
+        for (name, val) in values:
+            # todo: handle ints?
+            _winreg.SetValueEx(hkey, name, 0, _winreg.REG_SZ, val)
         
     # register the extension on Approved list
     try:
     print cls._reg_desc_, "registration complete."
 
 def UnregisterServer(cls):
-    for category, keyname in cls.registry_keys:
-        try:
-            _winreg.DeleteKey(category, keyname)
-        except WindowsError, details:
-            import errno
-            if details.errno != errno.ENOENT:
-                raise
+    for category, keyname, values in cls.registry_keys:
+        hkey = _winreg.OpenKey(category, keyname, 0, _winreg.KEY_ALL_ACCESS)
+        for (name, val) in values:
+            # todo: handle ints?
+            try:
+                _winreg.DeleteValue(hkey, name)
+            except WindowsError, exc:
+                print "Failed to remove registry key %s: %s" % (keyname, exc)
 
     # unregister the extension from Approved list
     try:
     print cls._reg_desc_, "unregistration complete."
 
 if __name__=='__main__':
+    check_tortoise_overlays()
+
     from win32com.server import register
     register.UseCommandLine(ContextMenuExtension,
             finalize_register = lambda: RegisterServer(ContextMenuExtension),