ChangeLog.py :  » Template-Engines » Clearsilver » clearsilver-0.10.5 » scripts » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Template Engines » Clearsilver 
Clearsilver » clearsilver 0.10.5 » scripts » ChangeLog.py
#!/neo/opt/bin/python

import sys, os, string, re, getopt, pwd, socket, time

def warn(*args):
  t = time.time()
  log_line = "[" + time.strftime("%m/%d %T", time.localtime(t)) + "] "
  l = []
  for arg in args:
    l.append(str(arg))
  log_line = log_line + string.join(l, " ") + "\n"
  sys.stderr.write(log_line)

class ChangeLog:
  def __init__ (self, module, release_from, release_to, copydir = None, cvsroot=None):
    self._module = module
    self._releaseFrom = release_from
    self._releaseTo = release_to
    self._cvsroot = cvsroot
    if cvsroot is None:
      self._cvsroot = os.environ.get("CVSROOT", None)

    self._copydir = copydir
    if copydir is None: 
      self._copydir = os.getcwd()
    self._names = {}

  def changeInfo (self):
    cmd = self.cvsCmd ("-q", "rdiff", "-s -r%s -r%s %s" % (self._releaseFrom, self._releaseTo, self._module))
    warn (cmd)
    fpi = os.popen (cmd)
    data = fpi.readlines()
    r = fpi.close()
    if r is None: r = 0
    if r != 0:
      warn ("Return code from command is %d\n" % r)
      return

    self.oldfiles = {}
    self.newfiles = []
    self.delfiles = []
    old_re = re.compile ("File (.*) changed from revision (.*) to (.*)")
    new_re = re.compile ("File (.*) is new; current revision (.*)")
    del_re = re.compile ("File (.*) is removed;")
    for line in data:
      m = old_re.match (line)
      if m:
        file = m.group(1)
        if file[:len(self._module)+1] == "%s/" % self._module:
          file = file[len(self._module)+1:]
        self.oldfiles[file] = (m.group(2), m.group(3))
        continue
      m = new_re.match (line)
      if m:
        file = m.group(1)
        if file[:len(self._module)+1] == "%s/" % self._module:
          file = file[len(self._module)+1:]
        self.newfiles.append(file)
        continue
      m = del_re.match (line)
      if m: 
        file = m.group(1)
        if file[:len(self._module)+1] == "%s/" % self._module:
          file = file[len(self._module)+1:]
        self.delfiles.append(file)
        continue
      warn ("Unknown response from changeInfo request:\n  %s" % line)

  def parselog (self, log):
    lines = string.split (log, '\n')
    in_header = 1
    x = 0
    num = len(lines)
    revisions = {}
    revision = None
    comment = []
    info_re = re.compile ("date: ([^; ]*) ([^;]*);  author: ([^;]*);")
    while (x < num):
      line = string.strip(lines[x])
      if line:
        if (x + 1 < num):
          nline = string.strip(lines[x+1])
        else:
          nline = None
        if in_header:
          (key, value) = string.split (line, ':', 1)
          if key == "Working file":
            filename = string.strip (value)
          elif key == "description":
            in_header = 0
        else:
          if (line == "----------------------------") and (nline[:9] == "revision "):
            if revision is not None:
              key = (date, author, string.join (comment, '\n'))
              try:
                revisions[key].append((filename, revision))
              except KeyError:
                revisions[key] = [(filename, revision)]
              comment = []
          elif line == "=" * 77:
            key = (date, author, string.join (comment, '\n'))
            try:
              revisions[key].append((filename, revision))
            except KeyError:
              revisions[key] = [(filename, revision)]
            in_header = 1
            revision = None
            comment = []
          elif line[:9] == "revision ":
            (rev, revision) = string.split (lines[x])
          else:
            m = info_re.match (lines[x])
            if m:
              date = m.group(1)
              author = m.group(3)
            else:
              comment.append (lines[x])
      x = x + 1
    return revisions

  def rcs2log (self):
    cwd = os.getcwd()
    os.chdir(self._copydir)
    files = string.join (self.oldfiles.keys(), ' ')
    cmd = 'rcs2log -v -r "-r%s:%s" %s' % (self._releaseFrom, self._releaseTo, files)
    fpi = os.popen (cmd)
    data = fpi.read()
    r = fpi.close()
    os.chdir(cwd)
    if r is None: r = 0
    if r != 0:
      warn (cmd)
      warn ("Return code from command is %d\n" % r)
      return

    fpo = open ("ChangeLog.%s" % self._releaseTo, 'w')
    fpo.write(data)
    fpo.close()

  def runCmd (self, cmd):
    cwd = os.getcwd()
    os.chdir(self._copydir)
    warn (cmd)
    fpi = os.popen (cmd)
    data = fpi.read()
    r = fpi.close()
    os.chdir(cwd)
    if r is None: r = 0
    if r != 0:
      warn ("Return code from command is %d\n" % r)
      return None
    return data

  def rcslog (self):
    inverted_log = {}
    if len(self.newfiles):
      cmd = self.cvsCmd ("", "log", "-N %s" % string.join(self.newfiles,' '))
      data = self.runCmd (cmd)
      if data is None: return
      revisions = self.parselog (data)
      for (key, value) in revisions.items():
        try:
          inverted_log[key] = inverted_log[key] + value
        except KeyError:
          inverted_log[key] = value

    filenames = string.join (self.oldfiles.keys(), ' ')
    if filenames:
      cmd = self.cvsCmd ("", "log", "-N -r%s:%s %s" % (self._releaseFrom, self._releaseTo, filenames))
      data = self.runCmd (cmd)
      if data is not None: 
        revisions = self.parselog (data)
        for (key, value) in revisions.items():
          for (filename, revision) in value:
            (rev1, rev2) = self.oldfiles[filename]
            if revision != rev1:
              try:
                inverted_log[key].append((filename, revision))
              except KeyError:
                inverted_log[key] = [(filename, revision)]

    fpo = open ("ChangeLog.%s" % self._releaseTo, 'w')
    fpo.write ("ChangeLog from %s to %s\n" % (self._releaseFrom, self._releaseTo))
    fpo.write ("=" * 72 + "\n")
    changes = inverted_log.items()
    changes.sort()
    changes.reverse()
    last_stamp = ""
    for (key, value) in changes:
      (date, author, comment) = key
      new_stamp = "%s  %s" % (date, self.fullname(author))
      if new_stamp != last_stamp:
        fpo.write ("%s\n\n" % new_stamp)
        last_stamp = new_stamp
      for (filename, revision) in value:
        fpo.write ("  * %s:%s\n" % (filename, revision))
      fpo.write ("    %s\n\n" % comment)
      
    fpo.close()

  def cvsCmd (self, cvsargs, cmd, cmdargs):
    root = ""
    if self._cvsroot is not None:
      root = "-d %s" % self._cvsroot

    cmd = "cvs -z3 %s %s %s %s" % (root, cvsargs, cmd, cmdargs)
    return cmd

  def fullname (self, author):
    try:
      return self._names[author]
    except KeyError:
      try:
        (name, passwd, uid, gid, gecos, dir, shell) = pwd.getpwnam(author)
        fullname = "%s  <%s@%s>" % (gecos, name, socket.gethostname())
      except KeyError:
        fullname = author

      self._names[author] = fullname
      return fullname
      

def usage (argv0):
  print "usage: %s [--help] module release1 release2" % argv0
  print __doc__

def main (argv, stdout, environ):
  list, args = getopt.getopt(argv[1:], "", ["help"])

  for (field, val) in list:
    if field == "--help":
      usage (argv[0])
      return

  if len (args) < 3:
    usage (argv[0])
    return

  cl = ChangeLog (args[0], args[1], args[2])
  cl.changeInfo()
  cl.rcslog()
  

if __name__ == "__main__":
  main (sys.argv, sys.stdout, os.environ)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.