coc-git 2.7.7 → 2.7.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/lib/index.js CHANGED
@@ -29,230 +29,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  ));
30
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
31
 
32
- // node_modules/isexe/windows.js
33
- var require_windows = __commonJS({
34
- "node_modules/isexe/windows.js"(exports2, module2) {
35
- module2.exports = isexe;
36
- isexe.sync = sync;
37
- var fs4 = require("fs");
38
- function checkPathExt(path8, options) {
39
- var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
40
- if (!pathext) {
41
- return true;
42
- }
43
- pathext = pathext.split(";");
44
- if (pathext.indexOf("") !== -1) {
45
- return true;
46
- }
47
- for (var i = 0; i < pathext.length; i++) {
48
- var p = pathext[i].toLowerCase();
49
- if (p && path8.substr(-p.length).toLowerCase() === p) {
50
- return true;
51
- }
52
- }
53
- return false;
54
- }
55
- function checkStat(stat, path8, options) {
56
- if (!stat.isSymbolicLink() && !stat.isFile()) {
57
- return false;
58
- }
59
- return checkPathExt(path8, options);
60
- }
61
- function isexe(path8, options, cb) {
62
- fs4.stat(path8, function(er, stat) {
63
- cb(er, er ? false : checkStat(stat, path8, options));
64
- });
65
- }
66
- function sync(path8, options) {
67
- return checkStat(fs4.statSync(path8), path8, options);
68
- }
69
- }
70
- });
71
-
72
- // node_modules/isexe/mode.js
73
- var require_mode = __commonJS({
74
- "node_modules/isexe/mode.js"(exports2, module2) {
75
- module2.exports = isexe;
76
- isexe.sync = sync;
77
- var fs4 = require("fs");
78
- function isexe(path8, options, cb) {
79
- fs4.stat(path8, function(er, stat) {
80
- cb(er, er ? false : checkStat(stat, options));
81
- });
82
- }
83
- function sync(path8, options) {
84
- return checkStat(fs4.statSync(path8), options);
85
- }
86
- function checkStat(stat, options) {
87
- return stat.isFile() && checkMode(stat, options);
88
- }
89
- function checkMode(stat, options) {
90
- var mod = stat.mode;
91
- var uid = stat.uid;
92
- var gid = stat.gid;
93
- var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
94
- var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
95
- var u = parseInt("100", 8);
96
- var g = parseInt("010", 8);
97
- var o = parseInt("001", 8);
98
- var ug = u | g;
99
- var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
100
- return ret;
101
- }
102
- }
103
- });
104
-
105
- // node_modules/isexe/index.js
106
- var require_isexe = __commonJS({
107
- "node_modules/isexe/index.js"(exports2, module2) {
108
- var fs4 = require("fs");
109
- var core;
110
- if (process.platform === "win32" || global.TESTING_WINDOWS) {
111
- core = require_windows();
112
- } else {
113
- core = require_mode();
114
- }
115
- module2.exports = isexe;
116
- isexe.sync = sync;
117
- function isexe(path8, options, cb) {
118
- if (typeof options === "function") {
119
- cb = options;
120
- options = {};
121
- }
122
- if (!cb) {
123
- if (typeof Promise !== "function") {
124
- throw new TypeError("callback not provided");
125
- }
126
- return new Promise(function(resolve, reject) {
127
- isexe(path8, options || {}, function(er, is) {
128
- if (er) {
129
- reject(er);
130
- } else {
131
- resolve(is);
132
- }
133
- });
134
- });
135
- }
136
- core(path8, options || {}, function(er, is) {
137
- if (er) {
138
- if (er.code === "EACCES" || options && options.ignoreErrors) {
139
- er = null;
140
- is = false;
141
- }
142
- }
143
- cb(er, is);
144
- });
145
- }
146
- function sync(path8, options) {
147
- try {
148
- return core.sync(path8, options || {});
149
- } catch (er) {
150
- if (options && options.ignoreErrors || er.code === "EACCES") {
151
- return false;
152
- } else {
153
- throw er;
154
- }
155
- }
156
- }
157
- }
158
- });
159
-
160
- // node_modules/which/which.js
161
- var require_which = __commonJS({
162
- "node_modules/which/which.js"(exports2, module2) {
163
- var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
164
- var path8 = require("path");
165
- var COLON = isWindows ? ";" : ":";
166
- var isexe = require_isexe();
167
- var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
168
- var getPathInfo = (cmd, opt) => {
169
- const colon = opt.colon || COLON;
170
- const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
171
- // windows always checks the cwd first
172
- ...isWindows ? [process.cwd()] : [],
173
- ...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */
174
- "").split(colon)
175
- ];
176
- const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
177
- const pathExt = isWindows ? pathExtExe.split(colon) : [""];
178
- if (isWindows) {
179
- if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
180
- pathExt.unshift("");
181
- }
182
- return {
183
- pathEnv,
184
- pathExt,
185
- pathExtExe
186
- };
187
- };
188
- var which2 = (cmd, opt, cb) => {
189
- if (typeof opt === "function") {
190
- cb = opt;
191
- opt = {};
192
- }
193
- if (!opt)
194
- opt = {};
195
- const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
196
- const found = [];
197
- const step = (i) => new Promise((resolve, reject) => {
198
- if (i === pathEnv.length)
199
- return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
200
- const ppRaw = pathEnv[i];
201
- const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
202
- const pCmd = path8.join(pathPart, cmd);
203
- const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
204
- resolve(subStep(p, i, 0));
205
- });
206
- const subStep = (p, i, ii) => new Promise((resolve, reject) => {
207
- if (ii === pathExt.length)
208
- return resolve(step(i + 1));
209
- const ext = pathExt[ii];
210
- isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
211
- if (!er && is) {
212
- if (opt.all)
213
- found.push(p + ext);
214
- else
215
- return resolve(p + ext);
216
- }
217
- return resolve(subStep(p, i, ii + 1));
218
- });
219
- });
220
- return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
221
- };
222
- var whichSync = (cmd, opt) => {
223
- opt = opt || {};
224
- const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
225
- const found = [];
226
- for (let i = 0; i < pathEnv.length; i++) {
227
- const ppRaw = pathEnv[i];
228
- const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
229
- const pCmd = path8.join(pathPart, cmd);
230
- const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
231
- for (let j = 0; j < pathExt.length; j++) {
232
- const cur = p + pathExt[j];
233
- try {
234
- const is = isexe.sync(cur, { pathExt: pathExtExe });
235
- if (is) {
236
- if (opt.all)
237
- found.push(cur);
238
- else
239
- return cur;
240
- }
241
- } catch (ex) {
242
- }
243
- }
244
- }
245
- if (opt.all && found.length)
246
- return found;
247
- if (opt.nothrow)
248
- return null;
249
- throw getNotFoundError(cmd);
250
- };
251
- module2.exports = which2;
252
- which2.sync = whichSync;
253
- }
254
- });
255
-
256
32
  // node_modules/colors/lib/styles.js
