1 #!/usr/bin/env python 2 3 """ 4 Merge page packages. 5 6 Copyright (C) 2013 Paul Boddie <paul@boddie.org.uk> 7 8 This software is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of 11 the License, or (at your option) any later version. 12 13 This software is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public 19 License along with this library; see the file LICENCE.txt 20 If not, write to the Free Software Foundation, Inc., 21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 """ 23 24 from os import chdir, getcwd, makedirs, mkdir, walk 25 from os.path import exists, extsep, join, normpath, relpath, split, splitext 26 from shutil import copy 27 from zipfile import ZipFile 28 from cStringIO import StringIO 29 import sys 30 31 def get_filenames(package): 32 results = [] 33 for path, dirnames, filenames in walk(package): 34 path = relpath(path, package) 35 for filename in filenames: 36 results.append(normpath(join(path, filename))) 37 return results 38 39 # Main program. 40 41 if __name__ == "__main__": 42 packages = sys.argv[2:] 43 44 if not packages: 45 print >>sys.stderr, """ 46 Please specify an output basename followed by a list of page packages. 47 For example: 48 49 %(progname)s OUT COM.zip DEV.zip DOC.zip SEC.zip 50 51 As a result of running this program, a page package will be created at the 52 specified basename along with an archive of the form OUT.zip given a basename of 53 OUT. 54 """ % {"progname" : split(sys.argv[0])[-1]} 55 56 sys.exit(1) 57 58 outdir = sys.argv[1] 59 outleafname = split(outdir)[-1] 60 61 if exists(outdir): 62 print >>sys.stderr, "Directory %s exists already. Please choose another or remove its contents." % outdir 63 sys.exit(1) 64 65 package_zip = outdir + extsep + "zip" 66 67 if exists(package_zip): 68 print >>sys.stderr, "Page package exists. Please remove or rename it:", package_zip 69 sys.exit(1) 70 71 # Make the output directory for the merged packages. 72 73 mkdir(outdir) 74 75 # Collect entries from all packages for sorting. 76 77 entries = [] 78 79 for package in packages: 80 is_zipfile = splitext(package)[-1] == extsep + "zip" 81 leafname = split(package)[-1] 82 83 if is_zipfile: 84 f = open(package, "rb") 85 zf = ZipFile(f) 86 ff = StringIO(zf.read("MOIN_PACKAGE")) 87 else: 88 ff = open(join(package, "MOIN_PACKAGE")) 89 90 try: 91 # Skip the first line and get the manifest entries. 92 # NOTE: We could use the MoinMoin.package API here. 93 94 ff.readline() 95 entries += [x.rstrip("\n").split("|") for x in ff.readlines()] 96 97 # Copy files from the package into the output directory. 98 99 if is_zipfile: 100 filenames = zf.namelist() 101 else: 102 filenames = get_filenames(package) 103 104 for filename in filenames: 105 if split(filename)[-1] == "MOIN_PACKAGE": 106 continue 107 108 # Extract files, tidying up any filesystem pathnames. 109 110 if is_zipfile: 111 zf.extract(filename, outdir) 112 else: 113 target = join(outdir, leafname, filename) 114 target_dir = split(target)[0] 115 if not exists(target_dir): 116 makedirs(target_dir) 117 copy(join(package, filename), target) 118 119 finally: 120 ff.close() 121 if is_zipfile: 122 zf.close() 123 124 # The final entry in each element is the mtime. 125 126 entries.sort(cmp=lambda x, y: cmp(int(x[-1]), int(y[-1]))) 127 128 # Write the combined manifest to the output directory. 129 130 output_manifest = join(outdir, "MOIN_PACKAGE") 131 132 f = open(output_manifest, "w") 133 write = f.write 134 try: 135 write("MoinMoinPackage|1\n") 136 for entry in entries: 137 write("|".join(entry) + "\n") 138 finally: 139 f.close() 140 141 # Write the page package. 142 143 page_package = ZipFile(package_zip, "w") 144 145 try: 146 page_package.write(join(outdir, "MOIN_PACKAGE"), "MOIN_PACKAGE") 147 148 for filename in get_filenames(outdir): 149 if split(filename)[-1] == "MOIN_PACKAGE": 150 continue 151 152 page_package.write(join(outleafname, filename), filename) 153 finally: 154 page_package.close() 155 156 # vim: tabstop=4 expandtab shiftwidth=4