From 035954c0b41954a005b714822f532e66189a3552 Mon Sep 17 00:00:00 2001 From: Gefei Hou Date: Wed, 11 Sep 2024 20:15:04 +0800 Subject: [PATCH] fix: windows support for cca --- .../create-cosmos-app/src/git-cca-template.ts | 13 +- packages/create-cosmos-app/src/utils.ts | 204 +++++++++--------- 2 files changed, 115 insertions(+), 102 deletions(-) diff --git a/packages/create-cosmos-app/src/git-cca-template.ts b/packages/create-cosmos-app/src/git-cca-template.ts index 0381811d8..cf0d3a5f3 100644 --- a/packages/create-cosmos-app/src/git-cca-template.ts +++ b/packages/create-cosmos-app/src/git-cca-template.ts @@ -4,7 +4,7 @@ import * as c from 'ansi-colors'; import { prompt } from './prompt'; import { join, dirname, basename, sep, relative } from 'path'; import { sync as mkdirp } from 'mkdirp'; -import { sync as glob } from 'glob'; +import { crossGlob as glob, toPosixPath } from './utils'; import * as fs from 'fs'; import { cloneRepo, @@ -14,14 +14,15 @@ import { } from './utils'; import { CCA_URL } from './constants'; +const posixPath = require('path').posix; const requiredTools = ['git', 'yarn']; const motd = (cmd: string, printCmd: boolean) => { const commandSection = printCmd ? `Now, run this command:\n\n${c.bold.whiteBright(cmd)}` : ''; return ` | _ _ - === |.===. '\\-//\` - (o o) {}o o{} (o o) + === |.===. '\\-//\` + (o o) {}o o{} (o o) ooO--(_)--Ooo-ooO--(_)--Ooo-ooO--(_)--Ooo- ✨ Have fun! Now you can start on your project ⚛️ @@ -93,7 +94,7 @@ export const createGitApp = (repo: string, version: string) => { // check version await warnIfOutdated(repo, clonedRepoDir, version); - // get template + // get template const list = shell.ls(`./${folderName}`); const { template } = await prompt([ { @@ -166,7 +167,7 @@ export const createGitApp = (repo: string, version: string) => { // Construct the file path - const relativeFilePath = templateFile.split(join(folderName, template) + sep)[1]; + const relativeFilePath = templateFile.split(toPosixPath(join(folderName, template) + '/'))[1]; // Replace keys in the entire file path const replacedFilePath = Object.keys(results).reduce((filePath, key) => { @@ -196,7 +197,7 @@ export const createGitApp = (repo: string, version: string) => { const closestPkgJson = [] .concat(glob(join(currentDirectory, name, '**', 'package.json'))) .reduce((shortest, current) => { - return current.split(sep).length < shortest.split(sep).length ? current : shortest; + return current.split(posixPath.sep).length < shortest.split(posixPath.sep).length ? current : shortest; }, fakeLongPath); // long string for kicks if (closestPkgJson === fakeLongPath) { diff --git a/packages/create-cosmos-app/src/utils.ts b/packages/create-cosmos-app/src/utils.ts index 55b6ceda5..3b9ac2922 100644 --- a/packages/create-cosmos-app/src/utils.ts +++ b/packages/create-cosmos-app/src/utils.ts @@ -3,7 +3,10 @@ import { prompt } from './prompt'; import { join } from 'path'; import { sync as mkdirp } from 'mkdirp'; import { tmpdir } from 'os' +import { sync as globSync } from 'glob'; import * as fs from 'fs'; + +const posixPath = require('path').posix; const dargs = require('dargs'); @@ -11,122 +14,131 @@ type TemplateFolder = 'templates' | 'boilerplates' | 'examples'; export const getTemplateFolder = async (argv) => { - let folderName: TemplateFolder = 'templates'; + let folderName: TemplateFolder = 'templates'; - // get example info - if (argv.examples || argv.example || argv.ex) { - folderName = 'examples'; - const example = argv.examples || argv.example || argv.ex; - if (typeof example === 'string') { - argv.template = example; - } + // get example info + if (argv.examples || argv.example || argv.ex) { + folderName = 'examples'; + const example = argv.examples || argv.example || argv.ex; + if (typeof example === 'string') { + argv.template = example; } - - // get boilerplate info - if (argv.boilerplates || argv.boilerplate) { - folderName = 'boilerplates'; - const boilerplate = argv.boilerplates || argv.boilerplate; - if (typeof boilerplate === 'string') { - argv.template = boilerplate; - } + } + + // get boilerplate info + if (argv.boilerplates || argv.boilerplate) { + folderName = 'boilerplates'; + const boilerplate = argv.boilerplates || argv.boilerplate; + if (typeof boilerplate === 'string') { + argv.template = boilerplate; } + } - return folderName; + return folderName; } export const cloneRepo = (argv, repo, name) => { - const tempname = Math.random().toString(36).slice(2, 7); - const dir = join(argv.tmpdir || tmpdir(), tempname); - mkdirp(dir); - shell.cd(dir); + const tempname = Math.random().toString(36).slice(2, 7); + const dir = join(argv.tmpdir || tmpdir(), tempname); + mkdirp(dir); + shell.cd(dir); - // Initialize the command arguments in an array - let gitCloneArgs = ['git', 'clone', '--depth', '1']; + // Initialize the command arguments in an array + let gitCloneArgs = ['git', 'clone', '--depth', '1']; - // Add the branch argument if argv.fromBranch is provided - if (argv.fromBranch) { - gitCloneArgs.push('-b', argv.fromBranch); - } + // Add the branch argument if argv.fromBranch is provided + if (argv.fromBranch) { + gitCloneArgs.push('-b', argv.fromBranch); + } - // Add the repository and name arguments - gitCloneArgs.push(repo, name); + // Add the repository and name arguments + gitCloneArgs.push(repo, name); - // Join the arguments with spaces to form the command - const gitCloneCommand = gitCloneArgs.join(' '); + // Join the arguments with spaces to form the command + const gitCloneCommand = gitCloneArgs.join(' '); - shell.exec(gitCloneCommand); - return dir; + shell.exec(gitCloneCommand); + return dir; } export const getQuestionsAndAnswers = async ( - argv, - name, - folderName: TemplateFolder + argv, + name, + folderName: TemplateFolder ) => { - const path = join(folderName, argv.template, '.questions.json') - if (fs.existsSync(path)) { - const questions = JSON.parse(fs.readFileSync(path, 'utf-8')); - - const fullname = shell - .exec('git config --global user.name', { silent: true }) - .trim(); - const email = shell - .exec('git config --global user.email', { silent: true }) - .trim(); - - // @__USERNAME__/__MODULENAME__ - // __PACKAGE_IDENTIFIER__ - const args = dargs( - { - _: [], - ...argv, - __QUESTIONS_EXIST_: true, - __MODULENAME__: name, - __USERFULLNAME__: fullname, - __USEREMAIL__: email, - }, - { allowCamelCase: true } - ); - - const results = await prompt(questions, args); - return results; - } else { - return {}; - } + const path = join(folderName, argv.template, '.questions.json') + if (fs.existsSync(path)) { + const questions = JSON.parse(fs.readFileSync(path, 'utf-8')); + + const fullname = shell + .exec('git config --global user.name', { silent: true }) + .trim(); + const email = shell + .exec('git config --global user.email', { silent: true }) + .trim(); + + // @__USERNAME__/__MODULENAME__ + // __PACKAGE_IDENTIFIER__ + const args = dargs( + { + _: [], + ...argv, + __QUESTIONS_EXIST_: true, + __MODULENAME__: name, + __USERFULLNAME__: fullname, + __USEREMAIL__: email, + }, + { allowCamelCase: true } + ); + + const results = await prompt(questions, args); + return results; + } else { + return {}; + } } export const getPackageLicAndAccessInfo = async (results) => { - let scopedResults; - - const license = await prompt( - [ - { - name: '__LICENSE__', - message: 'Which license?', - choices: ['MIT', 'closed'], - type: 'list', - required: true, - }, - ], - [] + let scopedResults; + + const license = await prompt( + [ + { + name: '__LICENSE__', + message: 'Which license?', + choices: ['MIT', 'closed'], + type: 'list', + required: true, + }, + ], + [] + ); + + if (results.__ACCESS__ === 'public') { + scopedResults = await prompt( + [ + { + type: 'confirm', + name: 'scoped', + message: 'use npm scopes?', + required: true, + }, + ], + [] ); + } + return { + license, + scopedResults + }; +} - if (results.__ACCESS__ === 'public') { - scopedResults = await prompt( - [ - { - type: 'confirm', - name: 'scoped', - message: 'use npm scopes?', - required: true, - }, - ], - [] - ); - } - return { - license, - scopedResults - }; +// Replace all \\ to / for windows support purpose +export const crossGlob = (input:string, options?:object) => { + return globSync(toPosixPath(input), options); } +// Unify all the path to posixPath for windows support purpose +export const toPosixPath = (mixedPath): string => { + return mixedPath.replace(/\\/g, posixPath.sep); +}