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>&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><command></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>&Cancel</label>
+ <disabled>1</disabled>
+ </object>
+ </object>
+ </object>
+ </object>
</application>
More information about the bazaar-commits
mailing list