From 32746249172760a6ce493ec78f12c360c3b2b7f6 Mon Sep 17 00:00:00 2001 From: "Kenneth G. Franqueiro" Date: Mon, 5 May 2014 21:30:12 -0400 Subject: [PATCH] Add support for `clean` option This adds support for a `clean` method/property, which receives a boolean indicating whether to remove the destination directory before writing. The default is `true` (consistent with previous behavior). Setting this to `false` can allow for use in situations where the source directory is a child of the destination directory, e.g. for gh-pages setups where the source is contained within the same repository. Note that moved/removed files will need to be cleaned up by other means. --- Readme.md | 4 +++ bin/metalsmith | 6 ++-- lib/index.js | 26 +++++++++++++-- test/fixtures/write-noclean/expected/empty.md | 0 test/fixtures/write-noclean/expected/index.md | 1 + test/index.js | 32 +++++++++++++++++++ 6 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/write-noclean/expected/empty.md create mode 100644 test/fixtures/write-noclean/expected/index.md diff --git a/Readme.md b/Readme.md index c2084e07..4660233c 100644 --- a/Readme.md +++ b/Readme.md @@ -139,6 +139,10 @@ Set the relative `path` to the source directory, or get the full one if no `path Set the relative `path` to the destination directory, or get the full one if no `path` is provided. The destination directory defaults to `./build`. +#### #clean(boolean) + +Set whether to remove the destination directory before writing to it, or get the current setting. Defaults to `true`. + #### #metadata(json) Get the global metadata. This is useful for plugins that want to set global-level metadata that can be applied to all files. diff --git a/bin/metalsmith b/bin/metalsmith index 593a5810..04d6a5ee 100755 --- a/bin/metalsmith +++ b/bin/metalsmith @@ -23,9 +23,9 @@ try { */ var metalsmith = new Metalsmith(process.cwd()); -if (json.source) metalsmith.source(json.source); -if (json.destination) metalsmith.destination(json.destination); -if (json.metadata) metalsmith.metadata(json.metadata); +['source', 'destination', 'metadata', 'clean'].forEach(function(key){ + if (json[key]) metalsmith[key](json[key]); +}); /** * Plugins. diff --git a/lib/index.js b/lib/index.js index f9a22727..8cd3d57f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -31,6 +31,7 @@ function Metalsmith(dir){ this.data = {}; this.source('src'); this.destination('build'); + this.clean(true); } /** @@ -84,6 +85,17 @@ Metalsmith.prototype.destination = function(path){ return this; }; +/** + * Get or set whether the destination directory will be removed before writing. + * @param {Boolean} clean + * @return {Boolean or Metalsmith} + */ +Metalsmith.prototype.clean = function(clean){ + if (!arguments.length) return this._clean; + this._clean = clean; + return this; +}; + /** * Join path `strs` with the working directory. * @@ -182,10 +194,18 @@ Metalsmith.prototype.read = function(fn){ Metalsmith.prototype.write = function(files, fn){ var dest = this.destination(); - rm(dest, function(err){ - if (err) return fn(err); + if (this.clean()) { + rm(dest, function(err){ + if (err) return fn(err); + writeAll(); + }); + } else { + writeAll(); + } + + function writeAll(){ each(Object.keys(files), write, fn); - }); + } function write(file, done){ var data = files[file]; diff --git a/test/fixtures/write-noclean/expected/empty.md b/test/fixtures/write-noclean/expected/empty.md new file mode 100644 index 00000000..e69de29b diff --git a/test/fixtures/write-noclean/expected/index.md b/test/fixtures/write-noclean/expected/index.md new file mode 100644 index 00000000..fb4c35e7 --- /dev/null +++ b/test/fixtures/write-noclean/expected/index.md @@ -0,0 +1 @@ +body \ No newline at end of file diff --git a/test/index.js b/test/index.js index 35728075..dff28bcc 100644 --- a/test/index.js +++ b/test/index.js @@ -35,6 +35,11 @@ describe('Metalsmith', function(){ assert('build' == m._dest); }); + it('should default clean to true', function(){ + var m = Metalsmith('test/tmp'); + assert(true === m._clean); + }); + describe('#use', function(){ it('should add a plugin to the middleware stack', function(){ var m = Metalsmith('test/tmp'); @@ -69,6 +74,19 @@ describe('Metalsmith', function(){ }); }); + describe('#clean', function(){ + it('should set the clean option', function(){ + var m = Metalsmith('test/tmp'); + m.clean(false); + assert(false === m._clean); + }); + + it('should get the value of the clean option', function(){ + var m = Metalsmith('test/tmp'); + assert(true === m.clean()); + }); + }); + describe('#metadata', function(){ it('should get metadata', function(){ var m = Metalsmith('test/tmp'); @@ -147,6 +165,20 @@ describe('Metalsmith', function(){ }); }); + it('should not remove existing destination directory if clean is false', function(done){ + var m = Metalsmith('test/fixtures/write-noclean'); + m.clean(false); + exec('mkdir -p test/fixtures/write-noclean/build && touch test/fixtures/write-noclean/build/empty.md', function(err){ + if (err) return done(err); + var files = { 'index.md': { contents: new Buffer('body') }}; + m.write(files, function(err){ + if (err) return done(err); + equal('test/fixtures/write-noclean/build', 'test/fixtures/write-noclean/expected'); + done(); + }); + }); + }); + it('should chmod an optional mode from file metadata', function(done){ var m = Metalsmith('test/fixtures/write-mode'); var files = {