I want to write a Rule
that overwrites a file every time. In the following and have MergeStrategy
set to Overwrite
:
coll
Thanks @cgatian for that hint!
Unfortunately it didn't worked to move
the templates to some location, so I had to add:
forEach(fileEntry => {
const destPath = join(options.output, fileEntry.path);
if (tree.exists(destPath)) {
tree.overwrite(destPath, fileEntry.content);
} else {
tree.create(destPath, fileEntry.content);
}
return null;
})
Until the MergeStrategy
works as expected,
this will do the trick passing the destination path in options.output
!
Thanks again!
Use --force
argument:
ng g c component-name --force
This may not be ideal if you are replacing many files. I came across this issue replacing the favicon.ico while adding boilerplate to the project. The solution I use is to explicitly delete it first.
export function scaffold(options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
tree.delete('src/favicon.ico');
const templateSource = apply(url('./files'), [
template({
...options,
}),
move('.'),
]);
return chain([
branchAndMerge(chain([
mergeWith(templateSource, MergeStrategy.Overwrite),
]), MergeStrategy.AllowOverwriteConflict),
])(tree, _context);
};
}
NOTE: This approach no longer works with current versions of Schematics.
The following seems to work for the 0.6.8 schematics.
export function scaffold(options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
const templateSource = apply(url('./files'), [
template({
...options,
}),
move('.'),
]);
return chain([
branchAndMerge(chain([
mergeWith(templateSource, MergeStrategy.Overwrite),
]), MergeStrategy.Overwrite),
])(tree, _context);
};
}
As a bonus, I no longer need to explicitly delete the file.
I experienced the same issue. By accident I found that adding a forEach
into the apply
allowed the files to be deleted and the new files created. This is with @angular-devkit/schematics-cli@0.6.8.
export function indexPage(options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
const rule = mergeWith(
apply(url('./files'), [
template({ ...options }),
forEach((fileEntry: FileEntry) => {
// Just by adding this is allows the file to be overwritten if it already exists
if (tree.exists(fileEntry.path)) return null;
return fileEntry;
})
])
);
return rule(tree, _context);
};
}
Modifying chris' answer I was able to come up with the following solution:
export function applyWithOverwrite(source: Source, rules: Rule[]): Rule {
return (tree: Tree, _context: SchematicContext) => {
const rule = mergeWith(
apply(source, [
...rules,
forEach((fileEntry) => {
if (tree.exists(fileEntry.path)) {
tree.overwrite(fileEntry.path, fileEntry.content);
return null;
}
return fileEntry;
}),
]),
);
return rule(tree, _context);
};
}
Replace your usage of apply
with calls to this function.
applyWithOverwrite(url('./files/stylelint'), [
template({
dot: '.',
}),
]),