@coderook/cli 0.29.4 → 0.30.0
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/.claude-plugin/plugin.json +1 -1
- package/dist/cli/src/api.js +46 -1
- package/dist/cli/src/cli.js +118 -7
- package/dist/cli/src/diff_command.js +218 -0
- package/dist/desktop-app/src/main/detect.js +91 -5
- package/dist/desktop-app/src/main/rules.js +21 -3
- package/dist/desktop-app/src/main/transfer_progress.js +109 -0
- package/dist/desktop-app/src/main/upload.js +617 -559
- package/dist/desktop-app/src/main/worktree.js +158 -5
- package/dist/desktop-app/src/shared/merge_diff.js +191 -0
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferProgress = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* How much of an upload has happened, and how fast it is going.
|
|
6
|
+
*
|
|
7
|
+
* Lifted out of the upload pass because nearly every number a person watches
|
|
8
|
+
* during a save comes from here, and three separate faults have come out of it
|
|
9
|
+
* being a handful of loose counters in the middle of a very long function:
|
|
10
|
+
*
|
|
11
|
+
* - Six lanes each added their own offset to one shared total, so the figure
|
|
12
|
+
* jumped between six different answers and the bar ran backwards.
|
|
13
|
+
* - The rate was `transferred` over the whole elapsed time while the bar
|
|
14
|
+
* beside it showed something else, so one real upload sat at
|
|
15
|
+
* "152 MB of 1.1 GB · 10 B/s" — not a slow upload, a number describing a
|
|
16
|
+
* different thing.
|
|
17
|
+
* - A lifetime average meant a slow first minute went on dragging the figure
|
|
18
|
+
* down long after the link had recovered, which is the opposite of what
|
|
19
|
+
* somebody watching it wants to know.
|
|
20
|
+
*
|
|
21
|
+
* So the counters and the arithmetic over them live together, with names, and
|
|
22
|
+
* can be tested without starting an upload.
|
|
23
|
+
*/
|
|
24
|
+
class TransferProgress {
|
|
25
|
+
windowMs;
|
|
26
|
+
now;
|
|
27
|
+
/** Bytes of files that have finished, whether they travelled or not. */
|
|
28
|
+
settled = 0;
|
|
29
|
+
/** Bytes that actually crossed the wire. */
|
|
30
|
+
moved = 0;
|
|
31
|
+
/** Files the service already held, so nothing crossed the wire for them. */
|
|
32
|
+
reused = 0;
|
|
33
|
+
/*
|
|
34
|
+
How far each lane is through the file it currently holds, kept apart so the
|
|
35
|
+
total is the sum of real work rather than six lanes' guesses about one
|
|
36
|
+
shared number.
|
|
37
|
+
*/
|
|
38
|
+
inFlight = new Map();
|
|
39
|
+
samples = [];
|
|
40
|
+
constructor(
|
|
41
|
+
/** How long a window the rate is measured over. */
|
|
42
|
+
windowMs = 5000,
|
|
43
|
+
/** Injected so a test can move time without waiting for it. */
|
|
44
|
+
now = Date.now) {
|
|
45
|
+
this.windowMs = windowMs;
|
|
46
|
+
this.now = now;
|
|
47
|
+
}
|
|
48
|
+
/** A file finished: its own size, and what it cost to send. */
|
|
49
|
+
finished(sourceBytes, wireBytes) {
|
|
50
|
+
this.settled += sourceBytes;
|
|
51
|
+
this.moved += wireBytes;
|
|
52
|
+
}
|
|
53
|
+
/** A file the service already had. Counted apart so "sent" stays honest. */
|
|
54
|
+
alreadyHeld() {
|
|
55
|
+
this.reused += 1;
|
|
56
|
+
}
|
|
57
|
+
/** Where one lane has got to inside the file it is sending. */
|
|
58
|
+
lane(index, offset) {
|
|
59
|
+
this.inFlight.set(index, offset);
|
|
60
|
+
}
|
|
61
|
+
/** That lane has finished, so its offset is now part of the settled total. */
|
|
62
|
+
laneDone(index) {
|
|
63
|
+
this.inFlight.delete(index);
|
|
64
|
+
}
|
|
65
|
+
/** Everything settled, plus how far the open lanes have got. */
|
|
66
|
+
bytes() {
|
|
67
|
+
let total = this.settled;
|
|
68
|
+
for (const offset of this.inFlight.values())
|
|
69
|
+
total += offset;
|
|
70
|
+
return total;
|
|
71
|
+
}
|
|
72
|
+
get sentBytes() {
|
|
73
|
+
return this.settled;
|
|
74
|
+
}
|
|
75
|
+
get transferred() {
|
|
76
|
+
return this.moved;
|
|
77
|
+
}
|
|
78
|
+
get alreadyOnAccount() {
|
|
79
|
+
return this.reused;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* How fast the thing on screen is moving, over a short trailing window.
|
|
83
|
+
*
|
|
84
|
+
* The same counter the bar uses, so the two agree. Sampled rather than
|
|
85
|
+
* recorded per call: this is asked once per report, and reports arrive per
|
|
86
|
+
* file, which for small files is thousands a second.
|
|
87
|
+
*/
|
|
88
|
+
rate() {
|
|
89
|
+
const now = this.now();
|
|
90
|
+
const bytes = this.bytes();
|
|
91
|
+
const last = this.samples[this.samples.length - 1];
|
|
92
|
+
if (!last || now - last.at >= 250)
|
|
93
|
+
this.samples.push({ at: now, bytes });
|
|
94
|
+
while (this.samples.length > 2 && now - this.samples[0].at > this.windowMs) {
|
|
95
|
+
this.samples.shift();
|
|
96
|
+
}
|
|
97
|
+
const oldest = this.samples[0];
|
|
98
|
+
const seconds = (now - oldest.at) / 1000;
|
|
99
|
+
/*
|
|
100
|
+
Nothing until there is something to divide. Answering zero keeps the
|
|
101
|
+
window quiet rather than showing a figure computed from a fraction of a
|
|
102
|
+
second, which reads as a stall on an upload that has barely begun.
|
|
103
|
+
*/
|
|
104
|
+
if (seconds < 0.5)
|
|
105
|
+
return 0;
|
|
106
|
+
return Math.max(0, Math.round((bytes - oldest.bytes) / seconds));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.TransferProgress = TransferProgress;
|