Reputation: 21485
If operation like git pull
are run at the same time as a background build in watch mode (in my case, webpack), it can often fail because of the compilation locking files that git
wants to overwrite.
I would like to add script to pause the watcher while any git
operation is currently modifying the working directory. This should be possible because git
itself checks if there is not another git
doing something at the same time.
Note that I am not interested if a merge is in progress etc., I am interested if git
is currently actively writing files.
Upvotes: 3
Views: 1685
Reputation: 21485
By using .git/index.lock
as suggested by other answer, I ended up modifying my build script to both wait for this file to be removed and to create it on its own during the build so that git cannot be started during build as well.
Posting in case the JavaScript code proves useful to someone else as well.
const gitIndexLock = path.join(__dirname, "..", ".git", "index.lock");
let hasWrittenOwnGitIndexLock = false;
function lockParallelGitOperations(callback) {
if (!fs.existsSync(gitIndexLock) || hasWrittenOwnGitIndexLock) {
writeLockFile();
callback();
return;
}
console.log("Git operation in progress... Waiting...");
const sleepStarted = Date.now();
sleep();
function sleep() {
setTimeout(() => {
if (fs.existsSync(gitIndexLock)) {
if (Date.now() - sleepStarted > 30000) {
console.log("Git has been locked for over 30 seconds. Removing foreign lock...");
fs.unlinkSync(gitIndexLock);
} else {
sleep();
return;
}
}
writeLockFile();
callback();
}, 200);
}
function writeLockFile() {
if (!hasWrittenOwnGitIndexLock) {
console.log("Creating .git/index.lock.");
fs.writeFileSync(gitIndexLock, "");
hasWrittenOwnGitIndexLock = true;
}
}
}
Upvotes: 0
Reputation: 25895
I think it may be enough to check if
yourepo/.git/index.lock
exists, when it doesn't create it, run a bit, delete it, sleep a bit, and then repeat. I think this is expensive if the background program really constantly runs. It may also block you at times from working until sleeping.
A feasible option would be to wrap the git
commands themselves. Purely in bash a function would do:
function mygit {
pid=$(ps -eo pid,comm a | grep webpack)
pid=${pid%% *}
kill -TSTP $pid
git $*
kill -CONT $pid
}
Running mygit
will suspend your process, run git, then let it continue. You can also change the way the git
command itself behaves, if that's your preference, through the git hook mechanism, which you can fine tune to only affect stuff that only change the index, such as things to run pre (suspend) and post (resume) commit. A tutorial to initialize this can fe found in https://coderwall.com/p/jp7d5q/create-a-global-git-commit-hook - basically it's just scripts with specific names in a specified directory.
EDIT
After reviewing the comments below I want to add that the git-hook
solution is completely feasible on Windows, since git
comes with it's own bash on Windows. A tutorial on how to do this is https://tygertec.com/git-hooks-practical-uses-windows/ here, but make sure the scripts are all bash and anything above will work. The only caveat is finding and suspending the PID.
taskkill //PID <num>
will kill it, I'm not sure how to suspend though. Maybe on windows 10 with bash it the above will work.
Upvotes: 1