Add manual aliasing to External.

This commit is contained in:
Young Hahn 2011-05-24 15:09:58 -04:00
parent a29f407c3e
commit 6e2d0e1b22
2 changed files with 54 additions and 79 deletions

View File

@ -15,38 +15,36 @@ var constants = ((!process.EEXIST) >= 1) ?
{ EEXIST: process.EEXIST };
function External(env, uri) {
function External(env, uri, alias) {
var local = !(/^https?:\/\//i.test(uri));
if (local) {
uri = path.join(env.local_data_dir, uri);
}
if (External.instances[uri]) return External.instances[uri];
local && (uri = path.join(env.local_data_dir, uri));
alias = (env.alias && alias) || crypto.createHash('md5').update(uri).digest('hex');
alias += path.extname(uri);
this.uri = uri;
this.env = env;
this.alias = alias;
this.format = path.extname(uri).toLowerCase();
this.type = External.findType(this.format);
this._callbacks = [];
this.done = false;
this.processor = External.processors[this.format];
this.tmp = local
? this.uri
: path.join(this.env.data_dir, this.alias);
External.mkdirp(this.env.data_dir, 0755);
if (local) {
this.localFile();
if (External.instances[this.path()]) {
return External.instances[this.path()];
} else {
this.downloadFile();
External.instances[this.path()] = this;
External.mkdirp(this.env.data_dir, 0755);
this.processFile(local);
}
External.instances[this.uri] = this;
}
sys.inherits(External, EventEmitter);
External.instances = {};
External.prototype.invokeCallbacks = function(err) {
delete External.instances[this.uri];
delete External.instances[this.path()];
if (err) {
this.emit('err', err);
} else {
@ -54,65 +52,34 @@ External.prototype.invokeCallbacks = function(err) {
}
};
External.prototype.processFile = function(local) {
var that = this;
fs.stat(that.path(), function(err, p) {
if (p) return that.invokeCallbacks();
External.prototype.localFile = function() {
// Only treat files as local that don't have to be processed.
this.isLocal = !External.processors[this.format];
this.tempPath = this.uri;
fs.stat(this.tempPath, this.processFile.bind(this));
};
External.prototype.downloadFile = function() {
this.tempPath = path.join(
this.env.data_dir,
crypto.createHash('md5').update(this.uri).digest('hex') +
path.extname(this.uri));
fs.stat(this.path(), function(err, stats) {
if (err) {
// This file does not yet exist. Download it!
(new get(this.uri)).toDisk(
this.tempPath,
this.processFile.bind(this));
} else {
this.invokeCallbacks(null);
}
}.bind(this));
};
External.prototype.processFile = function(err) {
if (err) {
this.invokeCallbacks(err);
} else {
if (this.isLocal) {
this.invokeCallbacks(null);
} else {
(External.processors[this.format] || External.processors['default'])(
this.tempPath,
this.path(),
function(err) {
if (err) {
this.invokeCallbacks(err);
} else {
this.invokeCallbacks(null);
}
}.bind(this)
);
}
}
Step(function() {
fs.stat(that.tmp, this);
},
function(err, t) {
if (t) return this();
if (local) throw new Error('File not found.');
return (new get(that.uri)).toDisk(that.tmp, this);
},
function(err) {
if (err) throw err;
if (that.processor) return that.processor(that.tmp, that.path(), this);
this();
},
function(err) {
that.invokeCallbacks(err);
});
});
};
External.prototype.path = function() {
if (this.isLocal) {
return this.tempPath;
} else {
return path.join(
this.env.data_dir,
(External.destinations[this.format] ||
External.destinations['default'])(this.uri)
);
}
return this.processor
? path.join(this.env.data_dir, External.destinations[this.format](this.alias))
: this.tmp;
};
External.prototype.findDataFile = function(callback) {
@ -258,11 +225,11 @@ External.findType = function(ext) {
// Destinations are names in the data_dir/cache directory.
External.destinations = {};
External.destinations['default'] = function(uri) {
return crypto.createHash('md5').update(uri).digest('hex') + path.extname(uri);
External.destinations['default'] = function(alias) {
return alias;
};
External.destinations['.zip'] = function(uri) {
return crypto.createHash('md5').update(uri).digest('hex');
External.destinations['.zip'] = function(alias) {
return path.basename(alias, path.extname(alias));
};
External.processors = {};
@ -273,7 +240,6 @@ External.processors['default'] = function(tempPath, destPath, callback) {
fs.rename(tempPath, destPath, callback);
}
};
External.processors['.zip'] = function(tempPath, destPath, callback) {
try {
sys.debug('unzipping file');
@ -314,6 +280,14 @@ External.processors['.zip'] = function(tempPath, destPath, callback) {
});
});
},
function(err) {
if (err) throw err;
if (path.dirname(tempPath) === path.dirname(destPath)) {
fs.unlink(tempPath, this);
} else {
this();
}
},
callback
);
};

View File

@ -15,6 +15,7 @@ require.paths.unshift(path.join(__dirname, '..', 'lib'));
// This is node-only for the time being.
carto.Renderer = function Renderer(env) {
env = _.extend({}, env);
if (!env.alias) env.alias = false;
if (!env.data_dir) env.data_dir = '/tmp/';
if (!env.local_data_dir) env.local_data_dir = '';
if (!env.validation_data) env.validation_data = false;
@ -91,7 +92,7 @@ carto.Renderer = function Renderer(env) {
return next(new Error('Layer does not have a datasource to download.'));
}
var external = new External(that.env, l.Datasource.file);
var external = new External(that.env, l.Datasource.file, l.name);
external.once('err', next)
external.once('complete', function(external) {
external.findDataFile(function(err, file) {
@ -124,7 +125,7 @@ carto.Renderer = function Renderer(env) {
// TODO: handle stylesheet externals
// that fail.
var next = group();
var external = new External(that.env, s);
var external = new External(that.env, s, path.basename(s));
external.once('complete', function(external) {
m.Stylesheet[k] = external.path();
next();