Re-post of https://github.com/angular/devkit/issues/745
x)- [x] bug report -> please search issues before submitting
- [ ] feature request
- [ ] devkit
- [x] schematics
Node v8.11.1
NPM 5.8.0
Mac OS High Sierra
Use the following schematic
import { Rule, url, apply, mergeWith, chain, MergeStrategy } from '@angular-devkit/schematics';
export function index(): Rule {
return chain([
simpleMerge(),
]);
}
function simpleMerge(): Rule {
const source = url('./files');
return mergeWith(source, MergeStrategy.Overwrite);
}
schematics .:boilerplate
ERROR! /src/app/app.component.html already exists.
ERROR! /src/app/app.component.spec.ts already exists.
ERROR! /src/app/app.component.ts already exists.
ERROR! /src/app/app.module.ts already exists.
ERROR! /src/assets/.gitkeep already exists.
ERROR! /src/environments/environment.prod.ts already exists.
ERROR! /src/environments/environment.ts already exists.
ERROR! /src/index.html already exists.
All files should be overwritten.
I tried every MergeStrategy possible (AllowOverwriteConflict, etc.), same result.
https://github.com/angular/devkit/issues/745
https://stackoverflow.com/questions/48957132/how-to-overwrite-file-with-angular-schematics
Could you provide the versions used?
I cannot answer with certainty without knowing the versions but this PR (https://github.com/angular/angular-cli/pull/11274) will most likely correct the behavior.
version 0.6.8
dup repo https://github.com/gatimus/schematics-merge-strategy
Could you try with the RC of 0.7? I fixed a lot of issues by reworking the whole Tree implementation, should have fixed a few of those merging issues (amongst others, e.g. branching).
Dupe of https://github.com/angular/angular-cli/issues/11246. Let's keep this one for tracking though as it has more information.
Still duplicating on 0.7.0-rc.3 https://github.com/gatimus/schematics-merge-strategy/tree/RC-0.7
This is making me cry 馃槩
Is this already fixed?
I have following workaround:
const templateSource = apply(url('./project-files'), [
template({ ...strings, ...options }),
move(options.path),
forEach((fileEntry: FileEntry) => {
if (host.exists(fileEntry.path)) {
host.overwrite(fileEntry.path, fileEntry.content);
}
return fileEntry;
}),
]);
Hi,
For me, the issue appears after upgrading my schematics "dependencies" from:
{
"@angular-devkit/core": "^0.6.8",
"@angular-devkit/schematics": "^0.6.8",
"typescript": "^2.5.1"
},
to:
{
"@angular-devkit/core": "^0.7.3",
"@angular-devkit/schematics": "^0.7.3",
"typescript": "^2.9.0"
},
Version v0.6.8's mergeWith was working fine...
@joeson1 : i tried your workaround, but it didn't help 馃槥 ...
@joeson1 where do you assign host?
@tinesoft I get the exact same behavior with v0.6.8 as with v0.7.3
I believe this is the same issue as #12088.
I originally commented this on #12088:
This issue still exists in 0.8.4.
The issue occurs on HostTree merge. I've detailed the simplified propagation below:
I'm still having this issue, in case someone needs to know it's still not fixed. Using version 0.8.6
I have the same issue qith 0.8.6, however if I run schematics my-schematic:my-schematic it will work BUT if I run ng g my-schematic:my-schematic it will give me the already exists error message. Can anyone explain why?
@egervari and @bautistaaa could you let me know if this workaround works for you?
As others have stated, this still seems to be an issue... I've reproduced with 0.6.8 and 0.7.2... Based on one of the suggestions in the thread linked by @cgatian, I was able to formulate a workaround for my specific situation...
In my method, I was attempting to call move() within the rules array of apply()... Essentially the source url() was a subdirectory of my 'files' directory in my schematic - and the destination in move() was a subdirectory of the project tree.
So, I had the schematics source assets in: schematics\ng-add\files\help\my-help\index.html
And I wanted my schematics source assets to be dropped in the projects source directory: \src\help\my-help\index.html.
When calling url('./files/help') and move('.', '/src/'), I would get "src/help/my-help/index.html already exists. The Schematic workflow failed."
To work around this, I changed my folder structure in my schematics assets to match the project folder structure - so instead of 'schematics\ng-add\files\help....' I used 'schematics\ng-add\files\src\help....'. I then updated url to be "url('./files')" and move to be "move('.')"... So now instead of explicitly setting the URL source as a subfolder containing the assets, it's just using the whole 'files' directory to overlay on top of the root of the project (move('.')).
I ran across this workaround when I by chance notice that I only got the 'already exists' error when operating on subfolders of the project - but in my troubleshooting, I realized that things behaved as expected when operating against the root of the project...
Here's a sample of my updated method which now works as desired in case it assists:
/** Add help assets to application */
// NOTE: work around due to busted MergeStrategy - https://github.com/angular/angular-cli/issues/11337
function addHelpToApplicationRoot(options: Schema) {
return (tree: Tree, context: SchematicContext) => {
context.logger.info(`Adding help assets to application help.`);
const rule = mergeWith(
apply(url('./files'), [
forEach((fileEntry) => {
if (tree.exists(fileEntry.path)) {
tree.overwrite(fileEntry.path, fileEntry.content);
return null;
}
return fileEntry;
}),
move('.')
]),
);
return rule(tree, context);
};
}
Seems that the important detail, at least in my case, was to make my 'files' assets be structured in a way that matches the project's folder structure rather than relying on url() and move() to work on specific subfolders.
@mattezell Thank you for workaround example. However, I'd assume that you don't need this "move('.')" - everything should work even w/o it.
I have the same problem not using a Source but trying to create/override custom stuff in the Tree. There's no simple way via MergeStrategy to avoid the exists check?
My hacky intuition thought that using tree.overwrite with MergeStrategy.AllowOverwriteConflict would default to create the files I'm trying to overwrite. Or create with AllowCreationConflict would overwrite, something like that would be useful.
There's no simple way via MergeStrategy to avoid the
existscheck?
I believe this is exactly what MergeStrategy.Overwrite is suppose to do.
Hi,
I experience the same issue.
I setup a minimal reproduction: https://github.com/GregOnNet/merge-strategie-issue
.prettierrcoverwrite loads another .prettierrc from ./templatesMergeStrategy.Overwrite is configured as 2nd parameter of apply.schematics failsRepro Steps to see the details.Node v11.11.0
NPM 6.9.0
Mac MacOS Mojave 10.14.3
@angular-devkit/core: 7.3.6
@angular-devkit/schematics: 7.3.6
git clone https://github.com/GregOnNet/merge-strategie-issue.git
cd merge-strategie-issue
npm install
npm test # Everything is fine
npm run build
schematics .:overwrite
# ERROR
ERROR! /.prettierrc already exists.
The Schematic workflow failed. See above.
If I can provide any further information, please let me know. 馃憤
Is there any plan to fix this? Any current workarounds?
@tscislo this is my current workaround:
export function overwriteIfExists(host: Tree): Rule {
return forEach(fileEntry => {
if (host.exists(fileEntry.path)) {
host.overwrite(fileEntry.path, fileEntry.content);
return null;
}
return fileEntry;
});
}
export function mySchematic(options: MyOptions): Rule {
return (host: Tree, context: SchematicContext) => {
/* ...logic... */
const templateSource = apply(
url('./files'),
[
template({
...strings,
...options
}),
move(options.path),
options.overwrite ? overwriteIfExists(host) : noop()
]
);
return mergeWith(templateSource);
};
}
derived from other variations in answers here https://stackoverflow.com/questions/48957132/how-to-overwrite-file-with-angular-schematics
For me even workarounds did not work.
When I apply them - changes are simply ignored and I get message Nothing to be done....
A note about the workaround using manual forEach and overwrite.
Make sure that you put the forEach before the move since the file paths that you get are relative to the root project. And also make sure that you create the files first before trying to overwrite them. (e.g calling externalSchematic first).Took me a while to notice that.
Most helpful comment
This is making me cry 馃槩