├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .verb.md ├── LICENSE ├── README.md ├── docs └── demo.gif ├── generator.js ├── index.js ├── lib ├── backup.js └── extract.js ├── package.json └── test ├── fixtures └── foo │ ├── .editorconfig │ ├── .eslintrc.json │ ├── .gitattributes │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── contributing.md │ ├── index.js │ └── package.json ├── plugin.js └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "modules": true, 4 | "experimentalObjectRestSpread": true 5 | }, 6 | "env": { 7 | "browser": false, 8 | "es6": true, 9 | "node": true, 10 | "mocha": true 11 | }, 12 | "globals": { 13 | "document": false, 14 | "navigator": false, 15 | "window": false 16 | }, 17 | "rules": { 18 | "accessor-pairs": 2, 19 | "arrow-spacing": [ 20 | 2, 21 | { 22 | "before": true, 23 | "after": true 24 | } 25 | ], 26 | "block-spacing": [ 27 | 2, 28 | "always" 29 | ], 30 | "brace-style": [ 31 | 2, 32 | "1tbs", 33 | { 34 | "allowSingleLine": true 35 | } 36 | ], 37 | "comma-dangle": [ 38 | 2, 39 | "never" 40 | ], 41 | "comma-spacing": [ 42 | 2, 43 | { 44 | "before": false, 45 | "after": true 46 | } 47 | ], 48 | "comma-style": [ 49 | 2, 50 | "last" 51 | ], 52 | "constructor-super": 2, 53 | "curly": [ 54 | 2, 55 | "multi-line" 56 | ], 57 | "dot-location": [ 58 | 2, 59 | "property" 60 | ], 61 | "eol-last": 2, 62 | "eqeqeq": [ 63 | 2, 64 | "allow-null" 65 | ], 66 | "generator-star-spacing": [ 67 | 2, 68 | { 69 | "before": true, 70 | "after": true 71 | } 72 | ], 73 | "handle-callback-err": [ 74 | 2, 75 | "^(err|error)$" 76 | ], 77 | "indent": [ 78 | 2, 79 | 2, 80 | { 81 | "SwitchCase": 1 82 | } 83 | ], 84 | "key-spacing": [ 85 | 2, 86 | { 87 | "beforeColon": false, 88 | "afterColon": true 89 | } 90 | ], 91 | "keyword-spacing": [ 92 | 2, 93 | { 94 | "before": true, 95 | "after": true 96 | } 97 | ], 98 | "new-cap": [ 99 | 2, 100 | { 101 | "newIsCap": true, 102 | "capIsNew": false 103 | } 104 | ], 105 | "new-parens": 2, 106 | "no-array-constructor": 2, 107 | "no-caller": 2, 108 | "no-class-assign": 2, 109 | "no-cond-assign": 2, 110 | "no-const-assign": 2, 111 | "no-control-regex": 2, 112 | "no-debugger": 2, 113 | "no-delete-var": 2, 114 | "no-dupe-args": 2, 115 | "no-dupe-class-members": 2, 116 | "no-dupe-keys": 2, 117 | "no-duplicate-case": 2, 118 | "no-empty-character-class": 2, 119 | "no-eval": 2, 120 | "no-ex-assign": 2, 121 | "no-extend-native": 2, 122 | "no-extra-bind": 2, 123 | "no-extra-boolean-cast": 2, 124 | "no-extra-parens": [ 125 | 2, 126 | "functions" 127 | ], 128 | "no-fallthrough": 2, 129 | "no-floating-decimal": 2, 130 | "no-func-assign": 2, 131 | "no-implied-eval": 2, 132 | "no-inner-declarations": [ 133 | 2, 134 | "functions" 135 | ], 136 | "no-invalid-regexp": 2, 137 | "no-irregular-whitespace": 2, 138 | "no-iterator": 2, 139 | "no-label-var": 2, 140 | "no-labels": 2, 141 | "no-lone-blocks": 2, 142 | "no-mixed-spaces-and-tabs": 2, 143 | "no-multi-spaces": 2, 144 | "no-multi-str": 2, 145 | "no-multiple-empty-lines": [ 146 | 2, 147 | { 148 | "max": 1 149 | } 150 | ], 151 | "no-native-reassign": 0, 152 | "no-negated-in-lhs": 2, 153 | "no-new": 2, 154 | "no-new-func": 2, 155 | "no-new-object": 2, 156 | "no-new-require": 2, 157 | "no-new-wrappers": 2, 158 | "no-obj-calls": 2, 159 | "no-octal": 2, 160 | "no-octal-escape": 2, 161 | "no-proto": 0, 162 | "no-redeclare": 2, 163 | "no-regex-spaces": 2, 164 | "no-return-assign": 2, 165 | "no-self-compare": 2, 166 | "no-sequences": 2, 167 | "no-shadow-restricted-names": 2, 168 | "no-spaced-func": 2, 169 | "no-sparse-arrays": 2, 170 | "no-this-before-super": 2, 171 | "no-throw-literal": 2, 172 | "no-trailing-spaces": 0, 173 | "no-undef": 2, 174 | "no-undef-init": 2, 175 | "no-unexpected-multiline": 2, 176 | "no-unneeded-ternary": [ 177 | 2, 178 | { 179 | "defaultAssignment": false 180 | } 181 | ], 182 | "no-unreachable": 2, 183 | "no-unused-vars": [ 184 | 2, 185 | { 186 | "vars": "all", 187 | "args": "none" 188 | } 189 | ], 190 | "no-useless-call": 0, 191 | "no-with": 2, 192 | "one-var": [ 193 | 0, 194 | { 195 | "initialized": "never" 196 | } 197 | ], 198 | "operator-linebreak": [ 199 | 0, 200 | "after", 201 | { 202 | "overrides": { 203 | "?": "before", 204 | ":": "before" 205 | } 206 | } 207 | ], 208 | "padded-blocks": [ 209 | 0, 210 | "never" 211 | ], 212 | "quotes": [ 213 | 2, 214 | "single", 215 | "avoid-escape" 216 | ], 217 | "radix": 2, 218 | "semi": [ 219 | 2, 220 | "always" 221 | ], 222 | "semi-spacing": [ 223 | 2, 224 | { 225 | "before": false, 226 | "after": true 227 | } 228 | ], 229 | "space-before-blocks": [ 230 | 2, 231 | "always" 232 | ], 233 | "space-before-function-paren": [ 234 | 2, 235 | "never" 236 | ], 237 | "space-in-parens": [ 238 | 2, 239 | "never" 240 | ], 241 | "space-infix-ops": 2, 242 | "space-unary-ops": [ 243 | 2, 244 | { 245 | "words": true, 246 | "nonwords": false 247 | } 248 | ], 249 | "spaced-comment": [ 250 | 0, 251 | "always", 252 | { 253 | "markers": [ 254 | "global", 255 | "globals", 256 | "eslint", 257 | "eslint-disable", 258 | "*package", 259 | "!", 260 | "," 261 | ] 262 | } 263 | ], 264 | "use-isnan": 2, 265 | "valid-typeof": 2, 266 | "wrap-iife": [ 267 | 2, 268 | "any" 269 | ], 270 | "yoda": [ 271 | 2, 272 | "never" 273 | ] 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "node" 5 | - "6" 6 | - "5" 7 | - "4" 8 | - "0.12" 9 | - "0.10" 10 | matrix: 11 | fast_finish: true 12 | allow_failures: 13 | - node_js: "4" 14 | - node_js: "0.10" 15 | - node_js: "0.12" 16 | -------------------------------------------------------------------------------- /.verb.md: -------------------------------------------------------------------------------- 1 | ## Usage 2 | 3 | ### CLI 4 | 5 | When installed globally, the `backup` generator is available to use through the `gen` command: 6 | 7 | Backup a folder to a tar file using the [default](#default) task. 8 | 9 | ```sh 10 | $ gen backup --src my-project --dest /backups/my-project 11 | ``` 12 | 13 | Extract a tar file to a folder using the [extract](#extract) task. 14 | 15 | ```sh 16 | $ gen backup:extract --src /backups/my-project/2017-01-02.tar --dest my-project-2 17 | ``` 18 | ### API 19 | 20 | **Params** 21 | 22 | * `app` **{Object}**: [generate](https://github.com/generate/generate) instance to add tasks to. 23 | 24 | **Example** 25 | 26 | ```js 27 | // use as a plugin with existing generate instance 28 | // $ gen backup 29 | app.use(require('generate-backup')); 30 | 31 | // use as a subgenerator on an existing generate instance 32 | // $ gen bkp 33 | app.register('bkp', require('generate-backup')); 34 | ``` 35 | 36 | 37 | ### Internal API 38 | 39 | Internal functions that are used inside the tasks to provide [backup](#backup) and [extract](#extract) functionality. 40 | 41 | {%= apidocs('lib/*.js') %} 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Brian Woodward 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 | 8 | Create backup archives with generate. 9 | 10 | # generate-backup 11 | 12 | [![NPM version](https://img.shields.io/npm/v/generate-backup.svg?style=flat)](https://www.npmjs.com/package/generate-backup) [![NPM monthly downloads](https://img.shields.io/npm/dm/generate-backup.svg?style=flat)](https://npmjs.org/package/generate-backup) [![Build Status](https://img.shields.io/travis/generate/generate-backup.svg?style=flat)](https://travis-ci.org/generate/generate-backup) 13 | 14 | ![generate-backup demo](https://raw.githubusercontent.com/generate/generate-backup/master/docs/demo.gif) 15 | 16 | ## Usage 17 | 18 | ### CLI 19 | 20 | When installed globally, the `backup` generator is available to use through the `gen` command: 21 | 22 | Backup a folder to a tar file using the [default](#default) task. 23 | 24 | ```sh 25 | $ gen backup --src my-project --dest /backups/my-project 26 | ``` 27 | 28 | Extract a tar file to a folder using the [extract](#extract) task. 29 | 30 | ```sh 31 | $ gen backup:extract --src /backups/my-project/2017-01-02.tar --dest my-project-2 32 | ``` 33 | 34 | ### API 35 | 36 | **Params** 37 | 38 | * `app` **{Object}**: [generate](https://github.com/generate/generate) instance to add tasks to. 39 | 40 | **Example** 41 | 42 | ```js 43 | // use as a plugin with existing generate instance 44 | // $ gen backup 45 | app.use(require('generate-backup')); 46 | 47 | // use as a subgenerator on an existing generate instance 48 | // $ gen bkp 49 | app.register('bkp', require('generate-backup')); 50 | ``` 51 | 52 | ### Internal API 53 | 54 | Internal functions that are used inside the tasks to provide [backup](#backup) and [extract](#extract) functionality. 55 | 56 | **Params** 57 | 58 | * `options` **{Object}**: Options to control what is archived. 59 | * `returns` **{Stream}**: The stream created by [tar-fs](https://github.com/mafintosh/tar-fs). 60 | 61 | **Example** 62 | 63 | ```js 64 | backup({src: './', dest: '/backups'}); 65 | ``` 66 | 67 | **Params** 68 | 69 | * `options` **{Object}**: Options to control what is extracted. 70 | * `returns` **{Stream}**: The stream created by [tar-fs](https://github.com/mafintosh/tar-fs). 71 | 72 | **Example** 73 | 74 | ```js 75 | extract({src: '/backups/2017-01-02.tar', dest: './'}); 76 | ``` 77 | 78 | ## What is "Generate"? 79 | 80 | Generate is a command line tool and developer framework for scaffolding out new GitHub projects using [generators](https://github.com/generate/generate/blob/master/docs/generators.md) and [tasks](https://github.com/generate/generate/blob/master/docs/tasks.md). 81 | 82 | Answers to prompts and the user's environment can be used to determine the templates, directories, files and contents to build. Support for [gulp](http://gulpjs.com), [base](https://github.com/node-base/base) and [assemble](https://github.com/assemble/assemble) plugins, and much more. 83 | 84 | **For more information**: 85 | 86 | * Visit the [generate project](https://github.com/generate/generate/) 87 | * Visit the [generate documentation](https://github.com/generate/generate/blob/master/docs/) 88 | * Find [generators on npm](https://www.npmjs.com/browse/keyword/generate-generator) (help us [author generators](https://github.com/generate/generate/blob/master/docs/micro-generators.md)) 89 | 90 | ## Getting started 91 | 92 | ### Install 93 | 94 | **Installing the CLI** 95 | 96 | To run the `backup` generator from the command line, you'll need to install [Generate](https://github.com/generate/generate) globally first. You can do that now with the following command: 97 | 98 | ```sh 99 | $ npm install --global generate 100 | ``` 101 | 102 | This adds the `gen` command to your system path, allowing it to be run from any directory. 103 | 104 | **Install generate-backup** 105 | 106 | Install this module with the following command: 107 | 108 | ```sh 109 | $ npm install --global generate-backup 110 | ``` 111 | 112 | ### Usage 113 | 114 | Run this generator's `default` [task](https://github.com/generate/generate/blob/master/docs/tasks.md#default) with the following command: 115 | 116 | ```sh 117 | $ gen backup 118 | ``` 119 | 120 | **What you should see in the terminal** 121 | 122 | If completed successfully, you should see both `starting` and `finished` events in the terminal, like the following: 123 | 124 | ```sh 125 | [00:44:21] starting ... 126 | ... 127 | [00:44:22] finished ✔ 128 | ``` 129 | 130 | If you do not see one or both of those events, please [let us know about it](../../issues). 131 | 132 | ### Help 133 | 134 | To see a general help menu and available commands for Generate's CLI, run: 135 | 136 | ```sh 137 | $ gen help 138 | ``` 139 | 140 | ## Tasks 141 | 142 | All available tasks. 143 | 144 | ### [backup](generator.js#L41) 145 | 146 | Default `backup` task that will backup the specified `--src` folder a `.tar` file in the specified `--dest` folder using an optional `--ignore` flag. 147 | 148 | **remove spaces in the ignore pattern** 149 | 150 | **Example** 151 | 152 | ```sh 153 | # backup all node projects to the /backups/projects folder but ignore any node_modules folders 154 | $ gen backup --dest /backups/projects --src projects --ignore '** /node_modules/{,** /*}' 155 | ``` 156 | 157 | ### [extract](generator.js#L59) 158 | 159 | `extract` task that will extract the files from the specified `--src` `.tar` file to the specified `--dest` folder using an optional `--ignore` flag. 160 | 161 | **Example** 162 | 163 | ```sh 164 | # extract the archived projects from /backups/projects/2017-01-02.tar to the ./restore/projects folder. 165 | $ gen backup --dest restore/projects --src /backups/projects/2017-01-02.tar 166 | ``` 167 | 168 | ### [default](generator.js#L71) 169 | 170 | Default task aliased for [backup](#backup) 171 | 172 | Visit Generate's [documentation for tasks](https://github.com/generate/generate/blob/master/docs/tasks.md). 173 | 174 | ## Next steps 175 | 176 | ### Running unit tests 177 | 178 | It's never too early to begin running unit tests. When you're ready to get started, the following command will ensure the project's dependencies are installed then run all of the unit tests: 179 | 180 | ```sh 181 | $ npm install && test 182 | ``` 183 | 184 | ### Publishing your generator 185 | 186 | If you're tests are passing and you're ready to publish your generator to [npm](https://www.npmjs.com), you can do that now with the following command: 187 | 188 | **Are you sure you're ready?!** 189 | 190 | Let's go! 191 | 192 | ```sh 193 | $ npm publish 194 | ``` 195 | 196 | ## About 197 | 198 | ### Related projects 199 | 200 | * [generate](https://www.npmjs.com/package/generate): Command line tool and developer framework for scaffolding out new GitHub projects. Generate offers the… [more](https://github.com/generate/generate) | [homepage](https://github.com/generate/generate "Command line tool and developer framework for scaffolding out new GitHub projects. Generate offers the robustness and configurability of Yeoman, the expressiveness and simplicity of Slush, and more powerful flow control and composability than either.") 201 | * [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") 202 | * [tar-fs](https://www.npmjs.com/package/tar-fs): filesystem bindings for tar-stream | [homepage](https://github.com/mafintosh/tar-fs "filesystem bindings for tar-stream") 203 | 204 | ### Community 205 | 206 | Are you using [Generate](https://github.com/generate/generate) in your project? Have you published a [generator](https://github.com/generate/generate/blob/master/docs/generators.md) and want to share your project with the world? 207 | 208 | Here are some suggestions! 209 | 210 | * If you get like Generate and want to tweet about it, please feel free to mention `@generatejs` or use the `#generatejs` hashtag 211 | * Show your love by starring [Generate](https://github.com/generate/generate) and `generate-backup` 212 | * Get implementation help on [StackOverflow](http://stackoverflow.com/questions/tagged/generate) (please use the `generatejs` tag in questions) 213 | * **Gitter** Discuss Generate with us on [Gitter](https://gitter.im/generate/generate) 214 | * If you publish an generator, thank you! To make your project as discoverable as possible, please add the keyword `generategenerator` to package.json. 215 | 216 | ### Contributing 217 | 218 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). 219 | 220 | ### Running tests 221 | 222 | Install dev dependencies: 223 | 224 | ```sh 225 | $ npm install -d && npm test 226 | ``` 227 | 228 | ### Author 229 | 230 | **Brian Woodward** 231 | 232 | * [github/doowb](https://github.com/doowb) 233 | * [twitter/doowb](http://twitter.com/doowb) 234 | 235 | ### License 236 | 237 | Copyright © 2017, [Brian Woodward](https://github.com/doowb). 238 | Released under the [MIT license](LICENSE). 239 | 240 | *** 241 | 242 | _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.2.3, on January 02, 2017._ -------------------------------------------------------------------------------- /docs/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/generate/generate-backup/5847e8760b3a8601e3568b7ee752c9b2ac522c5e/docs/demo.gif -------------------------------------------------------------------------------- /generator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var isValid = require('is-valid-app'); 4 | var backup = require('./lib/backup'); 5 | var extract = require('./lib/extract'); 6 | 7 | /** 8 | * [generate][] plugin or subgenerator that adds a [backup](#backup) and [extract](#extract) tasks for archiving and extract tar archives. 9 | * Advantages of using this generator include being able to specify complex ignore patterns (handled by [micromatch][]). 10 | * 11 | * ```js 12 | * // use as a plugin with existing generate instance 13 | * // $ gen backup 14 | * app.use(require('generate-backup')); 15 | * 16 | * // use as a subgenerator on an existing generate instance 17 | * // $ gen bkp 18 | * app.register('bkp', require('generate-backup')); 19 | * ``` 20 | * 21 | * @param {Object} `app` [generate][] instance to add tasks to. 22 | */ 23 | 24 | module.exports = function(app) { 25 | if (!isValid(app, 'generate-backup')) return; 26 | 27 | /** 28 | * Default `backup` task that will backup the specified `--src` folder a `.tar` file in the specified `--dest` folder 29 | * using an optional `--ignore` flag. 30 | * 31 | * __remove spaces in the ignore pattern__ 32 | * 33 | * ```sh 34 | * # backup all node projects to the /backups/projects folder but ignore any node_modules folders 35 | * $ gen backup --dest /backups/projects --src projects --ignore '** /node_modules/{,** /*}' 36 | * ``` 37 | * @name backup 38 | * @api public 39 | */ 40 | 41 | app.task('backup', function(cb) { 42 | backup(app.options) 43 | .once('error', cb) 44 | .once('finish', cb); 45 | }); 46 | 47 | /** 48 | * `extract` task that will extract the files from the specified `--src` `.tar` file to the specified `--dest` folder 49 | * using an optional `--ignore` flag. 50 | * 51 | * ```sh 52 | * # extract the archived projects from /backups/projects/2017-01-02.tar to the ./restore/projects folder. 53 | * $ gen backup --dest restore/projects --src /backups/projects/2017-01-02.tar 54 | * ``` 55 | * @name extract 56 | * @api public 57 | */ 58 | 59 | app.task('extract', function(cb) { 60 | extract(app.options) 61 | .once('error', cb) 62 | .once('finish', cb); 63 | }); 64 | 65 | /** 66 | * Default task aliased for [backup](#backup) 67 | * @name default 68 | * @api public 69 | */ 70 | 71 | app.task('default', ['backup']); 72 | }; 73 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./generator'); 2 | -------------------------------------------------------------------------------- /lib/backup.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var tar = require('tar-fs'); 6 | var mkdirp = require('mkdirp'); 7 | var mm = require('micromatch'); 8 | var extend = require('extend-shallow'); 9 | 10 | /** 11 | * Backup the specified `.src` folder to the specified `.dest` folder using the current date to create a `.tar` file. 12 | * Additional `.ignore` option may be passed to ignore files and directories. The `.ignore` property may be anything that 13 | * is acceptable to pass to the `[micromatch][].filter` method. 14 | * 15 | * ```js 16 | * backup({src: './', dest: '/backups'}); 17 | * ``` 18 | * @param {Object} `options` Options to control what is archived. 19 | * @return {Stream} The stream created by [tar-fs][]. 20 | * @api public 21 | */ 22 | 23 | module.exports = function(options) { 24 | var opts = extend({}, options); 25 | var dest = opts.dest; 26 | if (!dest) throw new Error('expected a `dest`'); 27 | 28 | var src = opts.src; 29 | if (!src) throw new Error('expected a `src`'); 30 | 31 | var ignore = function() {}; 32 | if (typeof opts.ignore === 'function') { 33 | ignore = opts.ignore; 34 | } 35 | 36 | if (typeof opts.ignore === 'string' || Array.isArray(opts.ignore)) { 37 | ignore = mm.filter(opts.ignore); 38 | } 39 | 40 | var fp = path.join(dest, format(new Date())) + '.tar'; 41 | mkdirp.sync(dest); 42 | 43 | var output = fs.createWriteStream(fp); 44 | 45 | return tar.pack(src, { 46 | ignore: function(file) { 47 | if (path.resolve(file) === fp) { 48 | return true; 49 | } 50 | return ignore(file); 51 | } 52 | }) 53 | .on('error', console.error) 54 | .pipe(output) 55 | .on('error', console.error); 56 | 57 | function format (date) { 58 | return date.getUTCFullYear() + '-' + pad(date.getUTCMonth() + 1) + '-' + pad(date.getUTCDate()); 59 | } 60 | 61 | function pad (n) { 62 | return (n < 10 ? '0' : '') + n; 63 | } 64 | }; 65 | 66 | 67 | -------------------------------------------------------------------------------- /lib/extract.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var tar = require('tar-fs'); 5 | var mkdirp = require('mkdirp'); 6 | var mm = require('micromatch'); 7 | var extend = require('extend-shallow'); 8 | 9 | /** 10 | * Extract the specified `.src` `.tar` file to the specified `.dest` folder. 11 | * Additional `.ignore` option may be passed to ignore files and directories. The `.ignore` property may be anything that 12 | * is acceptable to pass to the `[micromatch][].filter` method. 13 | * 14 | * ```js 15 | * extract({src: '/backups/2017-01-02.tar', dest: './'}); 16 | * ``` 17 | * @param {Object} `options` Options to control what is extracted. 18 | * @return {Stream} The stream created by [tar-fs][]. 19 | * @api public 20 | */ 21 | 22 | module.exports = function(options) { 23 | var opts = extend({}, options); 24 | var dest = opts.dest; 25 | if (!dest) throw new Error('expected a `dest`'); 26 | 27 | var src = opts.src; 28 | if (!src) throw new Error('expected a `src`'); 29 | 30 | var ignore = function() {}; 31 | if (typeof opts.ignore === 'function') { 32 | ignore = opts.ignore; 33 | } 34 | 35 | if (typeof opts.ignore === 'string' || Array.isArray(opts.ignore)) { 36 | ignore = mm.filter(opts.ignore); 37 | } 38 | 39 | mkdirp.sync(dest); 40 | return fs.createReadStream(src) 41 | .on('error', console.error) 42 | .pipe(tar.extract(dest, {ignore: ignore})) 43 | .on('error', console.error); 44 | }; 45 | 46 | 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generate-backup", 3 | "description": "Create backup archives with generate.", 4 | "version": "0.1.0", 5 | "homepage": "https://github.com/generate/generate-backup", 6 | "author": "Brian Woodward (https://github.com/doowb)", 7 | "repository": "generate/generate-backup", 8 | "bugs": { 9 | "url": "https://github.com/generate/generate-backup/issues" 10 | }, 11 | "license": "MIT", 12 | "files": [ 13 | "generator.js", 14 | "index.js", 15 | "lib" 16 | ], 17 | "main": "index.js", 18 | "engines": { 19 | "node": ">=0.10.0" 20 | }, 21 | "scripts": { 22 | "test": "mocha" 23 | }, 24 | "dependencies": { 25 | "extend-shallow": "^2.0.1", 26 | "is-valid-app": "^0.2.1", 27 | "micromatch": "^2.3.11", 28 | "mkdirp": "^0.5.1", 29 | "tar-fs": "^1.14.0" 30 | }, 31 | "devDependencies": { 32 | "delete": "^0.3.2", 33 | "generate": "^0.13.1", 34 | "gulp-format-md": "^0.1.11", 35 | "mocha": "^3.1.2", 36 | "moment": "^2.17.1", 37 | "npm-install-global": "^0.1.2" 38 | }, 39 | "keywords": [ 40 | "archive", 41 | "backup", 42 | "bkp", 43 | "extract", 44 | "generate", 45 | "generate-backup", 46 | "generategenerator", 47 | "generator", 48 | "tar" 49 | ], 50 | "verb": { 51 | "toc": false, 52 | "layout": "generator", 53 | "tasks": [ 54 | "readme" 55 | ], 56 | "plugins": [ 57 | "gulp-format-md" 58 | ], 59 | "lint": { 60 | "reflinks": true 61 | }, 62 | "related": { 63 | "list": [ 64 | "generate", 65 | "micromatch", 66 | "tar-fs" 67 | ] 68 | }, 69 | "reflinks": [ 70 | "assemble", 71 | "base", 72 | "generate", 73 | "gulp", 74 | "tar-fs", 75 | "verb", 76 | "verb-generate-readme" 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /test/fixtures/foo/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /test/fixtures/foo/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "modules": true, 4 | "experimentalObjectRestSpread": true 5 | }, 6 | "env": { 7 | "browser": false, 8 | "es6": true, 9 | "node": true, 10 | "mocha": true 11 | }, 12 | "globals": { 13 | "document": false, 14 | "navigator": false, 15 | "window": false 16 | }, 17 | "rules": { 18 | "accessor-pairs": 2, 19 | "arrow-spacing": [ 20 | 2, 21 | { 22 | "before": true, 23 | "after": true 24 | } 25 | ], 26 | "block-spacing": [ 27 | 2, 28 | "always" 29 | ], 30 | "brace-style": [ 31 | 2, 32 | "1tbs", 33 | { 34 | "allowSingleLine": true 35 | } 36 | ], 37 | "comma-dangle": [ 38 | 2, 39 | "never" 40 | ], 41 | "comma-spacing": [ 42 | 2, 43 | { 44 | "before": false, 45 | "after": true 46 | } 47 | ], 48 | "comma-style": [ 49 | 2, 50 | "last" 51 | ], 52 | "constructor-super": 2, 53 | "curly": [ 54 | 2, 55 | "multi-line" 56 | ], 57 | "dot-location": [ 58 | 2, 59 | "property" 60 | ], 61 | "eol-last": 2, 62 | "eqeqeq": [ 63 | 2, 64 | "allow-null" 65 | ], 66 | "generator-star-spacing": [ 67 | 2, 68 | { 69 | "before": true, 70 | "after": true 71 | } 72 | ], 73 | "handle-callback-err": [ 74 | 2, 75 | "^(err|error)$" 76 | ], 77 | "indent": [ 78 | 2, 79 | 2, 80 | { 81 | "SwitchCase": 1 82 | } 83 | ], 84 | "key-spacing": [ 85 | 2, 86 | { 87 | "beforeColon": false, 88 | "afterColon": true 89 | } 90 | ], 91 | "keyword-spacing": [ 92 | 2, 93 | { 94 | "before": true, 95 | "after": true 96 | } 97 | ], 98 | "new-cap": [ 99 | 2, 100 | { 101 | "newIsCap": true, 102 | "capIsNew": false 103 | } 104 | ], 105 | "new-parens": 2, 106 | "no-array-constructor": 2, 107 | "no-caller": 2, 108 | "no-class-assign": 2, 109 | "no-cond-assign": 2, 110 | "no-const-assign": 2, 111 | "no-control-regex": 2, 112 | "no-debugger": 2, 113 | "no-delete-var": 2, 114 | "no-dupe-args": 2, 115 | "no-dupe-class-members": 2, 116 | "no-dupe-keys": 2, 117 | "no-duplicate-case": 2, 118 | "no-empty-character-class": 2, 119 | "no-eval": 2, 120 | "no-ex-assign": 2, 121 | "no-extend-native": 2, 122 | "no-extra-bind": 2, 123 | "no-extra-boolean-cast": 2, 124 | "no-extra-parens": [ 125 | 2, 126 | "functions" 127 | ], 128 | "no-fallthrough": 2, 129 | "no-floating-decimal": 2, 130 | "no-func-assign": 2, 131 | "no-implied-eval": 2, 132 | "no-inner-declarations": [ 133 | 2, 134 | "functions" 135 | ], 136 | "no-invalid-regexp": 2, 137 | "no-irregular-whitespace": 2, 138 | "no-iterator": 2, 139 | "no-label-var": 2, 140 | "no-labels": 2, 141 | "no-lone-blocks": 2, 142 | "no-mixed-spaces-and-tabs": 2, 143 | "no-multi-spaces": 2, 144 | "no-multi-str": 2, 145 | "no-multiple-empty-lines": [ 146 | 2, 147 | { 148 | "max": 1 149 | } 150 | ], 151 | "no-native-reassign": 0, 152 | "no-negated-in-lhs": 2, 153 | "no-new": 2, 154 | "no-new-func": 2, 155 | "no-new-object": 2, 156 | "no-new-require": 2, 157 | "no-new-wrappers": 2, 158 | "no-obj-calls": 2, 159 | "no-octal": 2, 160 | "no-octal-escape": 2, 161 | "no-proto": 0, 162 | "no-redeclare": 2, 163 | "no-regex-spaces": 2, 164 | "no-return-assign": 2, 165 | "no-self-compare": 2, 166 | "no-sequences": 2, 167 | "no-shadow-restricted-names": 2, 168 | "no-spaced-func": 2, 169 | "no-sparse-arrays": 2, 170 | "no-this-before-super": 2, 171 | "no-throw-literal": 2, 172 | "no-trailing-spaces": 0, 173 | "no-undef": 2, 174 | "no-undef-init": 2, 175 | "no-unexpected-multiline": 2, 176 | "no-unneeded-ternary": [ 177 | 2, 178 | { 179 | "defaultAssignment": false 180 | } 181 | ], 182 | "no-unreachable": 2, 183 | "no-unused-vars": [ 184 | 2, 185 | { 186 | "vars": "all", 187 | "args": "none" 188 | } 189 | ], 190 | "no-useless-call": 0, 191 | "no-with": 2, 192 | "one-var": [ 193 | 0, 194 | { 195 | "initialized": "never" 196 | } 197 | ], 198 | "operator-linebreak": [ 199 | 0, 200 | "after", 201 | { 202 | "overrides": { 203 | "?": "before", 204 | ":": "before" 205 | } 206 | } 207 | ], 208 | "padded-blocks": [ 209 | 0, 210 | "never" 211 | ], 212 | "quotes": [ 213 | 2, 214 | "single", 215 | "avoid-escape" 216 | ], 217 | "radix": 2, 218 | "semi": [ 219 | 2, 220 | "always" 221 | ], 222 | "semi-spacing": [ 223 | 2, 224 | { 225 | "before": false, 226 | "after": true 227 | } 228 | ], 229 | "space-before-blocks": [ 230 | 2, 231 | "always" 232 | ], 233 | "space-before-function-paren": [ 234 | 2, 235 | "never" 236 | ], 237 | "space-in-parens": [ 238 | 2, 239 | "never" 240 | ], 241 | "space-infix-ops": 2, 242 | "space-unary-ops": [ 243 | 2, 244 | { 245 | "words": true, 246 | "nonwords": false 247 | } 248 | ], 249 | "spaced-comment": [ 250 | 0, 251 | "always", 252 | { 253 | "markers": [ 254 | "global", 255 | "globals", 256 | "eslint", 257 | "eslint-disable", 258 | "*package", 259 | "!", 260 | "," 261 | ] 262 | } 263 | ], 264 | "use-isnan": 2, 265 | "valid-typeof": 2, 266 | "wrap-iife": [ 267 | 2, 268 | "any" 269 | ], 270 | "yoda": [ 271 | 2, 272 | "never" 273 | ] 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /test/fixtures/foo/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /test/fixtures/foo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage -------------------------------------------------------------------------------- /test/fixtures/foo/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 'node' 5 | - '6' 6 | -------------------------------------------------------------------------------- /test/fixtures/foo/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Brian Woodward 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/fixtures/foo/README.md: -------------------------------------------------------------------------------- 1 | # foo [![NPM version](https://badge.fury.io/js/foo.svg)](https://npmjs.org/package/foo) [![Build Status](https://travis-ci.org/doowb/foo.svg?branch=master)](https://travis-ci.org/doowb/foo) 2 | 3 | > test project 4 | 5 | ## Installation 6 | 7 | ```sh 8 | $ npm install --save foo 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```js 14 | var foo = require('foo'); 15 | foo(); 16 | ``` 17 | 18 | ## License 19 | 20 | MIT © [Brian Woodward](https://github.com/doowb) 21 | -------------------------------------------------------------------------------- /test/fixtures/foo/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to foo 2 | 3 | First and foremost, thank you! We appreciate that you want to contribute to foo, your time is valuable, and your contributions mean a lot to us. 4 | 5 | **What does "contributing" mean?** 6 | 7 | Creating an issue is the simplest form of contributing to a project. But there are many ways to contribute, including the following: 8 | 9 | - Updating or correcting documentation 10 | - Feature requests 11 | - Bug reports 12 | 13 | If you'd like to learn more about contributing in general, the [Guide to Idiomatic Contributing](https://github.com/jonschlinkert/idiomatic-contributing) has a lot of useful information. 14 | 15 | **Showing support for foo** 16 | 17 | Please keep in mind that open source software is built by people like you, who spend their free time creating things the rest the community can use. 18 | 19 | Don't have time to contribute? No worries, here are some other ways to show your support for foo: 20 | 21 | - star the [project](https://github.com/doowb/foo) 22 | - tweet your support for foo 23 | 24 | ## Issues 25 | 26 | ### Before creating an issue 27 | 28 | Please try to determine if the issue is caused by an underlying library, and if so, create the issue there. Sometimes this is difficult to know. We only ask that you attempt to give a reasonable attempt to find out. Oftentimes the readme will have advice about where to go to create issues. 29 | 30 | Try to follow these guidelines 31 | 32 | - **Investigate the issue**: 33 | - **Check the readme** - oftentimes you will find notes about creating issues, and where to go depending on the type of issue. 34 | - Create the issue in the appropriate repository. 35 | 36 | ### Creating an issue 37 | 38 | Please be as descriptive as possible when creating an issue. Give us the information we need to successfully answer your question or address your issue by answering the following in your issue: 39 | 40 | - **version**: please note the version of foo are you using 41 | - **extensions, plugins, helpers, etc** (if applicable): please list any extensions you're using 42 | - **error messages**: please paste any error messages into the issue, or a [gist](https://gist.github.com/) 43 | 44 | ## Above and beyond 45 | 46 | Here are some tips for creating idiomatic issues. Taking just a little bit extra time will make your issue easier to read, easier to resolve, more likely to be found by others who have the same or similar issue in the future. 47 | 48 | - read the [Guide to Idiomatic Contributing](https://github.com/jonschlinkert/idiomatic-contributing) 49 | - take some time to learn basic markdown. This [markdown cheatsheet](https://gist.github.com/jonschlinkert/5854601) is super helpful, as is the GitHub guide to [basic markdown](https://help.github.com/articles/markdown-basics/). 50 | - Learn about [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown/). And if you want to really go above and beyond, read [mastering markdown](https://guides.github.com/features/mastering-markdown/). 51 | - use backticks to wrap code. This ensures that code will retain its format, making it much more readable to others 52 | - use syntax highlighting by adding the correct language name after the first "code fence" 53 | 54 | 55 | [node-glob]: https://github.com/isaacs/node-glob 56 | [micromatch]: https://github.com/jonschlinkert/micromatch 57 | [so]: http://stackoverflow.com/questions/tagged/foo -------------------------------------------------------------------------------- /test/fixtures/foo/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function() { 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/foo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foo", 3 | "description": "test project", 4 | "version": "0.1.0", 5 | "homepage": "https://github.com/doowb/foo", 6 | "author": "Brian Woodward (https://github.com/doowb)", 7 | "repository": "doowb/foo", 8 | "bugs": { 9 | "url": "https://github.com/doowb/foo/issues" 10 | }, 11 | "license": "MIT", 12 | "files": [ 13 | "index.js", 14 | "LICENSE" 15 | ], 16 | "main": "index.js", 17 | "engines": { 18 | "node": ">=0.10.0" 19 | }, 20 | "scripts": { 21 | "test": "mocha" 22 | }, 23 | "keywords": [ 24 | "generategenerator" 25 | ], 26 | "dependencies": { 27 | "node-bar": "^0.2.0", 28 | "node-foo": "^0.2.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('mocha'); 4 | var assert = require('assert'); 5 | var generate = require('generate'); 6 | var generator = require('../'); 7 | var app; 8 | 9 | describe('generate-backup', function() { 10 | beforeEach(function() { 11 | app = generate(); 12 | }); 13 | 14 | describe('plugin', function() { 15 | it('should add tasks to the instance', function() { 16 | app.use(generator); 17 | assert(app.tasks.hasOwnProperty('default')); 18 | assert(app.tasks.hasOwnProperty('backup')); 19 | }); 20 | 21 | it('should only register the plugin once', function(cb) { 22 | var count = 0; 23 | app.on('plugin', function(name) { 24 | if (name === 'generate-backup') { 25 | count++; 26 | } 27 | }); 28 | app.use(generator); 29 | app.use(generator); 30 | app.use(generator); 31 | assert.equal(count, 1); 32 | cb(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('mocha'); 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | var assert = require('assert'); 7 | var moment = require('moment'); 8 | var generate = require('generate'); 9 | var npm = require('npm-install-global'); 10 | var del = require('delete'); 11 | var pkg = require('../package'); 12 | var generator = require('..'); 13 | var app; 14 | 15 | var today = moment.utc().format('YYYY-MM-DD'); 16 | var isTravis = process.env.CI || process.env.TRAVIS; 17 | var fixtures = path.resolve.bind(path, __dirname, 'fixtures'); 18 | var actual = path.resolve.bind(path, __dirname, 'actual'); 19 | 20 | function exists(name, cb) { 21 | return function(err) { 22 | if (err) return cb(err); 23 | var filepath = actual(name); 24 | 25 | fs.stat(filepath, function(err, stat) { 26 | if (err) return cb(err); 27 | assert(stat); 28 | del(actual(), cb); 29 | }); 30 | }; 31 | } 32 | 33 | describe('generate-backup', function() { 34 | this.timeout(5000); 35 | this.slow(250); 36 | 37 | if (!process.env.CI && !process.env.TRAVIS) { 38 | before(function(cb) { 39 | npm.maybeInstall('generate', cb); 40 | }); 41 | } 42 | 43 | beforeEach(function(cb) { 44 | app = generate({silent: true}); 45 | app.cwd = fixtures(); 46 | app.option('dest', actual()); 47 | app.option('src', fixtures()); 48 | 49 | // see: https://github.com/jonschlinkert/ask-when 50 | app.option('askWhen', 'not-answered'); 51 | 52 | // set default data to use in templates. feel free to remove anything 53 | // that isn't used (e.g. if "username" isn't defined in templates, just remove it) 54 | app.data(pkg); 55 | app.data('project', pkg); 56 | app.data('username', 'foo'); 57 | app.data('owner', 'foo'); 58 | del(actual(), cb); 59 | }); 60 | 61 | afterEach(function(cb) { 62 | del(actual(), cb); 63 | }); 64 | 65 | describe('tasks', function() { 66 | it('should extend tasks onto the instance', function() { 67 | app.use(generator); 68 | assert(app.tasks.hasOwnProperty('default')); 69 | assert(app.tasks.hasOwnProperty('backup')); 70 | }); 71 | 72 | it('should run the `default` task with .build', function(cb) { 73 | this.timeout(30000); 74 | app.use(generator); 75 | app.build('default', exists(`${today}.tar`, cb)); 76 | }); 77 | 78 | it('should run the `default` task with .generate', function(cb) { 79 | app.use(generator); 80 | app.generate('default', exists(`${today}.tar`, cb)); 81 | }); 82 | }); 83 | 84 | describe('backup (CLI)', function() { 85 | it('should run the default task using the `generate-backup` name', function(cb) { 86 | if (isTravis) { 87 | this.skip(); 88 | return; 89 | } 90 | app.use(generator); 91 | app.generate('generate-backup', exists(`${today}.tar`, cb)); 92 | }); 93 | 94 | it('should run the default task using the `generator` generator alias', function(cb) { 95 | if (isTravis) { 96 | this.skip(); 97 | return; 98 | } 99 | app.use(generator); 100 | app.generate('backup', exists(`${today}.tar`, cb)); 101 | }); 102 | }); 103 | 104 | describe('backup (API)', function() { 105 | it('should run the default task on the generator', function(cb) { 106 | app.register('backup', generator); 107 | app.generate('backup', exists(`${today}.tar`, cb)); 108 | }); 109 | 110 | it('should run the `backup` task', function(cb) { 111 | app.register('backup', generator); 112 | app.generate('backup:backup', exists(`${today}.tar`, cb)); 113 | }); 114 | 115 | it('should run the `default` task when defined explicitly', function(cb) { 116 | app.register('backup', generator); 117 | app.generate('backup:default', exists(`${today}.tar`, cb)); 118 | }); 119 | }); 120 | 121 | describe('sub-generator', function() { 122 | it('should work as a sub-generator', function(cb) { 123 | app.register('foo', function(foo) { 124 | foo.register('backup', generator); 125 | }); 126 | app.generate('foo.backup', exists(`${today}.tar`, cb)); 127 | }); 128 | 129 | it('should run the `default` task by default', function(cb) { 130 | app.register('foo', function(foo) { 131 | foo.register('backup', generator); 132 | }); 133 | app.generate('foo.backup', exists(`${today}.tar`, cb)); 134 | }); 135 | 136 | it('should run the `generator:default` task when defined explicitly', function(cb) { 137 | app.register('foo', function(foo) { 138 | foo.register('backup', generator); 139 | }); 140 | app.generate('foo.backup:default', exists(`${today}.tar`, cb)); 141 | }); 142 | 143 | it('should run the `generator:backup` task', function(cb) { 144 | app.register('foo', function(foo) { 145 | foo.register('backup', generator); 146 | }); 147 | app.generate('foo.backup:backup', exists(`${today}.tar`, cb)); 148 | }); 149 | 150 | it('should work with nested sub-generators', function(cb) { 151 | app 152 | .register('foo', generator) 153 | .register('bar', generator) 154 | .register('baz', generator) 155 | 156 | app.generate('foo.bar.baz', exists(`${today}.tar`, cb)); 157 | }); 158 | }); 159 | }); 160 | --------------------------------------------------------------------------------