🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more →

git-pull-run

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

git-pull-run - npm Package Compare versions

Comparing version

to
1.6.0

#!/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)}
{
"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 @@ [![npm](https://img.shields.io/npm/v/git-pull-run?label=git-pull-run)](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