3

I'm building a custom yeoman generator, so when it's time to create files they're created one directory above my current location, or at .., so for example if I run:

yo koala

From /home/diegoaguilar/koala the files will be created at /home/diegoaguilar. How am I supposed to tell the path where the generator should copy files? I really thought that would be process.cwd() or simply where yeoman generator is being ran from.

This is the code I got for files generation:

  writing: {
    app: function () {
      this.fs.copyTpl(
        this.templatePath('_package.json'),
        this.destinationPath('package.json'),
        {appname: this.appname}
      );
      this.fs.copy(
        this.templatePath('_bower.json'),
        this.destinationPath('bower.json')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('editorconfig'),
        this.destinationPath('.editorconfig')
      );
      this.fs.copy(
        this.templatePath('jshintrc'),
        this.destinationPath('.jshintrc')
      );
    }
  },
diegoaguilar
  • 8,179
  • 14
  • 80
  • 129

1 Answers1

3

First, I find it easier to use yeoman's this.template(), instead of using this.fs.copy()/this.fs.copyTpl() that are coming from the included instance of mem-fs-editor, but YMMV

Regardless, you need to set the this.sourceRoot('rel/path/to/source/root') and this.destinationRoot('rel/path/to/dest/root') in the generator before you try to write to make sure you have set the correct template and destination contexts. See yeoman's getting started guide on interacting with the files system from more information. The this.destinationRoot() should be defined relative to the root directory of your current project (I explain this below), while the this.sourceRoot() should be defined relative to the root directory of your generator's files.

You also have to consider that yeoman will try to figure out the root directory of whatever app you are currently in at the command line. It does this by navigating upwards (i.e. /home/diegoaguilar/koala -> /home/diegoaguilar/) until it finds a .yo-rc.json file. Yeoman then takes the directory of the nearest .yo-rc.json to where you ran the command as the intended root directory for your project.

In your case you may want to delete/move/rename /home/diegoaguilar/.yo-rc.json if it exists. Then you can create the directory you want your project to live inside and run the generator there. This would look like

/home/diegoaguilar/ $> mkdir koala
/home/diegoaguilar/ $> cd koala
/home/diegoaguilar/koala/ $> yo koala

If you want or need to leave your /home/diegoaguilar/.yo-rc.json there, you should set the this.destinationRoot() in the generator relative to /home/diegoaguilar/, so to write into /home/diegoaguilar/koala/ you would use this.destinationRoot('koala').

Joshua Skrzypek
  • 448
  • 5
  • 9
  • @diegoaguilar asked elsewhere why I prefer `this.template()`, so I thought I'd include the answer here as well: The main advantage of `this.template()` is that you can use it in place of both `this.fs.copy()` and `this.fs.copyTpl()`, and it defaults to providing the current generator instance (i.e. the `this`) as the template context. If your file is a direct copy with no `ejs` tags to be templated then it doesn't matter whether the `this` is provided; `mem-fs-editor` will handle it correctly. – Joshua Skrzypek Nov 04 '15 at 10:50
  • The only place this might be a problem is if you want to do a `this.fs.copy()` and pass a process option to `mem-fs-editor` as discussed in [this answer on another question](http://stackoverflow.com/a/28975192/3991403). After digging into it a bit I saw that the `copyTpl()` function doesn't allow a `process` function like `copy()` does precisely because `copyTpl()` itself actually calls `copy()` and itself already passes a function calling `ejs.render()` in the `process` option. – Joshua Skrzypek Nov 04 '15 at 10:52