git-pull-run
Advanced tools
Comparing version
#!/usr/bin/env node | ||
import { Command } from 'commander'; | ||
import debugLog from 'debug'; | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
import { gitPullRun } from './index.js'; | ||
const debug = debugLog('git-pull-run:cli'); | ||
const packageJsonPath = path.join(fileURLToPath(import.meta.url), '../../package.json'); | ||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); | ||
const version = packageJson.version; | ||
const program = new Command() | ||
.version(version) | ||
.requiredOption('-p, --pattern <glob>', 'pattern to match files (required)') | ||
.option('-c, --command <command>', 'execute shell command for each matched file') | ||
.option('-s, --script <script>', 'execute npm script for each matched file') | ||
.option('-m, --message <message>', 'print message to the console if matches were found') | ||
.option('-d, --debug', 'print additional debug information', false) | ||
.option('-o, --once', 'run command only once if any files match the pattern', false) | ||
.parse(); | ||
const options = program.opts(); | ||
if (options.debug) | ||
debugLog.enable('git-pull-run*'); | ||
debug(`Started git-pull-run@${version}`); | ||
gitPullRun(options) | ||
.then(() => { | ||
debug(`Finished git-pull-run@${version}`); | ||
process.exitCode = 0; | ||
}) | ||
.catch(() => { | ||
process.exitCode = 1; | ||
}); | ||
//# sourceMappingURL=cli.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import fs from"node:fs";import path from"node:path";import{fileURLToPath}from"node:url";import{Command,Option}from"@commander-js/extra-typings";import debugLog from"debug";import{detect}from"package-manager-detector/detect";import{gitPullRun}from"./index.js";var installOption=new Option("-i, --install","detect package manager and run install");var patternOption=new Option("-p, --pattern <glob>","pattern to match files (required)");var commandOption=new Option("-c, --command <command>","execute shell command for each matched file");var scriptOption=new Option("-s, --script <script>","execute npm script for each matched file");var messageOption=new Option("-m, --message <message>","print message to the console if matches were found");var debugOption=new Option("-d, --debug","print additional debug information");var onceOption=new Option("-o, --once","run command only once if any files match the pattern");var debug=debugLog("git-pull-run:cli");var packageJsonPath=path.join(fileURLToPath(import.meta.url),"../../package.json");var packageJson=JSON.parse(fs.readFileSync(packageJsonPath).toString());var version=packageJson.version;var program=new Command("git-pull-run").name("git-pull-run").version(version).addOption(installOption.conflicts("pattern").implies({once:true})).addOption(patternOption.conflicts("install")).addOption(commandOption.conflicts("install")).addOption(scriptOption).addOption(messageOption).addOption(debugOption.default(false)).addOption(onceOption.default(false)).action(/*#__PURE__*/function(){var _ref=_async_to_generator(function(options){var pm,_options_pattern,_options_command,_options_script,_options_message;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(!options.install)return[3,2];return[4,detect()];case 1:pm=_state.sent();if(!pm)program.error("Could not detect package manager");options.pattern=function(){switch(pm===null||pm===void 0?void 0:pm.name){case"npm":return"+(package.json|package-lock.json)";case"yarn":return"+(package.json|yarn.lock)";case"pnpm":return"+(package.json|pnpm-lock.yaml)";case"bun":return"+(package.json|bun.lock|bun.lockb)";case"deno":return"+(package.json|deno.json|deno.jsonc|deno.lock)";default:return program.error("Unsupported package manager: found ".concat(pm===null||pm===void 0?void 0:pm.name,", expecting npm, yarn, pnpm, bun or deno"))}}();options.command="".concat(pm===null||pm===void 0?void 0:pm.name," install");return[3,3];case 2:if(!options.pattern){program.error("error: required option '-p, --pattern <glob>' not specified")}else if(!options.install&&!options.pattern){program.error("error: required option '-p, --pattern <glob>' not specified")}_state.label=3;case 3:if(options.debug)debugLog.enable("git-pull-run*");debug("Started git-pull-run@".concat(version));gitPullRun({pattern:(_options_pattern=options.pattern)!==null&&_options_pattern!==void 0?_options_pattern:"",command:(_options_command=options.command)!==null&&_options_command!==void 0?_options_command:"",script:(_options_script=options.script)!==null&&_options_script!==void 0?_options_script:"",message:(_options_message=options.message)!==null&&_options_message!==void 0?_options_message:"",debug:options.debug,once:options.once}).then(function(){debug("Finished git-pull-run@".concat(version));process.exitCode=0}).catch(function(){process.exitCode=1});return[2]}})});return function(options){return _ref.apply(this,arguments)}}());await program.parseAsync(process.argv); |
@@ -1,10 +0,1 @@ | ||
import debugLog from 'debug'; | ||
import { parse, resolve } from 'path'; | ||
const debug = debugLog('git-pull-run:getAbsolutePath'); | ||
export function getAbsolutePath(baseDir, path) { | ||
const { dir: relativeDir, base: file } = parse(path); | ||
const absoluteDir = resolve(baseDir, relativeDir); | ||
debug(`Absolute path resolved: ${absoluteDir}`); | ||
return { directory: absoluteDir, file }; | ||
} | ||
//# sourceMappingURL=getAbsolutePath.js.map | ||
import{parse,resolve}from"node:path";import debugLog from"debug";var debug=debugLog("git-pull-run:getAbsolutePath");export function getAbsolutePath(baseDir,path){var _parse=parse(path),relativeDir=_parse.dir,file=_parse.base;var absoluteDir=resolve(baseDir,relativeDir);debug("Absolute path resolved: ".concat(absoluteDir));return{directory:absoluteDir,file:file}} |
@@ -1,15 +0,1 @@ | ||
import { runGit } from './runGit.js'; | ||
import debugLog from 'debug'; | ||
import micromatch from 'micromatch'; | ||
const debug = debugLog('git-pull-run:getChanges'); | ||
export async function getChanges(pattern) { | ||
debug('Get changed files'); | ||
const cmd = 'git diff --name-only HEAD@{1} HEAD'; | ||
const result = await runGit(cmd); | ||
const files = result.split('\n'); | ||
debug('Changed files:', files); | ||
const changes = micromatch(files, pattern); | ||
debug(`Changes that match pattern '${pattern}':`, changes); | ||
return changes; | ||
} | ||
//# sourceMappingURL=getChanges.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import debugLog from"debug";import micromatch from"micromatch";import{runGit}from"./runGit.js";var debug=debugLog("git-pull-run:getChanges");export function getChanges(pattern){return _getChanges.apply(this,arguments)}function _getChanges(){_getChanges=_async_to_generator(function(pattern){var cmd,result,files,changes;return _ts_generator(this,function(_state){switch(_state.label){case 0:debug("Get changed files");cmd="git diff --name-only HEAD@{1} HEAD";return[4,runGit(cmd)];case 1:result=_state.sent();files=result.split("\n");debug("Changed files:",files);changes=micromatch(files,pattern);debug("Changes that match pattern '".concat(pattern,"':"),changes);return[2,changes]}})});return _getChanges.apply(this,arguments)} |
@@ -1,11 +0,1 @@ | ||
import debugLog from 'debug'; | ||
import { runGit } from './runGit.js'; | ||
const debug = debugLog('git-pull-run:getGitDirectory'); | ||
export async function getGitDirectory() { | ||
debug('Get git directory'); | ||
const cmd = 'git rev-parse --show-toplevel'; | ||
const gitDir = await runGit(cmd); | ||
debug('Git directory:', gitDir); | ||
return gitDir; | ||
} | ||
//# sourceMappingURL=getGitDirectory.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import debugLog from"debug";import{runGit}from"./runGit.js";var debug=debugLog("git-pull-run:getGitDirectory");export function getGitDirectory(){return _getGitDirectory.apply(this,arguments)}function _getGitDirectory(){_getGitDirectory=_async_to_generator(function(){var cmd,gitDir;return _ts_generator(this,function(_state){switch(_state.label){case 0:debug("Get git directory");cmd="git rev-parse --show-toplevel";return[4,runGit(cmd)];case 1:gitDir=_state.sent();debug("Git directory:",gitDir);return[2,gitDir]}})});return _getGitDirectory.apply(this,arguments)} |
@@ -1,61 +0,1 @@ | ||
import { dim, green } from 'colorette'; | ||
import { Listr } from 'listr2'; | ||
import { getAbsolutePath } from './getAbsolutePath.js'; | ||
import { getChanges } from './getChanges.js'; | ||
import { getGitDirectory } from './getGitDirectory.js'; | ||
import { runCommand } from './runCommand.js'; | ||
import { runScript } from './runScript.js'; | ||
export async function gitPullRun({ pattern, message, command, script, once }) { | ||
const runner = new Listr([ | ||
{ | ||
title: 'Preparing git-pull-run...', | ||
task: async (ctx, task) => { | ||
task.output = 'Preparing git-pull-run...'; | ||
ctx.gitDir = await getGitDirectory(); | ||
task.output = `Collecting changes for ${green(pattern)}...`; | ||
ctx.changes = await getChanges(pattern); | ||
task.output = ctx.changes.length > 0 | ||
? `Found ${ctx.changes.length} ${ctx.changes.length === 1 ? 'change' : 'changes'} for ${green(pattern)}` | ||
: `No relevant changes for ${green(pattern)}`; | ||
}, | ||
options: { persistentOutput: true }, | ||
}, | ||
{ | ||
title: message, | ||
task: async (ctx, task) => { }, | ||
options: { persistentOutput: true }, | ||
enabled: (ctx) => !!message && message.length > 0 && ctx.changes && ctx.changes.length > 0, | ||
}, | ||
{ | ||
title: 'Running tasks...', | ||
task: (ctx, task) => { | ||
const createTasks = (directory) => ({ | ||
title: `${dim(directory)}`, | ||
task: async (ctx, task) => task.newListr([ | ||
{ | ||
title: `${green(command)}`, | ||
task: () => runCommand(command, directory), | ||
enabled: () => !!command, | ||
}, | ||
{ | ||
title: `npm run ${green(script)}`, | ||
task: () => runScript(script, directory), | ||
enabled: () => !!script, | ||
}, | ||
]) | ||
}); | ||
const subtasks = once | ||
? [createTasks(ctx.gitDir)] | ||
: ctx.changes.map(change => { | ||
const { directory } = getAbsolutePath(ctx.gitDir, change); | ||
return createTasks(directory); | ||
}); | ||
return task.newListr([...subtasks], { concurrent: true, rendererOptions: { collapse: false } }); | ||
}, | ||
enabled: (ctx) => (!!command || !!script) && ctx.changes && ctx.changes.length > 0, | ||
options: { persistentOutput: true }, | ||
}, | ||
], { concurrent: false }); | ||
await runner.run(); | ||
} | ||
//# sourceMappingURL=index.js.map | ||
function _array_like_to_array(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _array_without_holes(arr){if(Array.isArray(arr))return _array_like_to_array(arr)}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _iterable_to_array(iter){if(typeof Symbol!=="undefined"&&iter[Symbol.iterator]!=null||iter["@@iterator"]!=null)return Array.from(iter)}function _non_iterable_spread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _to_consumable_array(arr){return _array_without_holes(arr)||_iterable_to_array(arr)||_unsupported_iterable_to_array(arr)||_non_iterable_spread()}function _unsupported_iterable_to_array(o,minLen){if(!o)return;if(typeof o==="string")return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(n);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import{dim,green}from"colorette";import{Listr}from"listr2";import{getAbsolutePath}from"./getAbsolutePath.js";import{getChanges}from"./getChanges.js";import{getGitDirectory}from"./getGitDirectory.js";import{runCommand}from"./runCommand.js";import{runScript}from"./runScript.js";export function gitPullRun(_){return _gitPullRun.apply(this,arguments)}function _gitPullRun(){_gitPullRun=_async_to_generator(function(param){var pattern,message,command,script,once,runner;return _ts_generator(this,function(_state){switch(_state.label){case 0:pattern=param.pattern,message=param.message,command=param.command,script=param.script,once=param.once;runner=new Listr([{title:"Preparing git-pull-run...",task:/*#__PURE__*/function(){var _ref=_async_to_generator(function(ctx,task){return _ts_generator(this,function(_state){switch(_state.label){case 0:task.output="Preparing git-pull-run...";return[4,getGitDirectory()];case 1:ctx.gitDir=_state.sent();task.output="Collecting changes for ".concat(green(pattern),"...");return[4,getChanges(pattern)];case 2:ctx.changes=_state.sent();task.output=ctx.changes.length>0?"Found ".concat(ctx.changes.length," ").concat(ctx.changes.length===1?"change":"changes"," for ").concat(green(pattern)):"No relevant changes for ".concat(green(pattern));return[2]}})});return function(ctx,task){return _ref.apply(this,arguments)}}(),rendererOptions:{persistentOutput:true}},{title:message,task:/*#__PURE__*/function(){var _ref=_async_to_generator(function(ctx,task){return _ts_generator(this,function(_state){return[2]})});return function(ctx,task){return _ref.apply(this,arguments)}}(),rendererOptions:{persistentOutput:true},enabled:function(ctx){return!!message&&message.length>0&&ctx.changes&&ctx.changes.length>0}},{title:"Running tasks...",task:function(ctx,task){var createTasks=function(directory){return{title:"".concat(dim(directory)),task:/*#__PURE__*/function(){var _ref=_async_to_generator(function(ctx,task){return _ts_generator(this,function(_state){return[2,task.newListr([{title:"".concat(green(command)),task:function(){return runCommand(command,directory)},enabled:function(){return!!command}},{title:"npm run ".concat(green(script)),task:function(){return runScript(script,directory)},enabled:function(){return!!script}}])]})});return function(ctx,task){return _ref.apply(this,arguments)}}()}};var subtasks=once?[createTasks(ctx.gitDir)]:ctx.changes.map(function(change){var directory=getAbsolutePath(ctx.gitDir,change).directory;return createTasks(directory)});return task.newListr(_to_consumable_array(subtasks),{concurrent:true,rendererOptions:{collapseSubtasks:false,collapseSkips:false,collapseErrors:false}})},enabled:function(ctx){return(!!command||!!script)&&ctx.changes&&ctx.changes.length>0},rendererOptions:{persistentOutput:true}}],{concurrent:false});return[4,runner.run()];case 1:_state.sent();return[2]}})});return _gitPullRun.apply(this,arguments)} |
@@ -1,20 +0,1 @@ | ||
import { execaCommand } from 'execa'; | ||
import debugLog from 'debug'; | ||
const debug = debugLog('git-pull-run:runCommand'); | ||
export async function runCommand(cmd, cwd) { | ||
debug(`Running command '${cmd}' in directory '${cwd}'`); | ||
try { | ||
const cmdProcess = execaCommand(cmd, { cwd }); | ||
debug.enabled && cmdProcess.stdout?.pipe(process.stdout); | ||
const { stdout, exitCode } = await cmdProcess; | ||
debug(`Command executed with exit code: ${exitCode}`); | ||
return stdout; | ||
} | ||
catch (error) { | ||
const cmdError = error; | ||
const { exitCode, message } = cmdError; | ||
debug(`Command failed with exit code: ${exitCode}`); | ||
throw new Error(message); | ||
} | ||
} | ||
//# sourceMappingURL=runCommand.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import debugLog from"debug";import{execaCommand}from"execa";var debug=debugLog("git-pull-run:runCommand");export function runCommand(cmd,cwd){return _runCommand.apply(this,arguments)}function _runCommand(){_runCommand=_async_to_generator(function(cmd,cwd){var _cmdProcess_stdout,cmdProcess,_ref,stdout,exitCode,error,cmdError,exitCode1,message;return _ts_generator(this,function(_state){switch(_state.label){case 0:debug("Running command '".concat(cmd,"' in directory '").concat(cwd,"'"));_state.label=1;case 1:_state.trys.push([1,3,,4]);cmdProcess=execaCommand(cmd,{cwd:cwd});debug.enabled&&((_cmdProcess_stdout=cmdProcess.stdout)===null||_cmdProcess_stdout===void 0?void 0:_cmdProcess_stdout.pipe(process.stdout));return[4,cmdProcess];case 2:_ref=_state.sent(),stdout=_ref.stdout,exitCode=_ref.exitCode;debug("Command executed with exit code: ".concat(exitCode));return[2,stdout];case 3:error=_state.sent();cmdError=error;exitCode1=cmdError.exitCode,message=cmdError.message;debug("Command failed with exit code: ".concat(exitCode1));throw new Error(message);case 4:return[2]}})});return _runCommand.apply(this,arguments)} |
@@ -1,20 +0,1 @@ | ||
import { execaCommand } from 'execa'; | ||
import debugLog from 'debug'; | ||
const debug = debugLog('git-pull-run:runGit'); | ||
export async function runGit(cmd) { | ||
debug(`Running git '${cmd}'`); | ||
try { | ||
const cmdProcess = execaCommand(cmd); | ||
debug.enabled && cmdProcess.stdout?.pipe(process.stdout); | ||
const { stdout, exitCode } = await cmdProcess; | ||
debug(`Git command executed with exit code: ${exitCode}`); | ||
return stdout; | ||
} | ||
catch (error) { | ||
const cmdError = error; | ||
const { exitCode, message } = cmdError; | ||
debug(`Git failed with exit code: ${exitCode}`); | ||
throw new Error(message); | ||
} | ||
} | ||
//# sourceMappingURL=runGit.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import debugLog from"debug";import{execaCommand}from"execa";var debug=debugLog("git-pull-run:runGit");export function runGit(cmd){return _runGit.apply(this,arguments)}function _runGit(){_runGit=_async_to_generator(function(cmd){var _cmdProcess_stdout,cmdProcess,_ref,stdout,exitCode,error,cmdError,exitCode1,message;return _ts_generator(this,function(_state){switch(_state.label){case 0:debug("Running git '".concat(cmd,"'"));_state.label=1;case 1:_state.trys.push([1,3,,4]);cmdProcess=execaCommand(cmd);debug.enabled&&((_cmdProcess_stdout=cmdProcess.stdout)===null||_cmdProcess_stdout===void 0?void 0:_cmdProcess_stdout.pipe(process.stdout));return[4,cmdProcess];case 2:_ref=_state.sent(),stdout=_ref.stdout,exitCode=_ref.exitCode;debug("Git command executed with exit code: ".concat(exitCode));return[2,stdout];case 3:error=_state.sent();cmdError=error;exitCode1=cmdError.exitCode,message=cmdError.message;debug("Git failed with exit code: ".concat(exitCode1));throw new Error(message);case 4:return[2]}})});return _runGit.apply(this,arguments)} |
@@ -1,21 +0,1 @@ | ||
import { execa } from 'execa'; | ||
import debugLog from 'debug'; | ||
const debug = debugLog('git-pull-run:runScript'); | ||
export async function runScript(script, cwd) { | ||
debug(`Running script '${script}' in directory '${cwd}'`); | ||
try { | ||
const commands = ['run-script', script]; | ||
const cmdProcess = execa('npm', commands, { cwd }); | ||
debug.enabled && cmdProcess.stdout?.pipe(process.stdout); | ||
const { stdout, exitCode } = await cmdProcess; | ||
debug(`Script executed with exit code: ${exitCode}`); | ||
return stdout; | ||
} | ||
catch (error) { | ||
const cmdError = error; | ||
const { exitCode, message } = cmdError; | ||
debug(`Script failed with exit code: ${exitCode}`); | ||
throw new Error(message); | ||
} | ||
} | ||
//# sourceMappingURL=runScript.js.map | ||
function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _ts_generator(thisArg,body){var f,y,t,g,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]};return g={next:verb(0),"throw":verb(1),"return":verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}import debugLog from"debug";import{execa}from"execa";var debug=debugLog("git-pull-run:runScript");export function runScript(script,cwd){return _runScript.apply(this,arguments)}function _runScript(){_runScript=_async_to_generator(function(script,cwd){var _cmdProcess_stdout,commands,cmdProcess,_ref,stdout,exitCode,error,cmdError,exitCode1,message;return _ts_generator(this,function(_state){switch(_state.label){case 0:debug("Running script '".concat(script,"' in directory '").concat(cwd,"'"));_state.label=1;case 1:_state.trys.push([1,3,,4]);commands=["run-script",script];cmdProcess=execa("npm",commands,{cwd:cwd});debug.enabled&&((_cmdProcess_stdout=cmdProcess.stdout)===null||_cmdProcess_stdout===void 0?void 0:_cmdProcess_stdout.pipe(process.stdout));return[4,cmdProcess];case 2:_ref=_state.sent(),stdout=_ref.stdout,exitCode=_ref.exitCode;debug("Script executed with exit code: ".concat(exitCode));return[2,stdout];case 3:error=_state.sent();cmdError=error;exitCode1=cmdError.exitCode,message=cmdError.message;debug("Script failed with exit code: ".concat(exitCode1));throw new Error(message);case 4:return[2]}})});return _runScript.apply(this,arguments)} |
108
package.json
{ | ||
"name": "git-pull-run", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Run commands and scripts after git pull", | ||
"bin": "./dist/cli.js", | ||
"exports": "./dist/index.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"type": "module", | ||
"scripts": { | ||
"prepublishOnly": "npm run build", | ||
"build": "rimraf dist && tsc --project tsconfig.build.json", | ||
"build:watch": "tsc --watch", | ||
"release:minor": "npm version $(semver $npm_package_version -i minor) && npm publish --tag latest", | ||
"release:patch": "npm version $(semver $npm_package_version -i patch) && npm publish --tag latest", | ||
"release:next": "npm version $(semver $npm_package_version -i prerelease --preid next ) && npm publish --tag next", | ||
"start": "tsx ./src/cli", | ||
"test": "jest", | ||
"lint": "biome check . --write", | ||
"dummy": "echo \"dummy\"", | ||
"post-merge": "echo \"dummy\"" | ||
}, | ||
"license": "MIT", | ||
"repository": { | ||
@@ -28,2 +10,7 @@ "type": "git", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/zirkelc/git-pull-run/issues" | ||
}, | ||
"homepage": "https://github.com/zirkelc/git-pull-run#readme", | ||
"author": "Christian Zirkel", | ||
"keywords": [ | ||
@@ -34,2 +21,6 @@ "git", | ||
"npm", | ||
"bun", | ||
"pnpm", | ||
"yarn", | ||
"deno", | ||
"install", | ||
@@ -39,35 +30,52 @@ "hooks", | ||
], | ||
"author": "Christian Zirkel", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/zirkelc/git-pull-run/issues" | ||
"bin": "./dist/cli.js", | ||
"type": "module", | ||
"exports": "./dist/index.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"prebuild": "npm run clean", | ||
"build": "swc src -d dist --strip-leading-paths", | ||
"build:watch": "npm run build -- --watch", | ||
"clean": "rimraf dist", | ||
"format": "biome check --write", | ||
"lint": "biome check", | ||
"prepublishOnly": "npm run build", | ||
"release:minor": "npm version $(semver $npm_package_version -i minor) && npm publish --tag latest", | ||
"release:next": "npm version $(semver $npm_package_version -i prerelease --preid next ) && npm publish --tag next", | ||
"release:patch": "npm version $(semver $npm_package_version -i patch) && npm publish --tag latest", | ||
"prestart": "npm run build", | ||
"start": "tsx ./src/cli", | ||
"pretest": "npm run build", | ||
"test": "jest" | ||
}, | ||
"homepage": "https://github.com/zirkelc/git-pull-run#readme", | ||
"dependencies": { | ||
"colorette": "2.0.19", | ||
"commander": "13.1.0", | ||
"debug": "4.3.3", | ||
"execa": "9.5.2", | ||
"listr2": "8.2.5", | ||
"micromatch": "4.0.4", | ||
"package-manager-detector": "1.1.0", | ||
"tsx": "4.19.3" | ||
}, | ||
"devDependencies": { | ||
"@biomejs/biome": "^1.9.4", | ||
"@gmrchk/cli-testing-library": "^0.1.2", | ||
"@tsconfig/node16": "^1.0.2", | ||
"@tsconfig/node16-strictest-esm": "^1.0.3", | ||
"@types/debug": "^4.1.7", | ||
"@types/jest": "^29.2.0", | ||
"@types/micromatch": "^4.0.2", | ||
"@types/node": "^16.11.12", | ||
"git-pull-run": "^1.4.0", | ||
"jest": "^29.2.2", | ||
"rimraf": "^3.0.2", | ||
"semver": "^7.3.8", | ||
"ts-jest": "^29.0.3", | ||
"ts-node": "^10.9.1", | ||
"tsup": "^8.3.0", | ||
"typescript": "^4.5.3" | ||
}, | ||
"dependencies": { | ||
"colorette": "^2.0.19", | ||
"commander": "^8.3.0", | ||
"debug": "^4.3.3", | ||
"execa": "^6.1.0", | ||
"listr2": "^5.0.5", | ||
"micromatch": "^4.0.4", | ||
"tsx": "^4.19.2" | ||
"@biomejs/biome": "1.9.4", | ||
"@commander-js/extra-typings": "13.1.0", | ||
"@gmrchk/cli-testing-library": "0.1.2", | ||
"@swc/cli": "0.6.0", | ||
"@swc/core": "1.11.13", | ||
"@swc/jest": "0.2.37", | ||
"@total-typescript/tsconfig": "1.0.4", | ||
"@types/debug": "4.1.7", | ||
"@types/jest": "29.2.0", | ||
"@types/micromatch": "4.0.2", | ||
"@types/node": "22.13.14", | ||
"git-pull-run": "1.4.0", | ||
"jest": "29.7.0", | ||
"rimraf": "6.0.1", | ||
"semver": "7.3.8", | ||
"typescript": "5.8.2" | ||
} | ||
} |
@@ -17,2 +17,3 @@ [](https://www.npmjs.com/package/git-pull-run) | ||
This package should be executed as a [`post-merge`](https://git-scm.com/docs/githooks#_post_merge) git hook. | ||
## Command Line Options | ||
@@ -25,5 +26,6 @@ ```sh | ||
-V --version output the version number | ||
-p, --pattern <glob> pattern to match files (required) | ||
-p, --pattern <glob> pattern to match files | ||
-c, --command <command> execute shell command for each matched file | ||
-s, --script <script> execute npm script for each matched file | ||
-i, --install detect the right package manager and run install command | ||
-m, --message <message> print message to the console if matches were found | ||
@@ -34,3 +36,3 @@ -d, --debug print additional debug information (default: false) | ||
``` | ||
- **`--pattern <pattern>`**: Required glob pattern to detect if certain files have changed on the remote repository when pulling changes. Each changed file (including path from root) is matched against this pattern. | ||
- **`--pattern <pattern>`**: Glob pattern to detect if certain files have changed on the remote repository when pulling changes. Each changed file (including path from root) is matched against this pattern. | ||
- uses [micromatch](https://www.npmjs.com/package/micromatch) internally and supports all matching features like wildcards, negation, extglobs and more. | ||
@@ -40,2 +42,3 @@ - **`--command <command>`**: Command to execute on the shell for each changed file that matches the `pattern`. The command is going to be executed inside the directory of the changed file. | ||
- **`--script <script>`**: NPM script to execute on the shell for each changed file that matches the `pattern`. Same as option **`--command "npm run <script>"`**. The script is going to be executed inside the directory of the changed file. | ||
- **`--install`**: Install dependencies with the right package manager (npm, pnpm, yarn, bun, deno). It implicitly sets the `pattern` and `command` options to the appropriate values for the package manager. | ||
- **`--message <message>`**: Message to print on the shell if any changed files matches the `pattern`. The message is printed only once and not for each changed file. | ||
@@ -45,9 +48,12 @@ - **`--once`**: Run the command or script only once in the git root directory if any files match the pattern, instead of running it for each matched file. | ||
> [!TIP] | ||
> The `--install` option is a shortcut to automatically detect the right package manager and run the install command. It cannot be used with the `--pattern` and `--command` options, because they are overwritten with the appropriate values for the package manager. | ||
## Usage | ||
Install [Husky](https://typicode.github.io/husky/how-to.html) or any other git hook manager to create a `post-merge` git hook. | ||
### Run `npm install` when `package-lock.json` changes | ||
`post-merge` git hook with [Husky](https://github.com/typicode/husky): | ||
```sh | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
# .husky/post-merge | ||
@@ -60,6 +66,4 @@ # matches only the package-lock.json inside project directory | ||
### Run `npm install` in a multi-package monorepo | ||
`post-merge` git hook with [Husky](https://github.com/typicode/husky): | ||
```sh | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
# .husky/post-merge | ||
@@ -72,6 +76,4 @@ # assumes monorepo structure with multiple packages in directory /packages | ||
### Show custom message | ||
`post-merge` git hook with [Husky](https://github.com/typicode/husky): | ||
```sh | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
# .husky/post-merge | ||
@@ -78,0 +80,0 @@ # matches only the package-lock.json inside project directory |
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
34412
36.59%95
2.15%8
14.29%11
-42.11%1
-99.45%1
Infinity%2
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated
Updated
Updated