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