Code

- fix some format errors in italian translation
[roundup.git] / roundup / install_util.py
index 5a47e4f92fee57868cc2ad51e916731a8380b163..51becb0880fffc929ee93ee67a914d96392ababa 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: install_util.py,v 1.1 2001-11-12 22:26:32 jhermann Exp $
+# $Id: install_util.py,v 1.11 2006-01-25 03:11:43 richard Exp $
 
-import os, sha
+"""Support module to generate and check fingerprints of installed files.
+"""
+__docformat__ = 'restructuredtext'
 
+import os, shutil
+from roundup.anypy.hashlib_ import sha1
+
+sgml_file_types = [".xml", ".ent", ".html"]
+hash_file_types = [".py", ".sh", ".conf", ".cgi"]
+slast_file_types = [".css"]
+
+digested_file_types = sgml_file_types + hash_file_types + slast_file_types
+
+def extractFingerprint(lines):
+    # get fingerprint from last line
+    if lines[-1].startswith("#SHA: "):
+        # handle .py/.sh comment
+        return lines[-1][6:].strip()
+    elif lines[-1].startswith("<!-- SHA: "):
+        # handle xml/html files
+        fingerprint = lines[-1][10:]
+        fingerprint = fingerprint.replace('-->', '')
+        return fingerprint.strip()
+    elif lines[-1].startswith("/* SHA: "):
+        # handle css files
+        fingerprint = lines[-1][8:]
+        fingerprint = fingerprint.replace('*/', '')
+        return fingerprint.strip()
+    return None
 
 def checkDigest(filename):
     """Read file, check for valid fingerprint, return TRUE if ok"""
@@ -27,21 +54,13 @@ def checkDigest(filename):
     lines = inp.readlines()
     inp.close()
 
-    # get fingerprint from last line
-    if lines[-1][:6] == "#SHA: ":
-        # handle .py/.sh comment
-        fingerprint = lines[-1][6:].strip()
-    elif lines[-1][:10] == "<!-- SHA: ":
-        # handle xml files
-        fingerprint = lines[-1][10:]
-        fingerprint = fingerprint.replace('-->', '')
-        fingerprint = fingerprint.strip()
-    else:
+    fingerprint = extractFingerprint(lines)
+    if fingerprint is None:
         return 0
     del lines[-1]
 
     # calculate current digest
-    digest = sha.new()
+    digest = sha1()
     for line in lines:
         digest.update(line)
 
@@ -56,49 +75,85 @@ class DigestFile:
 
     def __init__(self, filename):
         self.filename = filename
-        self.digest = sha.new()
+        self.digest = sha1()
         self.file = open(self.filename, "w")
 
     def write(self, data):
+        lines = data.splitlines()
+        # if the file is coming from an installed tracker being used as a
+        # template, then we will want to re-calculate the SHA
+        fingerprint = extractFingerprint(lines)
+        if fingerprint is not None:
+            data = '\n'.join(lines[:-1]) + '\n'
         self.file.write(data)
         self.digest.update(data)
 
     def close(self):
         file, ext = os.path.splitext(self.filename)
 
-        if ext in [".xml", ".ent"]:
+        if ext in sgml_file_types:
             self.file.write("<!-- SHA: %s -->\n" % (self.digest.hexdigest(),))
-        elif ext in [".py", ".sh", ".conf", '']:
+        elif ext in hash_file_types:
             self.file.write("#SHA: %s\n" % (self.digest.hexdigest(),))
+        elif ext in slast_file_types:
+            self.file.write("/* SHA: %s */\n" % (self.digest.hexdigest(),))
 
         self.file.close()
 
 
+def copyDigestedFile(src, dst, copystat=1):
+    """ Copy data from `src` to `dst`, adding a fingerprint to `dst`.
+        If `copystat` is true, the file status is copied, too
+        (like shutil.copy2).
+    """
+    if os.path.isdir(dst):
+        dst = os.path.join(dst, os.path.basename(src))
+
+    dummy, ext = os.path.splitext(src)
+    if ext not in digested_file_types:
+        if copystat:
+            return shutil.copy2(src, dst)
+        else:
+            return shutil.copyfile(src, dst)
+
+    fsrc = None
+    fdst = None
+    try:
+        fsrc = open(src, 'r')
+        fdst = DigestFile(dst)
+        shutil.copyfileobj(fsrc, fdst)
+    finally:
+        if fdst: fdst.close()
+        if fsrc: fsrc.close()
+
+    if copystat: shutil.copystat(src, dst)
+
+
 def test():
     import sys
 
     testdata = open(sys.argv[0], 'r').read()
-    testfile = "digest_test.py"
 
-    out = DigestFile(testfile)
-    out.write(testdata)
-    out.close()
+    for ext in digested_file_types:
+        testfile = "__digest_test" + ext
+
+        out = DigestFile(testfile)
+        out.write(testdata)
+        out.close()
 
-    assert checkDigest(testfile), "digest ok w/o modification"
+        assert checkDigest(testfile), "digest ok w/o modification"
 
-    mod = open(testfile, 'r+')
-    mod.seek(0)
-    mod.write('# changed!')
-    mod.close()
+        mod = open(testfile, 'r+')
+        mod.seek(0)
+        mod.write('# changed!')
+        mod.close()
 
-    assert not checkDigest(testfile), "digest fails after modification"
+        assert not checkDigest(testfile), "digest fails after modification"
 
-    os.remove(testfile)
+        os.remove(testfile)
 
 
 if __name__ == '__main__':
     test()
 
-#
-# $Log: not supported by cvs2svn $
-
+# vim: set filetype=python ts=4 sw=4 et si