Saturday, March 08, 2008

Creating a patch as a zip

#diffdiff.py
# Create a zip file containing the difference between two directories.
# Usage: python dirdiff.py newdir olddir [outputfile]
# Files files in newdir that are different in olddir or are not present
# will be zipped. If the outputfile parameter is not  provided the a 
# file diff.zip will be created.
#

from os import walk, stat
from os.path import join, sep, split
from sys import argv
from itertools import izip
from zipfile import ZipFile, ZIP_DEFLATED

def chop(base, path):
    if not base.endswith(sep):
        base = base + sep
    return path[len(base):]

def listfiles(path):
    for base, dirs, files in walk(path):
        for f in files:
            yield join(base, f)

def dirdiff(new_path, old_path, diff_file):
    zf = ZipFile(diff_file, "w")
    def write(file_path):
        zf.write(file_path, chop(new_path, file_path), ZIP_DEFLATED)
    for old, new in izip(walk(old_path), walk(new_path)):
        (old_base, old_dirs, old_files) = old
        (new_base, new_dirs, new_files) = new
        for d in set(new_dirs).difference(old_dirs):
            for f in listfiles(join(new_base, d)):
                write(f)
        for f in set(new_files).difference(old_files):
            write(join(new_base,f))
        fs = set(old_files) & set(new_files)
        ds = set(old_dirs) & set(new_dirs)
        old_dirs[:] = ds
        new_dirs[:] = ds
        for f in fs:
            file_old = join(old_base, f)
            file_new = join(new_base, f)
            if (stat(file_old).st_mtime != stat(file_new).st_mtime 
                and file(file_old).read()!=file(file_new).read()):
                write(join(new_base, f))
    zf.close()

if __name__ == "__main__":
    new = argv[1]
    old = argv[2]
    if len(argv) == 4:
        out=argv[3]
    else:
        out="diff.zip"
    dirdiff(new, old, out)

1 Comments:

At 6:48 AM, Blogger Arnar Birgisson said...

Reminds me of this feature in Trac:
http://trac.edgewall.org/ticket/303

 

Post a Comment

<< Home