zapdev 0.7.1 → 0.8.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/README.md +3 -0
- package/dist/cli.js +90 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ zapdev commit
|
|
|
36
36
|
| --- | --- |
|
|
37
37
|
| `-m, --model <model>` | Override the Ollama model |
|
|
38
38
|
| `-t, --type <type>` | Force the Conventional Commits type (`feat`, `fix`, `chore`, …) |
|
|
39
|
+
| `--pull` | Rebase onto upstream (`git pull --rebase`) after committing, before pushing |
|
|
39
40
|
| `-p, --push` | Push after committing without asking |
|
|
40
41
|
| `-y, --yes` | Skip prompts and commit directly |
|
|
41
42
|
|
|
@@ -43,6 +44,8 @@ zapdev commit
|
|
|
43
44
|
zapdev commit -t feat # force the type; the model still writes scope + description
|
|
44
45
|
```
|
|
45
46
|
|
|
47
|
+
Pushing is optimistic — no preliminary fetch, so the common case stays a single round-trip. If the push is rejected because the branch is behind its upstream, in a TTY it offers to `git pull --rebase` and retry; non-interactively (`--yes` / piped) it stops and asks you to re-run with `--pull`. Pass `--pull` to rebase onto upstream right after the commit (a rebase conflict stops before pushing). `--yes` only silences prompts; it never rebases on its own.
|
|
48
|
+
|
|
46
49
|
Without a TTY (piped / CI), it commits automatically and only pushes when `--push` is set.
|
|
47
50
|
|
|
48
51
|
### `zapdev reset`
|
package/dist/cli.js
CHANGED
|
@@ -1718,7 +1718,7 @@ function _getBuiltinFlags(long, short, userNames, userAliases) {
|
|
|
1718
1718
|
// package.json
|
|
1719
1719
|
var package_default = {
|
|
1720
1720
|
name: "zapdev",
|
|
1721
|
-
version: "0.
|
|
1721
|
+
version: "0.8.0",
|
|
1722
1722
|
description: "Fast, performant and lightweight git chores and dev tools using your terminal and your own local LLM.",
|
|
1723
1723
|
type: "module",
|
|
1724
1724
|
bin: {
|
|
@@ -2222,6 +2222,16 @@ async function push() {
|
|
|
2222
2222
|
async function pushSetUpstream(branch) {
|
|
2223
2223
|
await git(["push", "-u", "origin", branch]);
|
|
2224
2224
|
}
|
|
2225
|
+
async function pullRebase() {
|
|
2226
|
+
await git(["pull", "--rebase"]);
|
|
2227
|
+
}
|
|
2228
|
+
async function fetchRemote() {
|
|
2229
|
+
await git(["fetch"]);
|
|
2230
|
+
}
|
|
2231
|
+
async function behindCount() {
|
|
2232
|
+
const out = await tryGit(["rev-list", "--count", `HEAD..${UPSTREAM_REF}`]);
|
|
2233
|
+
return out === null ? 0 : Number(out.trim()) || 0;
|
|
2234
|
+
}
|
|
2225
2235
|
async function findRepos(path) {
|
|
2226
2236
|
if (await isGitRepo(path)) return [path];
|
|
2227
2237
|
const entries = await readdir(path, { withFileTypes: true }).catch(() => null);
|
|
@@ -2372,6 +2382,10 @@ var commitCommand = defineCommand({
|
|
|
2372
2382
|
alias: "t",
|
|
2373
2383
|
description: `Force the Conventional Commits type (${COMMIT_TYPES.join(", ")}).`
|
|
2374
2384
|
},
|
|
2385
|
+
pull: {
|
|
2386
|
+
type: "boolean",
|
|
2387
|
+
description: "Rebase onto upstream (git pull --rebase) after committing, before pushing."
|
|
2388
|
+
},
|
|
2375
2389
|
push: {
|
|
2376
2390
|
type: "boolean",
|
|
2377
2391
|
alias: "p",
|
|
@@ -2457,6 +2471,10 @@ var commitCommand = defineCommand({
|
|
|
2457
2471
|
}
|
|
2458
2472
|
await commit(finalMessage);
|
|
2459
2473
|
if (interactive) log.success(`Committed: ${finalMessage}`);
|
|
2474
|
+
if (args.pull && !await rebaseOnUpstream(interactive)) {
|
|
2475
|
+
process.exitCode = 1;
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2460
2478
|
let shouldPush = Boolean(args.push);
|
|
2461
2479
|
if (!shouldPush && interactive && !args.yes) {
|
|
2462
2480
|
const answer = await confirm({ message: "Push?", initialValue: false });
|
|
@@ -2467,16 +2485,8 @@ var commitCommand = defineCommand({
|
|
|
2467
2485
|
shouldPush = answer;
|
|
2468
2486
|
}
|
|
2469
2487
|
if (shouldPush) {
|
|
2470
|
-
const
|
|
2471
|
-
|
|
2472
|
-
try {
|
|
2473
|
-
const [upstream, branch] = await Promise.all([hasUpstream(), currentBranch()]);
|
|
2474
|
-
if (upstream) await push();
|
|
2475
|
-
else await pushSetUpstream(branch);
|
|
2476
|
-
pushLoader?.stop("\u2713 Pushed");
|
|
2477
|
-
} catch (error) {
|
|
2478
|
-
pushLoader?.error("Push failed");
|
|
2479
|
-
log.error(`Push failed: ${errorMessage(error)}`);
|
|
2488
|
+
const pushed = await pushOptimistic(interactive, Boolean(args.yes));
|
|
2489
|
+
if (!pushed) {
|
|
2480
2490
|
process.exitCode = 1;
|
|
2481
2491
|
return;
|
|
2482
2492
|
}
|
|
@@ -2484,6 +2494,75 @@ var commitCommand = defineCommand({
|
|
|
2484
2494
|
if (interactive) outro("Done.");
|
|
2485
2495
|
}
|
|
2486
2496
|
});
|
|
2497
|
+
async function rebaseOnUpstream(interactive) {
|
|
2498
|
+
if (!await hasUpstream()) {
|
|
2499
|
+
log.info("No upstream to pull from; skipping --pull.");
|
|
2500
|
+
return true;
|
|
2501
|
+
}
|
|
2502
|
+
const loader = interactive ? spinner() : void 0;
|
|
2503
|
+
loader?.start("Pulling --rebase");
|
|
2504
|
+
try {
|
|
2505
|
+
await pullRebase();
|
|
2506
|
+
loader?.stop("\u2713 Rebased on upstream");
|
|
2507
|
+
return true;
|
|
2508
|
+
} catch (error) {
|
|
2509
|
+
loader?.error("Rebase failed");
|
|
2510
|
+
log.error(`Rebase failed (resolve conflicts, then push): ${errorMessage(error)}`);
|
|
2511
|
+
return false;
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
async function pushOptimistic(interactive, assumeYes) {
|
|
2515
|
+
const [upstream, branch] = await Promise.all([hasUpstream(), currentBranch()]);
|
|
2516
|
+
const doPush = () => upstream ? push() : pushSetUpstream(branch);
|
|
2517
|
+
const first = await tryPush(interactive, doPush);
|
|
2518
|
+
if (first.ok) return true;
|
|
2519
|
+
if (upstream && await isBehind(interactive)) {
|
|
2520
|
+
if (assumeYes || !interactive) {
|
|
2521
|
+
log.error("Behind upstream \u2014 re-run with --pull to rebase and push.");
|
|
2522
|
+
return false;
|
|
2523
|
+
}
|
|
2524
|
+
const answer = await confirm({ message: "Pull --rebase and retry push?", initialValue: true });
|
|
2525
|
+
if (isCancel(answer) || !answer) {
|
|
2526
|
+
log.info("Not pushed (still behind).");
|
|
2527
|
+
return true;
|
|
2528
|
+
}
|
|
2529
|
+
if (!await rebaseOnUpstream(interactive)) return false;
|
|
2530
|
+
const retry = await tryPush(interactive, doPush);
|
|
2531
|
+
if (retry.ok) return true;
|
|
2532
|
+
log.error(`Push failed: ${errorMessage(retry.error)}`);
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
log.error(`Push failed: ${errorMessage(first.error)}`);
|
|
2536
|
+
return false;
|
|
2537
|
+
}
|
|
2538
|
+
async function tryPush(interactive, doPush) {
|
|
2539
|
+
const loader = interactive ? spinner() : void 0;
|
|
2540
|
+
loader?.start("Pushing");
|
|
2541
|
+
try {
|
|
2542
|
+
await doPush();
|
|
2543
|
+
loader?.stop("\u2713 Pushed");
|
|
2544
|
+
return { ok: true };
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
loader?.error("Push failed");
|
|
2547
|
+
return { ok: false, error };
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
async function isBehind(interactive) {
|
|
2551
|
+
const loader = interactive ? spinner() : void 0;
|
|
2552
|
+
loader?.start("Checking upstream");
|
|
2553
|
+
try {
|
|
2554
|
+
await fetchRemote();
|
|
2555
|
+
const behind = await behindCount();
|
|
2556
|
+
loader?.stop(
|
|
2557
|
+
behind > 0 ? `Behind upstream by ${behind} commit${behind > 1 ? "s" : ""}` : "Up to date with upstream"
|
|
2558
|
+
);
|
|
2559
|
+
return behind > 0;
|
|
2560
|
+
} catch (error) {
|
|
2561
|
+
loader?.error("Could not check upstream");
|
|
2562
|
+
log.warn(`Could not check upstream: ${errorMessage(error)}`);
|
|
2563
|
+
return false;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2487
2566
|
|
|
2488
2567
|
// src/commands/reset.ts
|
|
2489
2568
|
var CANCEL = /* @__PURE__ */ Symbol("cancel");
|