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
This commit is contained in:
Mike Thomas
2007-11-15 21:56:34 +00:00
parent c68df0bab2
commit c73ec397e0
4 changed files with 92 additions and 66 deletions
@@ -150,7 +150,8 @@ public class ComponentBundlerTask extends Task
ArrayList sources = (ArrayList)_filesets.clone(); ArrayList sources = (ArrayList)_filesets.clone();
sources.add(_mapfile); sources.add(_mapfile);
sources.add(_actionDef); 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."); System.out.println(_target.getPath() + " is up to date.");
return; return;
} }
@@ -205,7 +206,7 @@ public class ComponentBundlerTask extends Task
mapping.put(cid, new Tuple(info[0], info[1])); mapping.put(cid, new Tuple(info[0], info[1]));
// process and store the main component image // 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 // pick up any auxiliary images as well like the shadow or
// crop files // crop files
@@ -216,17 +217,19 @@ public class ComponentBundlerTask extends Task
FileUtil.resuffix(cfile, ext, AUX_EXTS[aa] + ext)); FileUtil.resuffix(cfile, ext, AUX_EXTS[aa] + ext));
if (afile.exists()) { if (afile.exists()) {
info[2] = action + AUX_EXTS[aa]; 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 // write our mapping table to the jar file as well
fout = nextEntry(fout, BundleUtil.COMPONENTS_PATH); if (!skipEntry(BundleUtil.COMPONENTS_PATH, newest)) {
ObjectOutputStream oout = new ObjectOutputStream(fout); fout = nextEntry(fout, BundleUtil.COMPONENTS_PATH);
oout.writeObject(mapping); ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.flush(); oout.writeObject(mapping);
oout.flush();
}
// seal up our jar file // seal up our jar file
fout.close(); fout.close();
@@ -245,12 +248,18 @@ public class ComponentBundlerTask extends Task
} }
protected void processComponent ( protected void processComponent (
String[] info, TileSet aset, File cfile, OutputStream fout) String[] info, TileSet aset, File cfile, OutputStream fout, long newest)
throws IOException, BuildException throws IOException, BuildException
{ {
// construct the path that'll go in the jar file // construct the path that'll go in the jar file
String ipath = composePath( String ipath = composePath(
info, BundleUtil.IMAGE_EXTENSION); 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); fout = nextEntry(fout, ipath);
// create a trimmed tileset based on the source action tileset and // 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); throw new BuildException(errmsg, t);
} }
// then write our trimmed tileset to the jar file // then write our trimmed tileset bundle data
if (tset != null) { if (tset != null) {
String tpath = composePath( String tpath = composePath(
info, BundleUtil.TILESET_EXTENSION); info, BundleUtil.TILESET_EXTENSION);
fout = nextEntry(fout, tpath); if (!skipEntry(tpath, newest)) {
fout = nextEntry(fout, tpath);
ObjectOutputStream oout = new ObjectOutputStream(fout); ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(tset); oout.writeObject(tset);
oout.flush(); 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;
} }
} }
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) { if (source instanceof FileSet) {
FileSet fs = (FileSet)source; FileSet fs = (FileSet)source;
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); DirectoryScanner ds = fs.getDirectoryScanner(getProject());
File fromDir = fs.getDir(getProject()); File fromDir = fs.getDir(getProject());
String[] srcFiles = ds.getIncludedFiles(); String[] srcFiles = ds.getIncludedFiles();
long tgtModificationDate = getTgtModificationDate(target); long newest = 0L;
for (int f = 0; f < srcFiles.length; f++) { for (int f = 0; f < srcFiles.length; f++) {
File cfile = new File(fromDir, srcFiles[f]); File cfile = new File(fromDir, srcFiles[f]);
if (newer(cfile, tgtModificationDate)) { newest = Math.max(newest, cfile.lastModified());
return true;
}
} }
return false; return newest;
} else if (source instanceof File) { } else if (source instanceof File) {
return newer((File)source, getTgtModificationDate(target)); return ((File)source).lastModified();
} else { } else {
System.err.println("Can't compare " + source + System.err.println("Can't get newest date for source: " + source + ".");
" to " + target + "."); return 0L;
return true;
} }
} }
/** /**
* Returns true if <code>source</code> is newer than * Returns whether we should skip updating the bundle if the target is newer than any component.
* <code>target</code>.
*/ */
protected boolean newer (File source, long tgtModificationDate) protected boolean skipIfTargetNewer ()
{ {
return source.lastModified() > tgtModificationDate; return true;
}
/**
* Returns the last modified date of <code>target</code> to be compared for out-of-dateness.
*/
protected long getTgtModificationDate (File target)
{
return target.lastModified();
} }
/** /**
@@ -470,6 +469,16 @@ public class ComponentBundlerTask extends Task
return lastEntry; 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. * Converts the tileset to a trimmed tile set and saves it at the specified location.
*/ */
@@ -46,6 +46,8 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask
return null; return null;
} }
@Override // documentation inherited @Override // documentation inherited
protected OutputStream nextEntry (OutputStream lastEntry, String path) protected OutputStream nextEntry (OutputStream lastEntry, String path)
throws IOException throws IOException
@@ -55,6 +57,13 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask
return new FileOutputStream(file); 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 @Override // documentation inherited
protected TrimmedTileSet trim (TileSet aset, OutputStream fout) protected TrimmedTileSet trim (TileSet aset, OutputStream fout)
throws IOException throws IOException
@@ -63,9 +72,9 @@ public class DirectoryComponentBundlerTask extends ComponentBundlerTask
} }
@Override // documentation inherited @Override // documentation inherited
protected long getTgtModificationDate (File target) protected boolean skipIfTargetNewer ()
{ {
// Return the oldest modification date of anything within the directory. // We have to check modification later on a file-by-file basis, so cannot skip.
return FileUtil.getOldestLastModified(target); return false;
} }
} }
@@ -58,17 +58,9 @@ public class DirectoryTileSetBundler extends TileSetBundler
super(configPath); super(configPath);
} }
/** @Override // documentation inherited
* 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.
*/
public boolean createBundle ( public boolean createBundle (
File target, TileSetBundle bundle, ImageProvider improv, String imageBase) File target, TileSetBundle bundle, ImageProvider improv, String imageBase, long newestMod)
throws IOException throws IOException
{ {
try { try {
@@ -101,6 +93,10 @@ public class DirectoryTileSetBundler extends TileSetBundler
// write the trimmed tileset image to the destination // write the trimmed tileset image to the destination
// output stream // output stream
File outFile = new File(target, imagePath); 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(); outFile.getParentFile().mkdirs();
FileOutputStream fout = new FileOutputStream(outFile); FileOutputStream fout = new FileOutputStream(outFile);
TrimmedObjectTileSet tset = TrimmedObjectTileSet tset =
@@ -123,9 +119,18 @@ public class DirectoryTileSetBundler extends TileSetBundler
// read the image file and convert it to our custom // read the image file and convert it to our custom
// format in the bundle // format in the bundle
File ifile = new File(imageBase, imagePath); File ifile = new File(imageBase, imagePath);
if (ifile.lastModified() > newestMod) {
// Our file's newer than the newest bundle mod - up to date.
continue;
}
try { try {
BufferedImage image = ImageIO.read(ifile); BufferedImage image = ImageIO.read(ifile);
File outFile = new File(target, imagePath); 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(); outFile.getParentFile().mkdirs();
FileOutputStream fout = new FileOutputStream(outFile); FileOutputStream fout = new FileOutputStream(outFile);
FileInputStream imgin = new FileInputStream(ifile); FileInputStream imgin = new FileInputStream(ifile);
@@ -141,6 +146,7 @@ public class DirectoryTileSetBundler extends TileSetBundler
// now write a serialized representation of the tileset bundle // now write a serialized representation of the tileset bundle
// object to the bundle jar file // object to the bundle jar file
File outFile = new File(target, BundleUtil.METADATA_PATH); File outFile = new File(target, BundleUtil.METADATA_PATH);
outFile.getParentFile().mkdirs(); outFile.getParentFile().mkdirs();
FileOutputStream fout = new FileOutputStream(outFile); FileOutputStream fout = new FileOutputStream(outFile);
ObjectOutputStream oout = new ObjectOutputStream(fout); ObjectOutputStream oout = new ObjectOutputStream(fout);
@@ -156,9 +162,9 @@ public class DirectoryTileSetBundler extends TileSetBundler
} }
@Override // documentation inherited @Override // documentation inherited
protected long getTgtModificationDate (File target) protected boolean skipIfTargetNewer ()
{ {
// Return the oldest modification date of anything within the directory. // We have to check modification later on a file-by-file basis, so cannot skip.
return FileUtil.getOldestLastModified(target); return false;
} }
} }
@@ -310,7 +310,7 @@ public class TileSetBundler
} }
// see if our newest file is newer than the tileset bundle // see if our newest file is newer than the tileset bundle
if (newest < getTgtModificationDate(target)) { if (skipIfTargetNewer() && newest < target.lastModified()) {
return false; 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 bundle contains the tilesets we'd like to save out to the bundle.
* @param improv the image provider. * @param improv the image provider.
* @param imageBase the base directory for getting images for non * @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. * ObjectTileSet tilesets.
*/ */
public boolean createBundle ( public boolean createBundle (
File target, TileSetBundle bundle, ImageProvider improv, String imageBase) File target, TileSetBundle bundle, ImageProvider improv, String imageBase, long newestMod)
throws IOException throws IOException
{ {
return createBundleJar(target, bundle, improv, imageBase); return createBundleJar(target, bundle, improv, imageBase);
@@ -455,11 +457,11 @@ public class TileSetBundler
} }
/** /**
* Returns the last modified date of <code>target</code> 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 <code>.raw</code>. */ /** Replaces the image suffix with <code>.raw</code>. */