From d3ded5bbdfb87873bc842266256dd3ae7f980573 Mon Sep 17 00:00:00 2001 From: SteveSandersonMS Date: Wed, 22 Jun 2016 10:57:00 +0100 Subject: [PATCH] Workaround for Yeoman generators not producing .gitignore files due to Yeoman issue #1862 --- .gitignore | 7 ++++++ .../{.gitignore => template_gitignore} | 0 .../{.gitignore => template_gitignore} | 0 .../{.gitignore => template_gitignore} | 0 .../{.gitignore => template_gitignore} | 0 .../{.gitignore => template_gitignore} | 0 templates/yeoman/src/build/build.ts | 25 +++++++++++-------- templates/yeoman/src/generator/app/index.ts | 15 +++++++---- templates/yeoman/src/generator/package.json | 2 +- 9 files changed, 32 insertions(+), 17 deletions(-) rename templates/Angular2Spa/{.gitignore => template_gitignore} (100%) rename templates/KnockoutSpa/{.gitignore => template_gitignore} (100%) rename templates/ReactReduxSpa/{.gitignore => template_gitignore} (100%) rename templates/ReactSpa/{.gitignore => template_gitignore} (100%) rename templates/WebApplicationBasic/{.gitignore => template_gitignore} (100%) diff --git a/.gitignore b/.gitignore index d60c9bf..62ebab8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,10 @@ project.lock.json .vs/ npm-debug.log /.build/ + +# The templates can't contain their own .gitignore files, because Yeoman has strange default handling for +# files with that name (https://github.com/npm/npm/issues/1862). So, each template instead has a template_gitignore +# file which gets renamed after the files are copied. And so any files that need to be excluded in the source +# repo have to be excluded here. +/templates/*/node_modules/ +/templates/*/wwwroot/dist/ diff --git a/templates/Angular2Spa/.gitignore b/templates/Angular2Spa/template_gitignore similarity index 100% rename from templates/Angular2Spa/.gitignore rename to templates/Angular2Spa/template_gitignore diff --git a/templates/KnockoutSpa/.gitignore b/templates/KnockoutSpa/template_gitignore similarity index 100% rename from templates/KnockoutSpa/.gitignore rename to templates/KnockoutSpa/template_gitignore diff --git a/templates/ReactReduxSpa/.gitignore b/templates/ReactReduxSpa/template_gitignore similarity index 100% rename from templates/ReactReduxSpa/.gitignore rename to templates/ReactReduxSpa/template_gitignore diff --git a/templates/ReactSpa/.gitignore b/templates/ReactSpa/template_gitignore similarity index 100% rename from templates/ReactSpa/.gitignore rename to templates/ReactSpa/template_gitignore diff --git a/templates/WebApplicationBasic/.gitignore b/templates/WebApplicationBasic/template_gitignore similarity index 100% rename from templates/WebApplicationBasic/.gitignore rename to templates/WebApplicationBasic/template_gitignore diff --git a/templates/yeoman/src/build/build.ts b/templates/yeoman/src/build/build.ts index 91cf323..ce07100 100644 --- a/templates/yeoman/src/build/build.ts +++ b/templates/yeoman/src/build/build.ts @@ -6,7 +6,7 @@ import * as _ from 'lodash'; import * as mkdirp from 'mkdirp'; import * as rimraf from 'rimraf'; -const textFileExtensions = ['.gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.ts', '.tsx', '.xproj']; +const textFileExtensions = ['.gitignore', 'template_gitignore', '.config', '.cs', '.cshtml', 'Dockerfile', '.html', '.js', '.json', '.jsx', '.md', '.ts', '.tsx', '.xproj']; const templates = { 'angular-2': '../../templates/Angular2Spa/', @@ -33,12 +33,15 @@ function isTextFile(filename: string): boolean { function writeFileEnsuringDirExists(root: string, filename: string, contents: string | Buffer) { let fullPath = path.join(root, filename); - mkdirp.sync(path.dirname(fullPath)); + mkdirp.sync(path.dirname(fullPath)); fs.writeFileSync(fullPath, contents); } -function listFilesExcludingGitignored(root: string): string[] { - let gitIgnorePath = path.join(root, '.gitignore'); +function listFilesExcludingGitignored(root: string): string[] { + // Note that the gitignore files, prior to be written by the generator, are called 'template_gitignore' + // instead of '.gitignore'. This is a workaround for Yeoman doing strange stuff with .gitignore files + // (it renames them to .npmignore, which is not helpful). + let gitIgnorePath = path.join(root, 'template_gitignore'); let gitignoreEvaluator = fs.existsSync(gitIgnorePath) ? gitignore.compile(fs.readFileSync(gitIgnorePath, 'utf8')) : { accepts: () => true }; @@ -49,36 +52,36 @@ function listFilesExcludingGitignored(root: string): string[] { function writeTemplate(sourceRoot: string, destRoot: string) { listFilesExcludingGitignored(sourceRoot).forEach(fn => { let sourceContent = fs.readFileSync(path.join(sourceRoot, fn)); - + // For text files, replace hardcoded values with template tags if (isTextFile(fn)) { let sourceText = sourceContent.toString('utf8'); contentReplacements.forEach(replacement => { sourceText = sourceText.replace(replacement.from, replacement.to); }); - + sourceContent = new Buffer(sourceText, 'utf8'); } - + // Also apply replacements in filenames filenameReplacements.forEach(replacement => { fn = fn.replace(replacement.from, replacement.to); }); - + writeFileEnsuringDirExists(destRoot, fn, sourceContent); - }); + }); } function copyRecursive(sourceRoot: string, destRoot: string, matchGlob: string) { glob.sync(matchGlob, { cwd: sourceRoot, dot: true, nodir: true }) .forEach(fn => { - const sourceContent = fs.readFileSync(path.join(sourceRoot, fn)); + const sourceContent = fs.readFileSync(path.join(sourceRoot, fn)); writeFileEnsuringDirExists(destRoot, fn, sourceContent); }); } const outputRoot = './generator-aspnetcore-spa'; -const outputTemplatesRoot = path.join(outputRoot, 'app/templates'); +const outputTemplatesRoot = path.join(outputRoot, 'app/templates'); rimraf.sync(outputTemplatesRoot); // Copy template files diff --git a/templates/yeoman/src/generator/app/index.ts b/templates/yeoman/src/generator/app/index.ts index 7a7e95c..ecb5366 100644 --- a/templates/yeoman/src/generator/app/index.ts +++ b/templates/yeoman/src/generator/app/index.ts @@ -22,7 +22,7 @@ class MyGenerator extends yeoman.Base { prompting() { const done = this.async(); - + this.prompt([{ type: 'list', name: 'framework', @@ -40,13 +40,18 @@ class MyGenerator extends yeoman.Base { done(); }); } - + writing() { var templateRoot = this.templatePath(this._answers.framework); glob.sync('**/*', { cwd: templateRoot, dot: true, nodir: true }).forEach(fn => { // Token replacement in filenames let outputFn = fn.replace(/tokenreplace\-([^\.\/]*)/g, (substr, token) => this._answers[token]); - + + // Rename template_gitignore to .gitignore in output + if (path.basename(fn) === 'template_gitignore') { + outputFn = path.join(path.dirname(fn), '.gitignore'); + } + this.fs.copyTpl( path.join(templateRoot, fn), this.destinationPath(outputFn), @@ -54,7 +59,7 @@ class MyGenerator extends yeoman.Base { ); }); } - + installingDeps() { this.installDependencies({ npm: true, @@ -62,7 +67,7 @@ class MyGenerator extends yeoman.Base { callback: () => { this.spawnCommandSync('dotnet', ['restore']); this.spawnCommandSync('./node_modules/.bin/webpack', ['--config', 'webpack.config.vendor.js']); - this.spawnCommandSync('./node_modules/.bin/webpack'); + this.spawnCommandSync('./node_modules/.bin/webpack'); } }); } diff --git a/templates/yeoman/src/generator/package.json b/templates/yeoman/src/generator/package.json index cca237f..1f9063c 100644 --- a/templates/yeoman/src/generator/package.json +++ b/templates/yeoman/src/generator/package.json @@ -1,6 +1,6 @@ { "name": "generator-aspnetcore-spa", - "version": "0.1.5", + "version": "0.1.6", "description": "Single-Page App templates for ASP.NET Core", "author": "Microsoft", "license": "Apache-2.0",