megit-app 0.4.1 → 0.5.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/CHANGELOG.md +40 -1
- package/dist/assets/ConflictView-DGLXjOa1.js +1 -0
- package/dist/assets/{DiffView-BKo75iUG.js → DiffView-DHHWx0R5.js} +21 -21
- package/dist/assets/TerminalPanel-DtRWBLUl.js +20 -0
- package/dist/assets/index-Bfrt9LxG.js +251 -0
- package/dist/assets/index-C845Od_q.css +1 -0
- package/dist/index.html +2 -2
- package/dist-server/index.js +131 -5
- package/dist-server/operation.js +16 -0
- package/package.json +6 -6
- package/dist/assets/TerminalPanel-uV6s4v6R.js +0 -37
- package/dist/assets/index-DPM0na5E.css +0 -1
- package/dist/assets/index-o0rujUbV.js +0 -249
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,42 @@ surface, and the HTTP API may change in any minor release.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.5.0] - 2026-08-08
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Merge conflicts can be resolved inside megit. A merge, rebase, cherry-pick or revert that
|
|
17
|
+
stops on a conflict now shows a banner above the graph naming the operation and the number of
|
|
18
|
+
conflicts left, with Abort (confirmed first) and Continue (enabled once nothing is unmerged).
|
|
19
|
+
Conflicted files get their own "Merge Changes" section in the commit panel — no Stage and no
|
|
20
|
+
Discard, because staging a file that still holds `<<<<<<<` commits the markers — and opening
|
|
21
|
+
one replaces the diff with a picker: every conflict block renders ours above theirs with Use
|
|
22
|
+
ours / Use theirs / Use both / Reset. Deciding the last block writes the file and stages it.
|
|
23
|
+
Files with nothing to pick — binary, delete/modify, submodule — get Keep ours / Keep theirs /
|
|
24
|
+
Delete instead, and a file fixed by hand in the terminal can be accepted with Mark resolved.
|
|
25
|
+
Picks are held in the client and written only on full resolution, so Reset costs nothing and
|
|
26
|
+
the watcher stays quiet. Stash-pop conflicts get the picker but no banner: git leaves no state
|
|
27
|
+
file to detect and has no `--continue`.
|
|
28
|
+
- A Rendered/Source toggle on `.svg` diffs. SVG is text rendered as a picture, which hides
|
|
29
|
+
exactly the edits worth reviewing — a changed `viewBox`, a renamed `id`, a `stroke-width`
|
|
30
|
+
tweak below visual threshold. Source mode shows the real patch with Unified/Split; the choice
|
|
31
|
+
is sticky across files and reloads. Raster images are deliberately excluded — their source
|
|
32
|
+
diff is `Binary files … differ`, a control that leads nowhere.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- The add-repo dialog is now two panes: recent repositories on the left, the current
|
|
37
|
+
directory's path header and folder list on the right. Recent entries show just the
|
|
38
|
+
repository name with a dot when it is already open and a highlight on the active one; folder
|
|
39
|
+
rows carry a chevron, and the path header bolds the directory you are in.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- "Stage all" and "Discard all" no longer touch unmerged paths. `git add -A` swept conflicted
|
|
44
|
+
files — markers and all — into the index, and `git restore --worktree -- .` failed outright on
|
|
45
|
+
paths with no stage-0 entry to restore from, taking the whole batch with it. Both now exclude
|
|
46
|
+
every unmerged path by pathspec.
|
|
47
|
+
|
|
12
48
|
## [0.4.1] - 2026-08-05
|
|
13
49
|
|
|
14
50
|
### Fixed
|
|
@@ -132,7 +168,10 @@ First public release.
|
|
|
132
168
|
- Windows (arm64, x64): builds and runs, but untested on real hardware — recursive `fs.watch` crashes the test worker there, so auto-refresh is not covered by CI
|
|
133
169
|
- Linux: everything except the terminal — `node-pty` is an `optionalDependency` with no Linux prebuild, and the terminal button is hidden when it is unavailable
|
|
134
170
|
|
|
135
|
-
[Unreleased]: https://github.com/vuongvu1/megit/compare/v0.
|
|
171
|
+
[Unreleased]: https://github.com/vuongvu1/megit/compare/v0.5.0...HEAD
|
|
172
|
+
[0.5.0]: https://github.com/vuongvu1/megit/compare/v0.4.1...v0.5.0
|
|
173
|
+
[0.4.1]: https://github.com/vuongvu1/megit/compare/v0.4.0...v0.4.1
|
|
174
|
+
[0.4.0]: https://github.com/vuongvu1/megit/compare/v0.3.0...v0.4.0
|
|
136
175
|
[0.3.0]: https://github.com/vuongvu1/megit/compare/v0.2.0...v0.3.0
|
|
137
176
|
[0.2.0]: https://github.com/vuongvu1/megit/compare/v0.1.0...v0.2.0
|
|
138
177
|
[0.1.0]: https://github.com/vuongvu1/megit/releases/tag/v0.1.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,i as t,n,r}from"./index-Bfrt9LxG.js";var i=e(),a=/^<<<<<<< ?(.*)$/,o=/^\|\|\|\|\|\|\| ?(.*)$/,s=/^=======$/,c=/^>>>>>>> ?(.*)$/,l=e=>e.replace(/\r?\n$/,``);function u(e){let t=e.split(/(?<=\n)/),n=[],r=[],i=null,u=`context`,d=()=>{r.length&&n.push({kind:`context`,lines:r}),r=[]};for(let e of t){let t=l(e),f=a.exec(t);if(f){if(u!==`context`)return null;d(),i={ours:[],base:null,theirs:[],oursLabel:f[1].trim(),theirsLabel:``},u=`ours`;continue}if(u===`context`){r.push(e);continue}if(o.exec(t)){if(u!==`ours`)return null;i.base=[],u=`base`;continue}if(s.test(t)){if(u!==`ours`&&u!==`base`)return null;u=`theirs`;continue}let p=c.exec(t);if(p){if(u!==`theirs`)return null;i.theirsLabel=p[1].trim(),n.push({kind:`conflict`,block:i}),i=null,u=`context`;continue}u===`ours`?i.ours.push(e):u===`base`?i.base.push(e):i.theirs.push(e)}return u===`context`?(d(),n.some(e=>e.kind===`conflict`)?n:null):null}function d(e,t){let n=[];return e.forEach((e,r)=>{if(e.kind===`context`){n.push(...e.lines);return}let i=t.get(r);if(!i)throw Error(`no pick for conflict at segment ${r}`);(i===`ours`||i===`both`)&&n.push(...e.block.ours),(i===`theirs`||i===`both`)&&n.push(...e.block.theirs)}),n.join(``)}var f=n(),p=[[`ours`,`Use ours`],[`theirs`,`Use theirs`],[`both`,`Use both`]];function m({note:e,busy:t,onPick:n,onMarkResolved:r}){return(0,f.jsxs)(`div`,{className:`cf-card`,children:[(0,f.jsx)(`div`,{className:`cf-card-note`,children:e}),(0,f.jsxs)(`div`,{className:`cf-card-actions`,children:[r&&(0,f.jsx)(`button`,{className:`primary`,disabled:t,onClick:r,children:`Mark resolved`}),(0,f.jsx)(`button`,{disabled:t,onClick:()=>n(`ours`),children:`Keep ours`}),(0,f.jsx)(`button`,{disabled:t,onClick:()=>n(`theirs`),children:`Keep theirs`}),(0,f.jsx)(`button`,{className:`danger`,disabled:t,onClick:()=>n(`delete`),children:`Delete file`})]})]})}function h({repo:e,file:n,onResolved:a}){let[o,s]=(0,i.useState)(null),[c,l]=(0,i.useState)(new Map),[h,g]=(0,i.useState)(``),[_,v]=(0,i.useState)(!1),y=`repo=${encodeURIComponent(e)}`;(0,i.useEffect)(()=>{s(null),l(new Map),g(``),r(`/api/conflict?${y}&file=${encodeURIComponent(n)}`).then(s).catch(e=>g(e.message))},[e,n]);let b=(0,i.useMemo)(()=>o?.content?u(o.content):null,[o]),x=(0,i.useMemo)(()=>b?.filter(e=>e.kind===`conflict`).length??0,[b]);(0,i.useEffect)(()=>{!b||!x||c.size<x||(v(!0),r(`/api/conflict?${y}`,t(`POST`,{action:`resolve`,file:n,content:d(b,c)})).then(a).catch(e=>{g(e.message),v(!1)}))},[c,b,x]);let S=e=>{v(!0),r(`/api/conflict?${y}`,t(`POST`,{action:e,file:n})).then(a).catch(e=>{g(e.message),v(!1)})},C=()=>{v(!0),r(`/api/conflict?${y}`,t(`POST`,{action:`resolve`,file:n,content:o?.content??``})).then(a).catch(e=>{g(e.message),v(!1)})},w=(e,t)=>l(n=>new Map(n).set(e,t)),T=e=>l(t=>{let n=new Map(t);return n.delete(e),n});return h?(0,f.jsx)(`div`,{className:`diffview error`,children:h}):o?o.tooLarge?(0,f.jsxs)(`div`,{className:`diffview empty`,children:[`File too large to resolve here (`,Math.round((o.size??0)/1024),` KB) — use the terminal`]}):o.binary?(0,f.jsx)(`div`,{className:`cf-view`,children:(0,f.jsx)(m,{note:`Binary file — there is nothing to merge line by line.`,busy:_,onPick:S})}):o.missing?(0,f.jsx)(`div`,{className:`cf-view`,children:(0,f.jsx)(m,{note:`Deleted on one side and modified on the other.`,busy:_,onPick:S})}):b?(0,f.jsxs)(`div`,{className:`cf-view`,children:[(0,f.jsxs)(`div`,{className:`cf-progress`,children:[c.size,` of `,x,` resolved`]}),b.map((e,t)=>{if(e.kind===`context`)return(0,f.jsx)(`pre`,{className:`cf-context`,children:e.lines.join(``)},t);let n=c.get(t);return(0,f.jsxs)(`div`,{className:`cf-block${n?` picked`:``}`,children:[(0,f.jsxs)(`div`,{className:`cf-bar`,children:[(0,f.jsx)(`span`,{className:`cf-side-name`,children:e.block.oursLabel||`ours`}),n?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`span`,{className:`cf-chosen`,children:[`took `,n]}),(0,f.jsx)(`button`,{disabled:_,onClick:()=>T(t),children:`Reset`})]}):p.map(([e,n])=>(0,f.jsx)(`button`,{disabled:_,onClick:()=>w(t,e),children:n},e))]}),(!n||n===`ours`||n===`both`)&&(0,f.jsx)(`pre`,{className:`cf-ours`,children:e.block.ours.join(``)}),!n&&(0,f.jsx)(`div`,{className:`cf-mid`,children:e.block.theirsLabel||`theirs`}),(!n||n===`theirs`||n===`both`)&&(0,f.jsx)(`pre`,{className:`cf-theirs`,children:e.block.theirs.join(``)})]},t)})]}):(0,f.jsx)(`div`,{className:`cf-view`,children:(0,f.jsx)(m,{note:`No conflict markers left in this file — it looks already resolved.`,busy:_,onPick:S,onMarkResolved:C})}):(0,f.jsx)(`div`,{className:`diffview empty`,children:`Loading…`})}export{h as default};
|