Skip to content

Commit

Permalink
add support for copying empty directories.
Browse files Browse the repository at this point in the history
this has been another big user request that should fit nicely along side
the new cwd option.
  • Loading branch information
ctalkington committed Nov 30, 2012
1 parent 66f6fc2 commit 3a3c591
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 127 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ v0.4.0:
data: 2012-12-xx
changes:
- Conversion to grunt v0.4 conventions.
- Replace basePath with cwd
- Replace basePath with cwd.
- Empty directory support.
v0.3.2:
date: 2012-10-18
changes:
- Pass copyOptions on single file copy
- Pass copyOptions on single file copy.
v0.3.1:
date: 2012-10-12
changes:
Expand Down
13 changes: 10 additions & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
module.exports = function(grunt) {
'use strict';

// Make an empty dir for testing as git doesn't track empty folders.
grunt.file.mkdir('test/fixtures/empty_folder');
grunt.file.mkdir('test/expected/copy_test_mix/empty_folder');

// Project configuration.
grunt.initConfig({
jshint: {
Expand All @@ -29,7 +33,8 @@ module.exports = function(grunt) {

test_vars: {
name: 'grunt-contrib-copy',
version: '0.1.0'
version: '0.1.0',
match: 'folder_one/*'
},

// Configuration to be run (and then tested).
Expand All @@ -39,8 +44,9 @@ module.exports = function(grunt) {
cwd: 'test/fixtures'
},
files: {
'tmp/copy_test_files/': ['*'],
'tmp/copy_test_v<%= test_vars.version %>/': ['**']
'tmp/copy_test_files/': ['*.*'],
'tmp/copy_test_mix/': ['**'],
'tmp/copy_test_v<%= test_vars.version %>/': ['<%= test_vars.match %>']
}
},

Expand All @@ -56,6 +62,7 @@ module.exports = function(grunt) {
minimatch: {
options: {
cwd: 'test/fixtures',
excludeEmpty: true,
minimatch: {
dot: true
}
Expand Down
236 changes: 121 additions & 115 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,115 +1,121 @@
# grunt-contrib-copy [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-contrib-copy.png?branch=master)](http://travis-ci.org/gruntjs/grunt-contrib-copy)

> Copy files and folders.

## Getting Started
If you haven't used [grunt][] before, be sure to check out the [Getting Started][] guide, as it explains how to create a [gruntfile][Getting Started] as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:

```shell
npm install grunt-contrib-copy --save-dev
```

[grunt]: http://gruntjs.com/
[Getting Started]: https://github.com/gruntjs/grunt/blob/devel/docs/getting_started.md


## Copy task
_Run this task with the `grunt copy` command._

_This task is a [multi task][] so any targets, files and options should be specified according to the [multi task][] documentation._
[multi task]: https://github.com/gruntjs/grunt/wiki/Configuring-tasks


### Options

#### cwd
Type: `String`

This option sets the current working directory for use with the minimatch and copy process. This helps translate paths when copied so that the destination stucture matches the source structure exactly. Without a `cwd` set, all paths are relative to the gruntfile directory which can cause extra depth to be added to your copied structure when it may not be desired.

When copying to a directory you must add a trailing slash to the destination due to added support of single file copy.

```js
copy: {
target: {
options: {
cwd: 'path/to/sources'
},
files: {
'tmp/test/': ['*', 'sub1/*']
}
}
}
```

#### flatten
Type: `Boolean`
Default: false

This option performs a flat copy that dumps all the files into the root of the destination directory, overwriting files if they exist.

#### processName
Type: `Function`

This option accepts a function that adjusts the filename of the copied file. Function is passed filename and should return a string.

```js
options: {
processName: function(filename) {
if (filename == "test.jpg") {
filename = "newname.jpg";
}
return filename;
}
}
```

#### processContent
Type: `Function`

This option is passed to `grunt.file.copy` as an advanced way to control the file contents that are copied.

#### processContentExclude
Type: `String`

This option is passed to `grunt.file.copy` as an advanced way to control which file contents are processed.

#### minimatch
Type: `Object`

These options will be forwarded on to expandFiles, as referenced in the [minimatch options section](https://github.com/isaacs/minimatch/#options)

### Usage Examples

```js
copy: {
dist: {
files: {
"path/to/directory/": "path/to/source/*", // includes files in dir
"path/to/directory/": "path/to/source/**", // includes files in dir and subdirs
"path/to/project-<%= pkg.version %>/": "path/to/source/**", // variables in destination
"path/to/directory/": ["path/to/sources/*.js", "path/to/more/*.js"], // include JS files in two diff dirs
"path/to/filename.ext": "path/to/source.ext"
}
}
}
```


## Release History

* 2012-11-28   v0.4.0   Conversion to grunt v0.4 conventions. Replace basePath with cwd
* 2012-10-17   v0.3.2   Pass copyOptions on single file copy
* 2012-10-11   v0.3.1   Rename grunt-contrib-lib dep to grunt-lib-contrib.
* 2012-09-23   v0.3.0   General cleanup and consolidation. Global options depreciated.
* 2012-09-17   v0.2.4   No valid source check.
* 2012-09-16   v0.2.3   Path.sep fallback for node <= 0.7.9.
* 2012-09-16   v0.2.2   Single file copy support. Test refactoring.
* 2012-09-06   v0.2.0   Refactored from grunt-contrib into individual repo.

---

Task submitted by [Chris Talkington](http://christalkington.com/)

*This file was generated on Wed Nov 28 2012 08:36:21.*
# grunt-contrib-copy [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-contrib-copy.png?branch=master)](http://travis-ci.org/gruntjs/grunt-contrib-copy)

> Copy files and folders.

## Getting Started
If you haven't used [grunt][] before, be sure to check out the [Getting Started][] guide, as it explains how to create a [gruntfile][Getting Started] as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:

```shell
npm install grunt-contrib-copy --save-dev
```

[grunt]: http://gruntjs.com/
[Getting Started]: https://github.com/gruntjs/grunt/blob/devel/docs/getting_started.md


## Copy task
_Run this task with the `grunt copy` command._

_This task is a [multi task][] so any targets, files and options should be specified according to the [multi task][] documentation._
[multi task]: https://github.com/gruntjs/grunt/wiki/Configuring-tasks


### Options

#### cwd
Type: `String`

This option sets the current working directory for use with the minimatch and copy process. This helps translate paths when copied so that the destination stucture matches the source structure exactly. Without a `cwd` set, all paths are relative to the gruntfile directory which can cause extra depth to be added to your copied structure when it may not be desired.

When copying to a directory you must add a trailing slash to the destination due to added support of single file copy.

```js
copy: {
target: {
options: {
cwd: 'path/to/sources'
},
files: {
'tmp/test/': ['*', 'sub1/*']
}
}
}
```

#### excludeEmpty
Type: `Boolean`
Default: false

This option excludes empty folders from being copied to the destination directory.

#### flatten
Type: `Boolean`
Default: false

This option performs a flat copy that dumps all the files into the root of the destination directory, overwriting files if they exist.

#### processName
Type: `Function`

This option accepts a function that adjusts the filename of the copied file. Function is passed filename and should return a string.

```js
options: {
processName: function(filename) {
if (filename == "test.jpg") {
filename = "newname.jpg";
}
return filename;
}
}
```

#### processContent
Type: `Function`

This option is passed to `grunt.file.copy` as an advanced way to control the file contents that are copied.

#### processContentExclude
Type: `String`

This option is passed to `grunt.file.copy` as an advanced way to control which file contents are processed.

#### minimatch
Type: `Object`

These options will be forwarded on to expandFiles, as referenced in the [minimatch options section](https://github.com/isaacs/minimatch/#options)

### Usage Examples

```js
copy: {
dist: {
files: {
"path/to/directory/": "path/to/source/*", // includes files in dir
"path/to/directory/": "path/to/source/**", // includes files in dir and subdirs
"path/to/project-<%= pkg.version %>/": "path/to/source/**", // variables in destination
"path/to/directory/": ["path/to/sources/*.js", "path/to/more/*.js"], // include JS files in two diff dirs
"path/to/filename.ext": "path/to/source.ext"
}
}
}
```


## Release History

* 2012-11-29   v0.4.0   Conversion to grunt v0.4 conventions. Replace basePath with cwd. Empty directory support.
* 2012-10-17   v0.3.2   Pass copyOptions on single file copy.
* 2012-10-11   v0.3.1   Rename grunt-contrib-lib dep to grunt-lib-contrib.
* 2012-09-23   v0.3.0   General cleanup and consolidation. Global options depreciated.
* 2012-09-17   v0.2.4   No valid source check.
* 2012-09-16   v0.2.3   Path.sep fallback for node <= 0.7.9.
* 2012-09-16   v0.2.2   Single file copy support. Test refactoring.
* 2012-09-06   v0.2.0   Refactored from grunt-contrib into individual repo.

---

Task submitted by [Chris Talkington](http://christalkington.com/)

*This file was generated on Thu Nov 29 2012 20:23:02.*
6 changes: 6 additions & 0 deletions docs/copy-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ copy: {
}
```

## excludeEmpty
Type: `Boolean`
Default: false

This option excludes empty folders from being copied to the destination directory.

## flatten
Type: `Boolean`
Default: false
Expand Down
24 changes: 20 additions & 4 deletions tasks/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = function(grunt) {

var options = helpers.options(this, {
cwd: '',
excludeEmpty: false,
flatten: false,
processName: false,
processContent: false,
Expand All @@ -37,10 +38,12 @@ module.exports = function(grunt) {
grunt.verbose.writeflags(options, 'Options');

var dest = path.normalize(this.file.dest);

var srcDirs = grunt.file.expandDirs(options.minimatch, this.file.srcRaw);
var srcFiles = grunt.file.expandFiles(options.minimatch, this.file.srcRaw);

if (srcFiles.length === 0) {
grunt.fail.warn('Unable to copy; no valid source files were found.');
if (srcFiles.length === 0 && options.excludeEmpty) {
grunt.fail.warn('Unable to copy; no valid sources were found.');
}

var srcFile;
Expand All @@ -59,10 +62,23 @@ module.exports = function(grunt) {
grunt.fail.warn('Unable to copy multiple files to the same destination filename, did you forget a trailing slash?');
}
} else if (destType === 'directory') {
grunt.verbose.or.write('Copying files' + ' to ' + dest.cyan + '...');

var destDir;
var destFile;

if (options.flatten === false && options.excludeEmpty === false && srcDirs.length > 0) {
grunt.verbose.or.write('Creating directories' + ' in ' + dest.cyan + '...');

srcDirs.forEach(function(dir) {
destDir = path.join(dest, dir);

grunt.file.mkdir(destDir);
});

grunt.verbose.or.ok();
}

grunt.verbose.or.write('Copying files' + ' to ' + dest.cyan + '...');

var fileName;
var filePath;

Expand Down
10 changes: 7 additions & 3 deletions test/copy_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ exports.copy = {
main: function(test) {
'use strict';

test.expect(2);
test.expect(3);

var actual = fs.readdirSync('tmp/copy_test_files').sort();
var expected = fs.readdirSync('test/expected/copy_test_files').sort();
test.deepEqual(expected, actual, 'should copy several files (with cwd support)');
test.deepEqual(expected, actual, 'should copy several files');

actual = fs.readdirSync('tmp/copy_test_mix').sort();
expected = fs.readdirSync('test/expected/copy_test_mix').sort();
test.deepEqual(expected, actual, 'should copy a mix of folders and files');

actual = fs.readdirSync('tmp/copy_test_v0.1.0').sort();
expected = fs.readdirSync('test/expected/copy_test_v0.1.0').sort();
test.deepEqual(expected, actual, 'should copy several folders and files (with template and cwd support)');
test.deepEqual(expected, actual, 'should parse both dest and src templates');

test.done();
},
Expand Down
1 change: 1 addition & 0 deletions test/expected/copy_minimatch/test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello');
1 change: 1 addition & 0 deletions test/expected/copy_test_files/test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello');
1 change: 1 addition & 0 deletions test/expected/copy_test_flatten/test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello');
1 change: 1 addition & 0 deletions test/expected/copy_test_mix/folder_one/one.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$(document).ready(function(){$.noConflict();});
File renamed without changes.
1 change: 1 addition & 0 deletions test/expected/copy_test_mix/test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello');
1 change: 1 addition & 0 deletions test/fixtures/test2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('hello');

0 comments on commit 3a3c591

Please sign in to comment.