Rev 2: Basic functionality has been implemented using a throbbing progress bar. in http://bzr.arbash-meinel.com/branches/bzr/merge_into

John Arbash Meinel john at arbash-meinel.com
Fri Dec 21 20:41:15 GMT 2007


At http://bzr.arbash-meinel.com/branches/bzr/merge_into

------------------------------------------------------------
revno: 2
revision-id:john at arbash-meinel.com-20071221204110-3mt64ech9v88hzpl
parent: john at arbash-meinel.com-20071221192530-564ucjewkx5g3s9z
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: merge_into
timestamp: Fri 2007-12-21 14:41:10 -0600
message:
  Basic functionality has been implemented using a throbbing progress bar.
modified:
  bzr_merge_into.py              bzr_merge_into.py-20071221192513-1fyh868lls6qugcq-1
  bzr_merge_into.wxg             bzr_merge_into.wxg-20071221185509-khngkqvqe1jjzb2i-1
-------------- next part --------------
=== modified file 'bzr_merge_into.py'
--- a/bzr_merge_into.py	2007-12-21 19:25:30 +0000
+++ b/bzr_merge_into.py	2007-12-21 20:41:10 +0000
@@ -18,11 +18,93 @@
 
 """A simple helper GUI for merging patches into branches."""
 
+import errno
 import os
+import subprocess
+import sys
+import time
 
 import wx
 
 
+class ProcessDialog(wx.Dialog):
+    def __init__(self, *args, **kwds):
+        # begin wxGlade: ProcessDialog.__init__
+        kwds["style"] = wx.RESIZE_BORDER|wx.THICK_FRAME
+        wx.Dialog.__init__(self, *args, **kwds)
+        self.label_3 = wx.StaticText(self, -1, "Processing")
+        self.lbl_command = wx.StaticText(self, -1, "<command>")
+        self.gauge_progress = wx.Gauge(self, -1, 10)
+        self.button_2 = wx.Button(self, wx.ID_CANCEL, "")
+
+        self.__set_properties()
+        self.__do_layout()
+        # end wxGlade
+
+    def __set_properties(self):
+        # begin wxGlade: ProcessDialog.__set_properties
+        self.SetTitle("Processing")
+        self.button_2.Enable(False)
+        # end wxGlade
+
+    def __do_layout(self):
+        # begin wxGlade: ProcessDialog.__do_layout
+        sizer_6 = wx.BoxSizer(wx.VERTICAL)
+        sizer_6.Add(self.label_3, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5)
+        sizer_6.Add(self.lbl_command, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 5)
+        sizer_6.Add(self.gauge_progress, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 5)
+        sizer_6.Add(self.button_2, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER_HORIZONTAL, 0)
+        self.SetSizer(sizer_6)
+        sizer_6.Fit(self)
+        self.Layout()
+        # end wxGlade
+
+    def runCommand(self, command, *args, **kwargs):
+        """Run a command, and poll it until it finishes."""
+        self.CenterOnParent()
+        self.lbl_command.SetLabel(' '.join(command))
+        parent = self.GetParent()
+        if parent:
+            parent.Freeze()
+        self.Fit()
+        self.Show()
+        wx.Yield()
+        try:
+            try:
+                p = subprocess.Popen(command, *args, **kwargs)
+            except OSError, e:
+                if e.errno in (errno.ENOENT,):
+                    cmd = command[0]
+                    dlg = wx.MessageDialog(self,
+                        message='Could not find:\n"%s"\n'
+                                'Is everything installed correctly?'
+                                % (cmd,),
+                        caption='Error: Failed to run "%s"' % (cmd,),
+                        style = wx.OK | wx.ICON_EXCLAMATION)
+                    dlg.ShowModal()
+                    return
+            # We want to poll, but we also want to grab sys.stdout and
+            # sys.stderr, how do we do that?
+            while p.poll() is None:
+                self.gauge_progress.Pulse()
+                wx.Yield()
+                time.sleep(0.1)
+            retcode = p.returncode
+            if retcode == 0:
+                return
+            else:
+                dlg = wx.MessageDialog(self,
+                        message='Failed with return code: %s\n'
+                                '%s\n'
+                                % (retcode, command))
+        finally:
+            self.Close()
+            if parent:
+                parent.Thaw()
+
+# end of class ProcessDialog
+
+
 class MergeIntoFrame(wx.Frame):
     def __init__(self, *args, **kwds):
         # begin wxGlade: MergeIntoFrame.__init__
@@ -34,6 +116,8 @@
         self.label_2 = wx.StaticText(self, -1, "Target Branch")
         self.btn_browse_branch = wx.Button(self, -1, "Browse")
         self.text_target_branch = wx.TextCtrl(self, -1, "/home/jameinel/dev/bzr/jam-integration")
+        self.radio_pull_overwrite = wx.RadioButton(self, -1, "pull --overwrite", style=wx.RB_GROUP)
+        self.radio_merge = wx.RadioButton(self, -1, "merge")
         self.button_1 = wx.Button(self, wx.ID_CANCEL, "")
         self.btn_ok = wx.Button(self, wx.ID_OK, "")
 
