git-watchtower 2.3.11 → 2.3.12

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.
@@ -63,6 +63,7 @@ const readline = require('readline');
63
63
  // Casino mode - Vegas-style feedback effects
64
64
  const casino = require('../src/casino');
65
65
  const casinoSounds = require('../src/casino/sounds');
66
+ const { sumPollChurn } = require('../src/casino/poll-churn');
66
67
 
67
68
  // Gitignore utilities for file watcher
68
69
  const { loadGitignorePatterns, shouldIgnoreFile } = require('../src/utils/gitignore');
@@ -1995,8 +1996,13 @@ async function pollGitChanges() {
1995
1996
  // Keep deleted branches in the list (don't remove them)
1996
1997
  const pollFilteredBranches = allBranches;
1997
1998
 
1998
- // Detect updates on other branches (for flash notification)
1999
+ // Detect updates on other branches (for flash notification).
2000
+ // We also capture each updated branch's pre-update commit so the casino
2001
+ // win calculation can compute REAL line churn via git diff, instead of
2002
+ // the old `notifyBranches.length * 100` placeholder that surfaced as
2003
+ // inflated dashboard numbers.
1999
2004
  const updatedBranches = [];
2005
+ const updatedBranchPrevCommits = new Map();
2000
2006
  const currentBranchName = store.get('currentBranch');
2001
2007
  const activeBranchNames = new Set();
2002
2008
  for (const branch of pollFilteredBranches) {
@@ -2007,6 +2013,7 @@ async function pollGitChanges() {
2007
2013
  const prevCommit = previousBranchStates.get(branch.name);
2008
2014
  if (prevCommit && prevCommit !== branch.commit && branch.name !== currentBranchName) {
2009
2015
  updatedBranches.push(branch);
2016
+ updatedBranchPrevCommits.set(branch.name, prevCommit);
2010
2017
  branch.justUpdated = true;
2011
2018
  }
2012
2019
  previousBranchStates.set(branch.name, branch.commit);
@@ -2041,14 +2048,25 @@ async function pollGitChanges() {
2041
2048
  showFlash(names);
2042
2049
  playSound();
2043
2050
 
2044
- // Casino mode: trigger win effect based on number of updated branches
2051
+ // Casino mode: trigger win effect based on REAL line churn from
2052
+ // each updated branch's prev → new commit. New branches (no prev
2053
+ // commit) contribute 0 — the win still fires from the slot animation
2054
+ // path, but no fake volume is added to totalLinesAdded.
2045
2055
  if (casinoOn) {
2046
- // Estimate line changes: more branches = bigger "win"
2047
- // Each branch update counts as ~100 lines (placeholder until we calculate actual diff)
2048
- const estimatedLines = notifyBranches.length * 100;
2049
- const winLevel = casino.getWinLevel(estimatedLines);
2056
+ const churn = await sumPollChurn(
2057
+ updatedBranches,
2058
+ updatedBranchPrevCommits,
2059
+ getDiffStats
2060
+ );
2061
+ const totalLines = churn.added + churn.deleted;
2062
+ // getWinLevel(0) returns null and would skip the slot result label
2063
+ // and the sound. Use max(1, totalLines) so a no-line update (e.g.
2064
+ // a tag-only commit, an empty merge) still registers as a "small"
2065
+ // win — the user did get a notification, after all.
2066
+ const winLines = Math.max(1, totalLines);
2067
+ const winLevel = casino.getWinLevel(winLines);
2050
2068
  casino.stopSlotReels(true, render, winLevel); // Win - matching symbols + flash + label
2051
- casino.triggerWin(estimatedLines, 0, render);
2069
+ casino.triggerWin(churn.added, churn.deleted, render);
2052
2070
  if (winLevel) {
2053
2071
  casinoSounds.playForWinLevel(winLevel.key);
2054
2072
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-watchtower",
3
- "version": "2.3.11",
3
+ "version": "2.3.12",
4
4
  "description": "Terminal-based Git branch monitor with activity sparklines and optional dev server with live reload",
5
5
  "main": "bin/git-watchtower.js",
6
6
  "bin": {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Casino mode "win" line-count aggregation.
3
+ *
4
+ * The polling loop used to fake the line-change total as
5
+ * `notifyBranches.length * 100` — a placeholder that surfaced as inflated
6
+ * (and incorrect) numbers in the dashboard's "+lines" / netWinnings
7
+ * displays. This module sums the REAL diff between each updated branch's
8
+ * previous commit and its new commit so the casino stats track actual
9
+ * code churn.
10
+ *
11
+ * @module casino/poll-churn
12
+ */
13
+
14
+ /**
15
+ * Sum the diff churn across a list of updated branches by running the
16
+ * caller-supplied diff function on each (prev → new) pair in parallel.
17
+ * Branches missing a prev commit (e.g. brand-new branches) contribute 0,
18
+ * so a notification still fires but no fake line count is invented.
19
+ *
20
+ * @param {Array<{name: string, commit: string}>} updatedBranches
21
+ * @param {Map<string, string>} prevCommits - map of branch.name → previous commit hash
22
+ * @param {(from: string, to: string) => Promise<{added: number, deleted: number}>} diffFn
23
+ * @returns {Promise<{added: number, deleted: number}>}
24
+ */
25
+ async function sumPollChurn(updatedBranches, prevCommits, diffFn) {
26
+ if (!updatedBranches || updatedBranches.length === 0) {
27
+ return { added: 0, deleted: 0 };
28
+ }
29
+ const results = await Promise.all(
30
+ updatedBranches.map(async (branch) => {
31
+ const prev = prevCommits ? prevCommits.get(branch.name) : null;
32
+ if (!prev || !branch.commit) return { added: 0, deleted: 0 };
33
+ try {
34
+ const r = await diffFn(prev, branch.commit);
35
+ return {
36
+ added: Number.isFinite(r && r.added) ? r.added : 0,
37
+ deleted: Number.isFinite(r && r.deleted) ? r.deleted : 0,
38
+ };
39
+ } catch (e) {
40
+ // diffFn already returns { added: 0, deleted: 0 } on git failure
41
+ // (see src/git/commands.js#getDiffStats), but guard against a
42
+ // throwing test stub or future caller passing a stricter fn.
43
+ return { added: 0, deleted: 0 };
44
+ }
45
+ })
46
+ );
47
+ return results.reduce(
48
+ (acc, d) => ({ added: acc.added + d.added, deleted: acc.deleted + d.deleted }),
49
+ { added: 0, deleted: 0 }
50
+ );
51
+ }
52
+
53
+ module.exports = { sumPollChurn };