dsh-ide-git 0.23.0 → 0.24.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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-ide-git",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "main": "./src/index.js",
5
5
  "description": "IDE 级 Git 操作面板:分支树 + 提交图谱 + 变更/暂存/提交 + 提交详情。装了 dsh-better-sidebar 时挂成它的原生 tab(右侧栏 + 底部工作台);没装时直接挂 DSH 原生右侧栏,单独安装即可用。JetBrains 风格 Git 工具窗口 for DeepSeek Harness.",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ide-git",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "DSH plugin: an IDE-grade Git tool window as a native dsh-better-sidebar tab — branch tree, commit graph, changes, commit details, JetBrains-style actions, in the right sidebar and the bottom panel. | DSH 插件:IDE 级 Git 工具窗口,以 dsh-better-sidebar 原生 Tab 挂载——分支树 / 提交图谱 / 变更与提交详情 / JetBrains 风格操作,右侧栏与底部面板双布局自适应。",
5
5
  "type": "module",
6
6
  "repository": {
@@ -39,6 +39,7 @@
39
39
  "icon.svg",
40
40
  "locale",
41
41
  "src/index.js",
42
+ "src/host",
42
43
  "src/client.js",
43
44
  "cordis.patch.yml",
44
45
  "dsh.plugin.json",
package/src/client.js CHANGED
@@ -434,6 +434,10 @@ window.__ModuleLoader__.load({
434
434
  'prompt.newTag': '新标签名',
435
435
  'prompt.fromHead': '当前 HEAD',
436
436
  'error.dismiss': '关闭',
437
+ 'error.pushRejected': '推送被拒绝:远程分支上有你本地没有的提交。请先「同步」(拉取并推送),或拉取合并后再推送。',
438
+ 'error.pullDiverged': '本地和远程各有新提交,无法快进。请用「拉取」合并,或改用「拉取(变基)」。',
439
+ 'error.pullConflict': '拉取时发生冲突:请在「变更」里解决冲突文件并提交,然后继续。',
440
+ 'error.pullDirty': '拉取会覆盖本地未提交的更改:请先提交或贮藏这些更改。',
437
441
  'status.loading': '正在读取...',
438
442
  'status.busy': '处理中...',
439
443
  'counts.staged': '已暂存 {n}',
@@ -802,6 +806,10 @@ window.__ModuleLoader__.load({
802
806
  'prompt.newTag': 'New tag name',
803
807
  'prompt.fromHead': 'current HEAD',
804
808
  'error.dismiss': 'Dismiss',
809
+ 'error.pushRejected': 'Push rejected: the remote branch has commits you do not have. Sync (pull and push), or pull (merge) and push again.',
810
+ 'error.pullDiverged': 'Local and remote have both moved, so a fast-forward is impossible. Pull with merge, or use Pull (Rebase).',
811
+ 'error.pullConflict': 'Pull stopped on conflicts: resolve the conflicted files under Changes, then commit.',
812
+ 'error.pullDirty': 'Pull would overwrite uncommitted local changes. Commit or stash them first.',
805
813
  'status.loading': 'Reading...',
806
814
  'status.busy': 'Working...',
807
815
  'counts.staged': 'Staged {n}',
@@ -1178,6 +1186,10 @@ window.__ModuleLoader__.load({
1178
1186
  'prompt.newTag': '新標籤名',
1179
1187
  'prompt.fromHead': '當前 HEAD',
1180
1188
  'error.dismiss': '關閉',
1189
+ 'error.pushRejected': '推送被拒絕:遠端分支有啲你本地冇嘅提交。請先同步(拉取並推送),或者拉取合併之後再推送。',
1190
+ 'error.pullDiverged': '本地同遠端各有新提交,唔可以快進。請用「拉取」合併,或者改用「拉取(變基)」。',
1191
+ 'error.pullConflict': '拉取時有衝突:喺「變更」入面解決衝突檔案並提交,然後繼續。',
1192
+ 'error.pullDirty': '拉取會覆蓋本地未提交嘅改動:請先提交或者貯藏呢啲改動。',
1181
1193
  'status.loading': '讀取中...',
1182
1194
  'status.busy': '處理中...',
1183
1195
  'counts.staged': '已暫存 {n}',
@@ -1546,6 +1558,10 @@ window.__ModuleLoader__.load({
1546
1558
  'prompt.newTag': '新標籤名稱',
1547
1559
  'prompt.fromHead': '目前 HEAD',
1548
1560
  'error.dismiss': '關閉',
1561
+ 'error.pushRejected': '推送被拒絕:遠端分支上有你本機沒有的提交。請先同步(拉取並推送),或拉取合併後再推送。',
1562
+ 'error.pullDiverged': '本機與遠端各有新提交,無法快進。請用「拉取」合併,或改用「拉取(變基)」。',
1563
+ 'error.pullConflict': '拉取時發生衝突:請在「變更」中解決衝突檔案並提交,然後繼續。',
1564
+ 'error.pullDirty': '拉取會覆蓋本機未提交的變更:請先提交或貯藏這些變更。',
1549
1565
  'status.loading': '讀取中...',
1550
1566
  'status.busy': '處理中...',
1551
1567
  'counts.staged': '已暫存 {n}',
@@ -1914,6 +1930,10 @@ window.__ModuleLoader__.load({
1914
1930
  'prompt.newTag': '新標籤名',
1915
1931
  'prompt.fromHead': '當前 HEAD',
1916
1932
  'error.dismiss': '關閉',
1933
+ 'error.pushRejected': '推送被拒絕:遠端分支有啲你本地冇嘅提交。請先同步(拉取並推送),或者拉取合併之後再推送。',
1934
+ 'error.pullDiverged': '本地同遠端各有新提交,唔可以快進。請用「拉取」合併,或者改用「拉取(變基)」。',
1935
+ 'error.pullConflict': '拉取時有衝突:喺「變更」入面解決衝突檔案並提交,然後繼續。',
1936
+ 'error.pullDirty': '拉取會覆蓋本地未提交嘅改動:請先提交或者貯藏呢啲改動。',
1917
1937
  'status.loading': '讀取中...',
1918
1938
  'status.busy': '處理中...',
1919
1939
  'counts.staged': '已暫存 {n}',
@@ -2282,6 +2302,10 @@ window.__ModuleLoader__.load({
2282
2302
  'prompt.newTag': '新しいタグ名',
2283
2303
  'prompt.fromHead': '現在の HEAD',
2284
2304
  'error.dismiss': '閉じる',
2305
+ 'error.pushRejected': 'プッシュが拒否されました:リモートブランチにローカルにないコミットがあります。先に同期(プルしてプッシュ)するか、プル(マージ)してから再プッシュしてください。',
2306
+ 'error.pullDiverged': 'ローカルとリモートの両方に新しいコミットがあり、fast-forward できません。「プル」(マージ)または「プル(リベース)」を使ってください。',
2307
+ 'error.pullConflict': 'プルで競合が発生しました。「変更」で競合ファイルを解決してコミットしてから続行してください。',
2308
+ 'error.pullDirty': 'プルするとローカルの未コミット変更が上書きされます。先にコミットするかスタッシュしてください。',
2285
2309
  'status.loading': '読み込み中...',
2286
2310
  'status.busy': '処理中...',
2287
2311
  'counts.staged': 'ステージ済み {n}',
@@ -2650,6 +2674,10 @@ window.__ModuleLoader__.load({
2650
2674
  'prompt.newTag': '새 태그 이름',
2651
2675
  'prompt.fromHead': '현재 HEAD',
2652
2676
  'error.dismiss': '닫기',
2677
+ 'error.pushRejected': '푸시가 거부되었습니다: 원격 브랜치에 로컬에 없는 커밋이 있습니다. 먼저 동기화(풀 후 푸시)하거나 풀(병합)한 뒤 다시 푸시하세요.',
2678
+ 'error.pullDiverged': '로컬과 원격에 각각 새 커밋이 있어 fast-forward할 수 없습니다. 풀(병합) 또는 풀(리베이스)을 사용하세요.',
2679
+ 'error.pullConflict': '풀 중 충돌이 발생했습니다. "변경"에서 충돌 파일을 해결하고 커밋한 뒤 계속하세요.',
2680
+ 'error.pullDirty': '풀을 하면 로컬의 커밋되지 않은 변경이 덮어써집니다. 먼저 커밋하거나 스태시하세요.',
2653
2681
  'status.loading': '읽는 중...',
2654
2682
  'status.busy': '처리 중...',
2655
2683
  'counts.staged': '스테이지됨 {n}',
@@ -3018,6 +3046,10 @@ window.__ModuleLoader__.load({
3018
3046
  'prompt.newTag': 'Name des neuen Tags',
3019
3047
  'prompt.fromHead': 'aktuelles HEAD',
3020
3048
  'error.dismiss': 'Schließen',
3049
+ 'error.pushRejected': 'Push abgelehnt: Der Remote-Branch enthält Commits, die lokal fehlen. Zuerst synchronisieren (Pull und Push) oder pullen (Merge) und dann erneut pushen.',
3050
+ 'error.pullDiverged': 'Lokal und remote sind beide weitergezogen; ein Fast-Forward ist unmöglich. Mit Merge pullen oder Pull (Rebase) verwenden.',
3051
+ 'error.pullConflict': 'Pull wurde wegen Konflikten gestoppt: Konfliktdateien unter „Änderungen“ auflösen, committen und dann fortfahren.',
3052
+ 'error.pullDirty': 'Pull würde lokale, nicht committete Änderungen überschreiben. Zuerst committen oder stashen.',
3021
3053
  'status.loading': 'Wird gelesen...',
3022
3054
  'status.busy': 'Arbeitet...',
3023
3055
  'counts.staged': 'Vorgemerkt {n}',
@@ -3386,6 +3418,10 @@ window.__ModuleLoader__.load({
3386
3418
  'prompt.newTag': 'Nom de la nouvelle étiquette',
3387
3419
  'prompt.fromHead': 'HEAD courant',
3388
3420
  'error.dismiss': 'Fermer',
3421
+ 'error.pushRejected': 'Push refusé : la branche distante contient des commits absents en local. Synchronisez (pull puis push) ou faites un pull (merge), puis poussez à nouveau.',
3422
+ 'error.pullDiverged': 'Local et distant ont tous deux avancé ; le fast-forward est impossible. Faites un pull (merge) ou un pull (rebase).',
3423
+ 'error.pullConflict': 'Le pull s\'est arrêté sur des conflits : résolvez les fichiers en conflit dans « Modifications », puis validez.',
3424
+ 'error.pullDirty': 'Le pull écraserait des modifications locales non validées. Validez-les ou remisez-les d\'abord.',
3389
3425
  'status.loading': 'Lecture...',
3390
3426
  'status.busy': 'En cours...',
3391
3427
  'counts.staged': 'Indexé {n}',
@@ -3754,6 +3790,10 @@ window.__ModuleLoader__.load({
3754
3790
  'prompt.newTag': 'Имя нового тега',
3755
3791
  'prompt.fromHead': 'текущий HEAD',
3756
3792
  'error.dismiss': 'Закрыть',
3793
+ 'error.pushRejected': 'Push отклонён: в удалённой ветке есть коммиты, которых нет локально. Сначала синхронизируйтесь (pull и push) или выполните pull (merge), затем повторите push.',
3794
+ 'error.pullDiverged': 'Локальная и удалённая ветки разошлись; fast-forward невозможен. Используйте pull (merge) или pull (rebase).',
3795
+ 'error.pullConflict': 'Pull остановился из-за конфликтов: разрешите конфликтные файлы в «Изменениях» и закоммитьте их.',
3796
+ 'error.pullDirty': 'Pull перезапишет незакоммиченные локальные изменения. Сначала закоммитьте или спрячьте их.',
3757
3797
  'status.loading': 'Чтение...',
3758
3798
  'status.busy': 'Работа...',
3759
3799
  'counts.staged': 'В индексе {n}',
@@ -4122,6 +4162,10 @@ window.__ModuleLoader__.load({
4122
4162
  'prompt.newTag': 'Nome da nova tag',
4123
4163
  'prompt.fromHead': 'HEAD atual',
4124
4164
  'error.dismiss': 'Fechar',
4165
+ 'error.pushRejected': 'Push rejeitado: o branch remoto tem commits que não existem localmente. Sincronize (pull e push) ou faça pull (merge) e envie novamente.',
4166
+ 'error.pullDiverged': 'Local e remoto avançaram; o fast-forward é impossível. Use pull (merge) ou pull (rebase).',
4167
+ 'error.pullConflict': 'O pull parou em conflitos: resolva os arquivos em conflito em "Alterações" e faça o commit.',
4168
+ 'error.pullDirty': 'O pull sobrescreveria alterações locais não commitadas. Faça commit ou stash primeiro.',
4125
4169
  'status.loading': 'Lendo...',
4126
4170
  'status.busy': 'Trabalhando...',
4127
4171
  'counts.staged': 'Preparado {n}',
@@ -4490,6 +4534,10 @@ window.__ModuleLoader__.load({
4490
4534
  'prompt.newTag': 'Nome del nuovo tag',
4491
4535
  'prompt.fromHead': 'HEAD corrente',
4492
4536
  'error.dismiss': 'Chiudi',
4537
+ 'error.pushRejected': 'Push rifiutato: il branch remoto contiene commit assenti in locale. Sincronizza (pull e push) oppure esegui pull (merge) e riprova.',
4538
+ 'error.pullDiverged': 'Locale e remoto sono avanzati entrambi; il fast-forward è impossibile. Usa pull (merge) o pull (rebase).',
4539
+ 'error.pullConflict': 'Il pull si è fermato per conflitti: risolvi i file in conflitto in "Modifiche", poi esegui il commit.',
4540
+ 'error.pullDirty': 'Il pull sovrascriverebbe modifiche locali non committate. Esegui prima commit o stash.',
4493
4541
  'status.loading': 'Lettura...',
4494
4542
  'status.busy': 'In corso...',
4495
4543
  'counts.staged': 'In stage {n}',
@@ -4858,6 +4906,10 @@ window.__ModuleLoader__.load({
4858
4906
  'prompt.newTag': 'Naam van de nieuwe tag',
4859
4907
  'prompt.fromHead': 'huidige HEAD',
4860
4908
  'error.dismiss': 'Sluiten',
4909
+ 'error.pushRejected': 'Push geweigerd: de remote branch heeft commits die lokaal ontbreken. Synchroniseer (pull en push) of pull (merge) en push daarna opnieuw.',
4910
+ 'error.pullDiverged': 'Lokaal en remote zijn beide verdergegaan; fast-forward is onmogelijk. Gebruik pull (merge) of pull (rebase).',
4911
+ 'error.pullConflict': 'Pull stopte door conflicten: los de conflictbestanden op onder "Wijzigingen" en commit daarna.',
4912
+ 'error.pullDirty': 'Pull zou niet-gecommitte lokale wijzigingen overschrijven. Commit of stash ze eerst.',
4861
4913
  'status.loading': 'Lezen...',
4862
4914
  'status.busy': 'Bezig...',
4863
4915
  'counts.staged': 'Gestaged {n}',
@@ -5226,6 +5278,10 @@ window.__ModuleLoader__.load({
5226
5278
  'prompt.newTag': 'Nazwa nowego tagu',
5227
5279
  'prompt.fromHead': 'bieżący HEAD',
5228
5280
  'error.dismiss': 'Zamknij',
5281
+ 'error.pushRejected': 'Push odrzucony: zdalna gałąź ma commity, których nie ma lokalnie. Najpierw zsynchronizuj (pull i push) albo wykonaj pull (merge) i ponów push.',
5282
+ 'error.pullDiverged': 'Lokalna i zdalna gałąź rozeszły się; fast-forward jest niemożliwy. Użyj pull (merge) lub pull (rebase).',
5283
+ 'error.pullConflict': 'Pull zatrzymał się na konfliktach: rozwiąż pliki konfliktów w „Zmianach” i zatwierdź zmiany.',
5284
+ 'error.pullDirty': 'Pull nadpisałby niezatwierdzone zmiany lokalne. Najpierw je zatwierdź lub schowaj.',
5229
5285
  'status.loading': 'Wczytywanie...',
5230
5286
  'status.busy': 'Praca...',
5231
5287
  'counts.staged': 'W indeksie {n}',
@@ -5594,6 +5650,10 @@ window.__ModuleLoader__.load({
5594
5650
  'prompt.newTag': 'Namn på ny tagg',
5595
5651
  'prompt.fromHead': 'aktuell HEAD',
5596
5652
  'error.dismiss': 'Stäng',
5653
+ 'error.pushRejected': 'Push avvisades: fjärrgrenen har commits som saknas lokalt. Synkronisera (pull och push) eller gör pull (merge) och pusha igen.',
5654
+ 'error.pullDiverged': 'Lokalt och fjärr har båda flyttats; fast-forward är omöjligt. Använd pull (merge) eller pull (rebase).',
5655
+ 'error.pullConflict': 'Pull stoppade på konflikter: lös konfliktfilerna under "Ändringar" och commit:a.',
5656
+ 'error.pullDirty': 'Pull skulle skriva över lokala ej commit:ade ändringar. Commit:a eller stash:a dem först.',
5597
5657
  'status.loading': 'Läser...',
5598
5658
  'status.busy': 'Arbetar...',
5599
5659
  'counts.staged': 'Klädda {n}',
@@ -5962,6 +6022,10 @@ window.__ModuleLoader__.load({
5962
6022
  'prompt.newTag': 'Yeni etiket adı',
5963
6023
  'prompt.fromHead': 'geçerli HEAD',
5964
6024
  'error.dismiss': 'Kapat',
6025
+ 'error.pushRejected': 'Push reddedildi: uzak dalda yerelde olmayan commit\'ler var. Önce senkronize edin (pull ve push) veya pull (merge) yapıp yeniden push\'layın.',
6026
+ 'error.pullDiverged': 'Yerel ve uzak dal ikisi de ilerledi; fast-forward mümkün değil. Pull (merge) veya pull (rebase) kullanın.',
6027
+ 'error.pullConflict': 'Pull çakışmalarda durdu: "Değişiklikler" altında çakışan dosyaları çözüp commit\'leyin.',
6028
+ 'error.pullDirty': 'Pull, commit\'lenmemiş yerel değişikliklerin üzerine yazar. Önce commit\'leyin veya stash\'leyin.',
5965
6029
  'status.loading': 'Okunuyor...',
5966
6030
  'status.busy': 'Çalışıyor...',
5967
6031
  'counts.staged': 'Hazırlanan {n}',
@@ -6330,6 +6394,10 @@ window.__ModuleLoader__.load({
6330
6394
  'prompt.newTag': 'Nama tag baru',
6331
6395
  'prompt.fromHead': 'HEAD saat ini',
6332
6396
  'error.dismiss': 'Tutup',
6397
+ 'error.pushRejected': 'Push ditolak: branch remote memiliki commit yang tidak ada di lokal. Sinkronkan (pull lalu push) atau pull (merge) lalu push lagi.',
6398
+ 'error.pullDiverged': 'Lokal dan remote sama-sama maju; fast-forward tidak mungkin. Gunakan pull (merge) atau pull (rebase).',
6399
+ 'error.pullConflict': 'Pull berhenti karena konflik: selesaikan file konflik di "Perubahan", lalu commit.',
6400
+ 'error.pullDirty': 'Pull akan menimpa perubahan lokal yang belum di-commit. Commit atau stash dulu.',
6333
6401
  'status.loading': 'Membaca...',
6334
6402
  'status.busy': 'Bekerja...',
6335
6403
  'counts.staged': 'Ter-stage {n}',
@@ -6698,6 +6766,10 @@ window.__ModuleLoader__.load({
6698
6766
  'prompt.newTag': 'Tên thẻ mới',
6699
6767
  'prompt.fromHead': 'HEAD hiện tại',
6700
6768
  'error.dismiss': 'Đóng',
6769
+ 'error.pushRejected': 'Push bị từ chối: nhánh remote có commit mà local chưa có. Hãy đồng bộ (pull rồi push) hoặc pull (merge) rồi push lại.',
6770
+ 'error.pullDiverged': 'Local và remote đều đã tiến lên; không thể fast-forward. Dùng pull (merge) hoặc pull (rebase).',
6771
+ 'error.pullConflict': 'Pull dừng do xung đột: giải quyết các tệp xung đột trong "Thay đổi" rồi commit.',
6772
+ 'error.pullDirty': 'Pull sẽ ghi đè thay đổi local chưa commit. Hãy commit hoặc stash trước.',
6701
6773
  'status.loading': 'Đang đọc...',
6702
6774
  'status.busy': 'Đang xử lý...',
6703
6775
  'counts.staged': 'Đã stage {n}',
@@ -7066,6 +7138,10 @@ window.__ModuleLoader__.load({
7066
7138
  'prompt.newTag': 'اسم الوسم الجديد',
7067
7139
  'prompt.fromHead': 'HEAD الحالي',
7068
7140
  'error.dismiss': 'إغلاق',
7141
+ 'error.pushRejected': 'تم رفض الدفع: الفرع البعيد يحتوي على commits غير موجودة محليًا. زامن أولًا (pull ثم push) أو اسحب (merge) ثم أعد الدفع.',
7142
+ 'error.pullDiverged': 'تقدّم الفرعان المحلي والبعيد؛ لا يمكن fast-forward. استخدم pull (merge) أو pull (rebase).',
7143
+ 'error.pullConflict': 'توقف pull بسبب تعارضات: حلّ ملفات التعارض في "التغييرات" ثم commit.',
7144
+ 'error.pullDirty': 'سيؤدي pull إلى الكتابة فوق تغييرات محلية غير مثبتة. ثبّتها أو خزّنها أولًا.',
7069
7145
  'status.loading': 'جارٍ القراءة...',
7070
7146
  'status.busy': 'جارٍ العمل...',
7071
7147
  'counts.staged': 'مُجهَّز {n}',
@@ -7434,6 +7510,10 @@ window.__ModuleLoader__.load({
7434
7510
  'prompt.newTag': 'नए टैग का नाम',
7435
7511
  'prompt.fromHead': 'वर्तमान HEAD',
7436
7512
  'error.dismiss': 'बंद करें',
7513
+ 'error.pushRejected': 'पुश अस्वीकृत: रिमोट ब्रांच में ऐसे commits हैं जो लोकल में नहीं हैं। पहले सिंक करें (pull फिर push) या pull (merge) करके फिर से push करें।',
7514
+ 'error.pullDiverged': 'लोकल और रिमोट दोनों आगे बढ़े हैं; fast-forward संभव नहीं। pull (merge) या pull (rebase) इस्तेमाल करें।',
7515
+ 'error.pullConflict': 'pull conflicts पर रुक गया: "परिवर्तन" में conflict फ़ाइलें हल करें, फिर commit करें।',
7516
+ 'error.pullDirty': 'pull लोकल की uncommitted changes को overwrite करेगा। पहले commit या stash करें।',
7437
7517
  'status.loading': 'पढ़ा जा रहा है...',
7438
7518
  'status.busy': 'कार्य जारी...',
7439
7519
  'counts.staged': 'स्टेज्ड {n}',
@@ -7802,6 +7882,10 @@ window.__ModuleLoader__.load({
7802
7882
  'prompt.newTag': 'ชื่อแท็กใหม่',
7803
7883
  'prompt.fromHead': 'HEAD ปัจจุบัน',
7804
7884
  'error.dismiss': 'ปิด',
7885
+ 'error.pushRejected': 'Push ถูกปฏิเสธ: สาขา remote มี commit ที่ยังไม่มีในเครื่องนี้ ให้ sync (pull แล้ว push) หรือ pull (merge) แล้ว push อีกครั้ง',
7886
+ 'error.pullDiverged': 'ทั้ง local และ remote มี commit ใหม่; fast-forward ไม่ได้ ใช้ pull (merge) หรือ pull (rebase)',
7887
+ 'error.pullConflict': 'Pull หยุดเพราะมี conflict: แก้ไฟล์ที่ขัดแย้งใน "การเปลี่ยนแปลง" แล้ว commit',
7888
+ 'error.pullDirty': 'Pull จะเขียนทับการเปลี่ยนแปลง local ที่ยังไม่ commit: ให้ commit หรือ stash ก่อน',
7805
7889
  'status.loading': 'กำลังอ่าน...',
7806
7890
  'status.busy': 'กำลังทำงาน...',
7807
7891
  'counts.staged': 'สเตจแล้ว {n}',
@@ -13055,6 +13139,9 @@ window.__ModuleLoader__.load({
13055
13139
  const [commits, setCommits] = useState([])
13056
13140
  const [hasMore, setHasMore] = useState(false)
13057
13141
  const [error, setError] = useState(null)
13142
+ /* Named failure code (push-rejected / pull-conflict / ...), kept beside
13143
+ the raw message so the banner can lead with an actionable sentence. */
13144
+ const [errorCode, setErrorCode] = useState(null)
13058
13145
  const [note, setNote] = useState(null)
13059
13146
  const [busy, setBusy] = useState(false)
13060
13147
  const [view, setView] = useState('history')
@@ -13398,10 +13485,13 @@ window.__ModuleLoader__.load({
13398
13485
  const guard = useCallback(async (work) => {
13399
13486
  setBusy(true)
13400
13487
  setError(null)
13488
+ setErrorCode(null)
13401
13489
  try {
13402
13490
  return await work()
13403
13491
  } catch (caught) {
13404
- setError(caught instanceof Error ? caught.message : String(caught))
13492
+ const failure = caught instanceof Error ? caught : new Error(String(caught))
13493
+ setError(failure.message)
13494
+ setErrorCode(typeof failure.code === 'string' ? failure.code : null)
13405
13495
  return undefined
13406
13496
  } finally {
13407
13497
  setBusy(false)
@@ -13446,7 +13536,7 @@ window.__ModuleLoader__.load({
13446
13536
  writePaintRepos(cwd, data)
13447
13537
  apply(data, readPaintRoot(cwd))
13448
13538
  } catch (caught) {
13449
- if (!cancelled) setError(caught instanceof Error ? caught.message : String(caught))
13539
+ if (!cancelled) { setErrorCode(null); setError(caught instanceof Error ? caught.message : String(caught)) }
13450
13540
  }
13451
13541
  })()
13452
13542
  return () => { cancelled = true }
@@ -13474,6 +13564,7 @@ window.__ModuleLoader__.load({
13474
13564
  const data = await request('gitLogs', {})
13475
13565
  setGitOutput(Array.isArray(data.entries) ? data.entries : [])
13476
13566
  } catch (caught) {
13567
+ setErrorCode(null)
13477
13568
  setError(caught instanceof Error ? caught.message : String(caught))
13478
13569
  }
13479
13570
  }, [request])
@@ -13699,7 +13790,11 @@ window.__ModuleLoader__.load({
13699
13790
 
13700
13791
  const run = useCallback(async (method, payload) => {
13701
13792
  const result = await guard(() => request(method, Object.assign({}, base, payload)))
13702
- if (result !== undefined) {
13793
+ /* A failed pull/push still changes repository state (merge conflicts,
13794
+ or a merge that landed before the push was rejected), so refresh on
13795
+ those failures too — otherwise the Changes list hides the conflict
13796
+ files the banner is asking the user to resolve. */
13797
+ if (result !== undefined || method === 'pull' || method === 'push') {
13703
13798
  await refresh()
13704
13799
  /* v0.21.2: the composer pill is a separate tree; without this it only
13705
13800
  learned about an in-panel checkout/commit at the next 30s poll. The
@@ -13760,6 +13855,7 @@ window.__ModuleLoader__.load({
13760
13855
  const data = await request('diff', Object.assign({}, base, seed))
13761
13856
  setPatch(data.patch)
13762
13857
  } catch (caught) {
13858
+ setErrorCode(null)
13763
13859
  setError(caught instanceof Error ? caught.message : String(caught))
13764
13860
  } finally {
13765
13861
  setPatchLoading(false)
@@ -13862,6 +13958,7 @@ window.__ModuleLoader__.load({
13862
13958
  try {
13863
13959
  setDetail(await request('commitDetail', Object.assign({}, base, { hash: commit.hash })))
13864
13960
  } catch (caught) {
13961
+ setErrorCode(null)
13865
13962
  setError(caught instanceof Error ? caught.message : String(caught))
13866
13963
  }
13867
13964
  }, [base])
@@ -14034,6 +14131,7 @@ window.__ModuleLoader__.load({
14034
14131
  const createWorktree = async (draft) => {
14035
14132
  setBusy(true)
14036
14133
  setError(null)
14134
+ setErrorCode(null)
14037
14135
  try {
14038
14136
  await request('worktreeAdd', Object.assign({}, base, draft))
14039
14137
  setDialog(null)
@@ -14049,6 +14147,7 @@ window.__ModuleLoader__.load({
14049
14147
  const removeWorktree = async (tree, force) => {
14050
14148
  setBusy(true)
14051
14149
  setError(null)
14150
+ setErrorCode(null)
14052
14151
  try {
14053
14152
  await request('worktreeRemove', Object.assign({}, base, { path: tree.path, confirm: true, force: force === true }))
14054
14153
  setDialog(null)
@@ -14062,6 +14161,7 @@ window.__ModuleLoader__.load({
14062
14161
  return message
14063
14162
  }
14064
14163
  setDialog(null)
14164
+ setErrorCode(null)
14065
14165
  setError(message)
14066
14166
  return message
14067
14167
  } finally {
@@ -14071,6 +14171,7 @@ window.__ModuleLoader__.load({
14071
14171
  const pruneWorktrees = async () => {
14072
14172
  setBusy(true)
14073
14173
  setError(null)
14174
+ setErrorCode(null)
14074
14175
  try {
14075
14176
  const data = await request('worktreePrune', Object.assign({}, base, { confirm: true }))
14076
14177
  setDialog(null)
@@ -14079,6 +14180,7 @@ window.__ModuleLoader__.load({
14079
14180
  return data
14080
14181
  } catch (caught) {
14081
14182
  setDialog(null)
14183
+ setErrorCode(null)
14082
14184
  setError(caught instanceof Error ? caught.message : String(caught))
14083
14185
  return null
14084
14186
  } finally {
@@ -14259,7 +14361,26 @@ window.__ModuleLoader__.load({
14259
14361
  ].filter((item) => item !== null))
14260
14362
  return
14261
14363
  }
14262
- const updateItem = { id: 'update', icon: 'fetch', tone: 'cyan', label: t('action.update'), run: () => { void run('fetch', { prune: true }) } }
14364
+ /* v0.24.0: the label was always 拉取, but this only ran git fetch.
14365
+ The checked-out branch now takes a real pull (merge, the new
14366
+ default); a non-HEAD branch keeps the safe refspec update, because
14367
+ git pull would merge into HEAD instead of into that branch. */
14368
+ const updateItem = {
14369
+ id: 'update', icon: 'fetch', tone: 'cyan', label: t('action.update'),
14370
+ run: () => {
14371
+ if (entry.head === true) {
14372
+ const upstream = entry.upstream
14373
+ if (upstream === null || upstream === undefined || upstream === '') { void run('fetch', { prune: true }); return }
14374
+ void run('pull', { mode: 'merge' })
14375
+ return
14376
+ }
14377
+ const upstream = entry.upstream
14378
+ if (upstream === null || upstream === undefined || upstream === '') { void run('fetch', { prune: true }); return }
14379
+ const slash = upstream.indexOf('/')
14380
+ const remote = slash >= 0 ? upstream.slice(0, slash) : upstream
14381
+ void run('fetch', { remote: remote, branch: entry.name + ':' + entry.name })
14382
+ },
14383
+ }
14263
14384
  const pushItem = { id: 'push', icon: 'push', tone: 'success', label: t('action.push'), disabled: blocked, reason: t('operation.hint'), run: () => setDialog({ kind: 'push' }) }
14264
14385
  const items = [
14265
14386
  { id: 'checkout', icon: 'checkout', tone: 'accent', label: t('action.checkout'), disabled: entry.head === true || entry.tag === true || blocked, reason: blocked ? t('operation.hint') : reason, run: () => { void checkout(entry) } },
@@ -14662,9 +14783,29 @@ window.__ModuleLoader__.load({
14662
14783
  E('span', { className: 'dig-topbar-spacer' }),
14663
14784
  busy ? E('span', { className: 'dig-busy' }, t('status.busy')) : null)
14664
14785
 
14786
+ /* Named git failures get a sentence that says what to do; the raw git
14787
+ output stays one hover away in the title. The two recoverable ones
14788
+ (push rejected, ff-only divergence) also offer the exact next action:
14789
+ Sync = pull with merge, then push again. */
14790
+ const errorHint = errorCode === 'push-rejected' ? t('error.pushRejected')
14791
+ : errorCode === 'pull-diverged' ? t('error.pullDiverged')
14792
+ : errorCode === 'pull-conflict' ? t('error.pullConflict')
14793
+ : errorCode === 'pull-dirty' ? t('error.pullDirty')
14794
+ : null
14795
+ const syncFromBanner = () => {
14796
+ setError(null)
14797
+ setErrorCode(null)
14798
+ void (async () => {
14799
+ const pulled = await run('pull', { mode: 'merge' })
14800
+ if (pulled !== undefined) await run('push', { confirm: true })
14801
+ })()
14802
+ }
14665
14803
  const banner = error === null ? null : E('div', { className: 'dig-banner' },
14666
- E('span', { className: 'dig-banner-text' }, error),
14667
- E('button', { type: 'button', className: 'dig-link', onClick: () => setError(null) }, t('error.dismiss')))
14804
+ E('span', { className: 'dig-banner-text', title: errorHint === null ? undefined : error }, errorHint === null ? error : errorHint),
14805
+ errorHint !== null && (errorCode === 'push-rejected' || errorCode === 'pull-diverged')
14806
+ ? E('button', { type: 'button', className: 'dig-link', onClick: syncFromBanner }, t('more.sync'))
14807
+ : null,
14808
+ E('button', { type: 'button', className: 'dig-link', onClick: () => { setError(null); setErrorCode(null) } }, t('error.dismiss')))
14668
14809
 
14669
14810
  const noteBanner = note === null ? null : E('div', { className: 'dig-note' },
14670
14811
  E('span', { className: 'dig-banner-text' }, note),
@@ -14856,7 +14997,7 @@ window.__ModuleLoader__.load({
14856
14997
  ] },
14857
14998
  null,
14858
14999
  /* —— top-level sync (VS Code header row) —— */
14859
- { id: 'mm-pull', icon: 'pull', tone: 'accent', label: t('toolbar.pull'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void run('pull', { mode: 'ff-only' }) } },
15000
+ { id: 'mm-pull', icon: 'pull', tone: 'accent', label: t('toolbar.pull'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void run('pull', { mode: 'merge' }) } },
14860
15001
  { id: 'mm-push', icon: 'push', tone: 'success', label: t('toolbar.push'), disabled: remoteReady !== true || blocked, reason, run: () => setDialog({ kind: 'push' }) },
14861
15002
  { id: 'mm-clone', icon: 'plus', tone: 'secondary', label: t('more.clone'), run: () => setDialog({ kind: 'clone' }) },
14862
15003
  { id: 'mm-checkout', icon: 'checkout', tone: 'accent', label: t('action.checkout') + '...', disabled: otherBranches.length === 0 || blocked, reason, run: (ev) => pickBranchMenu(ev, 'checkout') },
@@ -14885,12 +15026,12 @@ window.__ModuleLoader__.load({
14885
15026
  ] },
14886
15027
  /* —— SCM ▸ Pull, Push ▸ —— */
14887
15028
  { id: 'sub-pullpush', icon: 'pull', tone: 'accent', label: t('more.pullpushGroup'), items: [
14888
- { id: 'pp-sync', label: t('more.sync'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void (async () => { await run('pull', { mode: 'ff-only' }); await run('push', { confirm: true }) })() } },
15029
+ { id: 'pp-sync', label: t('more.sync'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void (async () => { await run('pull', { mode: 'merge' }); await run('push', { confirm: true }) })() } },
14889
15030
  { id: 'pp-sync-rebase', label: t('more.syncRebase'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void (async () => { await run('pull', { mode: 'rebase' }); await run('push', { confirm: true }) })() } },
14890
15031
  null,
14891
- { id: 'pp-pull', label: t('toolbar.pull'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void run('pull', { mode: 'ff-only' }) } },
15032
+ { id: 'pp-pull', label: t('toolbar.pull'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void run('pull', { mode: 'merge' }) } },
14892
15033
  { id: 'pp-pull-rebase', label: t('more.pullRebase'), disabled: remoteReady !== true || tracked !== true || blocked, reason, run: () => { void run('pull', { mode: 'rebase' }) } },
14893
- { id: 'pp-pull-from', label: t('more.pullFrom'), disabled: remoteNames.length === 0, reason, run: pickRemote((name) => { void run('pull', { mode: 'ff-only', remote: name }) }) },
15034
+ { id: 'pp-pull-from', label: t('more.pullFrom'), disabled: remoteNames.length === 0, reason, run: pickRemote((name) => { void run('pull', { mode: 'merge', remote: name }) }) },
14894
15035
  null,
14895
15036
  { id: 'pp-push', label: t('toolbar.push'), disabled: remoteReady !== true || blocked, reason, run: () => setDialog({ kind: 'push' }) },
14896
15037
  { id: 'pp-push-force', label: t('more.pushForce'), danger: true, disabled: remoteReady !== true || blocked, reason, run: () => setDialog({ kind: 'pushForce' }) },
@@ -15017,7 +15158,7 @@ window.__ModuleLoader__.load({
15017
15158
  const pullPickedBranches = async (picked) => {
15018
15159
  for (const item of picked) {
15019
15160
  if (item.kind !== 'local') continue
15020
- if (item.entry.head === true) { await run('pull', { mode: 'ff-only' }); continue }
15161
+ if (item.entry.head === true) { await run('pull', { mode: 'merge' }); continue }
15021
15162
  const upstream = item.entry.upstream
15022
15163
  if (upstream === null || upstream === undefined || upstream === '') continue
15023
15164
  const slash = upstream.indexOf('/')
@@ -15076,7 +15217,7 @@ window.__ModuleLoader__.load({
15076
15217
  }
15077
15218
  else if (spec.id === 'pull') {
15078
15219
  if (railPickedLocals.length > 0) { entry.label = fill(t('toolbar.pullPicked'), { n: railPickedLocals.length }); entry.disabled = blocked; entry.run = () => { void pullPickedBranches(railPickedLocals) } }
15079
- else { entry.disabled = remoteReady !== true || tracked !== true || blocked; entry.run = () => { void run('pull', { mode: 'ff-only' }) } }
15220
+ else { entry.disabled = remoteReady !== true || tracked !== true || blocked; entry.run = () => { void run('pull', { mode: 'merge' }) } }
15080
15221
  }
15081
15222
  else if (spec.id === 'push') {
15082
15223
  if (railPickedLocals.length > 0) { entry.label = fill(t('toolbar.pushPicked'), { n: railPickedLocals.length }); entry.disabled = blocked; entry.run = () => setDialog({ kind: 'pushMany', items: railPickedLocals.map((item) => ({ name: item.name, upstream: item.entry.upstream })) }) }