@coderook/cli 0.25.1 → 0.25.3
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.
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "coderook",
|
|
3
3
|
"displayName": "CodeRook",
|
|
4
4
|
"description": "Save, browse and restore whole-snapshot versions of a project on CodeRook, from Claude Code.",
|
|
5
|
-
"version": "0.25.
|
|
5
|
+
"version": "0.25.3",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ACCA Gaming Productions",
|
|
8
8
|
"url": "https://coderook.com"
|
package/README.md
CHANGED
|
@@ -109,12 +109,15 @@ somebody looking for where they can save needs to see the one they cannot.
|
|
|
109
109
|
## Ignore rules
|
|
110
110
|
|
|
111
111
|
```
|
|
112
|
-
cbx
|
|
113
|
-
cbx
|
|
114
|
-
cbx
|
|
115
|
-
cbx
|
|
112
|
+
cbx ignore show the rules in force
|
|
113
|
+
cbx ignore --init write a starter .gitignore
|
|
114
|
+
cbx ignore --suggest what is here that probably should not be sent
|
|
115
|
+
cbx ignore --suggest --apply add the confident ones
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
`cbx rules` is the same command under another name, so anything already
|
|
119
|
+
written against it keeps working.
|
|
120
|
+
|
|
118
121
|
`--suggest` looks at what the folder would actually send and names the
|
|
119
122
|
dependency directories, virtual environments and build output in it, with how
|
|
120
123
|
much each is costing you. Lines marked `+` are safe to assume and are the ones
|
|
@@ -21,6 +21,7 @@ exports.versionsInOrder = versionsInOrder;
|
|
|
21
21
|
exports.stamp = stamp;
|
|
22
22
|
exports.importRef = importRef;
|
|
23
23
|
exports.quotePath = quotePath;
|
|
24
|
+
exports.refPlacements = refPlacements;
|
|
24
25
|
/**
|
|
25
26
|
* Git's constant hash for the empty tree.
|
|
26
27
|
*
|
|
@@ -223,3 +224,35 @@ function quotePath(filePath) {
|
|
|
223
224
|
.replaceAll("\n", "\\n")
|
|
224
225
|
.replaceAll("\r", "\\r")}"`;
|
|
225
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Where each ref git asked for has to be pointed, once the commits exist.
|
|
229
|
+
*
|
|
230
|
+
* Git holds the helper to the whole batch: it names the refs it wants, and
|
|
231
|
+
* if any one of them does not exist when the stream ends it aborts the fetch
|
|
232
|
+
* — `could not read ref refs/coderook/<name>` — and the clone fails with
|
|
233
|
+
* nothing to show for it.
|
|
234
|
+
*
|
|
235
|
+
* Emitting commits is not enough to guarantee that, because a commit is
|
|
236
|
+
* written once per *version* while refs are per *line*. Two lines can share
|
|
237
|
+
* one version — making a line from where another already is does exactly
|
|
238
|
+
* that — so a single commit is expected to satisfy two refs, and only the
|
|
239
|
+
* first is written. A line whose version arrived in an earlier fetch has no
|
|
240
|
+
* commit emitted for it at all, and lands in the same hole.
|
|
241
|
+
*
|
|
242
|
+
* So each ref is stated separately rather than inferred from the commits.
|
|
243
|
+
* A ref whose head has no mark is reported rather than guessed at: pointing
|
|
244
|
+
* it somewhere plausible would hand back a branch that is quietly not the
|
|
245
|
+
* one asked for.
|
|
246
|
+
*/
|
|
247
|
+
function refPlacements(wanted, markOfVersion) {
|
|
248
|
+
const placed = [];
|
|
249
|
+
const unplaceable = [];
|
|
250
|
+
for (const [ref, head] of wanted) {
|
|
251
|
+
const mark = markOfVersion.get(head);
|
|
252
|
+
if (mark === undefined)
|
|
253
|
+
unplaceable.push(ref);
|
|
254
|
+
else
|
|
255
|
+
placed.push({ ref, mark });
|
|
256
|
+
}
|
|
257
|
+
return { placed, unplaceable };
|
|
258
|
+
}
|
|
@@ -529,9 +529,40 @@ async function doImport(refs, url) {
|
|
|
529
529
|
let nextMark = 1;
|
|
530
530
|
for (const mark of commitMark.values())
|
|
531
531
|
nextMark = Math.max(nextMark, mark + 1);
|
|
532
|
+
/*
|
|
533
|
+
Point every ref git asked for at the commit its line's head became.
|
|
534
|
+
|
|
535
|
+
Which ref needs what is worked out in `refPlacements`; this only says it.
|
|
536
|
+
`reset` is idempotent, so naming a ref that a commit in this stream has
|
|
537
|
+
already set costs a line and changes nothing.
|
|
538
|
+
*/
|
|
539
|
+
const settleRefs = () => {
|
|
540
|
+
const { placed, unplaceable } = (0, git_history_js_1.refPlacements)(wanted, commitMark);
|
|
541
|
+
for (const { ref, mark } of placed) {
|
|
542
|
+
send(`reset ${(0, git_history_js_1.importRef)(ref)}`);
|
|
543
|
+
send(`from :${mark}`);
|
|
544
|
+
}
|
|
545
|
+
for (const ref of unplaceable) {
|
|
546
|
+
say(` could not place ${ref}: no commit for its head version`);
|
|
547
|
+
}
|
|
548
|
+
};
|
|
532
549
|
const fresh = order.filter((version) => !commitMark.has(version.id));
|
|
533
550
|
if (!fresh.length) {
|
|
534
551
|
say(`Already up to date with ${slug}.`);
|
|
552
|
+
/*
|
|
553
|
+
Still has to name the refs. "Nothing new to fetch" and "this ref does
|
|
554
|
+
not exist" are different answers, and a line added since the last fetch
|
|
555
|
+
is the first case while looking like the second.
|
|
556
|
+
|
|
557
|
+
The marks table is loaded first because the refs are placed by mark,
|
|
558
|
+
and without it those marks name nothing in this stream.
|
|
559
|
+
*/
|
|
560
|
+
if (marks) {
|
|
561
|
+
send("feature done");
|
|
562
|
+
send(`feature import-marks-if-exists=${marks.file.replaceAll("\\", "/")}`);
|
|
563
|
+
send(`feature export-marks=${marks.file.replaceAll("\\", "/")}`);
|
|
564
|
+
settleRefs();
|
|
565
|
+
}
|
|
535
566
|
send("done");
|
|
536
567
|
return;
|
|
537
568
|
}
|
|
@@ -612,6 +643,8 @@ async function doImport(refs, url) {
|
|
|
612
643
|
say(` ${done}/${fresh.length} versions`);
|
|
613
644
|
}
|
|
614
645
|
}
|
|
646
|
+
/* Every ref git asked for, named outright now the commits exist. */
|
|
647
|
+
settleRefs();
|
|
615
648
|
/*
|
|
616
649
|
Releases come back as tags, because that is the same statement in the
|
|
617
650
|
other vocabulary: a version somebody gave a name to.
|
|
@@ -321,6 +321,27 @@ async function commandTransfer(parsed) {
|
|
|
321
321
|
if (!parsed.flags.has("issues")) {
|
|
322
322
|
console.log(dim(" · issues — pass --issues to bring the open ones"));
|
|
323
323
|
}
|
|
324
|
+
/*
|
|
325
|
+
Said plainly rather than implied by the word "transfer".
|
|
326
|
+
|
|
327
|
+
Nothing here checks whose repository this is, and nothing could: a public
|
|
328
|
+
repository is readable by anybody, which is exactly why cloning one needs
|
|
329
|
+
no token. What that means in practice is that this is `git clone`
|
|
330
|
+
followed by a publish — no more permission than anyone already has, and
|
|
331
|
+
no claim of ownership either. The licence that came with the files is
|
|
332
|
+
still the thing that governs what may be done with them, which matters
|
|
333
|
+
most at the moment somebody makes the project public.
|
|
334
|
+
*/
|
|
335
|
+
console.log([
|
|
336
|
+
"",
|
|
337
|
+
`${dim("On ownership:")} nothing was checked, and nothing could be.`,
|
|
338
|
+
"A public repository is readable by anyone, which is why cloning one",
|
|
339
|
+
"needs no token — so this is a clone and a publish, not a claim. The",
|
|
340
|
+
"licence that came with the files is still what governs them.",
|
|
341
|
+
...(facts && facts.visibility === "public"
|
|
342
|
+
? ["Worth reading before you make this project public."]
|
|
343
|
+
: []),
|
|
344
|
+
].join("\n"));
|
|
324
345
|
console.log(`\nFetch it anywhere with ${accent(`cbx clone ${project.slug}`)}` +
|
|
325
346
|
`${dim(", or ")}${accent(`git clone coderook://${project.slug}`)}${dim(".")}`);
|
|
326
347
|
return 0;
|