git-watchtower 1.13.1 → 1.14.1
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 +36 -5
- package/package.json +1 -1
- package/src/git/commands.js +20 -6
package/bin/git-watchtower.js
CHANGED
|
@@ -1583,8 +1583,33 @@ async function pullCurrentBranch() {
|
|
|
1583
1583
|
addLog(`Pulling from ${REMOTE_NAME}/${branch}...`, 'update');
|
|
1584
1584
|
render();
|
|
1585
1585
|
|
|
1586
|
-
|
|
1587
|
-
|
|
1586
|
+
// Capture HEAD before pull so we can diff against it when git pull
|
|
1587
|
+
// doesn't put a clean "already up to date" message on stdout.
|
|
1588
|
+
const preHead = await execGitSilent(['rev-parse', 'HEAD'], { cwd: PROJECT_ROOT });
|
|
1589
|
+
const oldCommit = preHead && preHead.stdout ? preHead.stdout.trim() : null;
|
|
1590
|
+
|
|
1591
|
+
const result = await execGit(['pull', REMOTE_NAME, branch], { cwd: PROJECT_ROOT, timeout: 60000 });
|
|
1592
|
+
const pullOutput = `${result.stdout || ''}\n${result.stderr || ''}`;
|
|
1593
|
+
|
|
1594
|
+
if (/already up[- ]to[- ]date/i.test(pullOutput)) {
|
|
1595
|
+
addLog(`Already up to date with ${REMOTE_NAME}/${branch}`, 'success');
|
|
1596
|
+
} else {
|
|
1597
|
+
// Prefer the summary line from git's own output (it's locale-sensitive
|
|
1598
|
+
// but matches how git reports its work). Fall back to a diff against
|
|
1599
|
+
// the old HEAD when git's summary line is missing (e.g. merge commit
|
|
1600
|
+
// without --stat).
|
|
1601
|
+
let summary = '';
|
|
1602
|
+
const diffStats = parseDiffStats(pullOutput);
|
|
1603
|
+
if (diffStats.added || diffStats.deleted) {
|
|
1604
|
+
summary = ` (+${diffStats.added}/-${diffStats.deleted})`;
|
|
1605
|
+
} else if (oldCommit) {
|
|
1606
|
+
const fallback = await getDiffStats(oldCommit, 'HEAD');
|
|
1607
|
+
if (fallback.added || fallback.deleted) {
|
|
1608
|
+
summary = ` (+${fallback.added}/-${fallback.deleted})`;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
addLog(`Pulled ${REMOTE_NAME}/${branch}${summary}`, 'success');
|
|
1612
|
+
}
|
|
1588
1613
|
pendingDirtyOperation = null;
|
|
1589
1614
|
notifyClients();
|
|
1590
1615
|
return { success: true };
|
|
@@ -1952,7 +1977,6 @@ async function pollGitChanges() {
|
|
|
1952
1977
|
|
|
1953
1978
|
try {
|
|
1954
1979
|
await execGit(['pull', REMOTE_NAME, autoPullBranchName], { cwd: PROJECT_ROOT, timeout: 60000 });
|
|
1955
|
-
addLog(`Pulled successfully from ${autoPullBranchName}`, 'success');
|
|
1956
1980
|
currentInfo.hasUpdates = false;
|
|
1957
1981
|
// Update the stored commit to the new one
|
|
1958
1982
|
const newCommit = await execGit(['rev-parse', '--short', 'HEAD'], { cwd: PROJECT_ROOT });
|
|
@@ -1962,9 +1986,10 @@ async function pollGitChanges() {
|
|
|
1962
1986
|
// Reload browsers
|
|
1963
1987
|
notifyClients();
|
|
1964
1988
|
|
|
1965
|
-
// Calculate actual diff for stats tracking
|
|
1989
|
+
// Calculate actual diff for stats tracking + status message
|
|
1990
|
+
let diffStats = { added: 0, deleted: 0 };
|
|
1966
1991
|
if (oldCommit) {
|
|
1967
|
-
|
|
1992
|
+
diffStats = await getDiffStats(oldCommit, 'HEAD');
|
|
1968
1993
|
const totalLines = diffStats.added + diffStats.deleted;
|
|
1969
1994
|
// Always track session churn
|
|
1970
1995
|
sessionStats.recordChurn(diffStats.added, diffStats.deleted);
|
|
@@ -1978,6 +2003,12 @@ async function pollGitChanges() {
|
|
|
1978
2003
|
}
|
|
1979
2004
|
}
|
|
1980
2005
|
}
|
|
2006
|
+
|
|
2007
|
+
// Indicate what was updated so the log isn't just a generic "success"
|
|
2008
|
+
const summary = (diffStats.added || diffStats.deleted)
|
|
2009
|
+
? ` (+${diffStats.added}/-${diffStats.deleted})`
|
|
2010
|
+
: '';
|
|
2011
|
+
addLog(`Auto-pulled ${autoPullBranchName}${summary}`, 'success');
|
|
1981
2012
|
} catch (e) {
|
|
1982
2013
|
const errMsg = e.stderr || e.stdout || e.message || String(e);
|
|
1983
2014
|
if (isMergeConflict(errMsg)) {
|
package/package.json
CHANGED
package/src/git/commands.js
CHANGED
|
@@ -198,7 +198,13 @@ async function log(branchName, options = {}) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
* Get commit count by day for sparkline
|
|
201
|
+
* Get commit count by day for sparkline.
|
|
202
|
+
*
|
|
203
|
+
* Buckets commits by local calendar date rather than by dividing a ms
|
|
204
|
+
* difference by 86 400 000, which breaks on DST transitions (a
|
|
205
|
+
* spring-forward day is only 23 h, causing Math.floor(23/24) = 0 and
|
|
206
|
+
* merging yesterday's commits into today's bucket).
|
|
207
|
+
*
|
|
202
208
|
* @param {string} branchName - Branch name
|
|
203
209
|
* @param {number} [days=7] - Number of days
|
|
204
210
|
* @param {string} [cwd] - Working directory
|
|
@@ -215,15 +221,23 @@ async function getCommitsByDay(branchName, days = 7, cwd) {
|
|
|
215
221
|
|
|
216
222
|
if (!stdout) return counts;
|
|
217
223
|
|
|
224
|
+
// Build a map from "YYYY-MM-DD" → bucket index. Using setDate()
|
|
225
|
+
// to step backwards is DST-safe because it adjusts the calendar
|
|
226
|
+
// day without relying on a fixed ms offset.
|
|
218
227
|
const today = new Date();
|
|
219
|
-
|
|
228
|
+
const dayBuckets = new Map();
|
|
229
|
+
for (let i = 0; i < days; i++) {
|
|
230
|
+
const d = new Date(today.getFullYear(), today.getMonth(), today.getDate() - i);
|
|
231
|
+
const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
232
|
+
dayBuckets.set(key, days - 1 - i);
|
|
233
|
+
}
|
|
220
234
|
|
|
221
235
|
for (const line of stdout.split('\n').filter(Boolean)) {
|
|
222
236
|
const commitDate = new Date(line);
|
|
223
|
-
commitDate.
|
|
224
|
-
const
|
|
225
|
-
if (
|
|
226
|
-
counts[
|
|
237
|
+
const key = `${commitDate.getFullYear()}-${String(commitDate.getMonth() + 1).padStart(2, '0')}-${String(commitDate.getDate()).padStart(2, '0')}`;
|
|
238
|
+
const idx = dayBuckets.get(key);
|
|
239
|
+
if (idx !== undefined) {
|
|
240
|
+
counts[idx]++;
|
|
227
241
|
}
|
|
228
242
|
}
|
|
229
243
|
} catch (error) {
|