需求描述
团队有一个后端模板项目,现在要求可以通过命令行拷贝这个项目本地,并且可以配置一些信息,具体要求如下:
- 命令行拷贝模板项目
- 可以配置git地址
- 可以新建git分支
功能设计
经过技术的调研,参考行业的做法,最终得出如下的功能设计:
- 通过命令行选择(list的方式)模板地址,并且可以选择手动输入模板地址。
- 通过命令行询问(input的方式)模板分支,后面会复制该分支的代码,配置默认值是main(这个根据每个团队的代码习惯修改)。
- 通过命令行询问(input的方式)文件夹,用来存放拷贝下来的模板,默认是当前根文件夹。
- 通过命令行询问(input的方式)新项目的git地址,目标项目git地址,可以为空,方便后续自定义配置。
- 通过命令行询问(input的方式)新项目的git分支,目标项目git分支,可以为空,方便后续自定义配置。
- clone模板到当前文件夹
- 将clone下来的模板复制到指定文件夹,并且删除多余的文件
- 修改git地址,并且新建分支
功能实现
询问方式的具体实现
利用inquirer库去进行选择,具体代码如下
import inquirer from "inquirer";
export default async () => {
const choices = [
{
name: "后端管理系统",
value:
"http://gitlab.xxxxxxxx",
},
{
name: "手动输入模版地址",
value: "",
},
];
return inquirer.prompt([
{
type: "list",
name: "remoteUrl",
choices,
message: "请输入项目新建分支",
},
]);
};
当判断选择的模板为空的时候,可以使用手动输入的方式
import selectTemplate from "../questions/selectTemplate.js";
import gitTemplateRemoteUrl from "../questions/remoteUrl.js";
let template = await selectTemplate();
// console.log(template);
if (!template.remoteUrl) {
template = await gitTemplateRemoteUrl(templatesDirRootPath);
}
import fs from "fs";
import inquirer from "inquirer";
export default async (templatesDirRootPath) => {
let remoteUrl =
"http://gitlab.xxxxxx";
if (fs.existsSync(`${templatesDirRootPath}/defaultRemoteUrl.txt`)) {
remoteUrl = fs.readFileSync(
`${templatesDirRootPath}/defaultRemoteUrl.txt`,
"utf-8"
);
}
return inquirer.prompt([
{
type: "input",
name: "remoteUrl",
default: remoteUrl || undefined,
message: "请设置模板仓库地址",
validate(val) {
// git仓库的正则表达式 http://cn.voidcc.com/question/p-qlprjeax-kd.html
const gitRemoteUrlReg =
/(\w+:\/\/)([email protected])*([\w\d\.]+)(:[\d]+){0,1}\/*(.*)/;
if (!val) {
return true;
} else if (!gitRemoteUrlReg.test(val)) {
return "远程仓库地址格式错误,请重新输入";
} else {
return true;
}
},
},
]);
};
其他的询问方式跟上面类似,只需要改个name和message
根据获取的信息进行git操作
//当前目录
const templatesDirRootPath = `/${processCwdArr[1]}/${processCwdArr[2]}`;
getGitRemoteResult = execaSync(
`git`,
["clone", "-b", config.branch, config.remoteUrl],
{
cwd: templatesDirRootPath,
stdio: [2, 2, 2], // 使子进程的输入输出流继承父进程,在当前父进程显示子进程的输入与输出
}
);
进行复制文件到指定文件夹,并且删除模板的.git
fs.rmSync(
`${templatesDirRootPath}/${gitRemoteFilename}/.git`,
{ recursive: true, force: true },
() => {}
);
const url = `${templatesDirRootPath}/${gitRemoteFilename}`;
if (gitRemoteFilename == config.createDir) {
setGit();
} else {
fse.copy(`${url}`, `./${config.createDir}`, (err) => {
if (err) {
console.error(err);
} else {
console.log("删除多余文件夹", url);
fs.rm(`${url}`, { recursive: true, force: true }, () => {});
setGit();
console.log(chalk.green("创建模块成功!"));
}
});
}
根据配置重新设置git信息
execaSync(`git`, ["init", "-b", config.gitBranch || config.branch], {
cwd: `${templatesDirRootPath}/${config.createDir}`,
stdio: [2, 2, 2], // 使子进程的输入输出流继承父进程,在当前父进程显示子进程的输入与输出
});
// execaSync(`git`, ["remote", "set-url", "origin", config.gitUrl]);
execaSync(`git`, ["remote", "add", "origin", config.gitUrl], {
cwd: `${templatesDirRootPath}/${config.createDir}`,
stdio: [2, 2, 2], // 使子进程的输入输出流继承父进程,在当前父进程显示子进程的输入与输出
});
execaSync(`git`, ["fetch"], {
cwd: `${templatesDirRootPath}/${config.createDir}`,
stdio: [2, 2, 2], // 使子进程的输入输出流继承父进程,在当前父进程显示子进程的输入与输出
});
console.log(chalk.green("同步远程仓库成功!"));
总结
这个需求没多复杂的操作,无非就是询问信息,获取信息,利用git下载模板,复制模板到指定文件夹,配置git的信息。发这篇文章跟大家一起学习。