]> thyrsus.com Git - comparator.git/commitdiff
Initial revision
authorEric S. Raymond <esr@thyrsus.com>
Sat, 30 Aug 2003 00:17:52 +0000 (00:17 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Sat, 30 Aug 2003 00:17:52 +0000 (00:17 +0000)
shredtree.py [new file with mode: 0755]

diff --git a/shredtree.py b/shredtree.py
new file mode 100755 (executable)
index 0000000..6f31a04
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# shredtree -- generate hash list in SHIF-A format for a given source tree
+
+import sys, os, os.path, re, md5, getopt
+import shred
+
+ws = re.compile(r"[ \t\n]+")
+
+def eligible(file):
+    "Is a file eligible for comparison?"
+    (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, st_size,
+     st_atime, st_mtime, st_ctime) = os.stat(file)
+    if st_size <= 0:
+        return False
+    elif c_only:
+        return filter(lambda x: file.endswith(x), ('.c','h','.txt'))
+    else:
+        return True
+
+def normalize(line):
+    if ws:
+        return ws.sub('', line)
+    else:
+        return line
+
+def emit_chunk(display, linecount):
+    m = md5.new()
+    for line in display:
+        if debug:
+            print `line[0]`
+        m.update(line[0])
+    print "%d\t%d\t%s" % (display[0][1], linecount, m.hexdigest())
+
+def shredfile(file):
+    "Emit shred tuples corresponding to a specified file."
+    print file
+    fp = open(file, "r")
+    display = []
+
+    accepted = linecount = 0;
+    while True:
+        line = fp.readline()
+        if not line:
+            break
+       linecount += 1;
+        line = normalize(line)
+        if not line:
+           continue;
+       accepted += 1
+
+       # create new shred
+        display.append((line, linecount))
+
+       # flush completed chunk
+        if accepted >= shredsize:
+           emit_chunk(display, linecount)
+
+       # shreds in progress are shifted down */
+        if len(display) >= shredsize:
+            display = display[1:]
+
+    fp.close()
+    if linecount < shredsize:
+       emit_chunk(display, linecount)
+    print ""
+
+if __name__ == '__main__':
+    try:
+        (optlist, args) = getopt.getopt(sys.argv[1:], 'cdhs:w')
+    except getopt.GetoptError:
+        sys.stderr.write("usage: shredtree [-c] [-d] [-w] [-s shredsize] tree\n")
+        sys.exit(2)
+    shredsize = 5
+    ws = debug = c_only = False
+    for (opt, val) in optlist:
+        if opt == '-c':
+            c_only = True
+        elif opt == '-d':
+            debug = True
+        elif opt == '-h':
+           sys.stderr.write("usage: shredtree [-c] [-s size] [-w] path\n");
+           sys.stderr.write(" -c      = do .c, .h, and .txt files only.\n");
+           sys.stderr.write(" -d      = debug, display chunks in output.\n");
+           sys.stderr.write(" -h      = help (display this message).\n");
+           sys.stderr.write(" -s size = set shred size (default %d)\n",
+                   shredsize);
+           sys.stderr.write(" -w      = remove whitespace.\n");
+           sys.exit(0);
+        elif opt == '-s':
+            shredsize = int(val)
+        elif opt == '-w':
+            ws = True
+    if args:
+        print "#SHIF-A 1.0"
+        print "Generator: shredtree.py 1.0"
+        print "Hash: MD5"
+        print "Shred-Size: %d" % shredsize
+        normalization = []
+        if ws: normalization.append("remove_whitespace")
+        if not normalization:
+            normalization.append("none")
+        print "Normalization: %s" % ",".join(normalization);
+        print "%%"        
+        filenames = []
+        for root, dirs, files in os.walk(args[0]):
+            for file in files:
+                fullpath = os.path.join(root, file)
+                if eligible(fullpath):
+                    filenames.append(fullpath)
+        filenames.sort()
+        for path in filenames:
+            shredfile(path)
+# End