From c73ec397e0eee8ffdcf6befd641eeab3045564cc Mon Sep 17 00:00:00 2001 From: Mike Thomas Date: Thu, 15 Nov 2007 21:56:34 +0000 Subject: [PATCH] The old way I had the Directory-based bundlers checking for out-of-dateness was prone to error in the face of new files or unfortunate subdirectory situations. Now check on an entry-by-entry basis instead, which is much happier. git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@351 ed5b42cb-e716-0410-a449-f6a68f950b19 --- .../bundle/tools/ComponentBundlerTask.java | 97 ++++++++++--------- .../tools/DirectoryComponentBundlerTask.java | 15 ++- .../bundle/tools/DirectoryTileSetBundler.java | 32 +++--- .../tile/bundle/tools/TileSetBundler.java | 14 +-- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java index 92b092d1..483ea1a8 100644 --- a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java +++ b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java @@ -150,7 +150,8 @@ public class ComponentBundlerTask extends Task ArrayList sources = (ArrayList)_filesets.clone(); sources.add(_mapfile); sources.add(_actionDef); - if (!outOfDate(sources, _target)) { + long newest = getNewestDate(sources); + if (skipIfTargetNewer() && newest < _target.lastModified()) { System.out.println(_target.getPath() + " is up to date."); return; } @@ -205,7 +206,7 @@ public class ComponentBundlerTask extends Task mapping.put(cid, new Tuple(info[0], info[1])); // process and store the main component image - processComponent(info, aset, cfile, fout); + processComponent(info, aset, cfile, fout, newest); // pick up any auxiliary images as well like the shadow or // crop files @@ -216,17 +217,19 @@ public class ComponentBundlerTask extends Task FileUtil.resuffix(cfile, ext, AUX_EXTS[aa] + ext)); if (afile.exists()) { info[2] = action + AUX_EXTS[aa]; - processComponent(info, aset, afile, fout); + processComponent(info, aset, afile, fout, newest); } } } } // write our mapping table to the jar file as well - fout = nextEntry(fout, BundleUtil.COMPONENTS_PATH); - ObjectOutputStream oout = new ObjectOutputStream(fout); - oout.writeObject(mapping); - oout.flush(); + if (!skipEntry(BundleUtil.COMPONENTS_PATH, newest)) { + fout = nextEntry(fout, BundleUtil.COMPONENTS_PATH); + ObjectOutputStream oout = new ObjectOutputStream(fout); + oout.writeObject(mapping); + oout.flush(); + } // seal up our jar file fout.close(); @@ -245,12 +248,18 @@ public class ComponentBundlerTask extends Task } protected void processComponent ( - String[] info, TileSet aset, File cfile, OutputStream fout) + String[] info, TileSet aset, File cfile, OutputStream fout, long newest) throws IOException, BuildException { // construct the path that'll go in the jar file String ipath = composePath( info, BundleUtil.IMAGE_EXTENSION); + + // If we decide that the entry is up to date and we don't need to process it, bail out. + if (skipEntry(ipath, newest)) { + return; + } + fout = nextEntry(fout, ipath); // create a trimmed tileset based on the source action tileset and @@ -273,69 +282,59 @@ public class ComponentBundlerTask extends Task throw new BuildException(errmsg, t); } - // then write our trimmed tileset to the jar file + // then write our trimmed tileset bundle data if (tset != null) { + String tpath = composePath( info, BundleUtil.TILESET_EXTENSION); - fout = nextEntry(fout, tpath); + if (!skipEntry(tpath, newest)) { + fout = nextEntry(fout, tpath); - ObjectOutputStream oout = new ObjectOutputStream(fout); - oout.writeObject(tset); - oout.flush(); - } - } - - protected boolean outOfDate (ArrayList sources, File target) - { - for (int ii = 0; ii < sources.size(); ii++) { - if (outOfDate(sources.get(ii), target)) { - return true; + ObjectOutputStream oout = new ObjectOutputStream(fout); + oout.writeObject(tset); + oout.flush(); } } - return false; } - protected boolean outOfDate (Object source, File target) + protected long getNewestDate (ArrayList sources) + { + long newest = 0L; + for (int ii = 0; ii < sources.size(); ii++) { + newest = Math.max(newest, getNewestDate(sources.get(ii))); + } + return newest; + } + + protected long getNewestDate (Object source) { if (source instanceof FileSet) { FileSet fs = (FileSet)source; DirectoryScanner ds = fs.getDirectoryScanner(getProject()); File fromDir = fs.getDir(getProject()); String[] srcFiles = ds.getIncludedFiles(); - long tgtModificationDate = getTgtModificationDate(target); + long newest = 0L; for (int f = 0; f < srcFiles.length; f++) { File cfile = new File(fromDir, srcFiles[f]); - if (newer(cfile, tgtModificationDate)) { - return true; - } + newest = Math.max(newest, cfile.lastModified()); } - return false; + return newest; } else if (source instanceof File) { - return newer((File)source, getTgtModificationDate(target)); + return ((File)source).lastModified(); } else { - System.err.println("Can't compare " + source + - " to " + target + "."); - return true; + System.err.println("Can't get newest date for source: " + source + "."); + return 0L; } } /** - * Returns true if source is newer than - * target. + * Returns whether we should skip updating the bundle if the target is newer than any component. */ - protected boolean newer (File source, long tgtModificationDate) + protected boolean skipIfTargetNewer () { - return source.lastModified() > tgtModificationDate; - } - - /** - * Returns the last modified date of target to be compared for out-of-dateness. - */ - protected long getTgtModificationDate (File target) - { - return target.lastModified(); + return true; } /** @@ -470,6 +469,16 @@ public class ComponentBundlerTask extends Task return lastEntry; } + /** + * Returns whether we should skip the specified entry in the bundle, presumably if it was + * already created and up to date. + */ + protected boolean skipEntry (String path, long newest) + { + // If we're making the bundle, by default, we don't skip anything. + return false; + } + /** * Converts the tileset to a trimmed tile set and saves it at the specified location. */ diff --git a/src/java/com/threerings/cast/bundle/tools/DirectoryComponentBundlerTask.java b/src/java/com/threerings/cast/bundle/tools/DirectoryComponentBundlerTask.java index 543fd1f1..f1e6948f 100644 --- a/src/java/com/threerings/cast/bundle/tools/DirectoryComponentBundlerTask.java +++ b/src/java/com/threerings/cast/bundle/tools/DirectoryComponentBundlerTask.java @@ -46,6 +46,8 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask return null; } + + @Override // documentation inherited protected OutputStream nextEntry (OutputStream lastEntry, String path) throws IOException @@ -55,6 +57,13 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask return new FileOutputStream(file); } + @Override // documentation inherited + protected boolean skipEntry (String path, long newest) + { + File file = new File(_target, path); + return (file.lastModified() > newest); + } + @Override // documentation inherited protected TrimmedTileSet trim (TileSet aset, OutputStream fout) throws IOException @@ -63,9 +72,9 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask } @Override // documentation inherited - protected long getTgtModificationDate (File target) + protected boolean skipIfTargetNewer () { - // Return the oldest modification date of anything within the directory. - return FileUtil.getOldestLastModified(target); + // We have to check modification later on a file-by-file basis, so cannot skip. + return false; } } diff --git a/src/java/com/threerings/media/tile/bundle/tools/DirectoryTileSetBundler.java b/src/java/com/threerings/media/tile/bundle/tools/DirectoryTileSetBundler.java index 23c6f299..06affa6b 100644 --- a/src/java/com/threerings/media/tile/bundle/tools/DirectoryTileSetBundler.java +++ b/src/java/com/threerings/media/tile/bundle/tools/DirectoryTileSetBundler.java @@ -58,17 +58,9 @@ public class DirectoryTileSetBundler extends TileSetBundler super(configPath); } - /** - * Finish the creation of a tileset bundle jar file. - * - * @param target the tileset bundle file that will be created. - * @param bundle contains the tilesets we'd like to save out to the bundle. - * @param improv the image provider. - * @param imageBase the base directory for getting images for non - * ObjectTileSet tilesets. - */ + @Override // documentation inherited public boolean createBundle ( - File target, TileSetBundle bundle, ImageProvider improv, String imageBase) + File target, TileSetBundle bundle, ImageProvider improv, String imageBase, long newestMod) throws IOException { try { @@ -101,6 +93,10 @@ public class DirectoryTileSetBundler extends TileSetBundler // write the trimmed tileset image to the destination // output stream File outFile = new File(target, imagePath); + if (outFile.lastModified() > newestMod) { + // Our file's newer than the newest bundle mod - up to date. + continue; + } outFile.getParentFile().mkdirs(); FileOutputStream fout = new FileOutputStream(outFile); TrimmedObjectTileSet tset = @@ -123,9 +119,18 @@ public class DirectoryTileSetBundler extends TileSetBundler // read the image file and convert it to our custom // format in the bundle File ifile = new File(imageBase, imagePath); + if (ifile.lastModified() > newestMod) { + // Our file's newer than the newest bundle mod - up to date. + continue; + } + try { BufferedImage image = ImageIO.read(ifile); File outFile = new File(target, imagePath); + if (outFile.lastModified() > newestMod) { + // Our file's newer than the newest bundle mod - up to date. + continue; + } outFile.getParentFile().mkdirs(); FileOutputStream fout = new FileOutputStream(outFile); FileInputStream imgin = new FileInputStream(ifile); @@ -141,6 +146,7 @@ public class DirectoryTileSetBundler extends TileSetBundler // now write a serialized representation of the tileset bundle // object to the bundle jar file File outFile = new File(target, BundleUtil.METADATA_PATH); + outFile.getParentFile().mkdirs(); FileOutputStream fout = new FileOutputStream(outFile); ObjectOutputStream oout = new ObjectOutputStream(fout); @@ -156,9 +162,9 @@ public class DirectoryTileSetBundler extends TileSetBundler } @Override // documentation inherited - protected long getTgtModificationDate (File target) + protected boolean skipIfTargetNewer () { - // Return the oldest modification date of anything within the directory. - return FileUtil.getOldestLastModified(target); + // We have to check modification later on a file-by-file basis, so cannot skip. + return false; } } diff --git a/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java b/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java index fe0ddaa2..749e05ad 100644 --- a/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java +++ b/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java @@ -310,7 +310,7 @@ public class TileSetBundler } // see if our newest file is newer than the tileset bundle - if (newest < getTgtModificationDate(target)) { + if (skipIfTargetNewer() && newest < target.lastModified()) { return false; } @@ -322,7 +322,7 @@ public class TileSetBundler } }; - return createBundle(target, bundle, improv, bundleDesc.getParent()); + return createBundle(target, bundle, improv, bundleDesc.getParent(), newest); } /** @@ -332,10 +332,12 @@ public class TileSetBundler * @param bundle contains the tilesets we'd like to save out to the bundle. * @param improv the image provider. * @param imageBase the base directory for getting images for non + * @param newestMod the most recent modification to any part of the bundle. By default we + * ignore this since we normally duck out if we're up to date. * ObjectTileSet tilesets. */ public boolean createBundle ( - File target, TileSetBundle bundle, ImageProvider improv, String imageBase) + File target, TileSetBundle bundle, ImageProvider improv, String imageBase, long newestMod) throws IOException { return createBundleJar(target, bundle, improv, imageBase); @@ -455,11 +457,11 @@ public class TileSetBundler } /** - * Returns the last modified date of target to be compared for out-of-dateness. + * Returns whether we should skip updating the bundle if the target is newer than any component. */ - protected long getTgtModificationDate (File target) + protected boolean skipIfTargetNewer () { - return target.lastModified(); + return true; } /** Replaces the image suffix with .raw. */