@@ -49,13 +133,16 @@
     def __set_properties(self):
         # begin wxGlade: MergeIntoFrame.__set_properties
         self.SetTitle("Bzr Merge Into")
-        self.SetSize((400, 180))
+        self.SetSize((400, 208))
+        self.radio_merge.SetValue(1)
+        self.btn_ok.SetDefault()
         # end wxGlade
 
     def __do_layout(self):
         # begin wxGlade: MergeIntoFrame.__do_layout
         sizer_1 = wx.BoxSizer(wx.VERTICAL)
         sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
         sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
         sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
         sizer_2.Add(self.label_1, 0, wx.ALIGN_BOTTOM, 0)
@@ -68,6 +155,9 @@
         sizer_3.Add(self.btn_browse_branch, 0, 0, 0)
         sizer_1.Add(sizer_3, 0, wx.ALL|wx.EXPAND, 3)
         sizer_1.Add(self.text_target_branch, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 3)
+        sizer_5.Add(self.radio_pull_overwrite, 0, 0, 0)
+        sizer_5.Add(self.radio_merge, 0, 0, 0)
+        sizer_1.Add(sizer_5, 0, wx.ALL|wx.EXPAND, 5)
         sizer_4.Add((10, 10), 1, 0, 0)
         sizer_4.Add(self.button_1, 0, wx.ALL, 5)
         sizer_4.Add(self.btn_ok, 0, wx.ALL, 5)
@@ -81,22 +171,68 @@
                             wildcard='Bazaar Patch (*.patch,*.diff,*.bundle)'
                                      '|*.patch;*.diff;*.bundle'
                                      '|All Files (*.*)|*')
+        path = self.text_merge_patch.GetValue()
+        if path:
+            dlg.SetPath(path)
         if dlg.ShowModal() == wx.ID_OK:
-            directory = dlg.GetDirectory()
-            fname = dlg.GetFilename()
-            path = os.path.join(directory, fname)
-            self.text_merge_patch.SetValue(path)
+            self.text_merge_patch.SetValue(dlg.GetPath())
 
     def onButtonBrowseBranch(self, event): # wxGlade: MergeIntoFrame.<event_handler>
