@forwardimpact/libutil 0.1.95 → 0.1.96
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/package.json +1 -1
- package/src/git-client.js +66 -0
package/package.json
CHANGED
package/src/git-client.js
CHANGED
|
@@ -337,10 +337,48 @@ export class GitClient {
|
|
|
337
337
|
return result.stdout.trim();
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Push `branch` to `remote` with the machine-readable per-ref status
|
|
342
|
+
* (`--porcelain`). Runs with `allowFailure` so the caller classifies the
|
|
343
|
+
* outcome from the remote-originated per-ref line rather than the exit code:
|
|
344
|
+
* the line is `<flag>\t<src>:<dst>\t<summary>`, flag ` `/`=` accepted,
|
|
345
|
+
* `!` rejected.
|
|
346
|
+
*/
|
|
347
|
+
async pushPorcelain(remote = "origin", branch, { cwd } = {}) {
|
|
348
|
+
const args = ["push", "--porcelain", remote];
|
|
349
|
+
if (branch) args.push(branch);
|
|
350
|
+
return this.#runRaw(args, { cwd, allowFailure: true });
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* The commit SHA the remote ref points at, read fresh with `ls-remote`.
|
|
355
|
+
* Throws a {@link GitError} on transport failure; returns "" when the ref
|
|
356
|
+
* does not exist on the remote.
|
|
357
|
+
*/
|
|
358
|
+
async remoteRefTip(remote = "origin", branch, { cwd } = {}) {
|
|
359
|
+
const r = await this.#runRaw(["ls-remote", remote, branch], { cwd });
|
|
360
|
+
return r.stdout.split("\t")[0]?.trim() ?? "";
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** Whether `ancestor` is an ancestor of `descendant` (`merge-base --is-ancestor`). */
|
|
364
|
+
async isAncestor(ancestor, descendant, { cwd } = {}) {
|
|
365
|
+
const r = await this.#runRaw(
|
|
366
|
+
["merge-base", "--is-ancestor", ancestor, descendant],
|
|
367
|
+
{ cwd, allowFailure: true },
|
|
368
|
+
);
|
|
369
|
+
return r.exitCode === 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** `git status --porcelain` output (for unmerged-path detection). */
|
|
373
|
+
async statusPorcelain({ cwd } = {}) {
|
|
374
|
+
return this.#runRaw(["status", "--porcelain"], { cwd });
|
|
375
|
+
}
|
|
376
|
+
|
|
340
377
|
/**
|
|
341
378
|
* The short name of the branch HEAD points at, or "" when HEAD is detached.
|
|
342
379
|
* An unborn HEAD on a branch (no commits yet) still returns that branch name —
|
|
343
380
|
* `symbolic-ref` reads the ref HEAD targets, not whether it resolves.
|
|
381
|
+
* `symbolic-ref -q HEAD` exits non-zero on a detached HEAD, swallowed here.
|
|
344
382
|
*/
|
|
345
383
|
async headBranch({ cwd } = {}) {
|
|
346
384
|
const r = await this.#runRaw(["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
@@ -413,6 +451,34 @@ export class GitClient {
|
|
|
413
451
|
});
|
|
414
452
|
}
|
|
415
453
|
|
|
454
|
+
/**
|
|
455
|
+
* Resolve `ref` to a commit SHA, or "" when it does not resolve
|
|
456
|
+
* (`rev-parse --verify -q`, swallowed).
|
|
457
|
+
*/
|
|
458
|
+
async revParse(ref, { cwd } = {}) {
|
|
459
|
+
const r = await this.#runRaw(["rev-parse", "--verify", "-q", ref], {
|
|
460
|
+
cwd,
|
|
461
|
+
allowFailure: true,
|
|
462
|
+
});
|
|
463
|
+
return r.exitCode === 0 ? r.stdout.trim() : "";
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Name-status lines between two tree-ish (`<code>\t<path>`). Codes read
|
|
468
|
+
* going `a`→`b`: a path present in `a` but gone in `b` is `D`, modified `M`,
|
|
469
|
+
* added `A`. The conservation guard calls it tip-first (a = remote tip,
|
|
470
|
+
* b = HEAD) so a dropped foreign file reads `D`.
|
|
471
|
+
*/
|
|
472
|
+
async diffNameStatus(a, b, { cwd } = {}) {
|
|
473
|
+
const r = await this.#runRaw(["diff", "--name-status", a, b], { cwd });
|
|
474
|
+
return r.stdout.trim();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/** Drop a stash addressed by SHA, never by stack position (`stash drop <sha>`). */
|
|
478
|
+
async stashDropBySha(sha, { cwd } = {}) {
|
|
479
|
+
return this.#runRaw(["stash", "drop", sha], { cwd, allowFailure: true });
|
|
480
|
+
}
|
|
481
|
+
|
|
416
482
|
/** Return a new client that threads `token` into the git env. */
|
|
417
483
|
withAuth(token) {
|
|
418
484
|
return new GitClient({ runtime: this.#runtime, token });
|