bisgit 0.1.0 → 0.3.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 +22 -22
- package/dist/chunks/chunk-7AM4AK3O.js +2 -0
- package/dist/chunks/chunk-IX3J52I6.js +2 -0
- package/dist/chunks/chunk-NAFT7YF6.js +2 -0
- package/dist/chunks/chunk-NWXSV6NP.js +2 -0
- package/dist/chunks/commands-2D4LDHYD.js +12 -0
- package/dist/chunks/log-4RIWY74K.js +2 -0
- package/dist/chunks/pages-KZAY5E2R.js +2 -0
- package/dist/chunks/status-UBYZMDYE.js +2 -0
- package/dist/main.js +1 -1
- package/package.json +10 -10
- package/dist/chunks/commands-AR5RPPHV.js +0 -12
- package/dist/chunks/demo-PL6P4QST.js +0 -2
package/README.md
CHANGED
|
@@ -8,39 +8,39 @@ Full Tui coming soon
|
|
|
8
8
|
|
|
9
9
|
### Commit Tooling
|
|
10
10
|
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
11
|
+
- `gi sha <commit>` copies the shortend sha to clipboard (uses HEAD as default)
|
|
12
|
+
- `gi amend` commits with `--no-edit` and `--amend`. Accepts extra flags too.
|
|
13
|
+
- `gi fixup <commit>` commits staged changes as aa rebase, and starts an interactive rebase on the target commit if it would not fail.
|
|
14
|
+
- `gi savepoint` makes a WIP commit with current timestamp.
|
|
15
15
|
|
|
16
16
|
### Merge Helpers
|
|
17
17
|
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
- `
|
|
18
|
+
- `gi backmerge <branch>` updates a branch and then merges it into the current branch.
|
|
19
|
+
- `gi conflict <branch>` shows all conflicts that would occur in a merge.
|
|
20
|
+
- `gi abort` and `gi continue` are useful in conflict resolution situations.
|
|
21
|
+
<!-- - `gi lines <branch> <ignore-file> <ignore-file> ...*` shows the number of lines changed. -->
|
|
22
22
|
|
|
23
23
|
### Branching
|
|
24
24
|
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
25
|
+
- `gi autoprune` deletes any already merged branches.
|
|
26
|
+
- `gi rebranch` If conflicts won't exist, create new branch from main and cherry-pick all commits from $
|
|
27
|
+
- `gi track <branch>` copies a remote branch to a local one and sets the origin upstream.
|
|
28
|
+
- `gi yank` is a force pull for the current branch. It commits a WIP commit and/or backup branch if commits don't exist in remote. Then it resets the local branch to match the remote. Useful way to handle a collaborator's force push.
|
|
29
29
|
|
|
30
30
|
### Github
|
|
31
31
|
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
35
|
-
- `
|
|
32
|
+
- `gi code-review <pr>` checks out a pr and creates a diff similar to github's code review diff viewer.
|
|
33
|
+
- `gi whoami` shows github username.
|
|
34
|
+
- `gi languages` prints the percentages of languages for this repo.
|
|
35
|
+
- `gi coauthor <username>` commits with a co-authorship description.
|
|
36
36
|
|
|
37
37
|
### Utility
|
|
38
38
|
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
- `
|
|
42
|
-
- `
|
|
43
|
-
- `
|
|
44
|
-
- `
|
|
39
|
+
- `gi pwd` shows repo root path.
|
|
40
|
+
- `gi wipe` clears all uncommitted trackable files
|
|
41
|
+
- `gi files <commit>` shows the files edited by the given commit.
|
|
42
|
+
- `gi churn` shows you the 25 most edited files.
|
|
43
|
+
- `gi exclude` and `gi include` allows you to ignore files locally without modifying the .gitignore file.
|
|
44
|
+
- `gi remote-default` shows whether the remote default branch is 'main', 'master', etc.
|
|
45
45
|
|
|
46
46
|
I turned many of my git aliases into commands. The original aliases are found this [gist](https://gist.github.com/alexanderdombroski/ddac491daeff48c5f1346ba2960462fa).
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{b as e,c as i}from"./chunk-HCUVDNFV.js";import{normalize as o}from"node:path";async function a(){let{stdout:t}=await e("git branch --show-current");return t.trim()}async function f(t){t??=await a();let{stdout:r}=await e(`git config --get branch.${t}.remote`);return r.trim()}async function p(t,r){try{let{stdout:n}=await e(`git rev-list --count ${t}/${r}..${r}`);return parseInt(n.trim(),10)}catch(n){return console.error("Error getting commits ahead:",n),NaN}}async function d(t,r){try{let{stdout:n}=await e(`git rev-list --count ${r}..${t}/${r}`);return parseInt(n.trim(),10)}catch(n){return console.error("Error getting commits behind:",n),NaN}}async function l(t){let{stdout:r}=await e(`git rev-parse --git-path ${t}`);return o(r.trim())}async function w(){let{stdout:t}=await e("git rev-parse --git-dir");return o(t.trim())}async function y(t){let{code:r}=await i("git",["remote","get-url",t],{stdio:"ignore"});return r===0}async function h(){let{stdout:t}=await e("git rev-parse --abbrev-ref HEAD");return t.trim()==="HEAD"}async function x(t,r){let n="git fetch";t&&(n+=` ${t}`),r&&(n+=` ${r}`),await e(n)}async function $(){let{stdout:t}=await i("git",["status","--porcelain"]);return!t?.trim()}async function v(){let{stdout:t}=await i("git",["status","--porcelain"]);return t?.trim()?.split(/\r?\n/)}async function c(t,r){let{stdout:n}=await e(`git merge-base ${t} ${r}`);return n.trim()}async function P(t,r){let n=await c(t,r),{stdout:s}=await i("git",["merge-tree",n,r,t]);return!s?.split(/\r?\n/)?.includes("+=======")}async function b(t){let{stdout:r}=await e(`git rev-parse ${t}`);return r.trim()}async function D(t,r,n){let{stdout:s}=await e(`git rev-list ${n?"--reverse":""} ${t}..${r}`);return s.trim().split(/\r?\n/)}async function A(){let{stdout:t}=await e("git for-each-ref --format='%(refname:short)' refs/heads");return t.trim().split(/\r?\n/)}export{a,f as b,p as c,d,l as e,w as f,y as g,h,x as i,$ as j,v as k,c as l,P as m,b as n,D as o,A as p};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{useStdout as y}from"ink";function A(){let{stdout:t}=y();return{width:t.columns,height:t.rows}}import{useState as p,createContext as N,useContext as h}from"react";import{jsx as C}from"react/jsx-runtime";var o={Status:"Status",Log:"Log","Commit Details":"Log"},c=Object.keys(o),v=N({});function k({children:t}){let[n,i]=p("Status"),[f,s]=p("Status"),d=e=>{s(e),i(o[e])},a=e=>{i(e),s(e)},l=()=>{s(e=>{let r=c.at((c.indexOf(e)+1)%c.length);return a(o[r]),r})},m=()=>{s(e=>{let r=c.at(c.indexOf(e)-1);return a(o[r]),r})};return C(v.Provider,{value:{activeGroup:n,setActiveGroup:a,activeSection:f,setActiveSection:d,prevSection:m,nextSection:l},children:t})}function S(){let t=h(v);if(!t)throw new Error("useNavContext must be used within a NavProvider");return t}import{Box as x,Text as G}from"ink";import{jsx as u}from"react/jsx-runtime";var w=Array.from(new Set(Object.values(o)));function D(){let{activeGroup:t}=S();return u(x,{width:"100%",flexDirection:"row",children:w.map((n,i)=>u(x,{borderStyle:"classic",borderLeft:!!i,borderRight:!1,borderTop:!1,borderBottom:!1,children:u(G,{color:n===t?"cyan":"",children:` [${i+1}]: ${n} `})},n))})}export{A as a,k as b,S as c,D as d};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{createContext as c,useContext as K,useState as u}from"react";import{jsx as v}from"react/jsx-runtime";var o=c(void 0),a=({children:e})=>{let[d,s]=u({}),g=(n,i)=>{s(t=>({...t,[n]:i}))},y=n=>{let i=Array.isArray(n)?n:[n];s(t=>{let r={...t};for(let b of i)delete r[b];return r})};return v(o.Provider,{value:{keybindings:d,setKeybinding:g,removeKeybinding:y},children:e})},p=()=>{let e=K(o);if(!e)throw new Error("useKeybindings must be used within a KeybindingsProvider");return e};export{a,p as b};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a,c as m}from"./chunk-IX3J52I6.js";import{Box as p,measureElement as P,Text as x}from"ink";import{useMemo as S,useRef as w}from"react";import{Fragment as y,jsx as c,jsxs as R}from"react/jsx-runtime";function L(n){let{title:e,footer:t,children:i,width:d,height:o,innerHeight:r}=n,{width:l}=a(),v=d??l,s=w(null),u=S(()=>{if(!s.current)return 0;let{width:b}=P(s.current);return b},[s.current]),h=u-8,B={...n,height:r,width:u},{activeSection:T}=m(),f=T===e?"cyan":"";return c(p,{ref:s,flexDirection:"column",height:o,width:v,children:u!==0&&R(y,{children:[e&&c(x,{color:f,children:"\u256D\u2500\u2500\u2500\u2500 "+e+" "+"\u2500".repeat(h-e.length)+"\u256E"}),c(p,{flexDirection:"column",...B,borderStyle:"round",borderColor:f,borderTop:!e,borderBottom:!t,paddingLeft:1,children:i}),t&&c(x,{color:f,children:"\u2570"+"\u2500".repeat(h-t.length)+" "+t+" \u2500\u2500\u2500\u2500\u256F"})]})})}import{useEffect as D,useState as g}from"react";function k(n,e=[]){let[t,i]=g(void 0),[d,o]=g(!1);return D(()=>{let r=!1;return o(!1),i(void 0),n().then(l=>{r||(i(l),o(!0))}).catch(()=>{r||o(!0)}),()=>{r=!0}},e),{value:t,resolved:d}}export{L as a,k as b};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{b as g,c as K}from"./chunk-5WTQIRZS.js";import{a as u,b as V,c as k,d as B,e as v,f as z,g as J,h as Z,i as H,j as h,k as W,l as x,m as Q,n as X,o as G,p as tt}from"./chunk-7AM4AK3O.js";import{a as $,b as s,c as q,d as l}from"./chunk-HCUVDNFV.js";import A from"node:path";import Ft from"fs/promises";async function w(t){try{return await Ft.access(t),!0}catch{return!1}}async function et(){let t=await W(),e=/^(UU|DU|UD)/;return!!t?.some(o=>e.test(o))}async function F(){let t=await z(),[e,o,r,i,n]=await Promise.all([await w(A.join(t,"MERGE_HEAD")),await w(A.join(t,"rebase-merge")),await w(A.join(t,"rebase-apply")),await w(A.join(t,"CHERRY_PICK_HEAD")),await w(A.join(t,"REVERT_HEAD"))]);return{merge:e,rebaseMerge:o,rebaseApply:r,cherryPick:i,revert:n}}async function ot(){let{merge:t,rebaseMerge:e,rebaseApply:o,cherryPick:r,revert:i}=await F(),n="";if(t)n="merge";else if(e||o)n="rebase";else if(r)n="cherry-pick";else if(i)n="revert";else{let a=await et()?"Conflicts exist, but likely are from a stash and are not abortable. Resolve them manually.":"Nothing to abort.";console.log(a);return}console.log(`Aborting the ${n}`),await l([n,"--abort"])}function rt(){$("git",["commit","--amend","--no-edit",...g()],{stdio:"inherit",silent:!0,triggerExit:!0})}import{render as Yt}from"ink";import{spawnSync as it}from"node:child_process";function D(t,e,o){let{status:r}=it(t,e,{stdio:"ignore"});r!==0&&(o&&console.error(o),process.exit(1))}var nt=()=>D("git",["rev-parse","--git-dir"],"Need to use command in a git repository."),R=()=>D("git",["rev-parse","HEAD"],"Need to create first commit."),d=(t="origin")=>D("git",["remote","get-url",t],`Need to add remote '${t}'.`),U=t=>D("git",["show-ref","--branches",t],`Branch '${t}' isn't tracked locally and may not exist.`),P=async()=>{await h()||(console.error("You should stash or commit your changes first."),process.exit(1))},M=async t=>{await w(t)||(console.error(`${t} must exist for this operation and it doesn't for some reason`),process.exit(1))},st=async()=>{await Z()&&(console.error("Operation not allowed in a 'detached HEAD' state"),process.exit(1))},at=t=>D("git",["rev-parse","--abbrev-ref","--symbolic-full-name",`${t}@{u}`],`branch '${t}' has no upstream`);function y(t="Error: missing required argument"){if(process.argv[3])return process.argv[3];console.error(t),process.exit(1)}async function N(){let{status:t}=it("git",["diff","--staged","--quiet"],{stdio:"ignore"});t===0&&(console.error("You have no staged changes"),process.exit(1))}import{render as jt}from"ink";import{Suspense as Mt,use as Nt,useEffect as Tt}from"react";import{Text as ct,useApp as Lt}from"ink";import It from"ink-spinner";import{jsx as T,jsxs as Ot}from"react/jsx-runtime";function c(t){let{msg:e}=t;return T(Mt,{fallback:Ot(ct,{children:[T(It,{type:"dots"}),"\xA0",e]}),children:T(Ut,{...t})})}function Ut({msg:t,promise:e}){let o=Nt(e),{exit:r}=Lt();return Tt(()=>{r()},[o]),T(ct,{children:`\u2714 ${typeof o=="string"?o:t}`})}import{jsx as _t}from"react/jsx-runtime";async function mt(){let t=process.argv[3],e=process.argv[4]??await u();if(U(t),U(e),t===e)return console.log(`No reason to merge '${t}' into '${e}'`);let o=await V(t);d(o),jt(_t(c,{msg:"Updating target branch and merging",promise:(async()=>{try{await S(o,t)}catch{console.error(`Error when updating branch ${t} with remote ${o}. Fix divergent branches before merging into ${e}`);return}await u()!==e&&await s(`git switch ${e}`),$("git",["merge",t],{stdio:"inherit",silent:!0})})()}))}async function S(t,e){await H(t,e);let[o,r,i]=await Promise.all([k(t,e),B(t,e),u()]);if(r!==0){if(o===0&&i!==e){await s(`git fetch ${t} ${e}:${e}`);return}if(await s(`git switch ${e}`),o===0){await s(`git merge ${t}/${e}`);return}await l(["merge",`${t}/${e}`],["ignore","ignore","inherit"])}}async function E(){R(),d();let{stdout:t,code:e}=await q("git",["rev-parse","--abbrev-ref","origin/HEAD"]);if(e===0)return lt(t.trim());await s("git remote set-head origin -a");let{stdout:o}=await s("git rev-parse --abbrev-ref origin/HEAD");return lt(o.trim())}async function ft(){let{remote:t,branch:e}=await E();console.log(`Remote default branch is '${t}/${e}'`)}async function lt(t){let e=t.split("/"),o=t.split("/").map((r,i)=>e.slice(0,i+1).join("/"));for(let r of o)if(await J(r)){let i=t.slice(r.length+1);return{remote:r,branch:i}}throw new Error("Failed to get default remote")}import{jsx as Vt}from"react/jsx-runtime";var Kt=["master","main","development","lingoport"];async function pt(){await P();let{branch:t,remote:e}=await E();await s(`git switch ${t}`);let o=(async()=>{await l(["fetch","--prune","--prune-tags"]),await S(e,t)})();Yt(Vt(c,{msg:"Fetching and pruning remote references",promise:o})),await o;let r=await tt();for(let i of r){if(i===t||Kt.includes(i))continue;let n=await x(i,t),{code:a}=await q("git",["diff","--quiet",n,i]);a===0&&await l(["branch","-D",i])}}import{spawn as zt}from"node:child_process";import{createInterface as Jt}from"node:readline/promises";async function gt(){R;let e=[...(await Zt()).entries()].sort(([,r],[,i])=>i-r).slice(0,25),o=e[0][1].toString().length;console.info(e.map(([r,i])=>`${String(i).padEnd(o)} ${r}:`).join(`
|
|
3
|
+
`))}async function Zt(){let{promise:t,resolve:e,reject:o}=Promise.withResolvers(),r=new Map,i=zt("git",["log","--all","-M","-C","--name-only","--format=format:"]),n=Jt({input:i.stdout,crlfDelay:1/0});return n.on("line",a=>{let m=a.trim();m&&r.set(m,(r.get(m)??0)+1)}),n.on("close",()=>e(r)),i.on("error",o),t}import{render as Qt}from"ink";import{jsx as te}from"react/jsx-runtime";async function ut(){await N();let t=y("Error: missing github username argument"),e=(async()=>{let i=await Xt(t);return i.email||(console.error(`Couldn't find an email for ${t}`),process.exit(1)),i})();Qt(te(c,{msg:"Fetching name and email",promise:e}));let{name:o,email:r}=await e;l(["commit","--edit","-m","<insert summary>","-m",`Co-authored-by: ${o} <${r}>`])}async function Xt(t){let{stdout:e}=await s(`gh api users/${t}`);return JSON.parse(e.trim())}import{render as O}from"ink";import{isDeepStrictEqual as ee}from"node:util";import{jsx as j}from"react/jsx-runtime";async function ht(){let t=y("Error: missing id of PR to checkout");await P();let e=(async()=>Promise.all([s(`gh co ${t}`),s(`gh pr view ${t} --json baseRefName -q .baseRefName`)]))();O(j(c,{msg:`Checking out pr #${t}`,promise:e}));let[,{stdout:o}]=await e,r=o.trim(),i=(async()=>{await s(`git switch ${r}`),await s("git pull"),await s("git switch -")})();O(j(c,{msg:`Updating ${r} branch merge destination`,promise:i})),await i;let n=(async()=>{let p=await x(r,"HEAD");return await s(`git reset ${p} --soft`),await oe("HEAD")})();O(j(c,{msg:"Creating an editable, explorable, local PR experience",promise:n}));let[a,m]=await Promise.all([n,re(t)]),{files:f,additions:b,deletions:I}=m;if(ee(a,m))return console.info(`Files: ${f}, +${b} -${I}`);console.info("The PR stat doesn't match the local stat."),console.info("LOCAL"),console.table(a),console.info("GITHUB"),console.table(m),console.info("One option to fix (there'll likely be conflicts):"),console.info("1. git stash -u"),console.info(`2. git merge ${r}`),console.info("3. git stash pop")}async function oe(t){let{stdout:e}=await s(`git diff --shortstat ${t}`),o=/(\d+)\s+files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/,r=e.trim().match(o);if(!r)throw new Error(`Couldn't generate short stat for ref(s): ${t}`);let[,i,n,a]=r;return{files:parseInt(i,10),additions:n?parseInt(n,10):0,deletions:a?parseInt(a,10):0}}async function re(t){let{stdout:e}=await s(`gh pr view ${t} --json deletions,files,additions`),o=JSON.parse(e.trim());return o.files=o.files.length,o}import{spawn as ie}from"node:child_process";import{createInterface as ne}from"node:readline/promises";import _ from"chalk";async function wt(){let t=y("Error: missing target branch argument"),e=await x("HEAD",t),{promise:o,resolve:r,reject:i}=Promise.withResolvers(),n=ie("git",["merge-tree",e,"HEAD",t]),a=ne({input:n.stdout,crlfDelay:1/0}),m=!1,f=0;a.on("line",p=>{p=p.trimEnd(),p==="+<<<<<<< .our"?(m=!0,console.info(_.red(p)),f+=1):p==="+>>>>>>> .their"?(m=!1,console.info(_.green(p))):p==="+======="?console.info(_.yellow(p)):m&&console.info(p)}),a.on("close",()=>r(f)),n.on("error",i);let b=await o,I=b?`\u274C ${b} conflicts would occur!`:"\u2705 No conflicts. Safe to merge.";console.info(I)}async function dt(){let{merge:t,rebaseMerge:e,rebaseApply:o,cherryPick:r,revert:i}=await F(),n="";if(t)n="merge";else if(e||o)n="rebase";else if(r)n="cherry-pick";else if(i)n="revert";else{console.log("Nothing to continue.");return}console.log(`Continuing the ${n}`),await l([n,"--continue"])}import{appendFileSync as ae}from"node:fs";import{readFile as se}from"node:fs/promises";async function L(t){return(await se(t,"utf-8")).split(/\r?\n/).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#"))}async function yt(){let t=await v("info/exclude");await M(t);let e=await L(t);g().forEach(o=>{e.includes(o)?console.info(`Already Exists: '${o}'`):(ae(t,`${o}
|
|
4
|
+
`),console.info(`Added '${o}'`))}),console.info(`
|
|
5
|
+
See file at ${t}`)}function bt(){$("git",["show","--name-only","--pretty=format:",...g()],{stdio:"inherit",silent:!0,triggerExit:!0})}import{spawn as ce}from"node:child_process";async function $t(){let t=y("Error: missing valid target ref argument");await N();let e=await X(t);await l(["commit",`--fixup=${e}`]);let r=(await G(`${e}^`,"HEAD",!0)).map(n=>me(n));(await Promise.all(r)).every(Boolean)||(console.warn("Rebase conflict would occur!"),await s("git reset HEAD~1 --soft"),process.exit(1)),await s(`git rebase -i --autosquash ${e}^`)}async function me(t){let{stdout:e}=await s(`git diff ${t}^ ${t}`),{promise:o,resolve:r,reject:i}=Promise.withResolvers(),n=ce("git",["apply","--check","--3way","-q"],{stdio:["pipe","ignore","ignore"]});return n.on("close",a=>{r(a===0)}),n.on("error",i),n.stdin.write(e),n.stdin.end(),o}import{readFile as le,writeFile as fe}from"node:fs/promises";async function xt(){let t=await v("info/exclude");await M(t);let e=await L(t),o=g();o.filter(a=>!e.includes(a)).forEach(a=>console.info(`No match: '${a}'`));let i=(await le(t,"utf-8")).split(/\r?\n/).map(a=>a.trim()),n=i.filter(a=>!o.includes(a));await fe(t,n.join(`
|
|
6
|
+
`)),console.info(`
|
|
7
|
+
Removed ${i.length-n.length} entries from ${t}`)}import{render as pe}from"ink";import{jsx as we}from"react/jsx-runtime";async function Rt(){let t=(async()=>{let i=await ge();return await ue(i)})();pe(we(c,{msg:"Fetching repo languages",promise:t}));let e=await t,o=Object.values(e).reduce((i,n)=>i+n,0),r=Object.entries(e).map(([i,n])=>`${i}: ${Math.round(n/o*100)}% - ${he(n)}`);console.log(r.join(`
|
|
8
|
+
`))}async function ge(){let{stdout:t}=await s("gh repo view --json nameWithOwner -q .nameWithOwner");return t.trim()}async function ue(t){let{stdout:e}=await s(`gh api repos/${t}/languages`);return JSON.parse(e.trim())}function he(t,e=2){if(t===0)return"0 B";let o=1024,r=e<0?0:e,i=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],n=Math.floor(Math.log(t)/Math.log(o));return`${parseFloat((t/Math.pow(o,n)).toFixed(r))} ${i[n]}`}import{execSync as de}from"node:child_process";function ye(){return de("git rev-parse --show-toplevel",{encoding:"utf-8"}).trim()}function Pt(){let t=ye();console.log(t)}import{render as vt}from"ink";function Ct(){return new Date().toLocaleString("en-US",{year:"2-digit",month:"2-digit",day:"2-digit",hour:"numeric",minute:"2-digit",hour12:!0}).replace(",","")}async function C(){let t=Ct();await s("git add -A"),await l(["commit","-m",`"WIP ${t}"`])}import{nanoid as be}from"nanoid";import $e from"chalk";import{jsx as At}from"react/jsx-runtime";async function Dt(){let{remote:t,branch:e}=await E(),o=process.argv[3]??e;await h()||await C(),await Q(o,"HEAD")||(console.warn("Conflicts would occur. Not safe to rebranch."),process.exit(1));let r=await u(),i=(async()=>{await S(t,o)})();vt(At(c,{msg:`Updating branch ${o}`,promise:i})),await i;let n=`${be(8)}`,a=(async()=>{await s(`git switch ${r}`),await s(`git branch ${n}`),await s(`git switch ${o}`),await s(`git branch -D ${r}`),await s(`git switch -c ${r}`);let m=await G(o,n,!0);for(let f of m)try{await s(`git cherry-pick ${f}`)}catch{let b=$e.yellow(`git branch -D ${r} && git branch -m ${n} ${r}`);throw new Error(`\u274C cherry pick failed at ${f}
|
|
9
|
+
Run this to restore backup branch
|
|
10
|
+
> ${b}`)}await s(`git branch -D ${n}`)})();vt(At(c,{msg:`Rewriting branch ${r}`,promise:a})),await a,console.info(`Successfully recreated branch ${r} from ${o}`)}import{execSync as xe}from"node:child_process";async function St(){R();let t=Re(process.argv[3]),{default:e}=await import("clipboardy");await e.write(t),console.log(`'${t}' copied to clipboard`)}function Re(t="HEAD"){return xe(`git rev-parse --short ${t}`,{encoding:"utf-8"}).trim()}import{render as Pe}from"ink";import{jsx as Ce}from"react/jsx-runtime";async function Et(){let{remote:t,branch:e}=await K();d(t),await P();let o=H(t,e);Pe(Ce(c,{msg:`Fetching branch ${e} from ${t}`,promise:o})),await o,await l(["switch","-c",e,"--track",`${t}/${e}`])}async function qt(){let[t,e]=await Promise.allSettled([await Ae("user.name"),await ve()]);t.status==="fulfilled"&&console.info(`Git: ${t.value}`),e.status==="fulfilled"&&console.info(`Github: ${e.value}`)}async function ve(){let{stdout:t}=await s("gh api user --jq .login");return t.trim()}async function Ae(t){let{stdout:e}=await s(`git config ${t}`);return e.trim()}import{render as He}from"ink";import{Text as De,useApp as Se,useInput as Ee}from"ink";import{useState as qe}from"react";import{Fragment as Be,jsx as ke,jsxs as kt}from"react/jsx-runtime";function Bt({prompt:t,msg:e,onConfirm:o}){let[r,i]=qe(""),{exit:n}=Se();return Ee((a,m)=>{if(r)return;let f=a.toLowerCase();f==="y"?i("Yes"):(f==="n"||m.return)&&(i("No"),n())}),kt(Be,{children:[kt(De,{children:[t," [y/N] ",r]}),r==="Yes"&&ke(c,{msg:e,promise:o()})]})}import{jsx as We}from"react/jsx-runtime";async function Ht(){if(nt(),await h())return console.log("Already a clean working tree");let t=await W();if(!t)throw new Error("git status cmd failed");let e=new Y(t);e.displayReport(),He(We(Bt,{prompt:"Approve these changes?",msg:"Running git reset && git clean",onConfirm:async()=>(await s("git reset --hard"),await s("git clean -f"),`Altered ${e.willDelete.length+e.willRecreate.length+e.willRevert.length} files.`)}))}var Y=class{willDelete=[];willRecreate=[];willRevert=[];constructor(e){e.forEach(o=>{if(o){let r=o.slice(0,2).trim(),i=o.slice(3);r.includes("?")||r.includes("A")?this.willDelete.push(i):r==="DU"||r==="D"?this.willRecreate.push(i):this.willRevert.push(i)}}),this.willDelete.sort(),this.willRecreate.sort(),this.willRevert.sort()}displayReport(){this.displaySection("Will Recreate:",this.willRecreate),this.displaySection("Will Revert:",this.willRevert),this.displaySection("Will Delete:",this.willDelete)}displaySection(e,o){o.length&&console.log(`${e}
|
|
11
|
+
${o.map(r=>`- ${r}
|
|
12
|
+
`)}`)}};import{nanoid as Ge}from"nanoid";import{render as Fe}from"ink";import{jsx as Me}from"react/jsx-runtime";async function Wt(){await st();let t=process.argv[3]??"origin";d(t);let e=await u();at(e);let o="",i=(async()=>{let n=[s(`git fetch ${t} ${e} --force`)];await h()||n.push(C()),await Promise.all(n);let[a,m]=await Promise.all([k(t,e),B(t,e)]);if(!(a===0&&m===0)){if(a!==0){let f=`${e}-${Ge(8)}`;o=`Created branch ${f}`,await s(`git branch ${f}`)}await s(`git reset --hard ${t}/${e}`)}})();Fe(Me(c,{msg:`Force pull reseting ${e} -> ${t}`,promise:i})),await i,o&&console.info(o)}var Gt={abort:ot,amend:rt,autoprune:pt,backmerge:mt,churn:gt,coauthor:ut,"code-review":ht,conflict:wt,continue:dt,exclude:yt,files:bt,fixup:$t,include:xt,languages:Rt,pwd:Pt,rebranch:Dt,"remote-default":ft,savepoint:C,sha:St,track:Et,whoami:qt,wipe:Ht,yank:Wt};async function Ki(t){return await Gt[t]?.(),Object.hasOwn(Gt,t)}export{Ki as runCommand};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as S,b as v}from"./chunk-NWXSV6NP.js";import{b as T}from"./chunk-NAFT7YF6.js";import{a as y,c as b}from"./chunk-IX3J52I6.js";import{b as f}from"./chunk-HCUVDNFV.js";import{useEffect as A}from"react";import{Box as a,Text as x,useInput as E}from"ink";import{useEffect as C,useState as D}from"react";function L(t,o){let[r,c]=D(0),[u,l]=D(0);C(()=>{c(0),l(0)},[t]);let p=Math.max(0,t.length-o),h=t.length-1,m=()=>{l(i=>{let n=Math.min(i+1,h);return c(s=>n>=s+o?Math.min(s+1,p):s),n})},d=()=>{l(i=>{let n=Math.max(i-1,0);return c(s=>n<s?Math.max(s-1,0):s),n})},g=t.slice(r,r+o),w=t[u];return{scrollDown:m,scrollUp:d,outList:g,selectedIndex:u,selectedValue:w}}import M from"ink-spinner";import{Fragment as I,jsx as e,jsxs as B}from"react/jsx-runtime";async function K(){let{stdout:t}=await f("git log --oneline -n 30");return t.trim().split(/\r?\n/).map(W)}async function O(t){if(!t)return;let{stdout:o}=await f(`git show ${t} --name-only`);return o.trim()}function U(){let{height:t,width:o}=y(),r=t-5,{resolved:c,value:u=[]}=v(K),{scrollUp:l,scrollDown:p,outList:h,selectedValue:m}=L(u,r-2);E((i,n)=>{n.upArrow&&l(),n.downArrow&&p(),i==="c"&&f(`git checkout ${m.sha}`)});let{activeSection:d}=b(),{setKeybinding:g,removeKeybinding:w}=T();return A(()=>{if(d==="Log")return g("c","checkout"),()=>{w("c")}},[d]),e(I,{children:B(a,{width:o,children:[e(S,{overflowY:"hidden",height:r,title:"Log",width:"50%",children:c?e(I,{children:h.map(({sha:i,message:n})=>B(a,{flexDirection:"row",flexWrap:"nowrap",children:[e(a,{minWidth:2,children:i===m.sha?e(x,{children:"> "}):null}),e(a,{minWidth:8,children:e(x,{color:"yellow",children:i})}),e(a,{children:e(x,{wrap:"truncate-end",children:n})})]},i))}):e(M,{})}),e(V,{sha:m?.sha})]})})}function V({sha:t}){let{resolved:o,value:r}=v(()=>O(t),[t]);return e(S,{title:"Commit Details",width:"50%",height:"100%",children:t&&o?e(x,{children:r}):e(M,{})})}function W(t){let o=t.indexOf(" ");return{sha:t.slice(0,o),message:t.slice(o+1)}}export{U as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as s,b as p}from"./chunk-NAFT7YF6.js";import{a as m,b as f,c,d as u}from"./chunk-IX3J52I6.js";import{render as q}from"ink";import{lazy as d,useEffect as S}from"react";import{Text as A,Box as a,useInput as K}from"ink";import{jsx as t,jsxs as P}from"react/jsx-runtime";var L=d(()=>import("./status-UBYZMDYE.js")),N=d(()=>import("./log-4RIWY74K.js"));function v(){let{prevSection:g,nextSection:l,activeGroup:r,setActiveGroup:n}=c();K((e,o)=>{o.tab&&o.shift?g():o.tab?l():e.toLowerCase()==="q"?process.exit():e==="1"?n("Status"):e==="2"&&n("Log")});let x=m(),{keybindings:b,setKeybinding:y}=p();return S(()=>y("q","quit"),[]),P(a,{flexDirection:"column",...x,children:[t(u,{}),r==="Log"&&t(N,{}),r==="Status"&&t(L,{}),t(a,{flexDirection:"row",children:Object.entries(b).map(([e,o])=>t(A,{children:`[${e}]: ${o} `},o))})]})}import{jsx as i}from"react/jsx-runtime";function B(){return i(f,{children:i(s,{children:i(v,{})})})}var O=()=>q(i(B,{}),{patchConsole:!0});export{O as renderApp};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as t,b as e}from"./chunk-NWXSV6NP.js";import"./chunk-IX3J52I6.js";import{k as o}from"./chunk-7AM4AK3O.js";import"./chunk-HCUVDNFV.js";import{Text as s}from"ink";import{jsx as i}from"react/jsx-runtime";function u(){let{value:r,resolved:m}=e(o);return i(t,{flexDirection:"column",title:"Bisgit",width:"100%",children:m&&r?.map((l,n)=>i(s,{children:l},n))})}export{u as default};
|
package/dist/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as n}from"./chunks/chunk-5WTQIRZS.js";async function a(){let r=n();if(!r){let{renderApp:e}=await import("./chunks/
|
|
2
|
+
import{a as n}from"./chunks/chunk-5WTQIRZS.js";async function a(){let r=n();if(!r){let{renderApp:e}=await import("./chunks/pages-KZAY5E2R.js");return e()}let{runCommand:o}=await import("./chunks/commands-2D4LDHYD.js");if(await o(r))return;let{runWrapper:t}=await import("./chunks/wrapper-5X5SODCK.js");await t(r)||(console.error("unknown command"),process.exit(1))}a().catch(r=>{console.error(`An error occurred: ${r.stderr??r.message}`),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bisgit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Git CLI tool to simplify common advanced git workflows",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
"type": "module",
|
|
30
30
|
"scripts": {
|
|
31
31
|
"start": "node dist/main.js",
|
|
32
|
-
"dev": "node
|
|
32
|
+
"dev": "node --watch dist/main.js",
|
|
33
|
+
"gi": "npm run package && node dist/main.js",
|
|
33
34
|
"build": "node esbuild.mjs --watch",
|
|
34
35
|
"package": "rm -rf dist && node esbuild.mjs --production",
|
|
35
36
|
"profile": "npm-run-all -p profile:*",
|
|
36
37
|
"profile:size": "esbuild-visualizer --metadata ./profile/meta.json --filename ./profile/visualizer.html && open ./profile/visualizer.html",
|
|
37
38
|
"profile:lazy": "esbuild-lazy-analyzer --metafile ./profile/meta.json --outmeta ./profile/lazy.json --outreport ./profile/lazy.html && open ./profile/lazy.html",
|
|
38
|
-
"gi": "npm run package && node dist/main.js",
|
|
39
39
|
"lint": "eslint src",
|
|
40
40
|
"check-types": "tsc --noEmit",
|
|
41
41
|
"prepare": "husky"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/node": "^25.0.
|
|
45
|
-
"@types/react": "^19.2.
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
47
|
-
"@typescript-eslint/parser": "^8.
|
|
44
|
+
"@types/node": "^25.0.9",
|
|
45
|
+
"@types/react": "^19.2.8",
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
47
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
48
48
|
"esbuild": "^0.27.2",
|
|
49
49
|
"esbuild-lazy-analyzer": "^1.4.0",
|
|
50
50
|
"esbuild-visualizer": "^0.7.0",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"husky": "^9.1.7",
|
|
54
54
|
"lint-staged": "^16.2.7",
|
|
55
55
|
"npm-run-all": "^4.1.5",
|
|
56
|
-
"prettier": "^3.
|
|
56
|
+
"prettier": "^3.8.0",
|
|
57
|
+
"react-devtools-core": "^6.1.5"
|
|
57
58
|
},
|
|
58
59
|
"dependencies": {
|
|
59
60
|
"chalk": "^5.6.2",
|
|
@@ -61,7 +62,6 @@
|
|
|
61
62
|
"ink": "^6.6.0",
|
|
62
63
|
"ink-spinner": "^5.0.0",
|
|
63
64
|
"nanoid": "^5.1.6",
|
|
64
|
-
"react": "^19.2.3"
|
|
65
|
-
"react-devtools-core": "^6.1.5"
|
|
65
|
+
"react": "^19.2.3"
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{b as h,c as V}from"./chunk-5WTQIRZS.js";import{a as P,b as n,c as g,d as l}from"./chunk-HCUVDNFV.js";import A from"node:path";import{normalize as z}from"node:path";async function u(){let{stdout:t}=await n("git branch --show-current");return t.trim()}async function K(t){t??=await u();let{stdout:e}=await n(`git config --get branch.${t}.remote`);return e.trim()}async function B(t,e){try{let{stdout:r}=await n(`git rev-list --count ${t}/${e}..${e}`);return parseInt(r.trim(),10)}catch(r){return console.error("Error getting commits ahead:",r),NaN}}async function k(t,e){try{let{stdout:r}=await n(`git rev-list --count ${e}..${t}/${e}`);return parseInt(r.trim(),10)}catch(r){return console.error("Error getting commits behind:",r),NaN}}async function D(t){let{stdout:e}=await n(`git rev-parse --git-path ${t}`);return z(e.trim())}async function J(){let{stdout:t}=await n("git rev-parse --git-dir");return z(t.trim())}async function Z(t){let{code:e}=await g("git",["remote","get-url",t],{stdio:"ignore"});return e===0}async function Q(){let{stdout:t}=await n("git rev-parse --abbrev-ref HEAD");return t.trim()==="HEAD"}async function H(t,e){let r="git fetch";t&&(r+=` ${t}`),e&&(r+=` ${e}`),await n(r)}async function w(){let{stdout:t}=await g("git",["status","--porcelain"]);return!t?.trim()}async function G(){let{stdout:t}=await g("git",["status","--porcelain"]);return t?.trim()?.split(/\r?\n/)}async function $(t,e){let{stdout:r}=await n(`git merge-base ${t} ${e}`);return r.trim()}async function X(t,e){let r=await $(t,e),{stdout:o}=await g("git",["merge-tree",r,e,t]);return!o?.split(/\r?\n/)?.includes("+=======")}async function tt(t){let{stdout:e}=await n(`git rev-parse ${t}`);return e.trim()}async function N(t,e,r){let{stdout:o}=await n(`git rev-list ${r?"--reverse":""} ${t}..${e}`);return o.trim().split(/\r?\n/)}async function et(){let{stdout:t}=await n("git for-each-ref --format='%(refname:short)' refs/heads");return t.trim().split(/\r?\n/)}import Ft from"fs/promises";async function d(t){try{return await Ft.access(t),!0}catch{return!1}}async function rt(){let t=await G(),e=/^(UU|DU|UD)/;return!!t?.some(r=>e.test(r))}async function W(){let t=await J(),[e,r,o,i,s]=await Promise.all([await d(A.join(t,"MERGE_HEAD")),await d(A.join(t,"rebase-merge")),await d(A.join(t,"rebase-apply")),await d(A.join(t,"CHERRY_PICK_HEAD")),await d(A.join(t,"REVERT_HEAD"))]);return{merge:e,rebaseMerge:r,rebaseApply:o,cherryPick:i,revert:s}}async function ot(){let{merge:t,rebaseMerge:e,rebaseApply:r,cherryPick:o,revert:i}=await W(),s="";if(t)s="merge";else if(e||r)s="rebase";else if(o)s="cherry-pick";else if(i)s="revert";else{let a=await rt()?"Conflicts exist, but likely are from a stash and are not abortable. Resolve them manually.":"Nothing to abort.";console.log(a);return}console.log(`Aborting the ${s}`),await l([s,"--abort"])}function it(){P("git",["commit","--amend","--no-edit",...h()],{stdio:"inherit",silent:!0,triggerExit:!0})}import{render as Vt}from"ink";import{spawnSync as nt}from"node:child_process";function E(t,e,r){let{status:o}=nt(t,e,{stdio:"ignore"});o!==0&&(r&&console.error(r),process.exit(1))}var st=()=>E("git",["rev-parse","--git-dir"],"Need to use command in a git repository."),v=()=>E("git",["rev-parse","HEAD"],"Need to create first commit."),y=(t="origin")=>E("git",["remote","get-url",t],`Need to add remote '${t}'.`),U=t=>E("git",["show-ref","--branches",t],`Branch '${t}' isn't tracked locally and may not exist.`),R=async()=>{await w()||(console.error("You should stash or commit your changes first."),process.exit(1))},F=async t=>{await d(t)||(console.error(`${t} must exist for this operation and it doesn't for some reason`),process.exit(1))},at=async()=>{await Q()&&(console.error("Operation not allowed in a 'detached HEAD' state"),process.exit(1))},ct=t=>E("git",["rev-parse","--abbrev-ref","--symbolic-full-name",`${t}@{u}`],`branch '${t}' has no upstream`);function b(t="Error: missing required argument"){if(process.argv[3])return process.argv[3];console.error(t),process.exit(1)}async function M(){let{status:t}=nt("git",["diff","--staged","--quiet"],{stdio:"ignore"});t===0&&(console.error("You have no staged changes"),process.exit(1))}import{render as _t}from"ink";import{Suspense as Mt,use as Lt,useEffect as Tt}from"react";import{Text as mt,useApp as It}from"ink";import Ut from"ink-spinner";import{jsx as L,jsxs as jt}from"react/jsx-runtime";function c(t){let{msg:e}=t;return L(Mt,{fallback:jt(mt,{children:[L(Ut,{type:"dots"}),"\xA0",e]}),children:L(Ot,{...t})})}function Ot({msg:t,promise:e}){let r=Lt(e),{exit:o}=It();return Tt(()=>{o()},[r]),L(mt,{children:`\u2714 ${typeof r=="string"?r:t}`})}import{jsx as Yt}from"react/jsx-runtime";async function lt(){let t=process.argv[3],e=process.argv[4]??await u();if(U(t),U(e),t===e)return console.log(`No reason to merge '${t}' into '${e}'`);let r=await K(t);y(r),_t(Yt(c,{msg:"Updating target branch and merging",promise:(async()=>{try{await S(r,t)}catch{console.error(`Error when updating branch ${t} with remote ${r}. Fix divergent branches before merging into ${e}`);return}await u()!==e&&await n(`git switch ${e}`),P("git",["merge",t],{stdio:"inherit",silent:!0})})()}))}async function S(t,e){await H(t,e);let[r,o,i]=await Promise.all([B(t,e),k(t,e),u()]);if(o!==0){if(r===0&&i!==e){await n(`git fetch ${t} ${e}:${e}`);return}if(await n(`git switch ${e}`),r===0){await n(`git merge ${t}/${e}`);return}await l(["merge",`${t}/${e}`],["ignore","ignore","inherit"])}}async function q(){v(),y();let{stdout:t,code:e}=await g("git",["rev-parse","--abbrev-ref","origin/HEAD"]);if(e===0)return ft(t.trim());await n("git remote set-head origin -a");let{stdout:r}=await n("git rev-parse --abbrev-ref origin/HEAD");return ft(r.trim())}async function pt(){let{remote:t,branch:e}=await q();console.log(`Remote default branch is '${t}/${e}'`)}async function ft(t){let e=t.split("/"),r=t.split("/").map((o,i)=>e.slice(0,i+1).join("/"));for(let o of r)if(await Z(o)){let i=t.slice(o.length+1);return{remote:o,branch:i}}throw new Error("Failed to get default remote")}import{jsx as Kt}from"react/jsx-runtime";var zt=["master","main","development","lingoport"];async function gt(){await R();let{branch:t,remote:e}=await q();await n(`git switch ${t}`);let r=(async()=>{await l(["fetch","--prune","--prune-tags"]),await S(e,t)})();Vt(Kt(c,{msg:"Fetching and pruning remote references",promise:r})),await r;let o=await et();for(let i of o){if(i===t||zt.includes(i))continue;let s=await $(i,t),{code:a}=await g("git",["diff","--quiet",s,i]);a===0&&await l(["branch","-D",i])}}import{spawn as Jt}from"node:child_process";import{createInterface as Zt}from"node:readline/promises";async function ut(){v;let e=[...(await Qt()).entries()].sort(([,o],[,i])=>i-o).slice(0,25),r=e[0][1].toString().length;console.info(e.map(([o,i])=>`${String(i).padEnd(r)} ${o}:`).join(`
|
|
3
|
-
`))}async function Qt(){let{promise:t,resolve:e,reject:r}=Promise.withResolvers(),o=new Map,i=Jt("git",["log","--all","-M","-C","--name-only","--format=format:"]),s=Zt({input:i.stdout,crlfDelay:1/0});return s.on("line",a=>{let m=a.trim();m&&o.set(m,(o.get(m)??0)+1)}),s.on("close",()=>e(o)),i.on("error",r),t}import{render as Xt}from"ink";import{jsx as ee}from"react/jsx-runtime";async function ht(){await M();let t=b("Error: missing github username argument"),e=(async()=>{let i=await te(t);return i.email||(console.error(`Couldn't find an email for ${t}`),process.exit(1)),i})();Xt(ee(c,{msg:"Fetching name and email",promise:e}));let{name:r,email:o}=await e;l(["commit","--edit","-m","<insert summary>","-m",`Co-authored-by: ${r} <${o}>`])}async function te(t){let{stdout:e}=await n(`gh api users/${t}`);return JSON.parse(e.trim())}import{render as O}from"ink";import{isDeepStrictEqual as re}from"node:util";import{jsx as j}from"react/jsx-runtime";async function wt(){let t=b("Error: missing id of PR to checkout");await R();let e=(async()=>Promise.all([n(`gh co ${t}`),n(`gh pr view ${t} --json baseRefName -q .baseRefName`)]))();O(j(c,{msg:`Checking out pr #${t}`,promise:e}));let[,{stdout:r}]=await e,o=r.trim(),i=(async()=>{await n(`git switch ${o}`),await n("git pull"),await n("git switch -")})();O(j(c,{msg:`Updating ${o} branch merge destination`,promise:i})),await i;let s=(async()=>{let p=await $(o,"HEAD");return await n(`git reset ${p} --soft`),await oe("HEAD")})();O(j(c,{msg:"Creating an editable, explorable, local PR experience",promise:s}));let[a,m]=await Promise.all([s,ie(t)]),{files:f,additions:x,deletions:I}=m;if(re(a,m))return console.info(`Files: ${f}, +${x} -${I}`);console.info("The PR stat doesn't match the local stat."),console.info("LOCAL"),console.table(a),console.info("GITHUB"),console.table(m),console.info("One option to fix (there'll likely be conflicts):"),console.info("1. git stash -u"),console.info(`2. git merge ${o}`),console.info("3. git stash pop")}async function oe(t){let{stdout:e}=await n(`git diff --shortstat ${t}`),r=/(\d+)\s+files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/,o=e.trim().match(r);if(!o)throw new Error(`Couldn't generate short stat for ref(s): ${t}`);let[,i,s,a]=o;return{files:parseInt(i,10),additions:s?parseInt(s,10):0,deletions:a?parseInt(a,10):0}}async function ie(t){let{stdout:e}=await n(`gh pr view ${t} --json deletions,files,additions`),r=JSON.parse(e.trim());return r.files=r.files.length,r}import{spawn as ne}from"node:child_process";import{createInterface as se}from"node:readline/promises";import _ from"chalk";async function dt(){let t=b("Error: missing target branch argument"),e=await $("HEAD",t),{promise:r,resolve:o,reject:i}=Promise.withResolvers(),s=ne("git",["merge-tree",e,"HEAD",t]),a=se({input:s.stdout,crlfDelay:1/0}),m=!1,f=0;a.on("line",p=>{p=p.trimEnd(),p==="+<<<<<<< .our"?(m=!0,console.info(_.red(p)),f+=1):p==="+>>>>>>> .their"?(m=!1,console.info(_.green(p))):p==="+======="?console.info(_.yellow(p)):m&&console.info(p)}),a.on("close",()=>o(f)),s.on("error",i);let x=await r,I=x?`\u274C ${x} conflicts would occur!`:"\u2705 No conflicts. Safe to merge.";console.info(I)}async function yt(){let{merge:t,rebaseMerge:e,rebaseApply:r,cherryPick:o,revert:i}=await W(),s="";if(t)s="merge";else if(e||r)s="rebase";else if(o)s="cherry-pick";else if(i)s="revert";else{console.log("Nothing to continue.");return}console.log(`Continuing the ${s}`),await l([s,"--continue"])}import{appendFileSync as ce}from"node:fs";import{readFile as ae}from"node:fs/promises";async function T(t){return(await ae(t,"utf-8")).split(/\r?\n/).map(r=>r.trim()).filter(r=>r&&!r.startsWith("#"))}async function bt(){let t=await D("info/exclude");await F(t);let e=await T(t);h().forEach(r=>{e.includes(r)?console.info(`Already Exists: '${r}'`):(ce(t,`${r}
|
|
4
|
-
`),console.info(`Added '${r}'`))}),console.info(`
|
|
5
|
-
See file at ${t}`)}function $t(){P("git",["show","--name-only","--pretty=format:",...h()],{stdio:"inherit",silent:!0,triggerExit:!0})}import{spawn as me}from"node:child_process";async function xt(){let t=b("Error: missing valid target ref argument");await M();let e=await tt(t);await l(["commit",`--fixup=${e}`]);let o=(await N(`${e}^`,"HEAD",!0)).map(s=>le(s));(await Promise.all(o)).every(Boolean)||(console.warn("Rebase conflict would occur!"),await n("git reset HEAD~1 --soft"),process.exit(1)),await n(`git rebase -i --autosquash ${e}^`)}async function le(t){let{stdout:e}=await n(`git diff ${t}^ ${t}`),{promise:r,resolve:o,reject:i}=Promise.withResolvers(),s=me("git",["apply","--check","--3way","-q"],{stdio:["pipe","ignore","ignore"]});return s.on("close",a=>{o(a===0)}),s.on("error",i),s.stdin.write(e),s.stdin.end(),r}import{readFile as fe,writeFile as pe}from"node:fs/promises";async function Pt(){let t=await D("info/exclude");await F(t);let e=await T(t),r=h();r.filter(a=>!e.includes(a)).forEach(a=>console.info(`No match: '${a}'`));let i=(await fe(t,"utf-8")).split(/\r?\n/).map(a=>a.trim()),s=i.filter(a=>!r.includes(a));await pe(t,s.join(`
|
|
6
|
-
`)),console.info(`
|
|
7
|
-
Removed ${i.length-s.length} entries from ${t}`)}import{render as ge}from"ink";import{jsx as de}from"react/jsx-runtime";async function vt(){let t=(async()=>{let i=await ue();return await he(i)})();ge(de(c,{msg:"Fetching repo languages",promise:t}));let e=await t,r=Object.values(e).reduce((i,s)=>i+s,0),o=Object.entries(e).map(([i,s])=>`${i}: ${Math.round(s/r*100)}% - ${we(s)}`);console.log(o.join(`
|
|
8
|
-
`))}async function ue(){let{stdout:t}=await n("gh repo view --json nameWithOwner -q .nameWithOwner");return t.trim()}async function he(t){let{stdout:e}=await n(`gh api repos/${t}/languages`);return JSON.parse(e.trim())}function we(t,e=2){if(t===0)return"0 B";let r=1024,o=e<0?0:e,i=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],s=Math.floor(Math.log(t)/Math.log(r));return`${parseFloat((t/Math.pow(r,s)).toFixed(o))} ${i[s]}`}import{execSync as ye}from"node:child_process";function be(){return ye("git rev-parse --show-toplevel",{encoding:"utf-8"}).trim()}function Rt(){let t=be();console.log(t)}import{render as Dt}from"ink";function Ct(){return new Date().toLocaleString("en-US",{year:"2-digit",month:"2-digit",day:"2-digit",hour:"numeric",minute:"2-digit",hour12:!0}).replace(",","")}async function C(){let t=Ct();await n("git add -A"),await l(["commit","-m",`"WIP ${t}"`])}import{nanoid as $e}from"nanoid";import xe from"chalk";import{jsx as At}from"react/jsx-runtime";async function Et(){let{remote:t,branch:e}=await q(),r=process.argv[3]??e;await w()||await C(),await X(r,"HEAD")||(console.warn("Conflicts would occur. Not safe to rebranch."),process.exit(1));let o=await u(),i=(async()=>{await S(t,r)})();Dt(At(c,{msg:`Updating branch ${r}`,promise:i})),await i;let s=`${$e(8)}`,a=(async()=>{await n(`git switch ${o}`),await n(`git branch ${s}`),await n(`git switch ${r}`),await n(`git branch -D ${o}`),await n(`git switch -c ${o}`);let m=await N(r,s,!0);for(let f of m)try{await n(`git cherry-pick ${f}`)}catch{let x=xe.yellow(`git branch -D ${o} && git branch -m ${s} ${o}`);throw new Error(`\u274C cherry pick failed at ${f}
|
|
9
|
-
Run this to restore backup branch
|
|
10
|
-
> ${x}`)}await n(`git branch -D ${s}`)})();Dt(At(c,{msg:`Rewriting branch ${o}`,promise:a})),await a,console.info(`Successfully recreated branch ${o} from ${r}`)}import{execSync as Pe}from"node:child_process";async function St(){v();let t=ve(process.argv[3]),{default:e}=await import("clipboardy");await e.write(t),console.log(`'${t}' copied to clipboard`)}function ve(t="HEAD"){return Pe(`git rev-parse --short ${t}`,{encoding:"utf-8"}).trim()}import{render as Re}from"ink";import{jsx as Ce}from"react/jsx-runtime";async function qt(){let{remote:t,branch:e}=await V();y(t),await R();let r=H(t,e);Re(Ce(c,{msg:`Fetching branch ${e} from ${t}`,promise:r})),await r,await l(["switch","-c",e,"--track",`${t}/${e}`])}async function Bt(){let[t,e]=await Promise.allSettled([await Ae("user.name"),await De()]);t.status==="fulfilled"&&console.info(`Git: ${t.value}`),e.status==="fulfilled"&&console.info(`Github: ${e.value}`)}async function De(){let{stdout:t}=await n("gh api user --jq .login");return t.trim()}async function Ae(t){let{stdout:e}=await n(`git config ${t}`);return e.trim()}import{render as Ge}from"ink";import{Text as Ee,useApp as Se,useInput as qe}from"ink";import{useState as Be}from"react";import{Fragment as He,jsx as ke,jsxs as kt}from"react/jsx-runtime";function Ht({prompt:t,msg:e,onConfirm:r}){let[o,i]=Be(""),{exit:s}=Se();return qe((a,m)=>{if(o)return;let f=a.toLowerCase();f==="y"?i("Yes"):(f==="n"||m.return)&&(i("No"),s())}),kt(He,{children:[kt(Ee,{children:[t," [y/N] ",o]}),o==="Yes"&&ke(c,{msg:e,promise:r()})]})}import{jsx as Ne}from"react/jsx-runtime";async function Gt(){if(st(),await w())return console.log("Already a clean working tree");let t=await G();if(!t)throw new Error("git status cmd failed");let e=new Y(t);e.displayReport(),Ge(Ne(Ht,{prompt:"Approve these changes?",msg:"Running git reset && git clean",onConfirm:async()=>(await n("git reset --hard"),await n("git clean -f"),`Altered ${e.willDelete.length+e.willRecreate.length+e.willRevert.length} files.`)}))}var Y=class{willDelete=[];willRecreate=[];willRevert=[];constructor(e){e.forEach(r=>{if(r){let o=r.slice(0,2).trim(),i=r.slice(3);o.includes("?")||o.includes("A")?this.willDelete.push(i):o==="DU"||o==="D"?this.willRecreate.push(i):this.willRevert.push(i)}}),this.willDelete.sort(),this.willRecreate.sort(),this.willRevert.sort()}displayReport(){this.displaySection("Will Recreate:",this.willRecreate),this.displaySection("Will Revert:",this.willRevert),this.displaySection("Will Delete:",this.willDelete)}displaySection(e,r){r.length&&console.log(`${e}
|
|
11
|
-
${r.map(o=>`- ${o}
|
|
12
|
-
`)}`)}};import{nanoid as We}from"nanoid";import{render as Fe}from"ink";import{jsx as Me}from"react/jsx-runtime";async function Nt(){await at();let t=process.argv[3]??"origin";y(t);let e=await u();ct(e);let r="",i=(async()=>{let s=[n(`git fetch ${t} ${e} --force`)];await w()||s.push(C()),await Promise.all(s);let[a,m]=await Promise.all([B(t,e),k(t,e)]);if(!(a===0&&m===0)){if(a!==0){let f=`${e}-${We(8)}`;r=`Created branch ${f}`,await n(`git branch ${f}`)}await n(`git reset --hard ${t}/${e}`)}})();Fe(Me(c,{msg:`Force pull reseting ${e} -> ${t}`,promise:i})),await i,r&&console.info(r)}var Wt={abort:ot,amend:it,autoprune:gt,backmerge:lt,churn:ut,coauthor:ht,"code-review":wt,conflict:dt,continue:yt,exclude:bt,files:$t,fixup:xt,include:Pt,languages:vt,pwd:Rt,rebranch:Et,"remote-default":pt,savepoint:C,sha:St,track:qt,whoami:Bt,wipe:Gt,yank:Nt};async function Zi(t){return await Wt[t]?.(),Object.hasOwn(Wt,t)}export{Zi as runCommand};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{useState as x}from"react";import{Text as e,Box as c,useInput as p,render as i}from"ink";import{jsx as t,jsxs as n}from"react/jsx-runtime";var f=()=>{let[o,s]=x(0);return p((r,m)=>{r==="q"&&process.exit(),r==="+"&&s(o+1),r==="-"&&s(o-1)}),n(c,{flexDirection:"column",children:[t(e,{children:"\u{1F44B} Welcome to the Demo Ink App!"}),t(e,{children:"---------------------------------"}),n(e,{children:["Count: ",o]}),t(e,{children:'Press "+" to increase, "-" to decrease'}),t(e,{children:'Press "q" to quit'})]})},d=()=>i(t(f,{}));export{d as renderApp};
|