-        print "Event handler `onButtonBrowseBranch' not implemented!"
-        event.Skip()
+        dlg = wx.DirDialog(self, message='Select a target branch',
+                            style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
+        path = self.text_target_branch.GetValue()
+        if path:
+            dlg.SetPath(path)
+        if dlg.ShowModal() == wx.ID_OK:
+            self.text_target_branch.SetValue(dlg.GetPath())
 
     def onCancel(self, event): # wxGlade: MergeIntoFrame.<event_handler>
         self.Close()
 
     def onOk(self, event): # wxGlade: MergeIntoFrame.<event_handler>
-        print "Event handler `onOk' not implemented!"
-        event.Skip()
+        patch = self.text_merge_patch.GetValue()
+        if not patch:
+            dlg = wx.MessageDialog(self,
+                    message="You must select a patch first",
+                    caption="Error: No Patch",
+                    style = wx.OK | wx.ICON_EXCLAMATION)
+            dlg.ShowModal()
+            return
+        if not os.path.isfile(patch):
+            dlg = wx.MessageDialog(self,
+                    message="%s\ndoes not exist" % (patch,),
+                    caption="Error: Not a File",
+                    style = wx.OK | wx.ICON_EXCLAMATION)
+            dlg.ShowModal()
+            return
+        # TODO: we should actually check if it is a mergeable bundle
+        target_branch = self.text_target_branch.GetValue()
+        if not target_branch:
+            dlg = wx.MessageDialog(self,
+                    message="No target branch selected",
+                    caption="Error: No Target",
+                    style = wx.OK | wx.ICON_EXCLAMATION)
+            dlg.ShowModal()
+            return
+        if not os.path.isdir(target_branch):
+            dlg = wx.MessageDialog(self,
+                    message="Target branch:\n%s\ndoes not exist"
+                            % (target_branch),
+                    caption="Error: No Target",
+                    style = wx.OK | wx.ICON_EXCLAMATION)
+            dlg.ShowModal()
+            return
+        # TODO: we should check that the target branch is a valid branch
+        #       and that the root of the branch is at that location.
+        #       For example, we *could* use 'bzr root' to check the path
+        #       matches.
+        if self.radio_merge.GetValue():
+            cmd = ['bzr', '--no-aliases', 'merge', patch]
+        else:
+            cmd = ['bzr', '--no-aliases', 'pull', '--overwrite', patch]
+
+        dlg = ProcessDialog(self)
+        dlg.runCommand(cmd, cwd=target_branch)
 
 # end of class MergeIntoFrame
 
@@ -106,6 +242,12 @@
         wx.InitAllImageHandlers()
         merge_into = MergeIntoFrame(None, -1, "")
         self.SetTopWindow(merge_into)
+        if len(sys.argv) > 1:
+            patch = sys.argv[1]
+            merge_into.text_merge_patch.SetValue(patch)
+        if len(sys.argv) > 2:
+            target = sys.argv[2]
+            merge_into.text_target_branch.SetValue(target)
         merge_into.Show()
         return 1
 

=== modified file 'bzr_merge_into.wxg'
--- a/bzr_merge_into.wxg	2007-12-21 19:25:30 +0000
+++ b/bzr_merge_into.wxg	2007-12-21 20:41:10 +0000
@@ -1,11 +1,11 @@
 <?xml version="1.0"?>
-<!-- generated by wxGlade 0.5 on Fri Dec 21 13:20:57 2007 -->
+<!-- generated by wxGlade 0.5 on Fri Dec 21 14:39:44 2007 -->
 
 <application path="bzr_merge_into.py" name="" class="MergeIntoApp" option="0" language="python" top_window="merge_into" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
     <object class="MergeIntoFrame" name="merge_into" base="EditFrame">
         <style>wxDEFAULT_FRAME_STYLE</style>
         <title>Bzr Merge Into</title>
-        <size>400, 180</size>
+        <size>400, 208</size>
         <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
             <orient>wxVERTICAL</orient>
             <object class="sizeritem">
@@ -47,7 +47,7 @@
                 <flag>wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND</flag>
                 <border>3</border>
                 <option>0</option>
-                <object class="wxTextCtrl" name="text_merge_target" base="EditTextCtrl">
+                <object class="wxTextCtrl" name="text_merge_patch" base="EditTextCtrl">
                 </object>
             </object>
             <object class="sizeritem">
@@ -94,6 +94,30 @@
                 </object>
             </object>
             <object class="sizeritem">
+                <flag>wxALL|wxEXPAND</flag>
+                <border>5</border>
+                <option>0</option>
+                <object class="wxBoxSizer" name="sizer_5" base="EditBoxSizer">
+                    <orient>wxHORIZONTAL</orient>
+                    <object class="sizeritem">
+                        <border>0</border>
+                        <option>0</option>
+                        <object class="wxRadioButton" name="radio_pull_overwrite" base="EditRadioButton">
+                            <style>wxRB_GROUP</style>
+                            <label>pull --overwrite</label>
+                        </object>
+                    </object>
+                    <object class="sizeritem">
+                        <border>0</border>
+                        <option>0</option>
+                        <object class="wxRadioButton" name="radio_merge" base="EditRadioButton">
+                            <clicked>1</clicked>
+                            <label>merge</label>
+                        </object>
+                    </object>
+                </object>
+            </object>
+            <object class="sizeritem">
                 <flag>wxEXPAND</flag>
                 <border>0</border>
                 <option>1</option>
@@ -125,6 +149,7 @@
                         <option>0</option>
                         <object class="wxButton" name="btn_ok" base="EditButton">
                             <stockitem>OK</stockitem>
+                            <default>1</default>
                             <label>&amp;OK</label>
                             <events>
                                 <handler event="EVT_BUTTON">onOk</handler>
@@ -135,4 +160,48 @@
             </object>
         </object>
     </object>
+    <object class="ProcessDialog" name="process_dialog" base="EditDialog">
+        <style>wxRESIZE_BORDER|wxTHICK_FRAME</style>
+        <title>Processing</title>
+        <object class="wxBoxSizer" name="sizer_6" base="EditBoxSizer">
+            <orient>wxVERTICAL</orient>
+            <object class="sizeritem">
+                <flag>wxALL|wxALIGN_CENTER_HORIZONTAL</flag>
+                <border>5</border>
+                <option>0</option>
+                <object class="wxStaticText" name="label_3" base="EditStaticText">
+                    <attribute>1</attribute>
+                    <label>Processing</label>
+                </object>
+            </object>
+            <object class="sizeritem">
+                <flag>wxLEFT|wxRIGHT|wxBOTTOM|wxALIGN_CENTER_HORIZONTAL</flag>
+                <border>5</border>
+                <option>0</option>
+                <object class="wxStaticText" name="lbl_command" base="EditStaticText">
+                    <attribute>1</attribute>
+                    <label>&lt;command&gt;</label>
+                </object>
+            </object>
+            <object class="sizeritem">
+                <flag>wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND</flag>
+                <border>5</border>
+                <option>0</option>
+                <object class="wxGauge" name="gauge_progress" base="EditGauge">
+                    <style>wxGA_HORIZONTAL</style>
+                    <range>10</range>
+                </object>
+            </object>
+            <object class="sizeritem">
+                <flag>wxALIGN_BOTTOM|wxALIGN_CENTER_HORIZONTAL</flag>
+                <border>0</border>
+                <option>0</option>
+                <object class="wxButton" name="button_2" base="EditButton">
+                    <stockitem>CANCEL</stockitem>
+                    <label>&amp;Cancel</label>
+                    <disabled>1</disabled>
+                </object>
+            </object>
+        </object>
+    </object>
 </application>



More information about the bazaar-commits mailing list