#!/usr/bin/env python '''UI for Publish/Catchup operations''' # Copyright (c) 2006 Qualcomm # Miki Tebeka # Publish/Catchup # Branch: _____ [...] # [Publish/Catchup] [Quit] # Log: # +----------------------+ # | | # | | # | | # | | # +----------------------+ import wx from wx.stc import StyledTextCtrl from wx.lib.dialogs import singleChoiceDialog, messageDialog from sys import path from os.path import join, dirname, isfile from os import environ from itertools import count from time import ctime from publish import publish, catchup, is_synced, has_opened_files, SUBMIT, \ UNDO, CLOSE from p4 import P4, P4Error from p4v_common import gen_p4, P4VAddin, optparser, branch_source, make_error error = make_error("Catchup/Publish Error") class ASK(wx.Dialog): def __init__(self, parent, change): wx.Dialog.__init__(self, parent, -1, "What now?") self.action = CLOSE sizer = wx.BoxSizer(wx.VERTICAL) b = wx.Button(self, -1, "Submit changelist %s" % change) self.Bind(wx.EVT_BUTTON, self.OnSubmit, b) sizer.Add(b, 0, wx.EXPAND) b = wx.Button(self, -1, "Close and leave changelist %s" % change) self.Bind(wx.EVT_BUTTON, self.OnClose, b) sizer.Add(b, 0, wx.EXPAND) b = wx.Button(self, -1, "Undo changes in changelist %s" % change) self.Bind(wx.EVT_BUTTON, self.OnUndo, b) sizer.Add(b, 0, wx.EXPAND) self.SetSizer(sizer) sizer.Fit(self) self.CenterOnScreen() def OnSubmit(self, evt): self.action = SUBMIT self.EndModal(wx.ID_OK) def OnClose(self, evt): self.action = CLOSE self.EndModal(wx.ID_OK) def OnUndo(self, evt): self.action = UNDO self.EndModal(wx.ID_OK) def ask(win, change): dlg = ASK(win, change) try: dlg.ShowModal() return dlg.action finally: dlg.Destroy() # We'll get the client and user from p4v class PubUp(P4VAddin): '''Main dialog''' def __init__(self, p4, is_catchup): if is_catchup: title = "Perforce Catchup" else: title = "Perforce Publish" P4VAddin.__init__(self, title) self.p4 = p4 # Branch list cache (used in get_branches) self.branch_list = None # Setup UI sizer = wx.BoxSizer(wx.VERTICAL) # Branch: _____ [...] hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.Add(wx.StaticText(self, -1, "Branch:"), 0, wx.ALIGN_CENTER_VERTICAL|wx.WEST, 2) self._branch = wx.TextCtrl(self, -1, size=(200, -1)) hsizer.Add(self._branch, 1, wx.EXPAND) b = wx.Button(self, -1, "...", style=wx.BU_EXACTFIT) self.Bind(wx.EVT_BUTTON, self.OnBranches, b) hsizer.Add(b) sizer.Add(hsizer, 0, wx.EXPAND) # [Publish/Catchup] [Quit] hsizer = wx.BoxSizer(wx.HORIZONTAL) def button(caption, id=-1, handler=None, focus=0): b = wx.Button(self, id, caption) if handler: self.Bind(wx.EVT_BUTTON, handler, b) hsizer.Add(b) return b sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.NORTH|wx.SOUTH, 5) if is_catchup: button("&Catchup", handler=self.OnCatchup) else: button("&Publish", handler=self.OnPublish) button("&Quit", id=wx.ID_CANCEL) # Log: # +----------------------+ # | | # | | # | | # | | # +----------------------+ sizer.Add(hsizer, 0, wx.EXPAND) sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.NORTH|wx.SOUTH, 5) sizer.Add(wx.StaticText(self, -1, "Log:"), 0, wx.WEST, 2) self._log = StyledTextCtrl(self, size=(800, 300)) self._log.SetReadOnly(1) sizer.Add(self._log, 0, wx.EXPAND) # Fit and center self.SetSizer(sizer) sizer.Fit(self) self.CenterOnScreen() self._branch.SetFocus() def log(self, msg): '''Log message msg - Message to log ''' self._log.SetReadOnly(0) self._log.AddText("%s\n" % msg) self._log.SetReadOnly(1) def go(self, is_catchup): '''Main operation is_catchup - Flag for catchup operation ''' try: branch = self.getval(self._branch, "branch") except ValueError, e: error("Please fill the %s" % e.args[0]) return if is_catchup: if is_synced(self.p4, branch): messageDialog(self, "private branch is fully synchronized", "Nothing to Do", wx.OK|wx.ICON_INFORMATION) return func = catchup else: func = publish integ = branch_source(self.p4, branch) if has_opened_files(self.p4, integ): error("Someone else is publishing now") return try: # Run without submitting change = func(self.p4, branch, 0, self.log) if not change: return result = ask(self, change) if result == SUBMIT: self.p4.run_submit("-c", change) title = "Submitted changes" msg = "Change %s submitted" % change elif result == UNDO: self.p4.run_revert("-c", change, "//...") self.p4.run_change("-d", change) title = "Change reverted" msg = "Change %s reverted" % change else: # Close msg = "Change %s created" % change title = "Change created" dlg = wx.MessageDialog(self, msg, title, wx.OK|wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() except (P4Error, OSError), e: error(e) def OnPublish(self, evt): '''Publish button handler''' self.go(0) def OnCatchup(self, evt): '''Catchup button handler''' self.go(1) def get_branches(self): if not self.branch_list: self.branch_list = [] for spec in self.p4.run_branches(): if spec["Owner"].lower() in (self.p4.user.lower(), ""): self.branch_list.append(spec["branch"]) return self.branch_list def OnBranches(self, evt): res = singleChoiceDialog(self, "Select integration branch", "Branches", self.get_branches()) if res.accepted: self._branch.SetValue(res.selection) def main(argv = None): if not argv: import sys argv = sys.argv[1:] parser = optparser("usage: %prog [options]") parser.add_option("--catchup", help="do a catchup", dest="catchup", action="store_true", default=0) opts, args = parser.parse_args() app = wx.PySimpleApp() p4 = gen_p4(opts) dlg = PubUp(p4, opts.catchup) dlg.ShowModal() dlg.Destroy() if __name__ == "__main__": try: main() except P4Error, e: error(e) raise SystemExit(1)