coc-git 2.4.8 → 2.4.9

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.
Files changed (3) hide show
  1. package/Readme.md +1 -0
  2. package/lib/index.js +118 -0
  3. package/package.json +5 -1
package/Readme.md CHANGED
@@ -222,6 +222,7 @@ related commands.
222
222
  - `:CocCommand git.chunkInfo` Show chunk info under cursor.
223
223
  - `:CocCommand git.chunkUndo` Undo current chunk.
224
224
  - `:CocCommand git.chunkStage` Stage current chunk.
225
+ - `:CocCommand git.chunkUnstage` Unstage chunk that contains current line.
225
226
  - `:CocCommand git.diffCached` Show cached diff in preview window.
226
227
  - `:CocCommand git.showCommit` Show commit of current chunk.
227
228
  - `:CocCommand git.browserOpen` Open current line in browser
package/lib/index.js CHANGED
@@ -4565,6 +4565,30 @@ var import_child_process = __toModule(require("child_process"));
4565
4565
  var import_coc = __toModule(require("coc.nvim"));
4566
4566
  var import_path = __toModule(require("path"));
4567
4567
  var import_which = __toModule(require_which());
4568
+ function reverseLine(line) {
4569
+ if (line.startsWith("-"))
4570
+ return "+" + line.slice(1);
4571
+ if (line.startsWith("+"))
4572
+ return "-" + line.slice(1);
4573
+ return line;
4574
+ }
4575
+ function createUnstagePatch(relpath, chunk) {
4576
+ if (chunk.remove.count == 0 && chunk.add.count == 0)
4577
+ return "";
4578
+ let head = `@@ -${chunk.add.lnum},${chunk.add.count} +${chunk.add.lnum + 1 - chunk.add.count},${chunk.remove.count} @@`;
4579
+ if (!head)
4580
+ return "";
4581
+ const lines = [
4582
+ `diff --git a/${relpath} b/${relpath}`,
4583
+ `index 000000..000000 100644`,
4584
+ `--- a/${relpath}`,
4585
+ `+++ b/${relpath}`,
4586
+ head
4587
+ ];
4588
+ lines.push(...chunk.lines.map((s) => reverseLine(s)));
4589
+ lines.push("");
4590
+ return lines.join("\n");
4591
+ }
4568
4592
  function wait(ms) {
4569
4593
  return new Promise((resolve) => {
4570
4594
  setTimeout(() => {
@@ -5840,6 +5864,12 @@ var DocumentManager = class {
5840
5864
  return;
5841
5865
  await buf.chunkStage();
5842
5866
  }
5867
+ async chunkUnstage() {
5868
+ let buf = await this.buffer;
5869
+ if (!buf)
5870
+ return;
5871
+ await buf.chunkUnstage();
5872
+ }
5843
5873
  async chunkUndo() {
5844
5874
  let buf = await this.buffer;
5845
5875
  if (buf)
@@ -5929,6 +5959,48 @@ var Repo = class {
5929
5959
  this.channel = channel;
5930
5960
  this.root = root;
5931
5961
  }
5962
+ async getStagedChunks(relpath) {
5963
+ let args = ["--no-pager", "diff", "-p", "-U0", "--no-color", "--staged"];
5964
+ if (relpath)
5965
+ args.push(toUnixSlash(relpath));
5966
+ const result = await this.exec(args);
5967
+ if (!result.stdout) {
5968
+ throw new Error(`No staged result.`);
5969
+ }
5970
+ let res = {};
5971
+ let idx = 0;
5972
+ let lines = result.stdout.split(/\r?\n/);
5973
+ let curr;
5974
+ let fsPath;
5975
+ while (idx < lines.length) {
5976
+ let line = lines[idx];
5977
+ if (fsPath && line.startsWith("@@")) {
5978
+ curr = void 0;
5979
+ let ms = line.match(/^@@\s+-(\d+),?(\d*)\s+\+(\d+),?(\d*)\s+@@/);
5980
+ if (ms) {
5981
+ curr = {
5982
+ remove: {lnum: Number(ms[1]), count: ms[2] ? Number(ms[2]) : 1},
5983
+ add: {lnum: Number(ms[3]), count: ms[4] ? Number(ms[4]) : 1},
5984
+ lines: []
5985
+ };
5986
+ res[fsPath] = res[fsPath] || [];
5987
+ res[fsPath].push(curr);
5988
+ }
5989
+ } else if (curr && /^[+\-]/.test(line)) {
5990
+ curr.lines.push(line);
5991
+ } else if (line.startsWith("diff --git")) {
5992
+ let ms = line.match(/diff\s--git\sa\/(.*)\sb\//);
5993
+ if (ms) {
5994
+ fsPath = ms[1];
5995
+ curr = void 0;
5996
+ idx += 4;
5997
+ continue;
5998
+ }
5999
+ }
6000
+ idx++;
6001
+ }
6002
+ return res;
6003
+ }
5932
6004
  async getHEAD() {
5933
6005
  try {
5934
6006
  const result = await this.exec(["symbolic-ref", "--short", "HEAD"]);
@@ -6558,6 +6630,49 @@ var GitBuffer = class {
6558
6630
  this.channel.appendLine(`[Error] ${e.message}`);
6559
6631
  }
6560
6632
  }
6633
+ async chunkUnstage() {
6634
+ let {nvim} = import_coc11.workspace;
6635
+ const {diffs} = this;
6636
+ let line = await nvim.call("line", ".");
6637
+ let adjust = 0;
6638
+ let invalid = false;
6639
+ for (let diff of diffs) {
6640
+ if (diff.end >= line) {
6641
+ if (diff.start <= line && diff.changeType != ChangeType.Delete) {
6642
+ import_coc11.window.showErrorMessage(`Current line contains unstaged change.`);
6643
+ invalid = true;
6644
+ }
6645
+ break;
6646
+ }
6647
+ adjust -= diff.added.count;
6648
+ adjust += diff.removed.count;
6649
+ }
6650
+ if (invalid)
6651
+ return;
6652
+ line = line + adjust;
6653
+ let stagedDiff = await this.repo.getStagedChunks(this.relpath);
6654
+ let chunks = Object.values(stagedDiff)[0];
6655
+ if (!chunks.length) {
6656
+ import_coc11.window.showErrorMessage(`Staged chunk not found`);
6657
+ return;
6658
+ }
6659
+ let chunk = chunks.find((o) => o.add.lnum <= line && o.add.lnum + o.add.count >= line);
6660
+ if (!chunk) {
6661
+ import_coc11.window.showErrorMessage(`Unable to find staged chunk on current line`);
6662
+ return;
6663
+ }
6664
+ this.channel.appendLine(`[Info] resolved chunk ${JSON.stringify(chunk, null, 2)}`);
6665
+ let patch = createUnstagePatch(this.relpath, chunk);
6666
+ if (!patch)
6667
+ return;
6668
+ try {
6669
+ await this.git.exec(this.repo.root, ["apply", "--cached", "--unidiff-zero", "-"], {input: patch});
6670
+ this.refresh();
6671
+ } catch (e) {
6672
+ import_coc11.window.showErrorMessage(`Unable to apply patch: ${e.message}`);
6673
+ this.channel.appendLine(`[Error] ${e.message}`);
6674
+ }
6675
+ }
6561
6676
  async nextChunk() {
6562
6677
  const {diffs} = this;
6563
6678
  let {nvim} = import_coc11.workspace;
@@ -7634,6 +7749,9 @@ async function activate(context) {
7634
7749
  subscriptions.push(import_coc14.commands.registerCommand("git.chunkStage", async () => {
7635
7750
  await manager.chunkStage();
7636
7751
  }));
7752
+ subscriptions.push(import_coc14.commands.registerCommand("git.chunkUnstage", async () => {
7753
+ await manager.chunkUnstage();
7754
+ }));
7637
7755
  subscriptions.push(import_coc14.commands.registerCommand("git.chunkUndo", async () => {
7638
7756
  await manager.chunkUndo();
7639
7757
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coc-git",
3
- "version": "2.4.8",
3
+ "version": "2.4.9",
4
4
  "description": "Git extension for coc.nvim",
5
5
  "main": "lib/index.js",
6
6
  "publisher": "chemzqm",
@@ -35,6 +35,10 @@
35
35
  "title": "Stage current chunk.",
36
36
  "command": "git.chunkStage"
37
37
  },
38
+ {
39
+ "title": "Unstage chunk that contains current line",
40
+ "command": "git.chunkUnstage"
41
+ },
38
42
  {
39
43
  "title": "Undo current chunk.",
40
44
  "command": "git.chunkUndo"