git-watchtower 1.10.11 → 1.10.13
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/package.json +1 -1
- package/src/config/loader.js +1 -210
- package/src/git/commands.js +5 -14
- package/src/index.js +0 -3
- package/src/utils/gitignore.js +4 -11
package/package.json
CHANGED
package/src/config/loader.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const { ConfigError } = require('../utils/errors');
|
|
8
|
-
const {
|
|
8
|
+
const { validateConfig, migrateConfig } = require('./schema');
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Default configuration file name
|
|
@@ -117,212 +117,6 @@ function deleteConfig(projectRoot) {
|
|
|
117
117
|
return true;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/**
|
|
121
|
-
* Apply CLI arguments to configuration
|
|
122
|
-
* CLI args take precedence over config file values
|
|
123
|
-
* @param {Object} config - Base configuration
|
|
124
|
-
* @param {Object} cliArgs - CLI arguments
|
|
125
|
-
* @returns {Object} - Merged configuration
|
|
126
|
-
*/
|
|
127
|
-
function applyCliArgs(config, cliArgs) {
|
|
128
|
-
const result = JSON.parse(JSON.stringify(config)); // Deep clone
|
|
129
|
-
|
|
130
|
-
// Server settings
|
|
131
|
-
if (cliArgs.mode !== undefined && cliArgs.mode !== null) {
|
|
132
|
-
result.server.mode = cliArgs.mode;
|
|
133
|
-
}
|
|
134
|
-
if (cliArgs.noServer) {
|
|
135
|
-
result.server.mode = 'none';
|
|
136
|
-
}
|
|
137
|
-
if (cliArgs.port !== undefined && cliArgs.port !== null) {
|
|
138
|
-
result.server.port = cliArgs.port;
|
|
139
|
-
}
|
|
140
|
-
if (cliArgs.staticDir !== undefined && cliArgs.staticDir !== null) {
|
|
141
|
-
result.server.staticDir = cliArgs.staticDir;
|
|
142
|
-
}
|
|
143
|
-
if (cliArgs.command !== undefined && cliArgs.command !== null) {
|
|
144
|
-
result.server.command = cliArgs.command;
|
|
145
|
-
}
|
|
146
|
-
if (cliArgs.restartOnSwitch !== undefined && cliArgs.restartOnSwitch !== null) {
|
|
147
|
-
result.server.restartOnSwitch = cliArgs.restartOnSwitch;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Web dashboard
|
|
151
|
-
if (cliArgs.web) {
|
|
152
|
-
result.web = { ...result.web, enabled: true };
|
|
153
|
-
}
|
|
154
|
-
if (cliArgs.webPort !== undefined && cliArgs.webPort !== null) {
|
|
155
|
-
result.web = { ...result.web, port: cliArgs.webPort };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Git settings
|
|
159
|
-
if (cliArgs.remote !== undefined && cliArgs.remote !== null) {
|
|
160
|
-
result.remoteName = cliArgs.remote;
|
|
161
|
-
}
|
|
162
|
-
if (cliArgs.autoPull !== undefined && cliArgs.autoPull !== null) {
|
|
163
|
-
result.autoPull = cliArgs.autoPull;
|
|
164
|
-
}
|
|
165
|
-
if (cliArgs.pollInterval !== undefined && cliArgs.pollInterval !== null) {
|
|
166
|
-
result.gitPollInterval = cliArgs.pollInterval;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// UI settings
|
|
170
|
-
if (cliArgs.sound !== undefined && cliArgs.sound !== null) {
|
|
171
|
-
result.soundEnabled = cliArgs.sound;
|
|
172
|
-
}
|
|
173
|
-
if (cliArgs.visibleBranches !== undefined && cliArgs.visibleBranches !== null) {
|
|
174
|
-
result.visibleBranches = cliArgs.visibleBranches;
|
|
175
|
-
}
|
|
176
|
-
if (cliArgs.casino !== undefined && cliArgs.casino !== null) {
|
|
177
|
-
result.casinoMode = cliArgs.casino;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Parse CLI arguments
|
|
185
|
-
* @param {string[]} [argv] - Command line arguments (defaults to process.argv.slice(2))
|
|
186
|
-
* @returns {Object} - Parsed arguments
|
|
187
|
-
*/
|
|
188
|
-
function parseCliArgs(argv = process.argv.slice(2)) {
|
|
189
|
-
const result = {
|
|
190
|
-
// Server settings
|
|
191
|
-
mode: null,
|
|
192
|
-
noServer: false,
|
|
193
|
-
port: null,
|
|
194
|
-
staticDir: null,
|
|
195
|
-
command: null,
|
|
196
|
-
restartOnSwitch: null,
|
|
197
|
-
// Git settings
|
|
198
|
-
remote: null,
|
|
199
|
-
autoPull: null,
|
|
200
|
-
pollInterval: null,
|
|
201
|
-
// UI settings
|
|
202
|
-
sound: null,
|
|
203
|
-
visibleBranches: null,
|
|
204
|
-
casino: null,
|
|
205
|
-
// Special flags
|
|
206
|
-
init: false,
|
|
207
|
-
help: false,
|
|
208
|
-
version: false,
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
for (let i = 0; i < argv.length; i++) {
|
|
212
|
-
const arg = argv[i];
|
|
213
|
-
|
|
214
|
-
switch (arg) {
|
|
215
|
-
// Server settings
|
|
216
|
-
case '--mode':
|
|
217
|
-
result.mode = argv[++i];
|
|
218
|
-
break;
|
|
219
|
-
case '--no-server':
|
|
220
|
-
result.noServer = true;
|
|
221
|
-
break;
|
|
222
|
-
case '--port':
|
|
223
|
-
case '-p':
|
|
224
|
-
result.port = parseInt(argv[++i], 10);
|
|
225
|
-
break;
|
|
226
|
-
case '--static-dir':
|
|
227
|
-
result.staticDir = argv[++i];
|
|
228
|
-
break;
|
|
229
|
-
case '--command':
|
|
230
|
-
case '-c':
|
|
231
|
-
result.command = argv[++i];
|
|
232
|
-
break;
|
|
233
|
-
case '--restart-on-switch':
|
|
234
|
-
result.restartOnSwitch = true;
|
|
235
|
-
break;
|
|
236
|
-
case '--no-restart-on-switch':
|
|
237
|
-
result.restartOnSwitch = false;
|
|
238
|
-
break;
|
|
239
|
-
|
|
240
|
-
// Git settings
|
|
241
|
-
case '--remote':
|
|
242
|
-
case '-r':
|
|
243
|
-
result.remote = argv[++i];
|
|
244
|
-
break;
|
|
245
|
-
case '--auto-pull':
|
|
246
|
-
result.autoPull = true;
|
|
247
|
-
break;
|
|
248
|
-
case '--no-auto-pull':
|
|
249
|
-
result.autoPull = false;
|
|
250
|
-
break;
|
|
251
|
-
case '--poll-interval':
|
|
252
|
-
result.pollInterval = parseInt(argv[++i], 10) * 1000; // Convert seconds to ms
|
|
253
|
-
break;
|
|
254
|
-
|
|
255
|
-
// UI settings
|
|
256
|
-
case '--sound':
|
|
257
|
-
result.sound = true;
|
|
258
|
-
break;
|
|
259
|
-
case '--no-sound':
|
|
260
|
-
result.sound = false;
|
|
261
|
-
break;
|
|
262
|
-
case '--visible-branches':
|
|
263
|
-
result.visibleBranches = parseInt(argv[++i], 10);
|
|
264
|
-
break;
|
|
265
|
-
case '--casino':
|
|
266
|
-
result.casino = true;
|
|
267
|
-
break;
|
|
268
|
-
case '--no-casino':
|
|
269
|
-
result.casino = false;
|
|
270
|
-
break;
|
|
271
|
-
|
|
272
|
-
// Special flags
|
|
273
|
-
case '--init':
|
|
274
|
-
result.init = true;
|
|
275
|
-
break;
|
|
276
|
-
case '--help':
|
|
277
|
-
case '-h':
|
|
278
|
-
result.help = true;
|
|
279
|
-
break;
|
|
280
|
-
case '--version':
|
|
281
|
-
case '-v':
|
|
282
|
-
result.version = true;
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return result;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Ensure configuration exists
|
|
292
|
-
* Loads from file, runs wizard if needed, and applies CLI args
|
|
293
|
-
* @param {Object} cliArgs - CLI arguments
|
|
294
|
-
* @param {Object} [options] - Options
|
|
295
|
-
* @param {string} [options.projectRoot] - Project root directory
|
|
296
|
-
* @param {boolean} [options.interactive=true] - Allow interactive prompts
|
|
297
|
-
* @param {Function} [options.runWizard] - Wizard function to run if needed
|
|
298
|
-
* @returns {Promise<Object>} - Final configuration
|
|
299
|
-
*/
|
|
300
|
-
async function ensureConfig(cliArgs, options = {}) {
|
|
301
|
-
const { projectRoot, interactive = true, runWizard } = options;
|
|
302
|
-
|
|
303
|
-
// Check if --init flag was passed (force reconfiguration)
|
|
304
|
-
if (cliArgs.init && runWizard) {
|
|
305
|
-
const config = await runWizard();
|
|
306
|
-
return applyCliArgs(config, cliArgs);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Load existing config
|
|
310
|
-
let config = loadConfig(projectRoot);
|
|
311
|
-
|
|
312
|
-
// If no config exists
|
|
313
|
-
if (!config) {
|
|
314
|
-
if (runWizard && interactive && process.stdin.isTTY) {
|
|
315
|
-
config = await runWizard();
|
|
316
|
-
} else {
|
|
317
|
-
// Use defaults
|
|
318
|
-
config = getDefaultConfig();
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Apply CLI args over config
|
|
323
|
-
return applyCliArgs(config, cliArgs);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
120
|
module.exports = {
|
|
327
121
|
CONFIG_FILE_NAME,
|
|
328
122
|
getConfigPath,
|
|
@@ -331,7 +125,4 @@ module.exports = {
|
|
|
331
125
|
loadConfig,
|
|
332
126
|
saveConfig,
|
|
333
127
|
deleteConfig,
|
|
334
|
-
applyCliArgs,
|
|
335
|
-
parseCliArgs,
|
|
336
|
-
ensureConfig,
|
|
337
128
|
};
|
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/index.js
CHANGED
|
@@ -151,9 +151,6 @@ module.exports = {
|
|
|
151
151
|
loadConfig: configLoader.loadConfig,
|
|
152
152
|
saveConfig: configLoader.saveConfig,
|
|
153
153
|
deleteConfig: configLoader.deleteConfig,
|
|
154
|
-
applyCliArgs: configLoader.applyCliArgs,
|
|
155
|
-
parseCliArgs: configLoader.parseCliArgs,
|
|
156
|
-
ensureConfig: configLoader.ensureConfig,
|
|
157
154
|
|
|
158
155
|
// Server process management
|
|
159
156
|
ProcessManager: serverProcess.ProcessManager,
|
package/src/utils/gitignore.js
CHANGED
|
@@ -125,19 +125,12 @@ function loadGitignorePatterns(searchPaths) {
|
|
|
125
125
|
* @returns {boolean} - True if the file is in the .git directory
|
|
126
126
|
*/
|
|
127
127
|
function isGitDirectory(filename) {
|
|
128
|
-
if (filename === '.git' || filename.startsWith('.git/') || filename.startsWith('.git\\')) {
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
128
|
// Normalize path separators for cross-platform support
|
|
133
|
-
const
|
|
129
|
+
const p = filename.replace(/\\/g, '/');
|
|
134
130
|
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return false;
|
|
131
|
+
// Match exactly ".git" as a path segment, not ".github", ".gitignore", etc.
|
|
132
|
+
// Valid matches: ".git", ".git/hooks/pre-commit", "src/.git/config"
|
|
133
|
+
return /^\.git(\/|$)/.test(p) || /\/\.git(\/|$)/.test(p);
|
|
141
134
|
}
|
|
142
135
|
|
|
143
136
|
/**
|