Reputation: 4217
I have already asked a simplified version of this question but the answer then did not work on my larger problem so I am going to post the whole thing here and see if anything comes of it.
Project Structure
I have many projects to work with that all share a structure like this (more child dirs/sub levels than this but you get the idea) :
|-build
|-sub_EN_01
|-assets
|-image.jpg
|-file_EN.txt
|-sub_EN_02
|-assets
|-image.jpg
|-file_EN.txt
When a new project is started I want to copy the contents of build
to a new dir and then run a task that will change all instances of EN
to FR
in both file/dir names and file contents.
Copy And Rename
The task I have written does this fine. A call like this gulp copy-dirs --match EN --replacement FR
specifies which strings should replace what and is all good but leaves me the original EN
files alongside the new FR
files :
var gulp = require("gulp");
var foreach = require("gulp-foreach");
var args = require("yargs").argv;
var rename = require("gulp-rename");
var replace = require("gulp-replace-task");
gulp.task("copy-dirs", function(){
return gulp.src("./build/*"+args.match+"*")//Original parent dirs to copy
.pipe(foreach(function(pDirStream, pDirFile){//Loop parent dirs
var newDirName = pDirFile.relative.replace(args.match, args.replacement);//Name of parent dir with replacement applied
gulp.src("./build/"+pDirFile.relative+"/**/*")//Get contents of dir
.pipe(foreach(function(childStream, childFile){//Loop child files
var newFileName = childFile.relative.replace(args.match, args.replacement);//Name of child with replacement applied
childStream.pipe(replace({usePrefix: false, patterns:[
{
match: args.match,
replacement: args.replacement
}
]}))
.pipe(rename(newFileName));
return childStream;
}))
.pipe(gulp.dest("./build/"+newDirName));//Save it to new location
return pDirStream;
}));
});
Cleaning Up
So, I wrote a second small task to clean up which if I then call with gulp clean --match EN
and it clears out the original EN
files:
var del = require("del");
gulp.task("clean", function(){
return del(["./build/*"+args.match+"*/**"]);
});
The Problem
Boom! Done. Except this only works if I run copy-dirs
and then manually run clean
. What I wanted to do was sequence them like this:
gulp.task("project-rename", ["clean"]);
gulp.task("clean", ["copy-dirs"], function(){
return del(["./build/*"+args.match+"*/**"]);
});
..but when I try this and call gulp project-rename --match EN --replacement FR
I get Error: ENOENT, lstat
followed a file path to an asset and am left with a selection of half copied/deleted projects.
The Hack
I managed to fix things by using gulp-wait
to pause for a second at the end of copy-dirs
but this just feels really hacky and so I would like to ask:
clean
task fail when I attempt to run them as a sequence?Thank You
If you got to here then you are a better person than me. I know this is a beast of post but I have tried to explain it as best I can. I love what gulp
offers but I just can't quite get my head around how it actually works in situations more complex than a single task. Any advice will be gratefully received.
Yours in frustrated desperation :)
Upvotes: 1
Views: 78
Reputation: 151370
You are trying to do things that Gulp and its plugins should do for you.
I've based the following solution on your prose description of what you want to do rather than the code you've shown so it is possible that it behaves a bit differently. I've commented the code to explain what it does. Also, I've tested it with a file tree that replicates what you've shown in your question and found it to work. One thing I'd do differently but which you seem to want is that I would not want a gulpfile.js
that takes its initial input and write its final output in the same directory. It seems dangerous to me.
var gulp = require("gulp");
var args = require("yargs").argv;
var rename = require("gulp-rename");
var replace = require("gulp-replace-task");
var del = require("del");
var gulpFilter = require('gulp-filter');
var match = args.match;
var replacement = args.replacement;
var match_re = RegExp(match, "g");
gulp.task("copy-dirs", function () {
// Set a filter that we'll use later. We have `restore: true` so
// that we can restore the stream to its original set of files
// after we are done with the filter.
var filter = gulpFilter("**/*.txt", {restore: true});
// We match all descendants of any directory in ./build that has
// the string specified by `match` in it.
return gulp.src("./build/*" + match + "*/**")
// In file paths every instance of the string contained by the
// `match` option will be replaced with the string specified by
// the `replacement` option.
.pipe(rename(function (path) {
path.dirname = path.dirname.replace(match_re, replacement);
path.basename = path.basename.replace(match_re, replacement);
// If you really want to change extensions, you'll also
// have to process path.ext.
}))
// Filter it down to only the files for which text replacement
// makes sense.
.pipe(filter)
.pipe(replace({usePrefix: false, patterns:[
{
match: match,
replacement: replacement
}
]}))
// Go back to the whole set of files so that we can store them.
.pipe(filter.restore)
.pipe(gulp.dest("./build"));
});
gulp.task("clean", ["copy-dirs"], function(){
return del(["./build/*"+match+"*/**"]);
});
gulp.task("project-rename", ["clean"]);
Upvotes: 2