git-watchtower 1.10.12 → 1.10.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/git-watchtower.js +12 -3
- package/package.json +1 -1
- package/src/git/commands.js +5 -14
- package/src/server/process.js +9 -4
package/bin/git-watchtower.js
CHANGED
|
@@ -656,6 +656,9 @@ function startServerProcess() {
|
|
|
656
656
|
env: { ...process.env, FORCE_COLOR: '1' },
|
|
657
657
|
shell: isWindows,
|
|
658
658
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
659
|
+
// On Unix, create a new process group so we can kill the entire tree
|
|
660
|
+
// (e.g. npm -> node -> next). On Windows, taskkill /t handles this.
|
|
661
|
+
detached: !isWindows,
|
|
659
662
|
};
|
|
660
663
|
|
|
661
664
|
try {
|
|
@@ -713,13 +716,19 @@ function stopServerProcess() {
|
|
|
713
716
|
if (process.platform === 'win32') {
|
|
714
717
|
spawn('taskkill', ['/pid', proc.pid.toString(), '/f', '/t']);
|
|
715
718
|
} else {
|
|
716
|
-
|
|
719
|
+
// Kill the entire process group (negative PID) so that
|
|
720
|
+
// grandchildren (e.g. npm -> node -> vite) are also terminated.
|
|
721
|
+
try {
|
|
722
|
+
process.kill(-proc.pid, 'SIGTERM');
|
|
723
|
+
} catch (e) {
|
|
724
|
+
// Process group may already be dead
|
|
725
|
+
}
|
|
717
726
|
// Force kill after grace period if process hasn't exited
|
|
718
727
|
const forceKillTimeout = setTimeout(() => {
|
|
719
728
|
try {
|
|
720
|
-
|
|
729
|
+
process.kill(-proc.pid, 'SIGKILL');
|
|
721
730
|
} catch (e) {
|
|
722
|
-
// Process may already be dead
|
|
731
|
+
// Process group may already be dead
|
|
723
732
|
}
|
|
724
733
|
}, 3000);
|
|
725
734
|
|
package/package.json
CHANGED
package/src/git/commands.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
const { execFile } = require('child_process');
|
|
7
7
|
const { GitError } = require('../utils/errors');
|
|
8
|
-
const { withTimeout } = require('../utils/async');
|
|
9
8
|
|
|
10
9
|
// Default timeout for git operations (30 seconds)
|
|
11
10
|
const DEFAULT_TIMEOUT = 30000;
|
|
@@ -44,10 +43,12 @@ async function execGit(args, options = {}) {
|
|
|
44
43
|
const command = `git ${args.join(' ')}`;
|
|
45
44
|
|
|
46
45
|
try {
|
|
47
|
-
const
|
|
46
|
+
const result = await new Promise((resolve, reject) => {
|
|
48
47
|
execFile('git', args, {
|
|
49
48
|
cwd,
|
|
50
49
|
maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large outputs
|
|
50
|
+
timeout, // kill child process after timeout ms
|
|
51
|
+
killSignal: 'SIGTERM',
|
|
51
52
|
}, (error, stdout, stderr) => {
|
|
52
53
|
if (error) {
|
|
53
54
|
error.stderr = stderr;
|
|
@@ -58,23 +59,13 @@ async function execGit(args, options = {}) {
|
|
|
58
59
|
});
|
|
59
60
|
});
|
|
60
61
|
|
|
61
|
-
const result = await withTimeout(
|
|
62
|
-
promise,
|
|
63
|
-
timeout,
|
|
64
|
-
`Git command timed out after ${timeout}ms: ${command}`
|
|
65
|
-
);
|
|
66
|
-
|
|
67
62
|
return {
|
|
68
63
|
stdout: result.stdout.trim(),
|
|
69
64
|
stderr: result.stderr.trim(),
|
|
70
65
|
};
|
|
71
66
|
} catch (error) {
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
throw new GitError(error.message, 'GIT_TIMEOUT', { command });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Handle exec error
|
|
67
|
+
// execFile sets error.killed = true when the process is killed due to
|
|
68
|
+
// timeout. GitError.fromExecError already maps killed → GIT_TIMEOUT.
|
|
78
69
|
throw GitError.fromExecError(error, command, error.stderr);
|
|
79
70
|
}
|
|
80
71
|
}
|
package/src/server/process.js
CHANGED
|
@@ -174,6 +174,9 @@ class ProcessManager {
|
|
|
174
174
|
env: { ...process.env, FORCE_COLOR: '1' },
|
|
175
175
|
shell: isWindows,
|
|
176
176
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
177
|
+
// On Unix, create a new process group so we can kill the entire tree
|
|
178
|
+
// (e.g. npm -> node -> next). On Windows, taskkill /t handles this.
|
|
179
|
+
detached: !isWindows,
|
|
177
180
|
};
|
|
178
181
|
|
|
179
182
|
try {
|
|
@@ -247,14 +250,16 @@ class ProcessManager {
|
|
|
247
250
|
}
|
|
248
251
|
} else {
|
|
249
252
|
try {
|
|
250
|
-
|
|
253
|
+
// Kill the entire process group (negative PID) so that
|
|
254
|
+
// grandchildren (e.g. npm -> node -> vite) are also terminated.
|
|
255
|
+
process.kill(-proc.pid, 'SIGTERM');
|
|
251
256
|
|
|
252
257
|
// Force kill after grace period
|
|
253
258
|
const forceKillTimeout = setTimeout(() => {
|
|
254
259
|
try {
|
|
255
|
-
|
|
260
|
+
process.kill(-proc.pid, 'SIGKILL');
|
|
256
261
|
} catch (e) {
|
|
257
|
-
// Process may already be dead
|
|
262
|
+
// Process group may already be dead
|
|
258
263
|
}
|
|
259
264
|
}, KILL_GRACE_PERIOD);
|
|
260
265
|
|
|
@@ -263,7 +268,7 @@ class ProcessManager {
|
|
|
263
268
|
clearTimeout(forceKillTimeout);
|
|
264
269
|
});
|
|
265
270
|
} catch (e) {
|
|
266
|
-
// Process may already be dead
|
|
271
|
+
// Process group may already be dead
|
|
267
272
|
}
|
|
268
273
|
}
|
|
269
274
|
|