id,summary,reporter,owner,description,type,status,priority,milestone,component,version,severity,resolution,keywords,cc,branch,changelog,apichanges,internalchanges 303,Get zip file with files changed in a changeset,arnarb@…,Christopher Lenz,"I develop software (in PHP) that needs to be deployed frequently to a Windows machine. Normally, I would use patches, but since that's nonstandard for Windows I have created by hand zip files containing changed files for each version. I then unzip the file on the target machine so that changed files are overwritten. It would be nice to be able to click a link on the changeset file and get in return a zip file containing the updated versions of changed/added files. Following is a small patch for a preliminary implementation of this {{{ Index: trac/Changeset.py =================================================================== --- trac/Changeset.py (revision 462) +++ trac/Changeset.py (working copy) @@ -151,6 +151,45 @@ def apply_textdelta(self, file_baton, base_checksum): self.print_diff (*file_baton) + def close(self): pass + +import zipfile +class ZipDiffEditor (delta.Editor): + def __init__(self,old_root,new_root,rev,output): + self.old_root = old_root + self.new_root = new_root + self.rev = rev + self.output = output + self.zip = zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) + + def addFileToZip(self, path, file_pool): + fd = fs.file_contents(self.new_root, path, file_pool) + info = zipfile.ZipInfo() + info.filename = path + date = fs.revision_prop(fs.root_fs(self.new_root), self.rev, util.SVN_PROP_REVISION_DATE, file_pool) + date = util.svn_time_from_cstring(date, file_pool) / 1000000 + date = time.localtime(date) + info.date_time = date[0:6] + info.compress_type = zipfile.ZIP_DEFLATED + data = """" + while 1: + chunk = util.svn_stream_read(fd, 512) + if not chunk: + break + data = data + chunk + self.zip.writestr(info, data) + + def add_file(self, path, parent_baton, copyfrom_path, + copyfrom_revision, file_pool): + self.addFileToZip(path, file_pool) + + def open_file(self, path, parent_baton, base_revision, file_pool): + self.addFileToZip(path, file_pool) + + def close(self): + self.zip.close() + + class UnifiedDiffEditor(HtmlDiffEditor): """""" generates a unified diff of the changes for a given changeset. @@ -199,6 +238,7 @@ repos.svn_repos_dir_delta(old_root, '', '', new_root, '', e_ptr, e_baton, authz_cb, 0, 1, 0, 1, pool) + editor.close() return output.getvalue() class Changeset (Module): @@ -266,5 +306,13 @@ self.req.end_headers() difftext = render_diffs(self.fs_ptr, int(self.rev), self.pool, UnifiedDiffEditor) self.req.write(difftext) + + def display_zipdiff (self): + self.req.send_response(200) + self.req.send_header('Content-Type', 'application/zip') + #self.req.send_header('Content-Type', 'text/plain') + self.req.end_headers() + difftext = render_diffs(self.fs_ptr, int(self.rev), self.pool, ZipDiffEditor) + self.req.write(difftext) Index: templates/changeset.cs =================================================================== --- templates/changeset.cs (revision 462) +++ templates/changeset.cs (working copy) @@ -2,6 +2,7 @@