changelog.py #2

  • //
  • guest/
  • miki_tebeka/
  • p4vaddins/
  • main/
  • changelog.py
  • View
  • Commits
  • Open Download .zip Download (5 KB)
#!/usr/bin/env python
'''Print changes from last label '''

# Copyright (c) 2006 Qualcomm
# Miki Tebeka <[email protected]>

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()
# Change User Description Committed
#2 5382 Miki Tebeka * Start of UNIX - File format and #!
* getvalue returns string (not unicode in some cases)
#1 5280 Miki Tebeka Initial checkin of project