257
33
  var require_styles = __commonJS({
258
34
  "node_modules/colors/lib/styles.js"(exports2, module2) {
@@ -914,31 +690,255 @@ var require_safe = __commonJS({
914
690
  }
915
691
  });
916
692
 
917
- // node_modules/debounce/index.js
918
- var require_debounce = __commonJS({
919
- "node_modules/debounce/index.js"(exports2, module2) {
920
- function debounce3(func, wait2, immediate) {
921
- var timeout, args, context, timestamp, result;
922
- if (null == wait2) wait2 = 100;
923
- function later() {
924
- var last = Date.now() - timestamp;
925
- if (last < wait2 && last >= 0) {
926
- timeout = setTimeout(later, wait2 - last);
927
- } else {
928
- timeout = null;
929
- if (!immediate) {
930
- result = func.apply(context, args);
931
- context = args = null;
932
- }
693
+ // node_modules/isexe/windows.js
694
+ var require_windows = __commonJS({
695
+ "node_modules/isexe/windows.js"(exports2, module2) {
696
+ module2.exports = isexe;
697
+ isexe.sync = sync;
698
+ var fs4 = require("fs");
699
+ function checkPathExt(path8, options) {
700
+ var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
701
+ if (!pathext) {
702
+ return true;
703
+ }
704
+ pathext = pathext.split(";");
705
+ if (pathext.indexOf("") !== -1) {
706
+ return true;
707
+ }
708
+ for (var i = 0; i < pathext.length; i++) {
709
+ var p = pathext[i].toLowerCase();
710
+ if (p && path8.substr(-p.length).toLowerCase() === p) {
711
+ return true;
933
712
  }
934
713
  }
935
- ;
714
+ return false;
715
+ }
716
+ function checkStat(stat, path8, options) {
717
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
718
+ return false;
719
+ }
720
+ return checkPathExt(path8, options);
721
+ }
722
+ function isexe(path8, options, cb) {
723
+ fs4.stat(path8, function(er, stat) {
724
+ cb(er, er ? false : checkStat(stat, path8, options));
725
+ });
726
+ }
727
+ function sync(path8, options) {
728
+ return checkStat(fs4.statSync(path8), path8, options);
729
+ }
730
+ }
731
+ });
732
+
733
+ // node_modules/isexe/mode.js
734
+ var require_mode = __commonJS({
735
+ "node_modules/isexe/mode.js"(exports2, module2) {
736
+ module2.exports = isexe;
737
+ isexe.sync = sync;
738
+ var fs4 = require("fs");
739
+ function isexe(path8, options, cb) {
740
+ fs4.stat(path8, function(er, stat) {
741
+ cb(er, er ? false : checkStat(stat, options));
742
+ });
743
+ }
744
+ function sync(path8, options) {
745
+ return checkStat(fs4.statSync(path8), options);
746
+ }
747
+ function checkStat(stat, options) {
748
+ return stat.isFile() && checkMode(stat, options);
749
+ }
750
+ function checkMode(stat, options) {
751
+ var mod = stat.mode;
752
+ var uid = stat.uid;
753
+ var gid = stat.gid;
754
+ var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
755
+ var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
756
+ var u = parseInt("100", 8);
757
+ var g = parseInt("010", 8);
758
+ var o = parseInt("001", 8);
759
+ var ug = u | g;
760
+ var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
761
+ return ret;
762
+ }
763
+ }
764
+ });
765
+
766
+ // node_modules/isexe/index.js
767
+ var require_isexe = __commonJS({
768
+ "node_modules/isexe/index.js"(exports2, module2) {
769
+ var fs4 = require("fs");
770
+ var core;
771
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
772
+ core = require_windows();
773
+ } else {
774
+ core = require_mode();
775
+ }
776
+ module2.exports = isexe;
777
+ isexe.sync = sync;
778
+ function isexe(path8, options, cb) {
779
+ if (typeof options === "function") {
780
+ cb = options;
781
+ options = {};
782
+ }
783
+ if (!cb) {
784
+ if (typeof Promise !== "function") {
785
+ throw new TypeError("callback not provided");
786
+ }
787
+ return new Promise(function(resolve, reject) {
788
+ isexe(path8, options || {}, function(er, is) {
789
+ if (er) {
790
+ reject(er);
791
+ } else {
792
+ resolve(is);
793
+ }
794
+ });
795
+ });
796
+ }
797
+ core(path8, options || {}, function(er, is) {
798
+ if (er) {
799
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
800
+ er = null;
801
+ is = false;
802
+ }
803
+ }
804
+ cb(er, is);
805
+ });
806
+ }
807
+ function sync(path8, options) {
808
+ try {
809
+ return core.sync(path8, options || {});
810
+ } catch (er) {
811
+ if (options && options.ignoreErrors || er.code === "EACCES") {
812
+ return false;
813
+ } else {
814
+ throw er;
815
+ }
816
+ }
817
+ }
818
+ }
819
+ });
820
+
821
+ // node_modules/which/which.js
822
+ var require_which = __commonJS({
823
+ "node_modules/which/which.js"(exports2, module2) {
824
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
825
+ var path8 = require("path");
826
+ var COLON = isWindows ? ";" : ":";
827
+ var isexe = require_isexe();
828
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
829
+ var getPathInfo = (cmd, opt) => {
830
+ const colon = opt.colon || COLON;
831
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
832
+ // windows always checks the cwd first
833
+ ...isWindows ? [process.cwd()] : [],
834
+ ...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */
835
+ "").split(colon)
836
+ ];
837
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
838
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
839
+ if (isWindows) {
840
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
841
+ pathExt.unshift("");
842
+ }
843
+ return {
844
+ pathEnv,
845
+ pathExt,
846
+ pathExtExe
847
+ };
848
+ };
849
+ var which2 = (cmd, opt, cb) => {
850
+ if (typeof opt === "function") {
851
+ cb = opt;
852
+ opt = {};
853
+ }
854
+ if (!opt)
855
+ opt = {};
856
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
857
+ const found = [];
858
+ const step = (i) => new Promise((resolve, reject) => {
859
+ if (i === pathEnv.length)
860
+ return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
861
+ const ppRaw = pathEnv[i];
862
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
863
+ const pCmd = path8.join(pathPart, cmd);
864
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
865
+ resolve(subStep(p, i, 0));
866
+ });
867
+ const subStep = (p, i, ii) => new Promise((resolve, reject) => {
868
+ if (ii === pathExt.length)
869
+ return resolve(step(i + 1));
870
+ const ext = pathExt[ii];
871
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
872
+ if (!er && is) {
873
+ if (opt.all)
874
+ found.push(p + ext);
875
+ else
876
+ return resolve(p + ext);
877
+ }
878
+ return resolve(subStep(p, i, ii + 1));
879
+ });
880
+ });
881
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
882
+ };
883
+ var whichSync = (cmd, opt) => {
884
+ opt = opt || {};
885
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
886
+ const found = [];
887
+ for (let i = 0; i < pathEnv.length; i++) {
888
+ const ppRaw = pathEnv[i];
889
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
890
+ const pCmd = path8.join(pathPart, cmd);
891
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
892
+ for (let j = 0; j < pathExt.length; j++) {
893
+ const cur = p + pathExt[j];
894
+ try {
895
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
896
+ if (is) {
897
+ if (opt.all)
898
+ found.push(cur);
899
+ else
900
+ return cur;
901
+ }
902
+ } catch (ex) {
903
+ }
904
+ }
905
+ }
906
+ if (opt.all && found.length)
907
+ return found;
908
+ if (opt.nothrow)
909
+ return null;
910
+ throw getNotFoundError(cmd);
911
+ };
912
+ module2.exports = which2;
913
+ which2.sync = whichSync;
914
+ }
915
+ });
916
+
917
+ // node_modules/debounce/index.js
918
+ var require_debounce = __commonJS({
919
+ "node_modules/debounce/index.js"(exports2, module2) {
920
+ function debounce3(func, wait, immediate) {
921
+ var timeout, args, context, timestamp, result;
922
+ if (null == wait) wait = 100;
923
+ function later() {
924
+ var last = Date.now() - timestamp;
925
+ if (last < wait && last >= 0) {
926
+ timeout = setTimeout(later, wait - last);
927
+ } else {
928
+ timeout = null;
929
+ if (!immediate) {
930
+ result = func.apply(context, args);
931
+ context = args = null;
932
+ }
933
+ }
934
+ }
935
+ ;
936
936
  var debounced = function() {
937
937
  context = this;
938
938
  args = arguments;
939
939
  timestamp = Date.now();
940
940
  var callNow = immediate && !timeout;
941
- if (!timeout) timeout = setTimeout(later, wait2);
941
+ if (!timeout) timeout = setTimeout(later, wait);
942
942
  if (callNow) {
943
943
  result = func.apply(context, args);
944
944
  context = args = null;
@@ -4533,7 +4533,8 @@ var require_lib = __commonJS({
4533
4533
  // src/index.ts
4534
4534
  var index_exports = {};
4535
4535
  __export(index_exports, {
4536
- activate: () => activate
4536
+ activate: () => activate,
4537
+ formatBlameText: () => formatBlameText
4537
4538
  });
4538
4539
  module.exports = __toCommonJS(index_exports);
4539
4540
  var import_coc16 = require("coc.nvim");
@@ -4583,290 +4584,17 @@ var DEFAULT_TYPES = [
4583
4584
  ];
4584
4585
 
4585
4586
  // src/lists/bcommits.ts
4586
- var import_child_process2 = require("child_process");
4587
- var import_coc2 = require("coc.nvim");
4587
+ var import_coc = require("coc.nvim");
4588
4588
  var import_events = require("events");
4589
4589
  var import_readline = __toESM(require("readline"));
4590
-
4591
- // src/util.ts
4592
- var import_child_process = require("child_process");
4593
- var import_coc = require("coc.nvim");
4594
- var import_path = __toESM(require("path"));
4595
- var import_which = __toESM(require_which());
4596
- function reverseLine(line) {
4597
- if (line.startsWith("-")) return "+" + line.slice(1);
4598
- if (line.startsWith("+")) return "-" + line.slice(1);
4599
- return line;
4600
- }
4601
- function createUnstagePatch(relpath, chunk) {
4602
- if (chunk.remove.count == 0 && chunk.add.count == 0) return "";
4603
- let head = `@@ -${chunk.add.lnum},${chunk.add.count} +${chunk.add.lnum + 1 - chunk.add.count},${chunk.remove.count} @@`;
4604
- if (!head) return "";
4605
- const lines = [
4606
- `diff --git a/${relpath} b/${relpath}`,
4607
- `index 000000..000000 100644`,
4608
- `--- a/${relpath}`,
4609
- `+++ b/${relpath}`,
4610
- head
4611
- ];
4612
- lines.push(...chunk.lines.map((s) => reverseLine(s)));
4613
- lines.push("");
4614
- return lines.join("\n");
4615
- }
4616
- function wait(ms) {
4617
- return new Promise((resolve) => {
4618
- setTimeout(() => {
4619
- resolve(void 0);
4620
- }, ms);
4621
- });
4622
- }
4623
- function shellescape(s) {
4624
- if (process.platform == "win32") {
4625
- return `"${s.replace(/"/g, '\\"')}"`;
4626
- }
4627
- if (/[^A-Za-z0-9_\/:=-]/.test(s)) {
4628
- s = "'" + s.replace(/'/g, "'\\''") + "'";
4629
- s = s.replace(/^(?:'')+/g, "").replace(/\\'''/g, "\\'");
4630
- return s;
4590
+ var CommitsTask = class extends import_events.EventEmitter {
4591
+ constructor(root, file) {
4592
+ super();
4593
+ this.root = root;
4594
+ this.file = file;
4631
4595
  }
4632
- return s;
4633
- }
4634
- function toUnixSlash(fsPath) {
4635
- if (process.platform == "win32") {
4636
- return fsPath.replace(/\\/g, "/");
4637
- }
4638
- return fsPath;
4639
- }
4640
- async function safeRun(cmd, opts = {}) {
4641
- try {
4642
- return await runCommand(cmd, opts, 5e3);
4643
- } catch (e) {
4644
- console.error(e.message);
4645
- return null;
4646
- }
4647
- }
4648
- function spawnCommand(cmd, args, cwd) {
4649
- const cp2 = (0, import_child_process.spawn)(cmd, args, { cwd });
4650
- let res = "";
4651
- return new Promise((resolve, reject) => {
4652
- cp2.stdout.on("data", (data) => {
4653
- res += data.toString();
4654
- });
4655
- cp2.stderr.on("data", (data) => {
4656
- import_coc.window.showErrorMessage(`"${cmd} ${args.join(" ")}" error: ${data.toString()}`);
4657
- });
4658
- cp2.on("close", (code) => {
4659
- if (code != 0) {
4660
- return reject(new Error(`${cmd} exited with code ${code}`));
4661
- }
4662
- resolve(res);
4663
- });
4664
- });
4665
- }
4666
- function runCommand(cmd, opts = {}, timeout) {
4667
- opts.maxBuffer = 5 * 1024 * 1024;
4668
- return new Promise((resolve, reject) => {
4669
- let timer;
4670
- if (timeout) {
4671
- timer = setTimeout(() => {
4672
- reject(new Error(`timeout after ${timeout}s`));
4673
- }, timeout * 1e3);
4674
- }
4675
- (0, import_child_process.exec)(cmd, opts, (err, stdout, stderr) => {
4676
- if (timer) clearTimeout(timer);
4677
- if (err) {
4678
- reject(new Error(`exited with ${err.code}
4679
- ${stderr}`));
4680
- return;
4681
- }
4682
- resolve(stdout);
4683
- });
4684
- });
4685
- }
4686
- function getStdout(cmd, opts = {}, timeout) {
4687
- return new Promise((resolve, reject) => {
4688
- let timer;
4689
- if (timeout) {
4690
- timer = setTimeout(() => {
4691
- reject(new Error(`timeout after ${timeout}s`));
4692
- }, timeout * 1e3);
4693
- }
4694
- opts.maxBuffer = 5 * 1024 * 1024;
4695
- (0, import_child_process.exec)(cmd, opts, (_err, stdout) => {
4696
- if (timer) clearTimeout(timer);
4697
- if (stdout) {
4698
- resolve(stdout);
4699
- return;
4700
- }
4701
- resolve(void 0);
4702
- });
4703
- });
4704
- }
4705
- function equals(one, other) {
4706
- if (one === other) {
4707
- return true;
4708
- }
4709
- if (one === null || one === void 0 || other === null || other === void 0) {
4710
- return false;
4711
- }
4712
- if (typeof one !== typeof other) {
4713
- return false;
4714
- }
4715
- if (typeof one !== "object") {
4716
- return false;
4717
- }
4718
- if (Array.isArray(one) !== Array.isArray(other)) {
4719
- return false;
4720
- }
4721
- let i;
4722
- let key;
4723
- if (Array.isArray(one)) {
4724
- if (one.length !== other.length) {
4725
- return false;
4726
- }
4727
- for (i = 0; i < one.length; i++) {
4728
- if (!equals(one[i], other[i])) {
4729
- return false;
4730
- }
4731
- }
4732
- } else {
4733
- const oneKeys = [];
4734
- for (key in one) {
4735
- oneKeys.push(key);
4736
- }
4737
- oneKeys.sort();
4738
- const otherKeys = [];
4739
- for (key in other) {
4740
- otherKeys.push(key);
4741
- }
4742
- otherKeys.sort();
4743
- if (!equals(oneKeys, otherKeys)) {
4744
- return false;
4745
- }
4746
- for (i = 0; i < oneKeys.length; i++) {
4747
- if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
4748
- return false;
4749
- }
4750
- }
4751
- }
4752
- return true;
4753
- }
4754
- function getRepoUrl(remote) {
4755
- if (import_path.default.isAbsolute(remote)) return null;
4756
- let url = remote.replace(/\s+$/, "").replace(/\.git$/, "");
4757
- if (url.startsWith("git@")) {
4758
- let str = url.slice(4);
4759
- let parts = str.split(":", 2);
4760
- url = `https://${parts[0]}/${parts[1]}`;
4761
- }
4762
- return url;
4763
- }
4764
- function getUrl(fix, repoURL, name, filepath, lines) {
4765
- let anchor = "";
4766
- if (lines && Array.isArray(lines)) {
4767
- anchor = lines ? lines.map((l) => `L${l}`).join("-") : "";
4768
- } else if (typeof lines == "string") {
4769
- anchor = lines;
4770
- }
4771
- let url = repoURL + "/blob/" + name + "/" + filepath + (anchor ? "#" + anchor : "");
4772
- let parts = fix.split("|");
4773
- let match = RegExp(parts[0]), result = parts[1];
4774
- return url.replace(match, result);
4775
- }
4776
- function parseVersion(raw) {
4777
- return raw.replace(/^git version /, "");
4778
- }
4779
- function findSystemGitWin32(base, onLookup) {
4780
- if (!base) {
4781
- return Promise.reject("Not found");
4782
- }
4783
- return findSpecificGit(import_path.default.join(base, "Git", "cmd", "git.exe"), onLookup);
4784
- }
4785
- function findGitWin32InPath(onLookup) {
4786
- const whichPromise = new Promise((c, e) => (0, import_which.default)("git.exe", (err, path8) => err ? e(err) : c(path8)));
4787
- return whichPromise.then((path8) => findSpecificGit(path8, onLookup));
4788
- }
4789
- function findGitWin32(onLookup) {
4790
- return findSystemGitWin32(process.env["ProgramW6432"], onLookup).then(void 0, () => findSystemGitWin32(process.env["ProgramFiles(x86)"], onLookup)).then(void 0, () => findSystemGitWin32(process.env["ProgramFiles"], onLookup)).then(void 0, () => findSystemGitWin32(import_path.default.join(process.env["LocalAppData"], "Programs"), onLookup)).then(void 0, () => findGitWin32InPath(onLookup));
4791
- }
4792
- function findSpecificGit(path8, onLookup) {
4793
- return new Promise((c, e) => {
4794
- onLookup(path8);
4795
- const buffers = [];
4796
- const child = (0, import_child_process.spawn)(path8, ["--version"]);
4797
- child.stdout.on("data", (b) => buffers.push(b));
4798
- child.on("error", cpErrorHandler(e));
4799
- child.on("exit", (code) => code ? e(new Error("Not found")) : c({ path: path8, version: parseVersion(Buffer.concat(buffers).toString("utf8").trim()) }));
4800
- });
4801
- }
4802
- function cpErrorHandler(cb) {
4803
- return (err) => {
4804
- if (/ENOENT/.test(err.message)) {
4805
- err = new Error("Failed to execute git (ENOENT)");
4806
- }
4807
- cb(err);
4808
- };
4809
- }
4810
- function findGitDarwin(onLookup) {
4811
- return new Promise((c, e) => {
4812
- (0, import_child_process.exec)("which git", (err, gitPathBuffer) => {
4813
- if (err) {
4814
- return e("git not found");
4815
- }
4816
- const path8 = gitPathBuffer.toString().replace(/^\s+|\s+$/g, "");
4817
- function getVersion(path9) {
4818
- onLookup(path9);
4819
- (0, import_child_process.exec)("git --version", (err2, stdout) => {
4820
- if (err2) {
4821
- return e("git not found");
4822
- }
4823
- return c({ path: path9, version: parseVersion(stdout.trim()) });
4824
- });
4825
- }
4826
- if (path8 !== "/usr/bin/git") {
4827
- return getVersion(path8);
4828
- }
4829
- getVersion(path8);
4830
- (0, import_child_process.exec)("xcode-select -p", (err2) => {
4831
- if (err2 && err2.code === 2) {
4832
- return e("git not found");
4833
- }
4834
- });
4835
- });
4836
- });
4837
- }
4838
- function findGit(hint, onLookup) {
4839
- const first = hint ? findSpecificGit(hint, onLookup) : Promise.reject(null);
4840
- return first.then(void 0, () => {
4841
- switch (process.platform) {
4842
- case "darwin":
4843
- return findGitDarwin(onLookup);
4844
- case "win32":
4845
- return findGitWin32(onLookup);
4846
- default:
4847
- return findSpecificGit("git", onLookup);
4848
- }
4849
- }).then(null, () => Promise.reject(new Error("Git installation not found.")));
4850
- }
4851
- function onceEvent(event) {
4852
- return (listener, thisArgs = null, disposables) => {
4853
- const result = event((e) => {
4854
- result.dispose();
4855
- return listener.call(thisArgs, e);
4856
- }, null, disposables);
4857
- return result;
4858
- };
4859
- }
4860
-
4861
- // src/lists/bcommits.ts
4862
- var CommitsTask = class extends import_events.EventEmitter {
4863
- constructor(root, file) {
4864
- super();
4865
- this.root = root;
4866
- this.file = file;
4867
- }
4868
- start(cmd, args, cwd) {
4869
- this.process = (0, import_child_process2.spawn)(cmd, args, { cwd });
4596
+ start(process2) {
4597
+ this.process = process2;
4870
4598
  this.process.on("error", (e) => {
4871
4599
  this.emit("error", e.message);
4872
4600
  });
@@ -4876,7 +4604,7 @@ var CommitsTask = class extends import_events.EventEmitter {
4876
4604
  const rl = import_readline.default.createInterface(this.process.stdout);
4877
4605
  rl.on("line", (line) => {
4878
4606
  if (!line.length) return;
4879
- let res = (0, import_coc2.ansiparse)(line);
4607
+ let res = (0, import_coc.ansiparse)(line);
4880
4608
  let idx = res.findIndex((o) => o.foreground == "yellow");
4881
4609
  let message = idx == -1 ? null : res[idx + 1].text;
4882
4610
  let item = res.find((o) => o.foreground == "red" && o.text.length > 4);
@@ -4901,7 +4629,7 @@ var CommitsTask = class extends import_events.EventEmitter {
4901
4629
  }
4902
4630
  }
4903
4631
  };
4904
- var Bcommits = class extends import_coc2.BasicList {
4632
+ var Bcommits = class extends import_coc.BasicList {
4905
4633
  constructor(nvim, manager) {
4906
4634
  super();
4907
4635
  this.manager = manager;
@@ -4912,7 +4640,7 @@ var Bcommits = class extends import_coc2.BasicList {
4912
4640
  let { commit, root } = item.data;
4913
4641
  let lines = [];
4914
4642
  if (commit) {
4915
- let content = await (0, import_coc2.runCommand)(`git --no-pager show ${commit}`, { cwd: root });
4643
+ let content = (await this.manager.git.exec(root, ["--no-pager", "show", commit])).stdout;
4916
4644
  lines = content.trim().split("\n");
4917
4645
  }
4918
4646
  await this.preview({
@@ -4931,7 +4659,7 @@ var Bcommits = class extends import_coc2.BasicList {
4931
4659
  await nvim.command(`${cmd} ${commit}`);
4932
4660
  } else {
4933
4661
  let cmd = ctx.options.position === "tab" ? "tabe" : "edit";
4934
- let content = await (0, import_coc2.runCommand)(`git --no-pager show ${commit}`, { cwd: root });
4662
+ let content = (await this.manager.git.exec(root, ["--no-pager", "show", commit])).stdout;
4935
4663
  let lines = content.trim().split("\n");
4936
4664
  nvim.pauseNotification();
4937
4665
  nvim.command(`${cmd} +setl\\ buftype=nofile [commit ${commit}]`, true);
@@ -4946,11 +4674,12 @@ var Bcommits = class extends import_coc2.BasicList {
4946
4674
  this.addAction("view", async (item, context) => {
4947
4675
  let { commit, root, file } = item.data;
4948
4676
  let { window: window10 } = context;
4949
- let content = await (0, import_coc2.runCommand)(`git show ${commit}:${shellescape(file)}`, { cwd: root });
4677
+ let content = (await this.manager.git.exec(root, ["show", `${commit}:${file}`])).stdout;
4950
4678
  let lines = content.replace(/\n$/, "").split("\n");
4679
+ let name = await nvim.call("fnameescape", [`(${commit}) ${file}`]);
4951
4680
  nvim.pauseNotification();
4952
4681
  nvim.call("win_gotoid", [window10.id], true);
4953
- nvim.command(`exe "tabe ".fnameescape('(${commit}) ${file}')`, true);
4682
+ nvim.command(`tabe ${name}`, true);
4954
4683
  nvim.call("append", [0, lines], true);
4955
4684
  nvim.command("normal! Gdd", true);
4956
4685
  nvim.command(`exe 1`, true);
@@ -4963,7 +4692,7 @@ var Bcommits = class extends import_coc2.BasicList {
4963
4692
  let filetype = await buffer.getOption("filetype");
4964
4693
  let { root, commit, file } = item.data;
4965
4694
  if (!commit) return;
4966
- let content = await (0, import_coc2.runCommand)(`git --no-pager show --no-color ${commit}:${file}`, { cwd: root });
4695
+ let content = (await this.manager.git.exec(root, ["--no-pager", "show", "--no-color", `${commit}:${file}`])).stdout;
4967
4696
  if (!content) return;
4968
4697
  let lines = content.replace(/\n$/, "").split(/\r?\n/);
4969
4698
  nvim.pauseNotification();
@@ -4980,7 +4709,7 @@ var Bcommits = class extends import_coc2.BasicList {
4980
4709
  nvim.command(`call setpos('.', [bufnr('%'), 0, 0, 0])`, true);
4981
4710
  await nvim.resumeNotification();
4982
4711
  });
4983
- import_coc2.events.on("BufEnter", async (bufnr) => {
4712
+ import_coc.events.on("BufEnter", async (bufnr) => {
4984
4713
  if (!this.bufnr || bufnr != this.bufnr) return;
4985
4714
  let diff = await nvim.eval("&diff");
4986
4715
  if (!diff) return;
@@ -5015,13 +4744,13 @@ var Bcommits = class extends import_coc2.BasicList {
5015
4744
  relpath
5016
4745
  ];
5017
4746
  let task = new CommitsTask(root, relpath);
5018
- task.start("git", args, root);
4747
+ task.start(this.manager.git.stream(root, args));
5019
4748
  return task;
5020
4749
  }
5021
4750
  };
5022
4751
 
5023
4752
  // src/lists/branches.ts
5024
- var import_coc3 = require("coc.nvim");
4753
+ var import_coc2 = require("coc.nvim");
5025
4754
  var import_safe = __toESM(require_safe());
5026
4755
  var Branches = class {
5027
4756
  constructor(nvim, manager) {
@@ -5034,7 +4763,7 @@ var Branches = class {
5034
4763
  name: "checkout",
5035
4764
  execute: async (item) => {
5036
4765
  let { root, branch } = item.data;
5037
- await safeRun(`git checkout ${branch}`, { cwd: root });
4766
+ await this.manager.git.exec(root, ["checkout", branch]);
5038
4767
  nvim.command("bufdo e", true);
5039
4768
  }
5040
4769
  });
@@ -5043,22 +4772,23 @@ var Branches = class {
5043
4772
  persist: true,
5044
4773
  reload: true,
5045
4774
  execute: async (item) => {
5046
- let cmd;
5047
4775
  let { root, branch, remote } = item.data;
5048
4776
  if (remote) {
5049
- let res = await import_coc3.window.showPrompt(`Delete remote branch ${branch}?`);
4777
+ let res = await import_coc2.window.showPrompt(`Delete remote branch ${branch}?`);
5050
4778
  if (!res) return;
5051
- let parts = branch.split("/", 2);
5052
- cmd = `git push ${parts[0]} --delete ${parts[1]}`;
5053
- await safeRun(cmd, { cwd: root });
5054
- await safeRun(`git fetch -p ${parts[0]}`);
4779
+ let separator = branch.indexOf("/");
4780
+ if (separator === -1) throw new Error(`Invalid remote branch: ${branch}`);
4781
+ let remoteName = branch.slice(0, separator);
4782
+ let remoteBranch = branch.slice(separator + 1);
4783
+ await this.manager.git.exec(root, ["push", remoteName, "--delete", remoteBranch]);
4784
+ await this.manager.git.exec(root, ["fetch", "-p", remoteName]);
5055
4785
  } else {
5056
- cmd = `git branch -d ${branch}`;
5057
- let res = await safeRun(cmd, { cwd: root });
5058
- if (res == null) {
5059
- let res2 = await import_coc3.window.showPrompt(`Delete failed, force delete ${branch}?`);
5060
- if (!res2) return;
5061
- await safeRun(`git branch -D ${branch}`, { cwd: root });
4786
+ try {
4787
+ await this.manager.git.exec(root, ["branch", "-d", branch]);
4788
+ } catch (_e) {
4789
+ let res = await import_coc2.window.showPrompt(`Delete failed, force delete ${branch}?`);
4790
+ if (!res) return;
4791
+ await this.manager.git.exec(root, ["branch", "-D", branch]);
5062
4792
  }
5063
4793
  }
5064
4794
  }
@@ -5067,8 +4797,7 @@ var Branches = class {
5067
4797
  name: "merge",
5068
4798
  execute: async (item) => {
5069
4799
  let { root, branch } = item.data;
5070
- let cmd = `git merge ${branch}`;
5071
- await safeRun(cmd, { cwd: root });
4800
+ await this.manager.git.exec(root, ["merge", branch]);
5072
4801
  nvim.command("bufdo e", true);
5073
4802
  }
5074
4803
  });
@@ -5076,8 +4805,7 @@ var Branches = class {
5076
4805
  name: "rebase",
5077
4806
  execute: async (item) => {
5078
4807
  let { root, branch } = item.data;
5079
- let cmd = `git rebase ${branch}`;
5080
- await safeRun(cmd, { cwd: root });
4808
+ await this.manager.git.exec(root, ["rebase", branch]);
5081
4809
  nvim.command("bufdo e", true);
5082
4810
  }
5083
4811
  });
@@ -5112,8 +4840,7 @@ var Branches = class {
5112
4840
  };
5113
4841
 
5114
4842
  // src/lists/commits.ts
5115
- var import_child_process3 = require("child_process");
5116
- var import_coc4 = require("coc.nvim");
4843
+ var import_coc3 = require("coc.nvim");
5117
4844
  var import_events2 = require("events");
5118
4845
  var import_readline2 = __toESM(require("readline"));
5119
4846
  var CommitsTask2 = class extends import_events2.EventEmitter {
@@ -5121,8 +4848,8 @@ var CommitsTask2 = class extends import_events2.EventEmitter {
5121
4848
  super();
5122
4849
  this.root = root;
5123
4850
  }
5124
- start(cmd, args, cwd) {
5125
- this.process = (0, import_child_process3.spawn)(cmd, args, { cwd });
4851
+ start(process2) {
4852
+ this.process = process2;
5126
4853
  this.process.on("error", (e) => {
5127
4854
  this.emit("error", e.message);
5128
4855
  });
@@ -5132,7 +4859,7 @@ var CommitsTask2 = class extends import_events2.EventEmitter {
5132
4859
  const rl = import_readline2.default.createInterface(this.process.stdout);
5133
4860
  rl.on("line", (line) => {
5134
4861
  if (!line.length) return;
5135
- let res = (0, import_coc4.ansiparse)(line);
4862
+ let res = (0, import_coc3.ansiparse)(line);
5136
4863
  let idx = res.findIndex((o) => o.foreground == "yellow");
5137
4864
  let message = idx == -1 ? null : res[idx + 1].text;
5138
4865
  let item = res.find((o) => o.foreground == "red" && o.text.length > 4);
@@ -5156,7 +4883,7 @@ var CommitsTask2 = class extends import_events2.EventEmitter {
5156
4883
  }
5157
4884
  }
5158
4885
  };
5159
- var Commits = class extends import_coc4.BasicList {
4886
+ var Commits = class extends import_coc3.BasicList {
5160
4887
  constructor(nvim, manager) {
5161
4888
  super();
5162
4889
  this.manager = manager;
@@ -5168,12 +4895,11 @@ var Commits = class extends import_coc4.BasicList {
5168
4895
  let { commit, root } = item.data;
5169
4896
  let lines = [];
5170
4897
  if (commit) {
5171
- lines = this.cachedCommits.get(commit);
4898
+ lines = this.getCached(root, commit);
5172
4899
  if (!lines) {
5173
- let content = await safeRun(`git --no-pager show ${commit}`, { cwd: root });
5174
- if (content == null) return;
4900
+ let content = (await this.manager.git.exec(root, ["--no-pager", "show", commit])).stdout;
5175
4901
  lines = content.replace(/\n$/, "").split(/\r?\n/);
5176
- this.cachedCommits.set(commit, lines);
4902
+ this.setCached(root, commit, lines);
5177
4903
  }
5178
4904
  }
5179
4905
  await this.preview({
@@ -5191,12 +4917,11 @@ var Commits = class extends import_coc4.BasicList {
5191
4917
  let cmd = ctx.options.position === "tab" ? "Gtabedit" : "Gedit";
5192
4918
  await nvim.command(`${cmd} ${commit}`);
5193
4919
  } else {
5194
- let lines = this.cachedCommits.get(commit);
4920
+ let lines = this.getCached(root, commit);
5195
4921
  if (!lines) {
5196
- let content = await safeRun(`git --no-pager show ${commit}`, { cwd: root });
5197
- if (content == null) return;
4922
+ let content = (await this.manager.git.exec(root, ["--no-pager", "show", commit])).stdout;
5198
4923
  lines = content.replace(/\n$/, "").split(/\r?\n/);
5199
- this.cachedCommits.set(commit, lines);
4924
+ this.setCached(root, commit, lines);
5200
4925
  }
5201
4926
  let cmd = ctx.options.position === "tab" ? "tabe" : "edit";
5202
4927
  nvim.pauseNotification();
@@ -5227,20 +4952,18 @@ var Commits = class extends import_coc4.BasicList {
5227
4952
  opt = "--hard";
5228
4953
  break;
5229
4954
  }
5230
- await runCommand(`git reset ${opt} ${commit}`, { cwd: root });
5231
- this.nvim.command("checktime", true);
5232
- await wait(100);
4955
+ await this.manager.git.exec(root, ["reset", opt, commit]);
4956
+ await this.nvim.command("checktime");
5233
4957
  });
5234
4958
  this.addAction("checkout", async (item) => {
5235
4959
  let { root, commit } = item.data;
5236
4960
  if (!commit) return;
5237
- await runCommand(`git checkout ${commit}`, { cwd: root });
4961
+ await this.manager.git.exec(root, ["checkout", commit]);
5238
4962
  });
5239
4963
  this.addMultipleAction("revert", async (items) => {
5240
4964
  let list = items.filter((item) => item.data.commit != null);
5241
4965
  if (!list.length) return;
5242
- let arg = list.map((o) => o.data.commit).join(" ");
5243
- await runCommand(`git revert ${arg}`, { cwd: list[0].data.root });
4966
+ await this.manager.git.exec(list[0].data.root, ["revert", ...list.map((o) => o.data.commit)]);
5244
4967
  });
5245
4968
  this.addMultipleAction("tabdiff", async (items) => {
5246
4969
  let list = items.filter((item) => item.data.commit != null);
@@ -5251,7 +4974,7 @@ var Commits = class extends import_coc4.BasicList {
5251
4974
  } else {
5252
4975
  arg = `${list[1].data.commit} ${list[0].data.commit}`;
5253
4976
  }
5254
- let content = await runCommand(`git --no-pager diff --no-ext-diff ${this.manager.diffOptions.join(" ")} ${arg}`, { cwd: list[0].data.root });
4977
+ let content = (await this.manager.git.exec(list[0].data.root, ["--no-pager", "diff", "--no-ext-diff", ...this.manager.diffOptions, ...arg.split(" ")])).stdout;
5255
4978
  let lines = content.replace(/\n$/, "").split("\n");
5256
4979
  nvim.pauseNotification();
5257
4980
  nvim.command(`tabe [diff ${arg}]`, true);
@@ -5275,7 +4998,7 @@ var Commits = class extends import_coc4.BasicList {
5275
4998
  } else {
5276
4999
  arg = `${list[1].data.commit} ${list[0].data.commit}`;
5277
5000
  }
5278
- let content = await runCommand(`git --no-pager diff ${this.manager.diffOptions.join(" ")} --no-ext-diff ${arg}`, { cwd: list[0].data.root });
5001
+ let content = (await this.manager.git.exec(list[0].data.root, ["--no-pager", "diff", ...this.manager.diffOptions, "--no-ext-diff", ...arg.split(" ")])).stdout;
5279
5002
  let lines = content.replace(/\n$/, "").split("\n");
5280
5003
  let winid = context.listWindow.id;
5281
5004
  let mod = context.options.position == "tab" ? "below" : "above";
@@ -5302,6 +5025,20 @@ var Commits = class extends import_coc4.BasicList {
5302
5025
  nvim.command(`CocList gfiles ${commit}`, true);
5303
5026
  });
5304
5027
  }
5028
+ cacheKey(root, commit) {
5029
+ return `${root}\0${commit}`;
5030
+ }
5031
+ getCached(root, commit) {
5032
+ return this.cachedCommits.get(this.cacheKey(root, commit));
5033
+ }
5034
+ setCached(root, commit, lines) {
5035
+ const key = this.cacheKey(root, commit);
5036
+ this.cachedCommits.delete(key);
5037
+ this.cachedCommits.set(key, lines);
5038
+ if (this.cachedCommits.size > 100) {
5039
+ this.cachedCommits.delete(this.cachedCommits.keys().next().value);
5040
+ }
5041
+ }
5305
5042
  async loadItems(context) {
5306
5043
  let buf = await context.window.buffer;
5307
5044
  let root = await this.manager.resolveGitRootFromBufferOrCwd(buf.id);
@@ -5320,15 +5057,23 @@ var Commits = class extends import_coc4.BasicList {
5320
5057
  ...context.args
5321
5058
  ];
5322
5059
  let task = new CommitsTask2(root);
5323
- task.start("git", args, root);
5060
+ task.start(this.manager.git.stream(root, args));
5324
5061
  return task;
5325
5062
  }
5326
5063
  };
5327
5064
 
5328
5065
  // src/lists/gfiles.ts
5329
- var import_coc5 = require("coc.nvim");
5330
- var import_path2 = __toESM(require("path"));
5331
- var Gfiles = class extends import_coc5.BasicList {
5066
+ var import_coc4 = require("coc.nvim");
5067
+ var import_path = __toESM(require("path"));
5068
+ function parseTreeEntry(entry) {
5069
+ const separator = entry.indexOf(" ");
5070
+ if (separator === -1) return void 0;
5071
+ const head = entry.slice(0, separator);
5072
+ const filepath = entry.slice(separator + 1);
5073
+ const sha = head.split(/\s+/)[2];
5074
+ return sha ? { sha, filepath } : void 0;
5075
+ }
5076
+ var Gfiles = class extends import_coc4.BasicList {
5332
5077
  constructor(nvim, manager) {
5333
5078
  super();
5334
5079
  this.manager = manager;
@@ -5337,7 +5082,7 @@ var Gfiles = class extends import_coc5.BasicList {
5337
5082
  this.detail = "Pass git sha as first command argument, when empty, HEAD is used.\nExample: :CocList gfiles 7b5c5cb";
5338
5083
  this.defaultAction = "edit";
5339
5084
  this.actions = [];
5340
- const preferences = import_coc5.workspace.getConfiguration("coc.preferences");
5085
+ const preferences = import_coc4.workspace.getConfiguration("coc.preferences");
5341
5086
  let jumpCommand = preferences.get("jumpCommand", "edit");
5342
5087
  for (let name of ["edit", "tabe", "vsplit", "split"]) {
5343
5088
  this.addAction(name, async (item, ctx) => {
@@ -5346,15 +5091,16 @@ var Gfiles = class extends import_coc5.BasicList {
5346
5091
  if (branch == "HEAD") {
5347
5092
  let cmd2 = name == "edit" ? jumpCommand : name;
5348
5093
  if (ctx.options.position === "tab") cmd2 = "tabe";
5349
- let fullpath = import_path2.default.join(root, filepath);
5350
- await import_coc5.workspace.jumpTo(import_coc5.Uri.file(fullpath).toString(), null, cmd2);
5094
+ let fullpath = import_path.default.join(root, filepath);
5095
+ await import_coc4.workspace.jumpTo(import_coc4.Uri.file(fullpath).toString(), null, cmd2);
5351
5096
  return;
5352
5097
  }
5353
- let content = await runCommand(`git cat-file -p ${sha}`, { cwd: root });
5098
+ let content = (await this.manager.git.exec(root, ["cat-file", "-p", sha])).stdout;
5354
5099
  let lines = content.replace(/\n$/, "").split("\n");
5355
5100
  let cmd = name == "edit" ? jumpCommand : name;
5101
+ let bufferName = await nvim.call("fnameescape", [`(${branch}) ${filepath}`]);
5356
5102
  nvim.pauseNotification();
5357
- nvim.command(`exe "${cmd} ".fnameescape('(${branch}) ${filepath}')`, true);
5103
+ nvim.command(`${cmd} ${bufferName}`, true);
5358
5104
  nvim.call("append", [0, lines], true);
5359
5105
  nvim.command("normal! Gdd", true);
5360
5106
  nvim.command(`exe 1`, true);
@@ -5363,54 +5109,291 @@ var Gfiles = class extends import_coc5.BasicList {
5363
5109
  await nvim.resumeNotification();
5364
5110
  }, { tabPersist: name === "edit" });
5365
5111
  }
5366
- this.addAction("preview", async (item, context) => {
5367
- let { root, sha, filepath, branch } = item.data;
5368
- if (!sha) return;
5369
- let content = await runCommand(`git --no-pager diff ${this.manager.diffOptions.join(" ")} --no-ext-diff ${branch} -- ${shellescape(filepath)}`, { cwd: root });
5370
- let lines = content.replace(/\n$/, "").split("\n");
5371
- await this.preview({
5372
- lines,
5373
- filetype: "diff",
5374
- sketch: true,
5375
- bufname: `(diff ${branch}) ${import_path2.default.basename(filepath)}`
5376
- }, context);
5377
- });
5112
+ this.addAction("preview", async (item, context) => {
5113
+ let { root, sha, filepath, branch } = item.data;
5114
+ if (!sha) return;
5115
+ let content = (await this.manager.git.exec(root, ["--no-pager", "diff", ...this.manager.diffOptions, "--no-ext-diff", branch, "--", filepath])).stdout;
5116
+ let lines = content.replace(/\n$/, "").split("\n");
5117
+ await this.preview({
5118
+ lines,
5119
+ filetype: "diff",
5120
+ sketch: true,
5121
+ bufname: `(diff ${branch}) ${import_path.default.basename(filepath)}`
5122
+ }, context);
5123
+ });
5124
+ }
5125
+ async loadItems(context) {
5126
+ let buf = await context.window.buffer;
5127
+ let root = await this.manager.resolveGitRootFromBufferOrCwd(buf.id);
5128
+ if (!root) {
5129
+ throw new Error(`Can't resolve git root.`);
5130
+ return;
5131
+ }
5132
+ const { args } = context;
5133
+ let revisions = args.length ? args : ["HEAD"];
5134
+ const output = (await this.manager.git.exec(root, ["-c", "core.quotepath=false", "ls-tree", "-r", "-z", ...revisions])).stdout;
5135
+ if (!output) return [];
5136
+ let res = [];
5137
+ for (let line of output.split("\0")) {
5138
+ if (!line) continue;
5139
+ const entry = parseTreeEntry(line);
5140
+ if (!entry) continue;
5141
+ const { sha, filepath } = entry;
5142
+ res.push({
5143
+ label: filepath,
5144
+ data: {
5145
+ branch: args[0] || "HEAD",
5146
+ filepath,
5147
+ root,
5148
+ sha
5149
+ }
5150
+ });
5151
+ }
5152
+ return res;
5153
+ }
5154
+ };
5155
+
5156
+ // src/lists/gstatus.ts
5157
+ var import_coc6 = require("coc.nvim");
5158
+ var import_safe2 = __toESM(require_safe());
5159
+ var import_fs = __toESM(require("fs"));
5160
+ var import_path3 = __toESM(require("path"));
5161
+
5162
+ // src/util.ts
5163
+ var import_child_process = require("child_process");
5164
+ var import_coc5 = require("coc.nvim");
5165
+ var import_path2 = __toESM(require("path"));
5166
+ var import_which = __toESM(require_which());
5167
+ function reverseLine(line) {
5168
+ if (line.startsWith("-")) return "+" + line.slice(1);
5169
+ if (line.startsWith("+")) return "-" + line.slice(1);
5170
+ return line;
5171
+ }
5172
+ function quoteGitPath(filepath) {
5173
+ if (!/[\s"\\\x00-\x1f\x7f]/.test(filepath)) return filepath;
5174
+ return `"${filepath.replace(/["\\\x00-\x1f\x7f]/g, (character) => {
5175
+ switch (character) {
5176
+ case '"':
5177
+ return '\\"';
5178
+ case "\\":
5179
+ return "\\\\";
5180
+ case " ":
5181
+ return "\\t";
5182
+ case "\n":
5183
+ return "\\n";
5184
+ case "\r":
5185
+ return "\\r";
5186
+ default:
5187
+ return `\\${character.charCodeAt(0).toString(8).padStart(3, "0")}`;
5188
+ }
5189
+ })}"`;
5190
+ }
5191
+ function createUnstagePatch(relpath, chunk) {
5192
+ if (chunk.remove.count == 0 && chunk.add.count == 0) return "";
5193
+ let head = `@@ -${chunk.add.lnum},${chunk.add.count} +${chunk.add.lnum + 1 - chunk.add.count},${chunk.remove.count} @@`;
5194
+ if (!head) return "";
5195
+ const from = quoteGitPath(`a/${relpath}`);
5196
+ const to = quoteGitPath(`b/${relpath}`);
5197
+ const lines = [
5198
+ `diff --git ${from} ${to}`,
5199
+ `index 000000..000000 100644`,
5200
+ `--- ${from}`,
5201
+ `+++ ${to}`,
5202
+ head
5203
+ ];
5204
+ lines.push(...chunk.lines.map((s) => reverseLine(s)));
5205
+ lines.push("");
5206
+ return lines.join("\n");
5207
+ }
5208
+ function formatBlameText(info, format2 = "(%a %t) %s") {
5209
+ let { author = "", time = "", summary = "", sha = "" } = info;
5210
+ return format2.replace(/%%/g, "\0").replace(/%a/g, author).replace(/%t/g, time).replace(/%s/g, summary).replace(/%S/g, sha.substring(0, 7)).replace(/\u0000/g, "%");
5211
+ }
5212
+ function toUnixSlash(fsPath) {
5213
+ if (process.platform == "win32") {
5214
+ return fsPath.replace(/\\/g, "/");
5215
+ }
5216
+ return fsPath;
5217
+ }
5218
+ function spawnCommand(cmd, args, cwd) {
5219
+ const cp2 = (0, import_child_process.spawn)(cmd, args, { cwd });
5220
+ let res = "";
5221
+ return new Promise((resolve, reject) => {
5222
+ cp2.on("error", reject);
5223
+ cp2.stdout.on("data", (data) => {
5224
+ res += data.toString();
5225
+ });
5226
+ cp2.stderr.on("data", (data) => {
5227
+ import_coc5.window.showErrorMessage(`"${cmd} ${args.join(" ")}" error: ${data.toString()}`);
5228
+ });
5229
+ cp2.on("close", (code) => {
5230
+ if (code != 0) {
5231
+ return reject(new Error(`${cmd} exited with code ${code}`));
5232
+ }
5233
+ resolve(res);
5234
+ });
5235
+ });
5236
+ }
5237
+ function equals(one, other) {
5238
+ if (one === other) {
5239
+ return true;
5240
+ }
5241
+ if (one === null || one === void 0 || other === null || other === void 0) {
5242
+ return false;
5243
+ }
5244
+ if (typeof one !== typeof other) {
5245
+ return false;
5246
+ }
5247
+ if (typeof one !== "object") {
5248
+ return false;
5249
+ }
5250
+ if (Array.isArray(one) !== Array.isArray(other)) {
5251
+ return false;
5252
+ }
5253
+ let i;
5254
+ let key;
5255
+ if (Array.isArray(one)) {
5256
+ if (one.length !== other.length) {
5257
+ return false;
5258
+ }
5259
+ for (i = 0; i < one.length; i++) {
5260
+ if (!equals(one[i], other[i])) {
5261
+ return false;
5262
+ }
5263
+ }
5264
+ } else {
5265
+ const oneKeys = [];
5266
+ for (key in one) {
5267
+ oneKeys.push(key);
5268
+ }
5269
+ oneKeys.sort();
5270
+ const otherKeys = [];
5271
+ for (key in other) {
5272
+ otherKeys.push(key);
5273
+ }
5274
+ otherKeys.sort();
5275
+ if (!equals(oneKeys, otherKeys)) {
5276
+ return false;
5277
+ }
5278
+ for (i = 0; i < oneKeys.length; i++) {
5279
+ if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
5280
+ return false;
5281
+ }
5282
+ }
5378
5283
  }
5379
- async loadItems(context) {
5380
- let buf = await context.window.buffer;
5381
- let root = await this.manager.resolveGitRootFromBufferOrCwd(buf.id);
5382
- if (!root) {
5383
- throw new Error(`Can't resolve git root.`);
5384
- return;
5284
+ return true;
5285
+ }
5286
+ function getRepoUrl(remote) {
5287
+ if (import_path2.default.isAbsolute(remote)) return null;
5288
+ let url = remote.replace(/\s+$/, "").replace(/\.git$/, "");
5289
+ if (url.startsWith("git@")) {
5290
+ let str = url.slice(4);
5291
+ let parts = str.split(":", 2);
5292
+ url = `https://${parts[0]}/${parts[1]}`;
5293
+ } else if (url.startsWith("ssh://git@")) {
5294
+ url = url.replace(/^ssh:\/\/git@([^/]+)\//, "https://$1/");
5295
+ } else if (url.startsWith("git://")) {
5296
+ url = url.replace(/^git:\/\//, "https://");
5297
+ }
5298
+ return /^https?:\/\//.test(url) ? url : null;
5299
+ }
5300
+ function getUrl(fix, repoURL, name, filepath, lines) {
5301
+ let anchor = "";
5302
+ if (lines && Array.isArray(lines)) {
5303
+ anchor = lines ? lines.map((l) => `L${l}`).join("-") : "";
5304
+ } else if (typeof lines == "string") {
5305
+ anchor = lines;
5306
+ }
5307
+ const encodePath = (value) => value.split("/").map(encodeURIComponent).join("/");
5308
+ let url = repoURL + "/blob/" + encodePath(name) + "/" + encodePath(filepath) + (anchor ? "#" + encodeURIComponent(anchor) : "");
5309
+ let parts = fix.split("|");
5310
+ if (parts.length < 2) return url;
5311
+ try {
5312
+ let match = RegExp(parts[0]), result = parts[1];
5313
+ return url.replace(match, result);
5314
+ } catch (_e) {
5315
+ return url;
5316
+ }
5317
+ }
5318
+ function parseVersion(raw) {
5319
+ return raw.replace(/^git version /, "");
5320
+ }
5321
+ function findSystemGitWin32(base, onLookup) {
5322
+ if (!base) {
5323
+ return Promise.reject("Not found");
5324
+ }
5325
+ return findSpecificGit(import_path2.default.join(base, "Git", "cmd", "git.exe"), onLookup);
5326
+ }
5327
+ function findGitWin32InPath(onLookup) {
5328
+ const whichPromise = new Promise((c, e) => (0, import_which.default)("git.exe", (err, path8) => err ? e(err) : c(path8)));
5329
+ return whichPromise.then((path8) => findSpecificGit(path8, onLookup));
5330
+ }
5331
+ function findGitWin32(onLookup) {
5332
+ return findSystemGitWin32(process.env["ProgramW6432"], onLookup).then(void 0, () => findSystemGitWin32(process.env["ProgramFiles(x86)"], onLookup)).then(void 0, () => findSystemGitWin32(process.env["ProgramFiles"], onLookup)).then(void 0, () => findSystemGitWin32(import_path2.default.join(process.env["LocalAppData"], "Programs"), onLookup)).then(void 0, () => findGitWin32InPath(onLookup));
5333
+ }
5334
+ function findSpecificGit(path8, onLookup) {
5335
+ return new Promise((c, e) => {
5336
+ onLookup(path8);
5337
+ const buffers = [];
5338
+ const child = (0, import_child_process.spawn)(path8, ["--version"]);
5339
+ child.stdout.on("data", (b) => buffers.push(b));
5340
+ child.on("error", cpErrorHandler(e));
5341
+ child.on("exit", (code) => code ? e(new Error("Not found")) : c({ path: path8, version: parseVersion(Buffer.concat(buffers).toString("utf8").trim()) }));
5342
+ });
5343
+ }
5344
+ function cpErrorHandler(cb) {
5345
+ return (err) => {
5346
+ if (/ENOENT/.test(err.message)) {
5347
+ err = new Error("Failed to execute git (ENOENT)");
5385
5348
  }
5386
- const { args } = context;
5387
- let arg = args.length ? args.join(" ") : "HEAD";
5388
- let output = await runCommand(`git ls-tree -r ${arg}`, { cwd: root });
5389
- output = output.replace(/\s+$/, "");
5390
- if (!output) return [];
5391
- let res = [];
5392
- for (let line of output.split(/\r?\n/)) {
5393
- let [head, filepath] = line.split(" ", 2);
5394
- let sha = head.split(" ")[2];
5395
- res.push({
5396
- label: filepath,
5397
- data: {
5398
- branch: args[0] || "HEAD",
5399
- filepath,
5400
- root,
5401
- sha
5349
+ cb(err);
5350
+ };
5351
+ }
5352
+ function findGitDarwin(onLookup) {
5353
+ return new Promise((c, e) => {
5354
+ (0, import_child_process.exec)("which git", (err, gitPathBuffer) => {
5355
+ if (err) {
5356
+ return e("git not found");
5357
+ }
5358
+ const path8 = gitPathBuffer.toString().replace(/^\s+|\s+$/g, "");
5359
+ if (path8 !== "/usr/bin/git") {
5360
+ findSpecificGit(path8, onLookup).then(c, e);
5361
+ return;
5362
+ }
5363
+ (0, import_child_process.exec)("xcode-select -p", (err2) => {
5364
+ if (err2 && err2.code === 2) {
5365
+ e("git not found");
5366
+ return;
5402
5367
  }
5368
+ findSpecificGit(path8, onLookup).then(c, e);
5403
5369
  });
5370
+ });
5371
+ });
5372
+ }
5373
+ function findGit(hint, onLookup) {
5374
+ const first = hint ? findSpecificGit(hint, onLookup) : Promise.reject(null);
5375
+ return first.then(void 0, () => {
5376
+ switch (process.platform) {
5377
+ case "darwin":
5378
+ return findGitDarwin(onLookup);
5379
+ case "win32":
5380
+ return findGitWin32(onLookup);
5381
+ default:
5382
+ return findSpecificGit("git", onLookup);
5404
5383
  }
5405
- return res;
5406
- }
5407
- };
5384
+ }).then(null, () => Promise.reject(new Error("Git installation not found.")));
5385
+ }
5386
+ function onceEvent(event) {
5387
+ return (listener, thisArgs = null, disposables) => {
5388
+ const result = event((e) => {
5389
+ result.dispose();
5390
+ return listener.call(thisArgs, e);
5391
+ }, null, disposables);
5392
+ return result;
5393
+ };
5394
+ }
5408
5395
 
5409
5396
  // src/lists/gstatus.ts
5410
- var import_coc6 = require("coc.nvim");
5411
- var import_safe2 = __toESM(require_safe());
5412
- var import_fs = __toESM(require("fs"));
5413
- var import_path3 = __toESM(require("path"));
5414
5397
  var STATUS_MAP = {
5415
5398
  " ": " ",
5416
5399
  M: import_safe2.default.cyan("~"),
@@ -5418,9 +5401,24 @@ var STATUS_MAP = {
5418
5401
  D: import_safe2.default.red("-"),
5419
5402
  R: import_safe2.default.magenta("\u2192"),
5420
5403
  C: import_safe2.default.yellow("C"),
5404
+ T: import_safe2.default.yellow("T"),
5421
5405
  U: import_safe2.default.blue("U"),
5422
- "?": import_safe2.default.gray("?")
5406
+ "?": import_safe2.default.gray("?"),
5407
+ "!": import_safe2.default.gray("!")
5423
5408
  };
5409
+ function parseStatusEntries(output) {
5410
+ let result = [];
5411
+ let entries = output.split("\0");
5412
+ for (let i = 0; i < entries.length; i++) {
5413
+ let line = entries[i];
5414
+ if (!line) continue;
5415
+ result.push({ index: line[0], tree: line[1], relative: line.slice(3) });
5416
+ if (line[0] === "R" || line[0] === "C" || line[1] === "R" || line[1] === "C") {
5417
+ i++;
5418
+ }
5419
+ }
5420
+ return result;
5421
+ }
5424
5422
  var GStatus = class extends import_coc6.BasicList {
5425
5423
  constructor(nvim, manager) {
5426
5424
  super();
@@ -5432,12 +5430,12 @@ var GStatus = class extends import_coc6.BasicList {
5432
5430
  this.addMultipleAction("add", async (items) => {
5433
5431
  let { root } = items[0].data;
5434
5432
  let fileArgs = items.map((o) => o.data.relative);
5435
- await spawnCommand("git", ["add", ...fileArgs], root);
5433
+ await this.manager.git.exec(root, ["add", "--", ...fileArgs]);
5436
5434
  }, { reload: true, persist: true });
5437
5435
  this.addMultipleAction("patch", async (items) => {
5438
5436
  let { root } = items[0].data;
5439
- let fileArgs = items.map((o) => o.data.relative.replace(/\s/, "\\ "));
5440
- let cmd = `git add ${fileArgs.join(" ")} --patch`;
5437
+ let fileArgs = items.map((o) => o.data.relative);
5438
+ let cmd = await this.manager.getTerminalGitCommand(["add", "--patch", "--", ...fileArgs]);
5441
5439
  await nvim.call("coc#util#open_terminal", [{
5442
5440
  cmd,
5443
5441
  cwd: root
@@ -5445,10 +5443,11 @@ var GStatus = class extends import_coc6.BasicList {
5445
5443
  });
5446
5444
  this.addMultipleAction("commit", async (items) => {
5447
5445
  let { root } = items[0].data;
5448
- await nvim.command(`exe "lcd ".fnameescape('${root}')`);
5449
- let filesArg = await nvim.eval(`join(map([${items.map((s) => "'" + s.data.relative + "'").join(",")}],'fnameescape(v:val)'),' ')`);
5446
+ let escapedRoot = await nvim.call("fnameescape", [root]);
5447
+ await nvim.command(`lcd ${escapedRoot}`);
5448
+ let escapedFiles = await Promise.all(items.map((item) => nvim.call("fnameescape", [item.data.relative])));
5450
5449
  try {
5451
- await nvim.command(`G commit -v ${filesArg}`);
5450
+ await nvim.command(`G commit -v -- ${escapedFiles.join(" ")}`);
5452
5451
  } catch (e) {
5453
5452
  import_coc6.window.showErrorMessage(`G commit command failed, make sure fugitive installed.`);
5454
5453
  }
@@ -5474,13 +5473,12 @@ var GStatus = class extends import_coc6.BasicList {
5474
5473
  let hasRmtrash = await nvim.call("executable", ["rmtrash"]);
5475
5474
  let fullpath = import_path3.default.join(root, relative);
5476
5475
  if (hasRmtrash) {
5477
- await runCommand(`rmtrash ${fullpath.replace(/\s/, "\\ ")}`);
5476
+ await spawnCommand("rmtrash", [fullpath], root);
5478
5477
  } else {
5479
- import_fs.default.unlinkSync(fullpath);
5478
+ await import_fs.default.promises.unlink(fullpath);
5480
5479
  }
5481
5480
  }
5482
- this.nvim.command("checktime", true);
5483
- await wait(100);
5481
+ await this.nvim.command("checktime");
5484
5482
  }, { reload: true, persist: true });
5485
5483
  this.addAction("preview", async (item, context) => {
5486
5484
  let { tree_symbol, index_symbol, root, relative } = item.data;
@@ -5498,8 +5496,7 @@ var GStatus = class extends import_coc6.BasicList {
5498
5496
  if (index_symbol == "M" && tree_symbol != "M") {
5499
5497
  args.push("--cached");
5500
5498
  }
5501
- let cmd = `git ${args.join(" ")} ${relative}`;
5502
- let content = await runCommand(cmd, { cwd: root });
5499
+ let content = (await this.manager.git.exec(root, [...args, "--", relative])).stdout;
5503
5500
  let lines = content.trim().split("\n");
5504
5501
  await this.preview({
5505
5502
  lines,
@@ -5510,10 +5507,10 @@ var GStatus = class extends import_coc6.BasicList {
5510
5507
  });
5511
5508
  }
5512
5509
  async reset(root, relative) {
5513
- await spawnCommand("git", ["reset", "HEAD", "--", relative], root);
5510
+ await this.manager.git.exec(root, ["reset", "--", relative]);
5514
5511
  }
5515
5512
  async checkout(root, relative) {
5516
- await spawnCommand("git", ["checkout", "--", relative], root);
5513
+ await this.manager.git.exec(root, ["checkout", "--", relative]);
5517
5514
  }
5518
5515
  async loadItems(context) {
5519
5516
  let buf = await context.window.buffer;
@@ -5525,24 +5522,24 @@ var GStatus = class extends import_coc6.BasicList {
5525
5522
  if (this.manager.gstatusSaveBeforeOpen) {
5526
5523
  await this.nvim.command(`wa`);
5527
5524
  }
5528
- let output = await runCommand(`git status --porcelain -uall ${context.args.join(" ")}`, { cwd: root });
5529
- output = output.replace(/\s+$/, "");
5525
+ let output = (await this.manager.git.exec(root, ["status", "--porcelain=v1", "-z", "-uall", ...context.args])).stdout;
5530
5526
  if (!output) return [];
5531
5527
  let res = [];
5532
- for (let line of output.split(/\r?\n/)) {
5533
- let filepath = import_path3.default.join(root, line.slice(3));
5534
- let index_symbol = STATUS_MAP[line[0]];
5535
- let tree_symbol = STATUS_MAP[line[1]];
5528
+ for (let entry of parseStatusEntries(output)) {
5529
+ let { index, tree, relative } = entry;
5530
+ let filepath = import_path3.default.join(root, relative);
5531
+ let index_symbol = STATUS_MAP[index];
5532
+ let tree_symbol = STATUS_MAP[tree];
5536
5533
  res.push({
5537
- label: `${index_symbol}${tree_symbol} ${line.slice(3)}`,
5538
- filterText: line.slice(3),
5534
+ label: `${index_symbol}${tree_symbol} ${relative}`,
5535
+ filterText: relative,
5539
5536
  data: {
5540
5537
  root,
5541
- relative: line.slice(3),
5542
- index_symbol: line[0],
5543
- tree_symbol: line[1],
5544
- staged: line[0] != " " && line[0] != "?",
5545
- tree: line[1] != " " && line[1] != "?"
5538
+ relative,
5539
+ index_symbol: index,
5540
+ tree_symbol: tree,
5541
+ staged: index != " " && index != "?",
5542
+ tree: tree != " " && tree != "?"
5546
5543
  },
5547
5544
  location: import_coc6.Uri.file(filepath).toString()
5548
5545
  });
@@ -5556,7 +5553,7 @@ var import_coc7 = require("coc.nvim");
5556
5553
  var import_safe3 = __toESM(require_safe());
5557
5554
  var GChunks = class extends import_coc7.BasicList {
5558
5555
  constructor(nvim, manager) {
5559
- super(nvim);
5556
+ super();
5560
5557
  this.manager = manager;
5561
5558
  this.name = "gchunks";
5562
5559
  this.description = "Git changes of current buffer";
@@ -5570,6 +5567,7 @@ var GChunks = class extends import_coc7.BasicList {
5570
5567
  });
5571
5568
  }
5572
5569
  async loadItems(context) {
5570
+ var _a;
5573
5571
  let buf = this.manager.getBuffer(context.buffer.id);
5574
5572
  if (!buf) {
5575
5573
  throw new Error(`Can't resolve git root.`);
@@ -5592,7 +5590,7 @@ var GChunks = class extends import_coc7.BasicList {
5592
5590
  try {
5593
5591
  let { relpath } = buf;
5594
5592
  let stagedDiff = await buf.repo.getStagedChunks(relpath);
5595
- let chunks = Object.values(stagedDiff)[0];
5593
+ let chunks = (_a = Object.values(stagedDiff)[0]) != null ? _a : [];
5596
5594
  if (chunks.length > 0) {
5597
5595
  for (let diff of chunks) {
5598
5596
  let adjust = 0;
@@ -5609,7 +5607,7 @@ var GChunks = class extends import_coc7.BasicList {
5609
5607
  res.push({
5610
5608
  label: `${stagedSign} Line:${line} ${diff.lines[0]}`,
5611
5609
  data: {
5612
- line: `${line}`
5610
+ line
5613
5611
  }
5614
5612
  });
5615
5613
  }
@@ -5682,6 +5680,21 @@ var GitStatus = class {
5682
5680
  this.disposables = [];
5683
5681
  this._enabled = false;
5684
5682
  this.mutex = new import_coc9.Mutex();
5683
+ this.disposed = false;
5684
+ this.loadConfiguration();
5685
+ import_coc9.workspace.onDidChangeConfiguration((e) => {
5686
+ if (!e.affectsConfiguration("git")) return;
5687
+ this.loadConfiguration();
5688
+ if (!this._enabled) this.setGitStatus("");
5689
+ this.scheduleRefresh(0);
5690
+ }, null, this.disposables);
5691
+ import_coc9.events.on("BufEnter", this.refresh, this, this.disposables);
5692
+ import_coc9.events.on("FocusGained", this.refresh, this, this.disposables);
5693
+ import_coc9.events.on("BufWritePost", () => this.scheduleRefresh(50), this, this.disposables);
5694
+ this.disposables.push({ dispose: () => this.clearTimer() });
5695
+ this.scheduleRefresh(300);
5696
+ }
5697
+ loadConfiguration() {
5685
5698
  let config = import_coc9.workspace.getConfiguration("git");
5686
5699
  this._enabled = config.get("enableGlobalStatus", true);
5687
5700
  this.branchCharacter = config.get("branchCharacter", "");
@@ -5691,41 +5704,40 @@ var GitStatus = class {
5691
5704
  stagedDecorator: config.get("stagedDecorator"),
5692
5705
  untrackedDecorator: config.get("untrackedDecorator")
5693
5706
  };
5694
- import_coc9.events.on("BufEnter", this.refresh, this, this.disposables);
5695
- import_coc9.events.on("FocusGained", this.refresh, this, this.disposables);
5696
- let timer;
5697
- import_coc9.events.on("BufWritePost", () => {
5698
- timer = setTimeout(() => {
5699
- this.refresh();
5700
- }, 50);
5701
- }, this, this.disposables);
5702
- this.disposables.push({
5703
- dispose: () => {
5704
- if (timer) clearTimeout(timer);
5705
- }
5706
- });
5707
- setTimeout(() => {
5708
- this.refresh().catch((_e) => {
5709
- });
5710
- }, 300);
5707
+ }
5708
+ clearTimer() {
5709
+ if (this.timer) clearTimeout(this.timer);
5710
+ this.timer = void 0;
5711
+ }
5712
+ scheduleRefresh(delay) {
5713
+ this.clearTimer();
5714
+ this.timer = setTimeout(() => {
5715
+ this.timer = void 0;
5716
+ this.refresh().catch((e) => this.service.log(`[Error] error on refresh: ${e.message}`));
5717
+ }, delay);
5711
5718
  }
5712
5719
  async refresh() {
5713
- if (!this._enabled) return;
5720
+ if (!this._enabled || this.disposed) return;
5714
5721
  let release = await this.mutex.acquire();
5715
5722
  try {
5723
+ if (this.disposed) return;
5716
5724
  let repo = await this.service.getCurrentRepo();
5725
+ if (this.disposed) return;
5717
5726
  if (repo) {
5718
5727
  let status = await repo.getStatus(this.branchCharacter, this.characters);
5728
+ if (!this._enabled || this.disposed) return;
5719
5729
  this.setGitStatus(status || "");
5720
5730
  } else {
5721
5731
  this.setGitStatus("");
5722
5732
  }
5723
5733
  } catch (e) {
5724
5734
  this.service.log(`[Error] error on refresh: ${e.message}`);
5735
+ } finally {
5736
+ release();
5725
5737
  }
5726
- release();
5727
5738
  }
5728
5739
  setGitStatus(status) {
5740
+ if (this.disposed) return;
5729
5741
  if (this.gitStatus == status) return;
5730
5742
  this.gitStatus = status;
5731
5743
  let { nvim } = import_coc9.workspace;
@@ -5736,6 +5748,8 @@ var GitStatus = class {
5736
5748
  }
5737
5749
  dispose() {
5738
5750
  (0, import_coc9.disposeAll)(this.disposables);
5751
+ this.setGitStatus("");
5752
+ this.disposed = true;
5739
5753
  }
5740
5754
  };
5741
5755
 
@@ -5752,21 +5766,32 @@ var DocumentManager = class {
5752
5766
  this.loadConfiguration();
5753
5767
  import_coc10.workspace.onDidChangeConfiguration(this.loadConfiguration, this, this.disposables);
5754
5768
  this.gitStatus = new GitStatus(service);
5755
- import_coc10.workspace.registerBufferSync((doc) => {
5769
+ this.disposables.push(import_coc10.workspace.registerBufferSync((doc) => {
5756
5770
  let disposed = false;
5757
5771
  let gitBuffer;
5758
5772
  let { bufnr, uri } = doc;
5759
5773
  service.createBuffer(doc, this.config).then((buf) => {
5760
- if (!buf || disposed) return;
5774
+ if (!buf) return;
5775
+ if (disposed) {
5776
+ buf.dispose();
5777
+ return;
5778
+ }
5761
5779
  gitBuffer = buf;
5762
5780
  this.defineSigns().catch((e) => {
5763
5781
  console.error(e.message);
5764
5782
  });
5765
5783
  this.buffers.set(doc.bufnr, buf);
5784
+ }).catch((e) => {
5785
+ service.log(`[Error] unable to create git buffer for ${uri}: ${e.message}`);
5766
5786
  });
5767
5787
  return {
5768
- onChange: () => {
5769
- if (gitBuffer) gitBuffer._refresh();
5788
+ onChange: (e) => {
5789
+ if (gitBuffer) {
5790
+ if (e.contentChanges.some((change) => change.text.includes("<<<<<<<"))) {
5791
+ gitBuffer.markConflictCheck();
5792
+ }
5793
+ gitBuffer._refresh().catch((e2) => service.log(`[Error] refresh error: ${e2.message}`));
5794
+ }
5770
5795
  },
5771
5796
  dispose: () => {
5772
5797
  disposed = true;
@@ -5775,28 +5800,44 @@ var DocumentManager = class {
5775
5800
  if (gitBuffer) gitBuffer.dispose();
5776
5801
  }
5777
5802
  };
5778
- });
5779
- import_coc10.events.on("CursorMoved", (0, import_debounce.default)(async (bufnr, cursor) => {
5803
+ }));
5804
+ const cursorMoved = (0, import_debounce.default)(async (bufnr, cursor) => {
5780
5805
  let buf = this.buffers.get(bufnr);
5781
- if (buf) await buf.showBlameInfo(cursor[0]);
5782
- }, 100), null, this.disposables);
5783
- import_coc10.workspace.registerAutocmd({
5806
+ if (buf) {
5807
+ try {
5808
+ await buf.showBlameInfo(cursor[0]);
5809
+ } catch (e) {
5810
+ service.log(`[Error] unable to show blame: ${e.message}`);
5811
+ }
5812
+ }
5813
+ }, 100);
5814
+ import_coc10.events.on("CursorMoved", cursorMoved, null, this.disposables);
5815
+ this.disposables.push({ dispose: () => cursorMoved.clear() });
5816
+ this.disposables.push(import_coc10.workspace.registerAutocmd({
5784
5817
  event: "BufWritePost",
5785
5818
  arglist: ["+expand('<abuf>')"],
5786
5819
  callback: (bufnr) => {
5787
5820
  if (!this.enableGutters || this.config.realtimeGutters) return;
5788
5821
  let buf = this.buffers.get(bufnr);
5789
- if (buf) buf.diffDocument(true);
5822
+ if (buf) {
5823
+ buf.diffDocument(true).catch((e) => service.log(`[Error] refresh error: ${e.message}`));
5824
+ }
5790
5825
  }
5791
- });
5826
+ }));
5792
5827
  import_coc10.events.on("FocusGained", async () => {
5793
5828
  let bufnr = await nvim.call("bufnr", ["%"]);
5794
5829
  let buf = this.buffers.get(bufnr);
5795
- if (buf) buf.refresh();
5830
+ if (buf) {
5831
+ buf.markConflictCheck();
5832
+ buf.refresh();
5833
+ }
5796
5834
  }, null, this.disposables);
5797
5835
  import_coc10.events.on("BufEnter", (bufnr) => {
5798
5836
  let buf = this.buffers.get(bufnr);
5799
- if (buf) buf.refresh();
5837
+ if (buf) {
5838
+ buf.markConflictCheck();
5839
+ buf.refresh();
5840
+ }
5800
5841
  }, null, this.disposables);
5801
5842
  }
5802
5843
  async defineSigns() {
@@ -5816,6 +5857,7 @@ var DocumentManager = class {
5816
5857
  await nvim.resumeNotification();
5817
5858
  }
5818
5859
  loadConfiguration(e) {
5860
+ var _a;
5819
5861
  if (e && !e.affectsConfiguration("git")) return;
5820
5862
  let config = import_coc10.workspace.getConfiguration("git");
5821
5863
  let obj = {
@@ -5825,6 +5867,7 @@ var DocumentManager = class {
5825
5867
  diffOptions: config.get("diffOptions", []),
5826
5868
  issueFormat: config.get("issueFormat", "#%i"),
5827
5869
  virtualTextPrefix: config.get("virtualTextPrefix", " "),
5870
+ blameFormat: config.get("blameFormat", "(%a %t) %s"),
5828
5871
  addGBlameToVirtualText: config.get("addGBlameToVirtualText", false),
5829
5872
  addGBlameToBufferVar: config.get("addGBlameToBufferVar", false),
5830
5873
  blameUseRealTime: config.get("blameUseRealTime", false),
@@ -5832,7 +5875,7 @@ var DocumentManager = class {
5832
5875
  realtimeGutters: config.get("realtimeGutters", true),
5833
5876
  showCommitInFloating: config.get("showCommitInFloating", false),
5834
5877
  signPriority: config.get("signPriority", 10),
5835
- pushArguments: config.get("pushArguments", []),
5878
+ pushArguments: (_a = config.get("pushArguments")) != null ? _a : [],
5836
5879
  splitWindowCommand: config.get("splitWindowCommand", "above sp"),
5837
5880
  changedSign: {
5838
5881
  text: config.get("changedSign.text", "~"),
@@ -5868,6 +5911,11 @@ var DocumentManager = class {
5868
5911
  conflictSrcId: this.conflictSrcId
5869
5912
  };
5870
5913
  this.config = Object.assign(this.config || {}, obj);
5914
+ if (e) {
5915
+ this.defined = false;
5916
+ for (let buffer of this.buffers.values()) buffer.markConflictCheck();
5917
+ this.defineSigns().catch((err) => this.service.log(`[Error] define signs: ${err.message}`));
5918
+ }
5871
5919
  }
5872
5920
  get enableGutters() {
5873
5921
  return this.config.enableGutters;
@@ -5881,10 +5929,15 @@ var DocumentManager = class {
5881
5929
  get diffOptions() {
5882
5930
  return this.config.diffOptions;
5883
5931
  }
5932
+ async getTerminalGitCommand(args) {
5933
+ const values = [this.git.path, ...args];
5934
+ const escaped = await Promise.all(values.map((value) => this.nvim.call("shellescape", [value, 1])));
5935
+ return escaped.join(" ");
5936
+ }
5884
5937
  async toggleGutters() {
5885
5938
  let enabled = this.enableGutters;
5886
5939
  let config = import_coc10.workspace.getConfiguration("git");
5887
- config.update("enableGutters", !enabled, true);
5940
+ await config.update("enableGutters", !enabled, true);
5888
5941
  for (let buf of this.buffers.values()) {
5889
5942
  await buf.toggleGutters(!enabled);
5890
5943
  }
@@ -5916,6 +5969,11 @@ var DocumentManager = class {
5916
5969
  let buf = await this.buffer;
5917
5970
  if (buf) await buf.chunkInfo();
5918
5971
  }
5972
+ async allChunkInfo() {
5973
+ let buf = await this.buffer;
5974
+ if (buf) return buf.allChunkInfo();
5975
+ return [];
5976
+ }
5919
5977
  async nextChunk() {
5920
5978
  let buf = await this.buffer;
5921
5979
  if (buf) await buf.nextChunk();
@@ -5992,7 +6050,7 @@ var DocumentManager = class {
5992
6050
  return;
5993
6051
  }
5994
6052
  if (args && args.length) {
5995
- await import_coc10.window.runTerminalCommand(`git push ${[...args, ...extra].join(" ")}`, root, true);
6053
+ await import_coc10.window.runTerminalCommand(await this.getTerminalGitCommand(["push", ...args, ...extra]), root, true);
5996
6054
  return;
5997
6055
  }
5998
6056
  let repo = this.service.getRepoFromRoot(root);
@@ -6007,12 +6065,12 @@ var DocumentManager = class {
6007
6065
  import_coc10.window.showWarningMessage(`current branch not found`);
6008
6066
  return;
6009
6067
  }
6010
- await import_coc10.window.runTerminalCommand(`git push ${remote} ${output}${extra.length ? " " + extra.join(" ") : ""}`, root, true);
6068
+ await import_coc10.window.runTerminalCommand(await this.getTerminalGitCommand(["push", remote, output, ...extra]), root, true);
6011
6069
  }
6012
6070
  get buffer() {
6013
6071
  return import_coc10.workspace.nvim.call("bufnr", "%").then((bufnr) => {
6014
6072
  let buf = this.buffers.get(bufnr);
6015
- if (!buf) import_coc10.window.showWarningMessage(`Cant't resolve git repository for current buffer.`);
6073
+ if (!buf) import_coc10.window.showWarningMessage(`Can't resolve git repository for current buffer.`);
6016
6074
  return buf;
6017
6075
  });
6018
6076
  }
@@ -6030,13 +6088,13 @@ var DocumentManager = class {
6030
6088
  return repo.getDiffAll(category);
6031
6089
  }
6032
6090
  dispose() {
6091
+ (0, import_coc10.disposeAll)(this.disposables);
6033
6092
  this.gitStatus.dispose();
6034
- this.service.dispose();
6035
6093
  for (let buf of this.buffers.values()) {
6036
6094
  buf.dispose();
6037
6095
  }
6038
6096
  this.buffers.clear();
6039
- (0, import_coc10.disposeAll)(this.disposables);
6097
+ this.service.dispose();
6040
6098
  }
6041
6099
  };
6042
6100
 
@@ -6130,6 +6188,13 @@ var startPattern = new RegExp(`^<{7} (${revPattern})(:? .+)?$`);
6130
6188
  var sepPattern = new RegExp(`^={7}$`);
6131
6189
  var endPattern = new RegExp(`^>{7} (${revPattern})(:? .+)?$`);
6132
6190
  var commonPattern = /^\|{7}\smerged\scommon\sancestors/;
6191
+ function getPreviousConflict(conflicts, line) {
6192
+ return conflicts.slice().reverse().find((conflict) => conflict.start < line);
6193
+ }
6194
+ function chunkContainsLine(chunk, line) {
6195
+ const end = chunk.add.count === 0 ? chunk.add.lnum : chunk.add.lnum + chunk.add.count - 1;
6196
+ return chunk.add.lnum <= line && end >= line;
6197
+ }
6133
6198
  var GitBuffer = class {
6134
6199
  constructor(doc, config, relpath, repo, git, channel, floatFactory, hasConflicts) {
6135
6200
  this.doc = doc;
@@ -6148,29 +6213,37 @@ var GitBuffer = class {
6148
6213
  this.foldEnabled = false;
6149
6214
  this._disposed = false;
6150
6215
  this.mutex = new import_coc11.Mutex();
6216
+ this.conflictCheckNeeded = hasConflicts;
6151
6217
  this.refresh = (0, import_debounce2.default)(() => {
6152
6218
  this._refresh().catch((e) => {
6153
6219
  channel.append(`[Error] ${e.message}`);
6154
6220
  });
6155
6221
  }, 200);
6156
- this._refresh();
6222
+ this._refresh().catch((e) => channel.append(`[Error] ${e.message}`));
6157
6223
  }
6158
6224
  get cachedDiffs() {
6159
6225
  return this.diffs;
6160
6226
  }
6227
+ markConflictCheck() {
6228
+ this.conflictCheckNeeded = true;
6229
+ }
6161
6230
  async _refresh() {
6162
6231
  if (this._disposed) return;
6163
6232
  this.refresh.clear();
6164
6233
  let release = await this.mutex.acquire();
6165
- let result = await Promise.allSettled([
6166
- this.diffDocument(),
6167
- this.loadBlames(),
6168
- this.parseConflicts()
6169
- ]);
6170
- result.forEach((res) => {
6171
- if (res.status === "rejected") this.channel.append(`[Error] refresh error ${res.reason}`);
6172
- });
6173
- release();
6234
+ try {
6235
+ if (this._disposed) return;
6236
+ let result = await Promise.all([
6237
+ this.diffDocument(),
6238
+ this.loadBlames(),
6239
+ this.parseConflicts()
6240
+ ].map((promise) => promise.then(() => void 0, (error) => error)));
6241
+ result.forEach((error) => {
6242
+ if (error) this.channel.append(`[Error] refresh error ${error}`);
6243
+ });
6244
+ } finally {
6245
+ release();
6246
+ }
6174
6247
  }
6175
6248
  getChunk(line) {
6176
6249
  if (!this.diffs || this.diffs.length == 0) return void 0;
@@ -6220,11 +6293,13 @@ var GitBuffer = class {
6220
6293
  } else if (diff.changeType === "changed" /* Change */) {
6221
6294
  head = `@@ -${diff.removed.start},${diff.removed.count} +${diff.removed.start},${diff.added.count} @@`;
6222
6295
  }
6296
+ const from = quoteGitPath(`a/${relpath}`);
6297
+ const to = quoteGitPath(`b/${relpath}`);
6223
6298
  const lines = [
6224
- `diff --git a/${relpath} b/${relpath}`,
6299
+ `diff --git ${from} ${to}`,
6225
6300
  `index 000000..000000 100644`,
6226
- `--- a/${relpath}`,
6227
- `+++ b/${relpath}`,
6301
+ `--- ${from}`,
6302
+ `+++ ${to}`,
6228
6303
  head
6229
6304
  ];
6230
6305
  lines.push(...diff.lines);
@@ -6237,6 +6312,7 @@ var GitBuffer = class {
6237
6312
  }
6238
6313
  }
6239
6314
  async chunkUnstage() {
6315
+ var _a;
6240
6316
  let { nvim } = import_coc11.workspace;
6241
6317
  const { diffs } = this;
6242
6318
  let line = await nvim.call("line", ".");
@@ -6256,12 +6332,12 @@ var GitBuffer = class {
6256
6332
  if (invalid) return;
6257
6333
  line = line + adjust;
6258
6334
  let stagedDiff = await this.repo.getStagedChunks(this.relpath);
6259
- let chunks = Object.values(stagedDiff)[0];
6335
+ let chunks = (_a = Object.values(stagedDiff)[0]) != null ? _a : [];
6260
6336
  if (!chunks.length) {
6261
6337
  import_coc11.window.showErrorMessage(`Staged chunk not found`);
6262
6338
  return;
6263
6339
  }
6264
- let chunk = chunks.find((o) => o.add.lnum <= line && o.add.lnum + o.add.count >= line);
6340
+ let chunk = chunks.find((o) => chunkContainsLine(o, line));
6265
6341
  if (!chunk) {
6266
6342
  import_coc11.window.showErrorMessage(`Unable to find staged chunk on current line`);
6267
6343
  return;
@@ -6329,7 +6405,7 @@ var GitBuffer = class {
6329
6405
  adjust += diff2.removed.count;
6330
6406
  }
6331
6407
  line = line + adjust;
6332
- let chunk = chunks.find((o) => o.add.lnum <= line && o.add.lnum + o.add.count >= line);
6408
+ let chunk = chunks.find((o) => chunkContainsLine(o, line));
6333
6409
  if (chunk) {
6334
6410
  let content = "Staged changes\n" + chunk.lines.join("\n");
6335
6411
  await this.showDoc(content, "diff");
@@ -6338,7 +6414,11 @@ var GitBuffer = class {
6338
6414
  }
6339
6415
  }
6340
6416
  }
6417
+ allChunkInfo() {
6418
+ return this.diffs ? this.diffs.slice() : [];
6419
+ }
6341
6420
  async showBlameInfo(lnum) {
6421
+ if (this._disposed) return;
6342
6422
  let { nvim } = import_coc11.workspace;
6343
6423
  let { virtualTextSrcId, addGBlameToBufferVar, addGBlameToVirtualText } = this.config;
6344
6424
  if (!this.showBlame) return;
@@ -6350,7 +6430,7 @@ var GitBuffer = class {
6350
6430
  } else {
6351
6431
  let info = infos.find((o) => lnum >= o.startLnum && lnum <= o.endLnum);
6352
6432
  if (info && info.author && info.author != "Not Committed Yet") {
6353
- blameText = `(${info.author} ${info.time}) ${info.summary}`;
6433
+ blameText = formatBlameText(info, this.config.blameFormat);
6354
6434
  } else {
6355
6435
  blameText = "Not committed yet";
6356
6436
  }
@@ -6403,7 +6483,7 @@ var GitBuffer = class {
6403
6483
  let eol = this.doc.textDocument["eol"];
6404
6484
  let encoding = await this.doc.buffer.getOption("fileencoding");
6405
6485
  const diffs = await this.repo.getDiff(this.relpath, eol ? content : content + "\n", revision, encoding || "utf8");
6406
- if (diffs == null) return;
6486
+ if (diffs == null || this._disposed) return;
6407
6487
  if (diffs.length === 0) {
6408
6488
  this.currentSigns = [];
6409
6489
  this.diffs = [];
@@ -6485,6 +6565,7 @@ var GitBuffer = class {
6485
6565
  let result = [];
6486
6566
  let indexed = await this.repo.isIndexed(this.relpath);
6487
6567
  if (indexed) result = await this.getBlameInfo();
6568
+ if (this._disposed) return;
6488
6569
  this.blameInfo = result;
6489
6570
  }
6490
6571
  async getBlameInfo(range) {
@@ -6494,14 +6575,16 @@ var GitBuffer = class {
6494
6575
  const useRealTime = this.config.blameUseRealTime;
6495
6576
  try {
6496
6577
  let currentAuthor = await this.repo.getUsername();
6497
- const args = ["--no-pager", "blame", "-w", "-b", "-p", "--incremental", "--root", "--date", "relative", "--contents", "-", relpath];
6578
+ const args = ["--no-pager", "blame", "-w", "-b", "-p", "--incremental", "--root", "--date", "relative", "--contents", "-"];
6498
6579
  if (range) args.push("-L", range.join(","));
6580
+ args.push("--", relpath);
6499
6581
  let r = await this.git.exec(root, args, {
6500
6582
  log: false,
6501
6583
  input: this.doc.content
6502
6584
  });
6503
6585
  if (!r.stdout) return res;
6504
6586
  let info;
6587
+ const commits = /* @__PURE__ */ new Map();
6505
6588
  for (let line of r.stdout.trim().split(/\r?\n/)) {
6506
6589
  line = line.trim();
6507
6590
  if (/^(author |committer )?External file \(--contents\)/.test(line)) {
@@ -6512,11 +6595,13 @@ var GitBuffer = class {
6512
6595
  let startLnum = parseInt(ms[3], 10);
6513
6596
  info = { startLnum, sha: ms[1], endLnum: startLnum + parseInt(ms[4], 10) - 1, index: ms[2] };
6514
6597
  if (!/^0+$/.test(ms[1])) {
6515
- let find = res.find((o) => o.sha == ms[1]);
6598
+ let find = commits.get(ms[1]);
6516
6599
  if (find) {
6517
6600
  info.author = find.author;
6518
6601
  info.time = find.time;
6519
6602
  info.summary = find.summary;
6603
+ } else {
6604
+ commits.set(ms[1], info);
6520
6605
  }
6521
6606
  }
6522
6607
  res.push(info);
@@ -6580,14 +6665,14 @@ var GitBuffer = class {
6580
6665
  return;
6581
6666
  }
6582
6667
  let line = await nvim.call("line", ".");
6583
- for (let conflict of this.conflicts) {
6584
- if (conflict.start > line) {
6585
- await import_coc11.window.moveTo({ line: Math.max(conflict.start - 1, 0), character: 0 });
6586
- return;
6587
- }
6668
+ let conflict = getPreviousConflict(this.conflicts, line);
6669
+ if (conflict) {
6670
+ await import_coc11.window.moveTo({ line: Math.max(conflict.start - 1, 0), character: 0 });
6671
+ return;
6588
6672
  }
6589
6673
  if (await nvim.getOption("wrapscan")) {
6590
- await import_coc11.window.moveTo({ line: Math.max(this.conflicts[0].start - 1, 0), character: 0 });
6674
+ conflict = this.conflicts[this.conflicts.length - 1];
6675
+ await import_coc11.window.moveTo({ line: Math.max(conflict.start - 1, 0), character: 0 });
6591
6676
  }
6592
6677
  }
6593
6678
  async conflictKeepPart(part) {
@@ -6660,21 +6745,26 @@ var GitBuffer = class {
6660
6745
  if (!uri.length) continue;
6661
6746
  let repoURL = getRepoUrl(uri);
6662
6747
  if (!repoURL) continue;
6663
- let tmp = new import_url.URL(repoURL);
6748
+ let tmp;
6749
+ try {
6750
+ tmp = new import_url.URL(repoURL);
6751
+ } catch (_e) {
6752
+ continue;
6753
+ }
6664
6754
  let hostname = tmp.hostname;
6665
6755
  let fix = "|";
6666
6756
  try {
6667
6757
  fix = config.get("urlFix")[hostname][permalink ? 1 : 0];
6668
6758
  } catch (e) {
6669
6759
  }
6670
- let url = getUrl(fix, repoURL, permalink ? head : branch, this.relpath.replace(/\\\\/g, "/"), lines);
6760
+ let url = getUrl(fix, repoURL, permalink ? head : branch || head, toUnixSlash(this.relpath), lines);
6671
6761
  if (url) urls.push(url);
6672
6762
  }
6673
6763
  if (urls.length == 1) {
6674
6764
  if (action == "open") {
6675
6765
  await import_coc11.workspace.openResource(urls[0]);
6676
6766
  } else {
6677
- nvim.command(`let @+ = '${urls[0]}'`, true);
6767
+ nvim.call("setreg", ["+", urls[0]], true);
6678
6768
  import_coc11.window.showInformationMessage("Copied url to clipboard");
6679
6769
  }
6680
6770
  } else if (urls.length > 1) {
@@ -6683,8 +6773,8 @@ var GitBuffer = class {
6683
6773
  if (action == "open") {
6684
6774
  await import_coc11.workspace.openResource(url);
6685
6775
  } else {
6686
- nvim.command(`let @+ = '${url}'`, true);
6687
- nvim.command(`let @* = '${url}'`, true);
6776
+ nvim.call("setreg", ["+", url], true);
6777
+ nvim.call("setreg", ["*", url], true);
6688
6778
  import_coc11.window.showInformationMessage("Copied url to clipboard");
6689
6779
  }
6690
6780
  }
@@ -6699,7 +6789,7 @@ var GitBuffer = class {
6699
6789
  }
6700
6790
  let nvim = import_coc11.workspace.nvim;
6701
6791
  let line = await nvim.eval('line(".")');
6702
- let args = ["--no-pager", "blame", "-w", "-l", "--root", "-t", `-L${line},${line}`, this.relpath];
6792
+ let args = ["--no-pager", "blame", "-w", "-l", "--root", "-t", `-L${line},${line}`, "--", this.relpath];
6703
6793
  let res = await this.repo.exec(args);
6704
6794
  let output = res.stdout.trim();
6705
6795
  if (!output.length) return;
@@ -6745,7 +6835,7 @@ var GitBuffer = class {
6745
6835
  import_coc11.window.showWarningMessage("No changes");
6746
6836
  return;
6747
6837
  }
6748
- let lnums = infos.map((o) => o.lnum);
6838
+ let changedLines = new Set(infos.map((o) => o.lnum));
6749
6839
  let foldContext = this.config.foldContext;
6750
6840
  let max = this.doc.lineCount;
6751
6841
  let ranges = [];
@@ -6757,7 +6847,7 @@ var GitBuffer = class {
6757
6847
  ranges.push([s, e]);
6758
6848
  };
6759
6849
  for (let i = 1; i <= doc.lineCount; i++) {
6760
- let fold = lnums.indexOf(i) == -1;
6850
+ let fold = !changedLines.has(i);
6761
6851
  if (fold && start == null) {
6762
6852
  start = i;
6763
6853
  continue;
@@ -6774,10 +6864,10 @@ var GitBuffer = class {
6774
6864
  if (enabled) {
6775
6865
  this.foldEnabled = false;
6776
6866
  let cursor = await nvim.eval('getpos(".")');
6777
- let lnums2 = ranges.map((o) => o[0]);
6867
+ let lnums = ranges.map((o) => o[0]);
6778
6868
  let settings = this.foldSettings;
6779
6869
  nvim.pauseNotification();
6780
- for (let lnum of lnums2) {
6870
+ for (let lnum of lnums) {
6781
6871
  nvim.command(`${lnum}normal! zd`, true);
6782
6872
  }
6783
6873
  win.setOption("foldmethod", settings.foldmethod, true);
@@ -6818,7 +6908,22 @@ var GitBuffer = class {
6818
6908
  }
6819
6909
  }
6820
6910
  async parseConflicts() {
6821
- if (!this.hasConflicts || !this.config.conflict.enabled) return;
6911
+ if (!this.config.conflict.enabled) {
6912
+ if (this.conflicts.length) {
6913
+ this.conflicts = [];
6914
+ await this.highlightConflicts([]);
6915
+ }
6916
+ return;
6917
+ }
6918
+ if (!this.hasConflicts && !this.conflictCheckNeeded) return;
6919
+ this.conflictCheckNeeded = false;
6920
+ this.hasConflicts = await this.repo.hasConflicts(this.relpath);
6921
+ if (this._disposed) return;
6922
+ if (!this.hasConflicts) {
6923
+ this.conflicts = [];
6924
+ await this.highlightConflicts([]);
6925
+ return;
6926
+ }
6822
6927
  const lines = this.doc.textDocument.lines;
6823
6928
  let conflicts = [];
6824
6929
  let conflict = null;
@@ -6884,12 +6989,13 @@ var GitBuffer = class {
6884
6989
  }
6885
6990
  });
6886
6991
  this.conflicts = conflicts;
6887
- this.highlightConflicts(conflicts);
6992
+ await this.highlightConflicts(conflicts);
6888
6993
  if (conflicts.length == 0) {
6889
6994
  this.hasConflicts = false;
6890
6995
  }
6891
6996
  }
6892
6997
  async highlightConflicts(conflicts) {
6998
+ if (this._disposed) return;
6893
6999
  let buffer = this.doc.buffer;
6894
7000
  let currentHlGroup = this.config.conflict.currentHlGroup;
6895
7001
  let incomingHlGroup = this.config.conflict.incomingHlGroup;
@@ -6917,7 +7023,7 @@ var GitBuffer = class {
6917
7023
  await this.floatFactory.show(docs, this.config.floatConfig);
6918
7024
  } else {
6919
7025
  const lines = content.split("\n");
6920
- import_coc11.workspace.nvim.call("coc#ui#preview_info", [lines, "diff"], true);
7026
+ import_coc11.workspace.nvim.call("coc#ui#preview_info", [lines, filetype], true);
6921
7027
  }
6922
7028
  }
6923
7029
  setBufferStatus(status) {
@@ -6950,9 +7056,12 @@ var GitBuffer = class {
6950
7056
  return this.config.addGBlameToVirtualText || this.config.addGBlameToBufferVar;
6951
7057
  }
6952
7058
  dispose() {
7059
+ if (this._disposed) return;
7060
+ this._disposed = true;
6953
7061
  let { nvim } = import_coc11.workspace;
6954
7062
  let { bufnr } = this.doc;
6955
7063
  let buffer = nvim.createBuffer(bufnr);
7064
+ nvim.pauseNotification();
6956
7065
  buffer.setVar("coc_git_status", "", true);
6957
7066
  buffer.clearNamespace(this.config.conflictSrcId, 0, -1);
6958
7067
  nvim.call("sign_unplace", [signGroup, { buffer: bufnr }], true);
@@ -6964,12 +7073,7 @@ var GitBuffer = class {
6964
7073
  buffer.clearNamespace(this.config.virtualTextSrcId);
6965
7074
  }
6966
7075
  nvim.resumeNotification(false, true);
6967
- this._disposed = true;
6968
7076
  this.foldEnabled = false;
6969
- this.blameInfo = void 0;
6970
- this.diffs = void 0;
6971
- this.conflicts = void 0;
6972
- this.currentSigns = void 0;
6973
7077
  }
6974
7078
  };
6975
7079
  function plus(val, count, max) {
@@ -6993,6 +7097,9 @@ var Git = class {
6993
7097
  this.gitInfo = gitInfo;
6994
7098
  this.channel = channel;
6995
7099
  }
7100
+ get path() {
7101
+ return this.gitInfo.path;
7102
+ }
6996
7103
  async getRepositoryRoot(repositoryPath) {
6997
7104
  const result = await this.exec(repositoryPath, ["rev-parse", "--show-toplevel"]);
6998
7105
  let repoRootPath = import_path5.default.normalize(result.stdout.trim());
@@ -7010,9 +7117,15 @@ var Git = class {
7010
7117
  return this.spawn(args, options);
7011
7118
  }
7012
7119
  async _exec(args, options = {}) {
7120
+ var _a, _b, _c, _d;
7121
+ if ((_a = options.cancellationToken) == null ? void 0 : _a.isCancellationRequested) {
7122
+ throw new Error("Cancelled");
7123
+ }
7013
7124
  const child = this.spawn(args, options);
7014
- if (options.input) {
7015
- child.stdin.end(options.input, "utf8");
7125
+ if (options.input !== void 0) {
7126
+ (_b = child.stdin) == null ? void 0 : _b.on("error", () => {
7127
+ });
7128
+ (_c = child.stdin) == null ? void 0 : _c.end(options.input, "utf8");
7016
7129
  }
7017
7130
  const bufferResult = await exec2(child, options.cancellationToken);
7018
7131
  if (options.log !== false && bufferResult.stderr.length > 0) {
@@ -7026,7 +7139,7 @@ var Git = class {
7026
7139
  stdout: import_iconv_lite.default.decode(bufferResult.stdout, encoding),
7027
7140
  stderr: bufferResult.stderr
7028
7141
  };
7029
- if (bufferResult.exitCode) {
7142
+ if (bufferResult.exitCode && !((_d = options.allowedExitCodes) == null ? void 0 : _d.includes(bufferResult.exitCode))) {
7030
7143
  this.channel.appendLine(`Error ${result.exitCode} on: 'git ${args.join(" ")}' in ${options.cwd}`);
7031
7144
  this.channel.append(result.stderr);
7032
7145
  this.channel.append(result.stdout);
@@ -7035,29 +7148,25 @@ var Git = class {
7035
7148
  return result;
7036
7149
  }
7037
7150
  spawn(args, options = {}) {
7038
- if (!options) {
7039
- options = {};
7151
+ const { input, encoding: _encoding, log: _log, cancellationToken: _cancellationToken, allowedExitCodes: _allowedExitCodes, ...spawnOptions } = options;
7152
+ if (!spawnOptions.stdio && input === void 0) {
7153
+ spawnOptions.stdio = ["ignore", null, null];
7040
7154
  }
7041
- if (!options.stdio && !options.input) {
7042
- options.stdio = ["ignore", null, null];
7043
- }
7044
- options.env = Object.assign({}, process.env, options.env || {}, {
7155
+ spawnOptions.env = Object.assign({}, process.env, spawnOptions.env || {}, {
7045
7156
  LC_ALL: "en_US.UTF-8",
7046
7157
  LANG: "en_US.UTF-8"
7047
7158
  });
7048
- if (process.platform === "win32") {
7049
- options.shell = true;
7050
- }
7051
7159
  if (options.log !== false) {
7052
7160
  this.log(`> git ${args.join(" ")}
7053
7161
  `);
7054
7162
  }
7055
- return cp.spawn(this.gitInfo.path, args, options);
7163
+ return cp.spawn(this.gitInfo.path, args, spawnOptions);
7056
7164
  }
7057
7165
  log(output) {
7058
7166
  this.channel.append(output);
7059
7167
  }
7060
7168
  };
7169
+ var git_default = Git;
7061
7170
  async function exec2(child, cancellationToken) {
7062
7171
  if (!child.stdout || !child.stderr) {
7063
7172
  throw new Error("Failed to get stdout or stderr from git process.");
@@ -7077,7 +7186,7 @@ async function exec2(child, cancellationToken) {
7077
7186
  let result = Promise.all([
7078
7187
  new Promise((c, e) => {
7079
7188
  once(child, "error", cpErrorHandler(e));
7080
- once(child, "exit", c);
7189
+ once(child, "exit", (code) => c(code != null ? code : -1));
7081
7190
  }),
7082
7191
  new Promise((c) => {
7083
7192
  const buffers = [];
@@ -7092,13 +7201,14 @@ async function exec2(child, cancellationToken) {
7092
7201
  ]);
7093
7202
  if (cancellationToken) {
7094
7203
  const cancellationPromise = new Promise((_, e) => {
7095
- onceEvent(cancellationToken.onCancellationRequested)(() => {
7204
+ const disposable = onceEvent(cancellationToken.onCancellationRequested)(() => {
7096
7205
  try {
7097
7206
  child.kill();
7098
7207
  } catch (err) {
7099
7208
  }
7100
7209
  e(new Error("Cancelled"));
7101
7210
  });
7211
+ disposables.push(disposable);
7102
7212
  });
7103
7213
  result = Promise.race([result, cancellationPromise]);
7104
7214
  }
@@ -7114,44 +7224,57 @@ async function exec2(child, cancellationToken) {
7114
7224
  var import_fs2 = __toESM(require("fs"));
7115
7225
  var import_os = __toESM(require("os"));
7116
7226
  var import_path6 = __toESM(require("path"));
7117
- var import_util8 = __toESM(require("util"));
7118
-
7119
- // node_modules/uuid/dist/esm-node/rng.js
7120
- var import_crypto = __toESM(require("crypto"));
7121
- function rng() {
7122
- return import_crypto.default.randomBytes(16);
7123
- }
7227
+ var import_util5 = __toESM(require("util"));
7124
7228
 
7125
- // node_modules/uuid/dist/esm-node/bytesToUuid.js
7229
+ // node_modules/uuid/dist/esm/stringify.js
7126
7230
  var byteToHex = [];
7127
- for (i = 0; i < 256; ++i) {
7128
- byteToHex[i] = (i + 256).toString(16).substr(1);
7231
+ for (let i = 0; i < 256; ++i) {
7232
+ byteToHex.push((i + 256).toString(16).slice(1));
7233
+ }
7234
+ function unsafeStringify(arr, offset = 0) {
7235
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
7129
7236
  }
7130
- var i;
7131
- function bytesToUuid(buf, offset) {
7132
- var i = offset || 0;
7133
- var bth = byteToHex;
7134
- return [bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], "-", bth[buf[i++]], bth[buf[i++]], "-", bth[buf[i++]], bth[buf[i++]], "-", bth[buf[i++]], bth[buf[i++]], "-", bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]]].join("");
7237
+
7238
+ // node_modules/uuid/dist/esm/rng.js
7239
+ var import_crypto = require("crypto");
7240
+ var rnds8Pool = new Uint8Array(256);
7241
+ var poolPtr = rnds8Pool.length;
7242
+ function rng() {
7243
+ if (poolPtr > rnds8Pool.length - 16) {
7244
+ (0, import_crypto.randomFillSync)(rnds8Pool);
7245
+ poolPtr = 0;
7246
+ }
7247
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
7135
7248
  }
7136
- var bytesToUuid_default = bytesToUuid;
7137
7249
 
7138
- // node_modules/uuid/dist/esm-node/v4.js
7250
+ // node_modules/uuid/dist/esm/native.js
7251
+ var import_crypto2 = require("crypto");
7252
+ var native_default = { randomUUID: import_crypto2.randomUUID };
7253
+
7254
+ // node_modules/uuid/dist/esm/v4.js
7139
7255
  function v4(options, buf, offset) {
7140
- var i = buf && offset || 0;
7141
- if (typeof options == "string") {
7142
- buf = options === "binary" ? new Array(16) : null;
7143
- options = null;
7256
+ var _a, _b, _c;
7257
+ if (native_default.randomUUID && !buf && !options) {
7258
+ return native_default.randomUUID();
7144
7259
  }
7145
7260
  options = options || {};
7146
- var rnds = options.random || (options.rng || rng)();
7261
+ const rnds = (_c = (_b = options.random) != null ? _b : (_a = options.rng) == null ? void 0 : _a.call(options)) != null ? _c : rng();
7262
+ if (rnds.length < 16) {
7263
+ throw new Error("Random bytes length must be >= 16");
7264
+ }
7147
7265
  rnds[6] = rnds[6] & 15 | 64;
7148
7266
  rnds[8] = rnds[8] & 63 | 128;
7149
7267
  if (buf) {
7150
- for (var ii = 0; ii < 16; ++ii) {
7151
- buf[i + ii] = rnds[ii];
7268
+ offset = offset || 0;
7269
+ if (offset < 0 || offset + 16 > buf.length) {
7270
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
7271
+ }
7272
+ for (let i = 0; i < 16; ++i) {
7273
+ buf[offset + i] = rnds[i];
7152
7274
  }
7275
+ return buf;
7153
7276
  }
7154
- return buf || bytesToUuid_default(rnds);
7277
+ return unsafeStringify(rnds);
7155
7278
  }
7156
7279
  var v4_default = v4;
7157
7280
 
@@ -7166,11 +7289,11 @@ var Repo = class {
7166
7289
  * Get staged info
7167
7290
  */
7168
7291
  async getStagedChunks(relpath) {
7169
- let args = ["--no-pager", "diff", "--no-ext-diff", "-p", "-U0", "--no-color", "--staged"];
7170
- if (relpath) args.push(toUnixSlash(relpath));
7292
+ let args = ["-c", "core.quotepath=false", "--no-pager", "diff", "--no-ext-diff", "--no-renames", "-p", "-U0", "--no-color", "--staged"];
7293
+ if (relpath) args.push("--", toUnixSlash(relpath));
7171
7294
  const result = await this.exec(args);
7172
7295
  if (!result.stdout) {
7173
- throw new Error(`No staged result.`);
7296
+ return {};
7174
7297
  }
7175
7298
  let res = {};
7176
7299
  let idx = 0;
@@ -7194,9 +7317,9 @@ var Repo = class {
7194
7317
  } else if (curr && /^[+\-]/.test(line)) {
7195
7318
  curr.lines.push(line);
7196
7319
  } else if (line.startsWith("diff --git")) {
7197
- let ms = line.match(/diff\s--git\sa\/(.*)\sb\//);
7198
- if (ms) {
7199
- fsPath = ms[1];
7320
+ const parsedPath = parseDiffPath(line);
7321
+ if (relpath || parsedPath) {
7322
+ fsPath = relpath ? toUnixSlash(relpath) : parsedPath;
7200
7323
  curr = void 0;
7201
7324
  idx += 4;
7202
7325
  continue;
@@ -7223,9 +7346,7 @@ var Repo = class {
7223
7346
  }
7224
7347
  async hasChanged() {
7225
7348
  let result = await this.exec(["diff", "--name-status"]);
7226
- if (!result.stdout) return false;
7227
- let lines = result.stdout.split(/\r?\n/);
7228
- return lines.some((l) => l.startsWith("M"));
7349
+ return result.stdout.trim().length > 0;
7229
7350
  }
7230
7351
  async getStaged() {
7231
7352
  let result = await this.exec(["diff", "--staged", "--name-status"]);
@@ -7244,23 +7365,23 @@ var Repo = class {
7244
7365
  return [conflicted, staged];
7245
7366
  }
7246
7367
  async hasUntracked() {
7247
- let cp2 = this.git.stream(this.root, ["ls-files", "--others", "--exclude-standard"]);
7368
+ let cp2 = this.git.stream(this.root, ["ls-files", "--others", "--exclude-standard", "--directory"]);
7248
7369
  return new Promise((resolve) => {
7249
- let hasData = false;
7250
- let timer = setTimeout(() => {
7251
- if (cp2.killed) return;
7252
- cp2.kill("SIGKILL");
7253
- resolve(false);
7254
- }, 100);
7370
+ let settled = false;
7371
+ const finish = (value) => {
7372
+ if (settled) return;
7373
+ settled = true;
7374
+ resolve(value);
7375
+ };
7255
7376
  cp2.stdout.on("data", () => {
7256
- clearTimeout(timer);
7257
- hasData = true;
7258
7377
  cp2.kill("SIGKILL");
7259
- resolve(hasData);
7378
+ finish(true);
7260
7379
  });
7261
7380
  cp2.on("exit", () => {
7262
- clearTimeout(timer);
7263
- resolve(hasData);
7381
+ finish(false);
7382
+ });
7383
+ cp2.on("error", () => {
7384
+ finish(false);
7264
7385
  });
7265
7386
  });
7266
7387
  }
@@ -7284,14 +7405,11 @@ var Repo = class {
7284
7405
  }
7285
7406
  async getDiff(relFilepath, content, revision = "", encoding = "utf8") {
7286
7407
  if (relFilepath.startsWith(`.git${import_path6.default.sep}`)) return;
7287
- let fullpath = import_path6.default.join(this.root, relFilepath);
7288
- if (!import_fs2.default.existsSync(fullpath)) return;
7289
7408
  let staged;
7290
7409
  try {
7291
7410
  let indexed = await this.isIndexed(relFilepath);
7292
7411
  if (!indexed) return;
7293
7412
  let res = await this.exec(["--no-pager", "show", `${revision}:${toUnixSlash(relFilepath)}`], { encoding });
7294
- if (!res.stdout) return;
7295
7413
  staged = res.stdout.replace(/\r?\n$/, "").split(/\r?\n/).join("\n");
7296
7414
  } catch (e) {
7297
7415
  this.channel.append(e.stack);
@@ -7299,39 +7417,55 @@ var Repo = class {
7299
7417
  }
7300
7418
  const stagedFile = import_path6.default.join(import_os.default.tmpdir(), `coc-${v4_default()}`);
7301
7419
  const currentFile = import_path6.default.join(import_os.default.tmpdir(), `coc-${v4_default()}`);
7302
- await import_util8.default.promisify(import_fs2.default.writeFile)(stagedFile, staged + "\n", "utf8");
7303
- await import_util8.default.promisify(import_fs2.default.writeFile)(currentFile, content, "utf8");
7304
- let output = await getStdout(`git --no-pager diff --no-ext-diff -p -U0 --no-color ${shellescape(stagedFile)} ${shellescape(currentFile)}`);
7305
- await import_util8.default.promisify(import_fs2.default.unlink)(stagedFile);
7306
- await import_util8.default.promisify(import_fs2.default.unlink)(currentFile);
7420
+ let output;
7421
+ try {
7422
+ await import_util5.default.promisify(import_fs2.default.writeFile)(stagedFile, staged + "\n", "utf8");
7423
+ await import_util5.default.promisify(import_fs2.default.writeFile)(currentFile, content, "utf8");
7424
+ const result = await this.exec([
7425
+ "--no-pager",
7426
+ "diff",
7427
+ "--no-index",
7428
+ "--no-ext-diff",
7429
+ "-p",
7430
+ "-U0",
7431
+ "--no-color",
7432
+ stagedFile,
7433
+ currentFile
7434
+ ], { allowedExitCodes: [1] });
7435
+ output = result.stdout;
7436
+ } finally {
7437
+ await Promise.all([
7438
+ import_util5.default.promisify(import_fs2.default.unlink)(stagedFile).catch(() => void 0),
7439
+ import_util5.default.promisify(import_fs2.default.unlink)(currentFile).catch(() => void 0)
7440
+ ]);
7441
+ }
7307
7442
  if (!output) return [];
7308
7443
  this.channel.appendLine(`> git diff ${relFilepath}`);
7309
- const lines = output.trim().split("\n");
7444
+ const lines = output.replace(/\r?\n$/, "").split(/\r?\n/);
7310
7445
  return parseDiff(lines);
7311
7446
  }
7312
7447
  async getDiffAll(category) {
7313
7448
  let diffGroups = /* @__PURE__ */ new Map();
7314
- let args = "";
7449
+ let args = ["-c", "core.quotepath=false", "--no-pager", "diff", "--no-ext-diff", "--no-renames", "-p", "-U0", "--no-color"];
7315
7450
  if (category === 0 /* All */) {
7316
- args = "HEAD";
7451
+ const head = await this.safeRun(["rev-parse", "--verify", "HEAD"]);
7452
+ if (head) {
7453
+ args.push("HEAD");
7454
+ } else {
7455
+ const emptyTree = await this.exec(["hash-object", "-t", "tree", "--stdin"], { input: "", log: false });
7456
+ args.push(emptyTree.stdout.trim());
7457
+ }
7317
7458
  } else if (category === 1 /* Staged */) {
7318
- args = "--cached";
7319
- } else {
7320
- args = "";
7459
+ args.push("--cached");
7321
7460
  }
7322
- let output = await getStdout(`git --no-pager diff --no-ext-diff -p -U0 --no-color ${args}`);
7461
+ let output = (await this.exec(args)).stdout;
7323
7462
  if (!output) return diffGroups;
7324
- const lines = output.trim().split("\n");
7463
+ const lines = output.replace(/\r?\n$/, "").split(/\r?\n/);
7325
7464
  let lineGroups = /* @__PURE__ */ new Map();
7326
7465
  let file = null;
7327
7466
  for (const line of lines) {
7328
7467
  if (line.startsWith("diff --git")) {
7329
- let ms = line.match(/diff\s--git\sa\/(.*)\sb\//);
7330
- if (ms) {
7331
- file = ms[1];
7332
- } else {
7333
- file = null;
7334
- }
7468
+ file = parseDiffPath(line) || null;
7335
7469
  }
7336
7470
  if (file) {
7337
7471
  if (!lineGroups.has(file)) {
@@ -7349,8 +7483,8 @@ var Repo = class {
7349
7483
  return diffGroups;
7350
7484
  }
7351
7485
  async isIgnored(relativePath) {
7352
- let res = await this.safeRun(["check-ignore", "--", relativePath]);
7353
- return res.trim() == relativePath;
7486
+ let res = await this.exec(["check-ignore", "-q", "--", relativePath], { allowedExitCodes: [1] });
7487
+ return res.exitCode === 0;
7354
7488
  }
7355
7489
  async hasConflicts(relativePath) {
7356
7490
  let indexed = await this.isIndexed(relativePath);
@@ -7393,6 +7527,67 @@ var Repo = class {
7393
7527
  }
7394
7528
  }
7395
7529
  };
7530
+ function readQuotedGitPath(input, start) {
7531
+ if (input[start] !== '"') return void 0;
7532
+ let value = "";
7533
+ for (let index = start + 1; index < input.length; index++) {
7534
+ const character = input[index];
7535
+ if (character === '"') return { value, end: index + 1 };
7536
+ if (character !== "\\") {
7537
+ value += character;
7538
+ continue;
7539
+ }
7540
+ const escaped = input[++index];
7541
+ if (escaped == null) return void 0;
7542
+ const escapes = {
7543
+ a: "\x07",
7544
+ b: "\b",
7545
+ t: " ",
7546
+ n: "\n",
7547
+ v: "\v",
7548
+ f: "\f",
7549
+ r: "\r",
7550
+ '"': '"',
7551
+ "\\": "\\"
7552
+ };
7553
+ if (escapes[escaped] != null) {
7554
+ value += escapes[escaped];
7555
+ continue;
7556
+ }
7557
+ if (/[0-7]/.test(escaped)) {
7558
+ let octal = escaped;
7559
+ while (octal.length < 3 && /[0-7]/.test(input[index + 1] || "")) octal += input[++index];
7560
+ value += String.fromCharCode(parseInt(octal, 8));
7561
+ continue;
7562
+ }
7563
+ value += escaped;
7564
+ }
7565
+ return void 0;
7566
+ }
7567
+ function parseDiffPath(line) {
7568
+ const prefix = "diff --git ";
7569
+ if (!line.startsWith(prefix)) return void 0;
7570
+ const value = line.slice(prefix.length);
7571
+ if (value.startsWith('"')) {
7572
+ const first = readQuotedGitPath(value, 0);
7573
+ if (!first) return void 0;
7574
+ const secondStart = value.indexOf('"', first.end);
7575
+ const second = secondStart === -1 ? void 0 : readQuotedGitPath(value, secondStart);
7576
+ if (!second || !first.value.startsWith("a/") || !second.value.startsWith("b/")) return void 0;
7577
+ const firstPath = first.value.slice(2);
7578
+ return firstPath === second.value.slice(2) ? firstPath : void 0;
7579
+ }
7580
+ if (!value.startsWith("a/")) return void 0;
7581
+ const paths = value.slice(2);
7582
+ let separator = paths.indexOf(" b/");
7583
+ while (separator !== -1) {
7584
+ const firstPath = paths.slice(0, separator);
7585
+ if (firstPath === paths.slice(separator + 3)) return firstPath;
7586
+ separator = paths.indexOf(" b/", separator + 1);
7587
+ }
7588
+ return void 0;
7589
+ }
7590
+ var repo_default = Repo;
7396
7591
  function parseDiff(diffLines) {
7397
7592
  const allLines = diffLines.slice(4);
7398
7593
  const diffs = [];
@@ -7456,11 +7651,11 @@ function parseDiff(diffLines) {
7456
7651
  var import_coc13 = require("coc.nvim");
7457
7652
  var import_fs3 = __toESM(require("fs"));
7458
7653
  var import_path7 = __toESM(require("path"));
7459
- var import_util10 = require("util");
7654
+ var import_util7 = require("util");
7460
7655
  async function getRealPath(fullpath) {
7461
7656
  let resolved;
7462
7657
  try {
7463
- resolved = await (0, import_util10.promisify)(import_fs3.default.realpath)(fullpath, "utf8");
7658
+ resolved = await (0, import_util7.promisify)(import_fs3.default.realpath)(fullpath, "utf8");
7464
7659
  } catch (e) {
7465
7660
  if (e.message.includes("ENOENT")) {
7466
7661
  try {
@@ -7515,7 +7710,7 @@ var Resolver = class {
7515
7710
  this.resolvedRoots.set(uri, root);
7516
7711
  } else {
7517
7712
  try {
7518
- let stat = import_fs3.default.statSync(fullpath);
7713
+ let stat = await (0, import_util7.promisify)(import_fs3.default.stat)(fullpath);
7519
7714
  let dir = stat.isDirectory() ? fullpath : import_path7.default.dirname(fullpath);
7520
7715
  root = await this.git.getRepositoryRoot(dir);
7521
7716
  if (import_path7.default.isAbsolute(root)) {
@@ -7550,12 +7745,11 @@ var Resolver = class {
7550
7745
  };
7551
7746
 
7552
7747
  // src/model/service.ts
7553
- var uriToRoot = /* @__PURE__ */ new Map();
7554
7748
  var GitService = class {
7555
7749
  constructor(gitInfo) {
7556
7750
  this.repos = /* @__PURE__ */ new Map();
7557
7751
  const outputChannel = this.outputChannel = import_coc14.window.createOutputChannel("git");
7558
- this._git = new Git(gitInfo, outputChannel);
7752
+ this._git = new git_default(gitInfo, outputChannel);
7559
7753
  this._resolver = new Resolver(this._git, outputChannel);
7560
7754
  if (typeof import_coc14.window.createFloatFactory === "function") {
7561
7755
  this.floatFactory = import_coc14.window.createFloatFactory({ modes: ["n"] });
@@ -7566,7 +7760,7 @@ var GitService = class {
7566
7760
  if (this.repos.has(root)) {
7567
7761
  return this.repos.get(root);
7568
7762
  }
7569
- let gitRepo = new Repo(this._git, this.outputChannel, root);
7763
+ let gitRepo = new repo_default(this._git, this.outputChannel, root);
7570
7764
  this.repos.set(root, gitRepo);
7571
7765
  return gitRepo;
7572
7766
  }
@@ -7579,19 +7773,15 @@ var GitService = class {
7579
7773
  if (!relpath) return void 0;
7580
7774
  let ignored = await repo.isIgnored(relpath);
7581
7775
  if (ignored) return void 0;
7582
- uriToRoot.set(doc.uri, root);
7583
7776
  let hasConflicts = await repo.hasConflicts(relpath);
7777
+ if (!doc.attached) return void 0;
7584
7778
  return new GitBuffer(doc, config, relpath, repo, this.git, this.outputChannel, this.floatFactory, hasConflicts);
7585
7779
  }
7586
7780
  async getCurrentRepo() {
7587
7781
  let editor = import_coc14.window.activeTextEditor;
7588
7782
  let root;
7589
7783
  if (editor) {
7590
- let { uri } = editor.document;
7591
- root = uriToRoot.get(uri);
7592
- if (!root) {
7593
- root = await this.resolver.resolveGitRoot(editor.document);
7594
- }
7784
+ root = await this.resolver.resolveGitRoot(editor.document);
7595
7785
  } else {
7596
7786
  let cwd = import_coc14.workspace.cwd;
7597
7787
  root = await this.resolver.resolveGitRoot({ uri: import_coc14.Uri.file(cwd).toString(), schema: "file", buftype: "" });
@@ -7620,13 +7810,15 @@ var GitService = class {
7620
7810
  // src/source.ts
7621
7811
  var import_coc15 = require("coc.nvim");
7622
7812
  var import_safe5 = __toESM(require_safe());
7813
+ var import_url2 = require("url");
7623
7814
  function byteSlice(content, start, end) {
7624
7815
  let buf = Buffer.from(content, "utf8");
7625
7816
  return buf.slice(start, end).toString("utf8");
7626
7817
  }
7627
7818
  var issuesMap = /* @__PURE__ */ new Map();
7628
7819
  function issuesFiletypes() {
7629
- return import_coc15.workspace.getConfiguration().get("coc.source.issues.filetypes");
7820
+ var _a;
7821
+ return (_a = import_coc15.workspace.getConfiguration().get("coc.source.issues.filetypes")) != null ? _a : [];
7630
7822
  }
7631
7823
  function getOrganizationNameAndRepoNameFromGitHubRemoteUrl(remoteUrl) {
7632
7824
  try {
@@ -7663,9 +7855,11 @@ function renderWord(issue, issueFormat) {
7663
7855
  }
7664
7856
  }).join("");
7665
7857
  }
7666
- function addSource(context, resolver) {
7858
+ function addSource(context, service) {
7667
7859
  let { subscriptions, logger } = context;
7860
+ const { resolver } = service;
7668
7861
  let statusItem = import_coc15.window.createStatusBarItem(0, { progress: true });
7862
+ subscriptions.push(statusItem, { dispose: () => issuesMap.clear() });
7669
7863
  statusItem.text = "loading issues";
7670
7864
  let statusItemCounter = 0;
7671
7865
  function onStartLoading() {
@@ -7675,7 +7869,7 @@ function addSource(context, resolver) {
7675
7869
  }
7676
7870
  }
7677
7871
  function onEndLoading() {
7678
- statusItemCounter--;
7872
+ statusItemCounter = Math.max(0, statusItemCounter - 1);
7679
7873
  if (statusItemCounter === 0) {
7680
7874
  statusItem.hide();
7681
7875
  }
@@ -7687,12 +7881,15 @@ function addSource(context, resolver) {
7687
7881
  const token = process.env["GITLAB_PRIVATE_TOKEN"];
7688
7882
  if (!token) return [];
7689
7883
  let repo;
7690
- if (res.startsWith("https")) {
7691
- const re = new RegExp(`^https:\\/\\/${host}\\/(.*)`);
7692
- let ms = res.match(re);
7693
- repo = ms ? ms[1].replace(/\.git$/, "") : null;
7694
- } else if (res.startsWith("git")) {
7695
- const re = new RegExp(`git@${host}:(.*)`);
7884
+ const escapedHost = host.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7885
+ if (res.startsWith("http")) {
7886
+ try {
7887
+ const url = new import_url2.URL(res);
7888
+ if (url.hostname === host) repo = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
7889
+ } catch (_e) {
7890
+ }
7891
+ } else {
7892
+ const re = new RegExp(`^(?:git@${escapedHost}:|ssh:\\/\\/git@${escapedHost}\\/)(.*)`);
7696
7893
  let ms = res.match(re);
7697
7894
  repo = ms ? ms[1].replace(/\.git$/, "") : null;
7698
7895
  }
@@ -7703,10 +7900,10 @@ function addSource(context, resolver) {
7703
7900
  onStartLoading();
7704
7901
  let issues = [];
7705
7902
  let pageIndex = 1;
7706
- while (true) {
7707
- const pageUri = `${uri}&page=${pageIndex}`;
7708
- pageIndex++;
7709
- try {
7903
+ try {
7904
+ while (true) {
7905
+ const pageUri = `${uri}&page=${pageIndex}`;
7906
+ pageIndex++;
7710
7907
  let info = await (0, import_coc15.fetch)(pageUri, { headers: { "Private-Token": token } });
7711
7908
  if (!info.length) {
7712
7909
  break;
@@ -7717,16 +7914,17 @@ function addSource(context, resolver) {
7717
7914
  title: info[i].title,
7718
7915
  createAt: new Date(info[i].created_at),
7719
7916
  creator: info[i].author.username,
7720
- body: info[i].description,
7917
+ body: info[i].description || "",
7721
7918
  repo,
7722
7919
  url: `https://${host}/${repo}/issues/${info[i].iid}`
7723
7920
  });
7724
7921
  }
7725
- } catch (e) {
7726
- logger.error(`Request GitLab ${host} issues error:`, e);
7727
7922
  }
7923
+ } catch (e) {
7924
+ logger.error(`Request GitLab ${host} issues error:`, e);
7925
+ } finally {
7926
+ onEndLoading();
7728
7927
  }
7729
- onEndLoading();
7730
7928
  return issues;
7731
7929
  }
7732
7930
  async function loadGitHubIssues(organizationName, repoName, shouldIncludeOrganizationNameAndRepoNameInAbbr = false) {
@@ -7753,7 +7951,7 @@ function addSource(context, resolver) {
7753
7951
  title: info[i].title,
7754
7952
  createAt: new Date(info[i].created_at),
7755
7953
  creator: info[i].user.login,
7756
- body: info[i].body,
7954
+ body: info[i].body || "",
7757
7955
  repo,
7758
7956
  url: `https://github.com/${repo}/issues/${info[i].number}`,
7759
7957
  shouldIncludeOrganizationNameAndRepoNameInAbbr
@@ -7769,7 +7967,8 @@ function addSource(context, resolver) {
7769
7967
  }
7770
7968
  async function loadIssues(root) {
7771
7969
  let config = import_coc15.workspace.getConfiguration("git", root);
7772
- const issueSources = (await safeRun(`git config --get coc-git.issuesources`, { cwd: root }) || "").trim();
7970
+ const repo = service.getRepoFromRoot(root);
7971
+ const issueSources = (await repo.safeRun(["config", "--get", "coc-git.issuesources"]) || "").trim();
7773
7972
  if (issueSources) {
7774
7973
  return Array.prototype.concat.apply(
7775
7974
  [],
@@ -7785,7 +7984,7 @@ function addSource(context, resolver) {
7785
7984
  );
7786
7985
  }
7787
7986
  let remoteName = config.get("remoteName", "origin");
7788
- let res = await safeRun(`git config --get remote.${remoteName}.url`, { cwd: root });
7987
+ let res = await repo.safeRun(["config", "--get", `remote.${remoteName}.url`]);
7789
7988
  res = res.trim();
7790
7989
  if (res.indexOf("github.com") > 0) {
7791
7990
  const organizationNameAndRepoName = getOrganizationNameAndRepoNameFromGitHubRemoteUrl(res);
@@ -7808,9 +8007,12 @@ function addSource(context, resolver) {
7808
8007
  }
7809
8008
  const loadIssuesFromDocument = (doc) => {
7810
8009
  resolver.resolveGitRoot(doc).then(async (root) => {
8010
+ var _a;
7811
8011
  if (root) {
7812
8012
  let issues = await loadIssues(root);
7813
- issuesMap.set(doc.bufnr, issues);
8013
+ if (((_a = import_coc15.workspace.getDocument(doc.bufnr)) == null ? void 0 : _a.uri) === doc.uri) {
8014
+ issuesMap.set(doc.bufnr, issues);
8015
+ }
7814
8016
  }
7815
8017
  }).catch(onError);
7816
8018
  };
@@ -7825,6 +8027,13 @@ function addSource(context, resolver) {
7825
8027
  loadIssuesFromDocument(doc);
7826
8028
  }
7827
8029
  }, null, subscriptions);
8030
+ subscriptions.push(import_coc15.workspace.registerAutocmd({
8031
+ event: "BufUnload",
8032
+ arglist: ["+expand('<abuf>')"],
8033
+ callback: (bufnr) => {
8034
+ issuesMap.delete(bufnr);
8035
+ }
8036
+ }));
7828
8037
  let source = {
7829
8038
  name: "issues",
7830
8039
  async doComplete(opt) {
@@ -7870,7 +8079,7 @@ function addSource(context, resolver) {
7870
8079
  execute: async (item, context2) => {
7871
8080
  let winid = context2.listWindow.id;
7872
8081
  let { body, id } = item.data;
7873
- let lines = body.split(/\r?\n/);
8082
+ let lines = (body || "").split(/\r?\n/);
7874
8083
  let mod = context2.options.position == "top" ? "below" : "above";
7875
8084
  let { nvim } = import_coc15.workspace;
7876
8085
  nvim.pauseNotification();
@@ -7907,6 +8116,7 @@ function addSource(context, resolver) {
7907
8116
 
7908
8117
  // src/index.ts
7909
8118
  async function activate(context) {
8119
+ var _a;
7910
8120
  const config = import_coc16.workspace.getConfiguration("git");
7911
8121
  const { subscriptions } = context;
7912
8122
  let gitInfo;
@@ -7923,7 +8133,7 @@ async function activate(context) {
7923
8133
  const service = new GitService(gitInfo);
7924
8134
  const manager = new DocumentManager(nvim, service, virtualTextSrcId, conflictSrcId);
7925
8135
  subscriptions.push(manager);
7926
- addSource(context, service.resolver);
8136
+ addSource(context, service);
7927
8137
  subscriptions.push(import_coc16.commands.registerCommand("git.refresh", () => {
7928
8138
  manager.refresh();
7929
8139
  }));
@@ -7975,6 +8185,9 @@ async function activate(context) {
7975
8185
  subscriptions.push(import_coc16.commands.registerCommand("git.chunkInfo", async () => {
7976
8186
  await manager.chunkInfo();
7977
8187
  }));
8188
+ subscriptions.push(import_coc16.commands.registerCommand("git.allChunkInfo", async () => {
8189
+ return await manager.allChunkInfo();
8190
+ }));
7978
8191
  subscriptions.push(import_coc16.commands.registerCommand("git.chunkStage", async () => {
7979
8192
  await manager.chunkStage();
7980
8193
  }));
@@ -8018,7 +8231,7 @@ async function activate(context) {
8018
8231
  subscriptions.push(import_coc16.listManager.registerList(new Gfiles(nvim, manager)));
8019
8232
  subscriptions.push(import_coc16.listManager.registerList(new GChunks(nvim, manager)));
8020
8233
  subscriptions.push(import_coc16.listManager.registerList(new GChanges(nvim, manager)));
8021
- subscriptions.push(import_coc16.languages.registerCompletionItemProvider("semantic-commit", "Commit", config.get("semanticCommit.filetypes"), {
8234
+ subscriptions.push(import_coc16.languages.registerCompletionItemProvider("semantic-commit", "Commit", (_a = config.get("semanticCommit.filetypes")) != null ? _a : [], {
8022
8235
  provideCompletionItems: async (document, position) => {
8023
8236
  if (position.line !== 0) {
8024
8237
  return [];
@@ -8068,6 +8281,7 @@ async function activate(context) {
8068
8281
  }
8069
8282
  // Annotate the CommonJS export names for ESM import in node:
8070
8283
  0 && (module.exports = {
8071
- activate
8284
+ activate,
8285
+ formatBlameText
8072
8286
  });
8073
8287
  //# sourceMappingURL=index.js.map