@biffo/cli 0.152.2 → 0.152.4
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/dist/index.js +50 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -657,6 +657,56 @@ var GitAdapter = class {
|
|
|
657
657
|
} catch {
|
|
658
658
|
throw new Error(`Failed to push branch '${branch}' to remote '${remote}'.`);
|
|
659
659
|
}
|
|
660
|
+
await this.setUpstreamAfterPush(cwd, branch, remote);
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Record the pushed branch's upstream, the way `git push -u` would (#758).
|
|
664
|
+
*
|
|
665
|
+
* ## Why not just pass `-u`
|
|
666
|
+
*
|
|
667
|
+
* Because on the token path `target` is a **URL with the token embedded in
|
|
668
|
+
* it**, and `-u` persists whatever it pushed to into `.git/config` as
|
|
669
|
+
* `branch.<name>.remote`. That would write a live credential into the repo's
|
|
670
|
+
* config — permanently, in plain text — which is the precise leak `push`'s own
|
|
671
|
+
* contract promises never to allow. So the upstream is written by hand, always
|
|
672
|
+
* naming the *remote*, never the URL.
|
|
673
|
+
*
|
|
674
|
+
* ## Why it matters at all
|
|
675
|
+
*
|
|
676
|
+
* Without an upstream, a branch this tool created is invisible to **both**
|
|
677
|
+
* standard ways of finding a dead branch, at once:
|
|
678
|
+
*
|
|
679
|
+
* - `git branch --merged <base>` misses it, because PRs are squash-merged
|
|
680
|
+
* and the branch tip is never an ancestor of the base;
|
|
681
|
+
* - `git branch -vv | grep ': gone]'` misses it, because there is no
|
|
682
|
+
* upstream to be reported gone.
|
|
683
|
+
*
|
|
684
|
+
* `git branch -d` then refuses it too (not an ancestor), leaving only `-D`,
|
|
685
|
+
* which reads as unsafe. The result was 190 accumulated local branches across
|
|
686
|
+
* three repos, with nothing ever looking wrong. One flag's worth of metadata
|
|
687
|
+
* is the difference between that and a one-line cleanup.
|
|
688
|
+
*
|
|
689
|
+
* ## Why the remote-tracking ref is written too
|
|
690
|
+
*
|
|
691
|
+
* Pushing to a *URL* does not update `refs/remotes/<remote>/<branch>`, only
|
|
692
|
+
* pushing via a remote *name* does. Setting the config without that ref would
|
|
693
|
+
* make a freshly-pushed branch report `: gone]` immediately — marking a live
|
|
694
|
+
* branch dead, which is worse than the problem being fixed. The push just
|
|
695
|
+
* succeeded, so the remote is at `HEAD` by construction and the ref can be
|
|
696
|
+
* written offline.
|
|
697
|
+
*
|
|
698
|
+
* ## Why failures here are swallowed
|
|
699
|
+
*
|
|
700
|
+
* The push has already succeeded and the PR is about to be opened. Aborting
|
|
701
|
+
* now would fail an upgrade that actually landed. An upstream is a hygiene
|
|
702
|
+
* affordance, not correctness — the cost of missing it is a leftover branch,
|
|
703
|
+
* which is exactly the state this repo has lived in until now.
|
|
704
|
+
*/
|
|
705
|
+
async setUpstreamAfterPush(cwd, branch, remote) {
|
|
706
|
+
const opts = { cwd, reject: false };
|
|
707
|
+
await execa("git", ["update-ref", `refs/remotes/${remote}/${branch}`, "HEAD"], opts);
|
|
708
|
+
await execa("git", ["config", `branch.${branch}.remote`, remote], opts);
|
|
709
|
+
await execa("git", ["config", `branch.${branch}.merge`, `refs/heads/${branch}`], opts);
|
|
660
710
|
}
|
|
661
711
|
};
|
|
662
712
|
function injectToken(repoUrl, token) {
|