cvslib.py :  » Mobile » Python-for-PalmOS » Python-1.5.2+reduced-1.0 » Demo » pdist » 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 » Mobile » Python for PalmOS 
Python for PalmOS » Python 1.5.2 reduced 1.0 » Demo » pdist » cvslib.py
"""Utilities for CVS administration."""

import string
import os
import time
import md5
import fnmatch

if not hasattr(time, 'timezone'):
  time.timezone = 0

class File:

  """Represent a file's status.

  Instance variables:

  file -- the filename (no slashes), None if uninitialized
  lseen -- true if the data for the local file is up to date
  eseen -- true if the data from the CVS/Entries entry is up to date
           (this implies that the entry must be written back)
  rseen -- true if the data for the remote file is up to date
  proxy -- RCSProxy instance used to contact the server, or None

  Note that lseen and rseen don't necessary mean that a local
  or remote file *exists* -- they indicate that we've checked it.
  However, eseen means that this instance corresponds to an
  entry in the CVS/Entries file.

  If lseen is true:
  
  lsum -- checksum of the local file, None if no local file
  lctime -- ctime of the local file, None if no local file
  lmtime -- mtime of the local file, None if no local file

  If eseen is true:

  erev -- revision, None if this is a no revision (not '0')
  enew -- true if this is an uncommitted added file
  edeleted -- true if this is an uncommitted removed file
  ectime -- ctime of last local file corresponding to erev
  emtime -- mtime of last local file corresponding to erev
  extra -- 5th string from CVS/Entries file

  If rseen is true:

  rrev -- revision of head, None if non-existent
  rsum -- checksum of that revision, Non if non-existent

  If eseen and rseen are both true:
  
  esum -- checksum of revision erev, None if no revision

  Note
  """

  def __init__(self, file = None):
    if file and '/' in file:
      raise ValueError, "no slash allowed in file"
    self.file = file
    self.lseen = self.eseen = self.rseen = 0
    self.proxy = None

  def __cmp__(self, other):
    return cmp(self.file, other.file)

  def getlocal(self):
    try:
      self.lmtime, self.lctime = os.stat(self.file)[-2:]
    except os.error:
      self.lmtime = self.lctime = self.lsum = None
    else:
      self.lsum = md5.md5(open(self.file).read()).digest()
    self.lseen = 1

  def getentry(self, line):
    words = string.splitfields(line, '/')
    if self.file and words[1] != self.file:
      raise ValueError, "file name mismatch"
    self.file = words[1]
    self.erev = words[2]
    self.edeleted = 0
    self.enew = 0
    self.ectime = self.emtime = None
    if self.erev[:1] == '-':
      self.edeleted = 1
      self.erev = self.erev[1:]
    if self.erev == '0':
      self.erev = None
      self.enew = 1
    else:
      dates = words[3]
      self.ectime = unctime(dates[:24])
      self.emtime = unctime(dates[25:])
    self.extra = words[4]
    if self.rseen:
      self.getesum()
    self.eseen = 1

  def getremote(self, proxy = None):
    if proxy:
      self.proxy = proxy
    try:
      self.rrev = self.proxy.head(self.file)
    except (os.error, IOError):
      self.rrev = None
    if self.rrev:
      self.rsum = self.proxy.sum(self.file)
    else:
      self.rsum = None
    if self.eseen:
      self.getesum()
    self.rseen = 1

  def getesum(self):
    if self.erev == self.rrev:
      self.esum = self.rsum
    elif self.erev:
      name = (self.file, self.erev)
      self.esum = self.proxy.sum(name)
    else:
      self.esum = None

  def putentry(self):
    """Return a line suitable for inclusion in CVS/Entries.

    The returned line is terminated by a newline.
    If no entry should be written for this file,
    return "".
    """
    if not self.eseen:
      return ""

    rev = self.erev or '0'
    if self.edeleted:
      rev = '-' + rev
    if self.enew:
      dates = 'Initial ' + self.file
    else:
      dates = gmctime(self.ectime) + ' ' + \
        gmctime(self.emtime)
    return "/%s/%s/%s/%s/\n" % (
      self.file,
      rev,
      dates,
      self.extra)

  def report(self):
    print '-'*50
    def r(key, repr=repr, self=self):
      try:
        value = repr(getattr(self, key))
      except AttributeError:
        value = "?"
      print "%-15s:" % key, value
    r("file")
    if self.lseen:
      r("lsum", hexify)
      r("lctime", gmctime)
      r("lmtime", gmctime)
    if self.eseen:
      r("erev")
      r("enew")
      r("edeleted")
      r("ectime", gmctime)
      r("emtime", gmctime)
    if self.rseen:
      r("rrev")
      r("rsum", hexify)
      if self.eseen:
        r("esum", hexify)


