@caozeal/dsh-next-git 0.1.7 → 0.1.8
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 +1 -1
- package/lib/client.js +29 -8
- package/package.json +1 -1
- package/src/operations.js +51 -0
package/README.md
CHANGED
package/lib/client.js
CHANGED
|
@@ -115,6 +115,10 @@ window.__ModuleLoader__.load({
|
|
|
115
115
|
'diff.deletions': '-{n}',
|
|
116
116
|
'diff.staged': '暂存区',
|
|
117
117
|
'diff.worktree': '工作区',
|
|
118
|
+
'diff.conflict': '冲突差异 · 当前分支 ↔ 合入分支',
|
|
119
|
+
'diff.conflictSame': '两边内容完全一致',
|
|
120
|
+
'diff.conflictDeleted': '该文件在合并的某一侧被删除',
|
|
121
|
+
'diff.conflictDeletedHint': '点右上角「解决冲突」决定保留还是删除',
|
|
118
122
|
'diff.commit': '提交 {hash}',
|
|
119
123
|
'diff.untracked': '新文件',
|
|
120
124
|
'status.loading': '加载中…',
|
|
@@ -272,6 +276,10 @@ window.__ModuleLoader__.load({
|
|
|
272
276
|
'diff.deletions': '-{n}',
|
|
273
277
|
'diff.staged': 'Staged',
|
|
274
278
|
'diff.worktree': 'Working tree',
|
|
279
|
+
'diff.conflict': 'Conflict · ours ↔ theirs',
|
|
280
|
+
'diff.conflictSame': 'Both sides are identical',
|
|
281
|
+
'diff.conflictDeleted': 'The file was deleted on one side of the merge',
|
|
282
|
+
'diff.conflictDeletedHint': 'Use "Resolve conflict" to keep or delete it',
|
|
275
283
|
'diff.commit': 'Commit {hash}',
|
|
276
284
|
'diff.untracked': 'New file',
|
|
277
285
|
'status.loading': 'Loading…',
|
|
@@ -1960,9 +1968,11 @@ window.__ModuleLoader__.load({
|
|
|
1960
1968
|
var diff = state.diff
|
|
1961
1969
|
if (state.diffLoading) return h(EmptyState, { spinner: true, title: tr('status.loading') })
|
|
1962
1970
|
if (!diff) return h(EmptyState, { title: tr('diff.empty') })
|
|
1963
|
-
var title = diff.
|
|
1964
|
-
? tr('diff.
|
|
1965
|
-
: diff.mode === '
|
|
1971
|
+
var title = diff.conflict
|
|
1972
|
+
? tr('diff.conflict')
|
|
1973
|
+
: diff.mode === 'commit'
|
|
1974
|
+
? tr('diff.commit', { hash: state.selected && state.selected.hash ? state.selected.hash.slice(0, 8) : '' })
|
|
1975
|
+
: diff.mode === 'staged' ? tr('diff.staged') : diff.mode === 'untracked' ? tr('diff.untracked') : tr('diff.worktree')
|
|
1966
1976
|
return h('div', { className: 'gm-scroll' },
|
|
1967
1977
|
h('div', { className: 'gm-content-inner gm-diff' },
|
|
1968
1978
|
h('div', { className: 'gm-diff-head' },
|
|
@@ -1971,11 +1981,22 @@ window.__ModuleLoader__.load({
|
|
|
1971
1981
|
h('span', { className: 'gm-spacer' }),
|
|
1972
1982
|
h('span', { className: 'gm-badge ok' }, '+' + diff.additions),
|
|
1973
1983
|
h('span', { className: 'gm-badge err' }, '-' + diff.deletions),
|
|
1974
|
-
diff.truncated ? h('span', { className: 'gm-badge warn' }, tr('diff.truncatedShort')) : null
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1984
|
+
diff.truncated ? h('span', { className: 'gm-badge warn' }, tr('diff.truncatedShort')) : null,
|
|
1985
|
+
diff.conflict
|
|
1986
|
+
? h(Btn, {
|
|
1987
|
+
label: tr('conflict.resolve'),
|
|
1988
|
+
icon: 'ai',
|
|
1989
|
+
small: true,
|
|
1990
|
+
variant: 'primary',
|
|
1991
|
+
onClick: function () { props.actions.openResolution({ path: diff.path }) },
|
|
1992
|
+
})
|
|
1993
|
+
: null),
|
|
1994
|
+
diff.conflict && (!diff.oursExists || !diff.theirsExists)
|
|
1995
|
+
? h(EmptyState, { title: tr('diff.conflictDeleted'), hint: tr('diff.conflictDeletedHint') })
|
|
1996
|
+
: diff.binary
|
|
1997
|
+
? h(EmptyState, { title: tr('diff.binary') })
|
|
1998
|
+
: diff.hunks.length === 0
|
|
1999
|
+
? h(EmptyState, { title: diff.conflict ? tr('diff.conflictSame') : tr('diff.noText') })
|
|
1979
2000
|
: diff.hunks.map(function (hunk, hunkIndex) {
|
|
1980
2001
|
return h('div', { key: 'h:' + hunkIndex },
|
|
1981
2002
|
h('div', { className: 'gm-hunk' }, hunk.header),
|
package/package.json
CHANGED
package/src/operations.js
CHANGED
|
@@ -289,6 +289,14 @@ export function createOperations(deps) {
|
|
|
289
289
|
}
|
|
290
290
|
const path = typeof params.path === 'string' && params.path !== '' ? params.path : ''
|
|
291
291
|
const safePath = path !== '' && path.startsWith('-') ? `./${path}` : path
|
|
292
|
+
// 未合并的文件不能走普通 git diff:它给的是 combined diff(diff --cc / @@@ / ++ 前缀),
|
|
293
|
+
// 不是 unified diff,解析器读不出 hunk,面板会是空的。改成 diff 两个 stage 的 blob。
|
|
294
|
+
if (mode === 'worktree' && safePath !== '') {
|
|
295
|
+
const stages = await conflictStages(root, safePath, signal)
|
|
296
|
+
if (Object.keys(stages).length > 0) {
|
|
297
|
+
return await conflictDiff(root, safePath, stages, signal)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
292
300
|
/** @type {string[]} */
|
|
293
301
|
let args
|
|
294
302
|
if (mode === 'worktree') {
|
|
@@ -594,6 +602,49 @@ export function createOperations(deps) {
|
|
|
594
602
|
return res.code === 0 ? res.stdout : null
|
|
595
603
|
}
|
|
596
604
|
|
|
605
|
+
/**
|
|
606
|
+
* 冲突文件的差异视图:当前分支(:2:)↔ 合入分支(:3:)。
|
|
607
|
+
* 直接 `git diff <blob> <blob>` 是合法的,拿到的是普通 unified diff,行级高亮照样能用。
|
|
608
|
+
* 某一侧没有这个文件(删除/改名冲突)时没有可比的两份内容,只回元数据让面板说明情况。
|
|
609
|
+
*/
|
|
610
|
+
async function conflictDiff(root, path, stages, signal) {
|
|
611
|
+
const oursHash = stages[2]
|
|
612
|
+
const theirsHash = stages[3]
|
|
613
|
+
const base = {
|
|
614
|
+
mode: 'conflict',
|
|
615
|
+
path,
|
|
616
|
+
conflict: true,
|
|
617
|
+
oursExists: Boolean(oursHash),
|
|
618
|
+
theirsExists: Boolean(theirsHash),
|
|
619
|
+
binary: false,
|
|
620
|
+
additions: 0,
|
|
621
|
+
deletions: 0,
|
|
622
|
+
hunks: [],
|
|
623
|
+
truncated: false,
|
|
624
|
+
raw: '',
|
|
625
|
+
}
|
|
626
|
+
if (!oursHash || !theirsHash) return base
|
|
627
|
+
const args = ['diff', '--no-color', oursHash, theirsHash]
|
|
628
|
+
const result = await runGit(args, { cwd: root, signal, allowFailure: true })
|
|
629
|
+
if (result.code !== 0 && result.code !== 1) throw gitFailure(['git', ...args], result)
|
|
630
|
+
let raw = result.stdout
|
|
631
|
+
let truncated = false
|
|
632
|
+
if (raw.length > DIFF_MAX_CHARS) {
|
|
633
|
+
raw = raw.slice(0, DIFF_MAX_CHARS)
|
|
634
|
+
truncated = true
|
|
635
|
+
}
|
|
636
|
+
const parsed = parseUnifiedDiff(raw)
|
|
637
|
+
return {
|
|
638
|
+
...base,
|
|
639
|
+
binary: parsed.binary,
|
|
640
|
+
additions: parsed.additions,
|
|
641
|
+
deletions: parsed.deletions,
|
|
642
|
+
hunks: parsed.hunks,
|
|
643
|
+
truncated,
|
|
644
|
+
raw,
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
597
648
|
/** 还剩几个未解决冲突(applyConflict / takeSide 之后用它回执)。 */
|
|
598
649
|
async function unmergedCount(root, signal) {
|
|
599
650
|
const res = await runGit(['diff', '--name-only', '--diff-filter=U', '-z'], {
|