#!/usr/bin/env python '''Print changes from last label ''' # Copyright (c) 2006 Qualcomm # Miki Tebeka import wx from wx.lib.dialogs import ScrolledMessageDialog from p4 import P4, P4Error from time import ctime from os.path import isfile, dirname, join from os import popen from sys import path def client_path(client): '''Return path for client''' return "//%s/..." % client def chlog(p4, label): '''Return lines of last change''' last = p4.run_changes("-m1")[0] prev = p4.run_changes("-m1", "%s@%s" % (client_path(p4.client), label)) s = "" changes = [] filerev = "%s@%s,@%s" % (path, prev["change"], last["change"]) for change in p4.run_changes(filerev): desc = p4.run_describe("-s", change["change"])[0] desc["time"] = ctime(int(desc["time"])) desc["files"] = "\t" + "\n\t".join(getlist(desc, "depotFile")) changes.append(CHANGE % desc) return "\n".join(changes) def get_client_list(p4): return sorted([client["client"] for client in p4.run_clients()]) def get_lable_list(p4, client=""): args = () if client: args = ("-c", client_path(client)) labels = [label for label in p4.rum_labels(*args)] labels.sort(lambda l1, l2: cmp(int(l2["Update"]), int(l1["Update"]))) return [label["label"] for label in labels] # UI WIDTH = 300 def add_button(self, sizer, caption, style=0, handler=None, id=-1): if style: b = wx.Button(self, id, caption, style=style) else: b = wx.Button(self, id, caption) if handler: self.Bind(wx.EVT_BUTTON, handler, b) sizer.Add(b) return b def get(ctrl): return ctrl.GetValue().strip() def error(msg): '''Show an error message''' msg = str(msg) # Make sure it's a string dlg = wx.MessageDialog(None, msg, "ChangeLog Error", wx.OK|wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() class ChlogUI(wx.Dialog): def __init__(self, client): wx.Dialog.__init__(self, None, -1, "Perforce Change Log") self.set_icon() sizer = wx.BoxSizer(wx.VERTICAL) gsizer = wx.FlexGridSizer(2, 3) # rows, cols gsizer.Add(wx.StaticText(self, -1, "Client:"), 0, wx.ALIGN_CENTER) self._client = wx.TextCtrl(self, -1, size=(WIDTH, -1)) self._client.SetValue(client) self.Bind(wx.EVT_TEXT, self.OnText, self._client) gsizer.Add(self._client, 0, wx.EXPAND) add_button(self, gsizer, "...", wx.BU_EXACTFIT, self.OnClient) gsizer.Add(wx.StaticText(self, -1, "Label:"), 0, wx.ALIGN_CENTER) self._label = wx.TextCtrl(self, -1, size=(WIDTH, -1)) gsizer.Add(self._label, 0, wx.EXPAND) self.Bind(wx.EVT_TEXT, self.OnText, self._label) add_button(self, gsizer, "...", wx.BU_EXACTFIT, self.OnLabel) sizer.Add(gsizer, 1, wx.EXPAND) hsizer = wx.BoxSizer(wx.HORIZONTAL) self._generate = \ add_button(self, hsizer, "Generate", handler=self.OnGenerate) self._generate.Disable() add_button(self, hsizer, "Quit", id=wx.ID_CANCEL) sizer.Add(hsizer, 0, wx.EXPAND) self.SetSizer(sizer) sizer.Fit(self) self.CenterOnScreen() if client: self._label.SetFocus() else: self._client.SetFocus() def set_icon(self): '''Set dialog icon''' # Icon appdir = path[0] if isfile(appdir): # py2exe appdir = dirname(appdir) iconfile = join(appdir, "addins.ico") if isfile(iconfile): icon = wx.Icon(iconfile, wx.BITMAP_TYPE_ICO) self.SetIcon(icon) def select(self, items, control, caption): dlg = wx.SingleChoiceDialog(self, "Please select on of the below", caption, items) if dlg.ShowModal() == wx.ID_OK: control.SetValue(dlg.GetStringSelection()) dlg.Destroy() def OnClient(self, evt): self.select(get_client_list(), self._client, "Select Client") def OnLabel(self, evt): labels = get_lable_list(self._client.GetValue().strip()) self.select(labels, self._label, "Select Label (newest first)") def OnText(self, evt): if get(self._client) and get(self._label): self._generate.Enable() else: self._generate.Disable() def OnGenerate(self, evt): msg = chlog(get(self._client), get(self._label)) dlg = ScrolledMessageDialog(self, msg, "Change Log") dlg.ShowModal() dlg.Destroy() if __name__ == "__main__": from os import environ from optparse import OptionParser # This need to be 1'st app = wx.PySimpleApp() parser = OptionParser("usage: %prog [options] PATH") parser.add_option("-u", help="user name", dest="user") parser.add_option("-c", help="client name", dest="client") parser.add_option("-p", help="server port", dest="port") opts, args = parser.parse_args() if len(args) != 1: error( if len(argv) not in (2, 3): err = "usage: changelog PORT [CLIENT]" error(err) raise SystemExit(1) if len(argv) == 2: try: client = environ["P4CLIENT"] except KeyError: client = "" else: client = argv[2] set_p4port(argv[1]) dlg = ChlogUI(client) dlg.ShowModal() dlg.Destroy()