class CVS:
  
  """Represent the contents of a CVS admin file (and more).

  Class variables:

  FileClass -- the class to be instantiated for entries
               (this should be derived from class File above)
  IgnoreList -- shell patterns for local files to be ignored

  Instance variables:

  entries -- a dictionary containing File instances keyed by
             their file name
  proxy -- an RCSProxy instance, or None
  """
  
  FileClass = File

  IgnoreList = ['.*', '@*', ',*', '*~', '*.o', '*.a', '*.so', '*.pyc']
  
  def __init__(self):
    self.entries = {}
    self.proxy = None
  
  def setproxy(self, proxy):
    if proxy is self.proxy:
      return
    self.proxy = proxy
    for e in self.entries.values():
      e.rseen = 0
  
  def getentries(self):
    """Read the contents of CVS/Entries"""
    self.entries = {}
    f = self.cvsopen("Entries")
    while 1:
      line = f.readline()
      if not line: break
      e = self.FileClass()
      e.getentry(line)
      self.entries[e.file] = e
    f.close()
  
  def putentries(self):
    """Write CVS/Entries back"""
    f = self.cvsopen("Entries", 'w')
    for e in self.values():
      f.write(e.putentry())
    f.close()

  def getlocalfiles(self):
    list = self.entries.keys()
    addlist = os.listdir(os.curdir)
    for name in addlist:
      if name in list:
        continue
      if not self.ignored(name):
        list.append(name)
    list.sort()
    for file in list:
      try:
        e = self.entries[file]
      except KeyError:
        e = self.entries[file] = self.FileClass(file)
      e.getlocal()

  def getremotefiles(self, proxy = None):
    if proxy:
      self.proxy = proxy
    if not self.proxy:
      raise RuntimeError, "no RCS proxy"
    addlist = self.proxy.listfiles()
    for file in addlist:
      try:
        e = self.entries[file]
      except KeyError:
        e = self.entries[file] = self.FileClass(file)
      e.getremote(self.proxy)

  def report(self):
    for e in self.values():
      e.report()
    print '-'*50
  
  def keys(self):
    keys = self.entries.keys()
    keys.sort()
    return keys

  def values(self):
    def value(key, self=self):
      return self.entries[key]
    return map(value, self.keys())

  def items(self):
    def item(key, self=self):
      return (key, self.entries[key])
    return map(item, self.keys())

  def cvsexists(self, file):
    file = os.path.join("CVS", file)
    return os.path.exists(file)
  
  def cvsopen(self, file, mode = 'r'):
    file = os.path.join("CVS", file)
    if 'r' not in mode:
      self.backup(file)
    return open(file, mode)
  
  def backup(self, file):
    if os.path.isfile(file):
      bfile = file + '~'
      try: os.unlink(bfile)
      except os.error: pass
      os.rename(file, bfile)

  def ignored(self, file):
    if os.path.isdir(file): return 1
    for pat in self.IgnoreList:
      if fnmatch.fnmatch(file, pat): return 1
    return 0


# hexify and unhexify are useful to print MD5 checksums in hex format

hexify_format = '%02x' * 16
def hexify(sum):
  "Return a hex representation of a 16-byte string (e.g. an MD5 digest)"
  if sum is None:
    return "None"
  return hexify_format % tuple(map(ord, sum))

def unhexify(hexsum):
  "Return the original from a hexified string"
  if hexsum == "None":
    return None
  sum = ''
  for i in range(0, len(hexsum), 2):
    sum = sum + chr(string.atoi(hexsum[i:i+2], 16))
  return sum


unctime_monthmap = {}
def unctime(date):
  if date == "None": return None
  if not unctime_monthmap:
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    i = 0
    for m in months:
      i = i+1
      unctime_monthmap[m] = i
  words = string.split(date) # Day Mon DD HH:MM:SS YEAR
  year = string.atoi(words[4])
  month = unctime_monthmap[words[1]]
  day = string.atoi(words[2])
  [hh, mm, ss] = map(string.atoi, string.splitfields(words[3], ':'))
  ss = ss - time.timezone
  return time.mktime((year, month, day, hh, mm, ss, 0, 0, 0))

def gmctime(t):
  if t is None: return "None"
  return time.asctime(time.gmtime(t))

def test_unctime():
  now = int(time.time())
  t = time.gmtime(now)
  at = time.asctime(t)
  print 'GMT', now, at
  print 'timezone', time.timezone
  print 'local', time.ctime(now)
  u = unctime(at)
  print 'unctime()', u
  gu = time.gmtime(u)
  print '->', gu
  print time.asctime(gu)

def test():
  x = CVS()
  x.getentries()
  x.getlocalfiles()
##  x.report()
  import rcsclient
  proxy = rcsclient.openrcsclient()
  x.getremotefiles(proxy)
  x.report()


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