loopsgruntjsgrunt-contrib-copy

Grunt loop for copy task, but copying only last file


Can you help me with this problem?

I'm trying to create a function in Gruntfile.js to copy template files to my project using a loop and .json file to "automate" a copy job, apparently the function looks great because Grunt runs the copy job according to the number of records in the .json file, using a grunt.log.write in a loop Grunt shows the names of the .json files but in reality it copies only the last registered file.

First my .json file:

{
    "config": {
        "modules": [
            {"name": "footer", "number": 2},
            {"name": "header", "number": 1}
        ]
    }
}

Second my copy task with the loop variables:

copy: {
    core: {
        files: [{
            expand: true,
            cwd: "core/<%=grunt.option('coreName')%>/<%=grunt.option('coreNumber')%>/",
            src: "**",
            dest: "../sass/2_deploy/core/"
        }]
    }
}

The intention was to get the file inside the directory of the version "header /1/", "footer/2/" and transfer into the deploy directory according to the code above.

Third, here is the function that reads the .json file and declares the variables and executes the task inside the loop:

function moveCoreFiles() {
    var models = require('./variables.json');
    var cores = models.config.modules;
    for (core in cores) {
        grunt.option('coreName', cores[core].name);
        grunt.option('coreNumber', cores[core].number);
        grunt.task.run('copy:core');
        grunt.log.write(grunt.option("coreName"));
    }
}
// ... enter code here
grunt.registerTask('moveCore', moveCoreFiles);

At this point, when executing the task, Grunt returns this information:

$ grunt moveCore
Running "moveCore" task
footerheader
Running "copy:core" (copy) task
Copied 1 file

Running "copy:core" (copy) task
Copied 1 file

From the description of the task it seems that grunt has executed task one for each record twice, but in practice it only moved the last "header" file to the directory, my question would be if this type of action is really possible or if I should abandon the loop within the Gruntfile.

Thanks a lot for the help! Regards!


Solution

  • I think you should build an array of files to copy, and then pass the array to the task, so grunt will run the task for all the folders to copy only once, instead of running the task multiple times.

    First you define the function that will create the array of files to copy:

    function getFiles() {
        var models = require('./variables.json');
        var cores = models.config.modules;
        var files = [];
        for (var core in cores) {
            files.push({
                expand: true,
                cwd: "core/" + cores[core].name + "/" + cores[core].number + "/",
                src: "**",
                dest: "../sass/2_deploy/core/"
            });
            grunt.log.write("core/" + cores[core].name + "/" + cores[core].number + "/\r\n");
        }
        return files;
    }
    

    Then, define the copy task to use the array of files:

    grunt.initConfig({
        copy: {
            core: {
                files: getFiles()
            }
        }
    });
    

    Then just define the task:

    grunt.registerTask('default', ['copy:core']);
    

    The resulting Gruntfile.js will looks as follows:

    module.exports = function(grunt) {
    
        function getFiles() {
            var models = require('./variables.json');
            var cores = models.config.modules;
            var files = [];
            for (var core in cores) {
                files.push({
                    expand: true,
                    cwd: "core/" + cores[core].name + "/" + cores[core].number + "/",
                    src: "**",
                    dest: "../sass/2_deploy/core/"
                });
                grunt.log.write("core/" + cores[core].name + "/" + cores[core].number + "/\r\n");
            }
            return files;
        }
    
        grunt.initConfig({
            copy: {
                core: {
                    files: getFiles()
                }
            }
        });
    
        grunt.loadNpmTasks('grunt-contrib-copy');
    
        grunt.registerTask('default', ['copy:core']);
    
    };
    

    Hope it helps!