const { exec } = require("child_process"); const getNonNullValue = (value) => { if (value != "") { return value; } else { return undefined; } }; const commandConfigMap = { init: { requireArgument: false, requirements: { arguments: [], message: "", }, action() { return [null, "git init"]; }, }, branch: { requireArgument: true, requirements: { arguments: ["branch name"], message: "branch= \n eg. branch=pws", }, action(value) { return [null, `git branch ${value}`]; }, }, checkout: { requireArgument: true, requirements: { arguments: ["branch name"], message: "checkout= \n eg. checkout=pws", }, action(value) { return [null, `git checkout ${value}`]; }, }, merge: { requireArgument: true, requirements: { arguments: ["branch name"], message: "merge= \n eg. merge=pws", }, action(value) { return [null, `git merge ${value}`]; }, }, "add-remote": { requireArgument: true, requirements: { arguments: ["remote name", "remote url"], message: 'add-remote= \n eg. add-remote="remotename https://github.com/username/reponame.git"', }, action(remoteName, remoteUrl) { return [null, `git remote add ${remoteName} ${remoteUrl}`]; }, }, "rm-remote": { requireArgument: true, requirements: { arguments: ["remote name"], message: "rm-remote= \n eg. rm-remote=pws", }, action(remoteName) { return [null, `git remote remove ${remoteName}`]; }, }, add: { requireArgument: true, requirements: { arguments: ["file path"], message: "add= \n eg. add=.", }, action(filePath) { return [null, `git add ${filePath}`]; }, }, commit: { requireArgument: true, requirements: { arguments: ["commit message"], message: 'commit= \n eg. commit="commit message"', }, action(commitMessage) { return [null, `git commit -m "${commitMessage}"`]; }, }, pull: { requireArgument: false, requirements: { arguments: ["remote name", "branch name"], message: 'pull= \n eg. pull="origin main"', }, action(remoteName = null, branchName = null) { if (getNonNullValue(remoteName) && !getNonNullValue(branchName)) { return [`${this.requirements.message} : branch name is missing`, null]; } if (!getNonNullValue(remoteName) && getNonNullValue(branchName)) { return [`${this.requirements.message} : remote name is missing`, null]; } return [ null, `git pull ${remoteName ? `${remoteName}` : ""} ${ branchName ? `${branchName}` : "" }`, ]; }, }, push: { requireArgument: false, requirements: { arguments: ["remote name", "branch name"], message: 'push= \n eg. push="origin main"', }, action(remoteName = null, branchName = null) { if (getNonNullValue(remoteName) && !getNonNullValue(branchName)) { return [`${this.requirements.message} : branch name is missing`, null]; } if (!getNonNullValue(remoteName) && getNonNullValue(branchName)) { return [`${this.requirements.message} : remote name is missing`, null]; } return [ null, `git push ${remoteName ? `${remoteName}` : ""} ${ branchName ? `${branchName}` : "" }`, ]; }, }, }; // const allowedCommands = [ // "init", // "branch", // "checkout", // "add-remote", // "rm-remote", // "add", // "commit", // "pull", // "push", // ]; const computeCommand = (commandConfig, values) => { const arguments = commandConfig?.requirements?.arguments?.length > 1 ? values : [values?.join(" ")]; const [error, command] = commandConfig?.action(...arguments); if (error) { return [error, null]; } return [null, command]; }; const runCommands = (commands, i) => { return new Promise((resolve, reject) => { return commandProcess(commands, i, resolve, reject); }); }; const commandProcess = (commands, i, resolve, reject) => { if (i >= commands.length) { return resolve([null, "All commands executed successfully"]); } const command = commands[i]; exec(command, (error, stdout, stderr) => { console.log(`\n$Git >> ${command}`); if (!error) { console.log(`$Git >> ${command} command output: ${stdout}`); commandProcess(commands, i + 1, resolve, reject); } else { console.error(`$Git >> Error executing Git command: ${stderr}`); } }); }; const argvs = process.argv.splice(2); const startGitProcess = async () => { return new Promise(async (resolve, reject) => { let commands = []; for (const commandEntry of argvs) { const [key, value] = commandEntry.split("="); const commandConfig = commandConfigMap[key]; const values = value?.trim()?.replace(/\s+/g, " ")?.split(" "); // console.log("values >>", values); if (!commandConfig) { return reject(`Command ${key} is not recognised as internal command`); } if (commandConfig.requireArgument) { if (!value) { return reject( `Argument is required: ${commandConfig.requirements.message}` ); } if (commandConfig.requirements.arguments.length > 1) { if (values.length !== commandConfig.requirements.arguments.length) { return reject( `Invalid number of arguments: ${commandConfig.requirements.message}` ); } } } const [error, command] = computeCommand(commandConfig, values); if (error) { return reject(error); } commands = commands.concat(command); } // console.log("$Git >> commands:", commands); if (!commands?.length) { return reject("No command to execute"); } const [error, message] = await runCommands(commands, 0); if (error) { return reject(error); } return resolve(message); }); }; const main = async () => { try { const result = await startGitProcess(); console.log("\n$Git >>", result); } catch (error) { console.error("\n$Git >> Error:", error); } }; main(); // git checkout master && git pull origin master && yarn build && git add . && git commit -m "Build Master" && git push origin master && git checkout wireframe && git merge master && git push origin wireframe // const operations = argvs.map((argv) => argv.split("=")[0]?.toLowerCase()) // const allowedCommands = Object.keys(commandConfigMap); // const commandValidation = operations.map((command) => { // if (!allowedCommands.includes(command.trim())) { // return { // command, // isValid: false, // }; // } // return { // command, // isValid: true, // }; // }); // const invalidCommands = commandValidation.filter((command) => !command.isValid); // if (invalidCommands.length) { // const errorMessage = invalidCommands // .map((command) => `${command.command} is not recognised as internal command`) // .join(", "); // return [errorMessage, null]; // } // "commit:script": "node git-script add=. commit="Update" push="origin pws" checkout=master merge=pws push="origin master" checkout=pws"