@gitkraken/core-gitlens 0.15.3 → 0.15.5

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 (91) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/dist/git/cache.d.ts +28 -18
  3. package/dist/git/cache.js +71 -25
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/context.d.ts +19 -2
  6. package/dist/git/context.js.map +1 -1
  7. package/dist/git/models/pullRequest.d.ts +7 -5
  8. package/dist/git/models/pullRequest.js.map +1 -1
  9. package/dist/git/models/reference.d.ts +8 -0
  10. package/dist/git/providers/branches.d.ts +43 -0
  11. package/dist/git/providers/provider.d.ts +7 -0
  12. package/dist/git/service.d.ts +5 -1
  13. package/dist/git/service.js +8 -4
  14. package/dist/git/service.js.map +1 -1
  15. package/dist/git/watching/changeEvent.d.ts +29 -3
  16. package/dist/git/watching/changeEvent.js +39 -3
  17. package/dist/git/watching/changeEvent.js.map +1 -1
  18. package/dist/git/watching/configSections.d.ts +35 -0
  19. package/dist/git/watching/configSections.js +210 -0
  20. package/dist/git/watching/configSections.js.map +1 -0
  21. package/dist/git/watching/watchGroup.d.ts +37 -4
  22. package/dist/git/watching/watchGroup.js +108 -2
  23. package/dist/git/watching/watchGroup.js.map +1 -1
  24. package/dist/git/watching/watchService.d.ts +14 -3
  25. package/dist/git/watching/watchService.js +10 -7
  26. package/dist/git/watching/watchService.js.map +1 -1
  27. package/dist/git/watching/watchSession.d.ts +52 -20
  28. package/dist/git/watching/watchSession.js +166 -43
  29. package/dist/git/watching/watchSession.js.map +1 -1
  30. package/dist/git/watching/watcherPatterns.js +1 -0
  31. package/dist/git/watching/watcherPatterns.js.map +1 -1
  32. package/dist/git/watching/worktreeSummary.d.ts +21 -3
  33. package/dist/git/watching/worktreeSummary.js +118 -17
  34. package/dist/git/watching/worktreeSummary.js.map +1 -1
  35. package/dist/git-cli/cliGitProvider.d.ts +6 -1
  36. package/dist/git-cli/cliGitProvider.js +45 -5
  37. package/dist/git-cli/cliGitProvider.js.map +1 -1
  38. package/dist/git-cli/parsers/refParser.js +2 -1
  39. package/dist/git-cli/parsers/refParser.js.map +1 -1
  40. package/dist/git-cli/providers/branches.d.ts +10 -3
  41. package/dist/git-cli/providers/branches.js +99 -25
  42. package/dist/git-cli/providers/branches.js.map +1 -1
  43. package/dist/git-cli/providers/config.d.ts +45 -9
  44. package/dist/git-cli/providers/config.js +150 -24
  45. package/dist/git-cli/providers/config.js.map +1 -1
  46. package/dist/git-cli/providers/operations.d.ts +35 -1
  47. package/dist/git-cli/providers/operations.js +175 -16
  48. package/dist/git-cli/providers/operations.js.map +1 -1
  49. package/dist/git-cli/providers/stash.d.ts +1 -0
  50. package/dist/git-cli/providers/stash.js +9 -3
  51. package/dist/git-cli/providers/stash.js.map +1 -1
  52. package/dist/git-cli/providers/worktrees.js +11 -4
  53. package/dist/git-cli/providers/worktrees.js.map +1 -1
  54. package/dist/git-cli/service.js +5 -1
  55. package/dist/git-cli/service.js.map +1 -1
  56. package/dist/plus/integrations/models/gitHostIntegration.d.ts +29 -14
  57. package/dist/plus/integrations/models/gitHostIntegration.js +41 -19
  58. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  59. package/dist/plus/integrations/providers/azure/azure.d.ts +16 -16
  60. package/dist/plus/integrations/providers/azure/azure.js +45 -25
  61. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  62. package/dist/plus/integrations/providers/azure/azure.utils.d.ts +12 -0
  63. package/dist/plus/integrations/providers/azure/azure.utils.js +17 -1
  64. package/dist/plus/integrations/providers/azure/azure.utils.js.map +1 -1
  65. package/dist/plus/integrations/providers/azure/search.d.ts +4 -0
  66. package/dist/plus/integrations/providers/azure/search.js +46 -2
  67. package/dist/plus/integrations/providers/azure/search.js.map +1 -1
  68. package/dist/plus/integrations/providers/azure/workItemSearch.d.ts +11 -0
  69. package/dist/plus/integrations/providers/azure/workItemSearch.js +54 -0
  70. package/dist/plus/integrations/providers/azure/workItemSearch.js.map +1 -0
  71. package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +2 -2
  72. package/dist/plus/integrations/providers/azure/workItemStateCategories.js +19 -15
  73. package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
  74. package/dist/plus/integrations/providers/azureDevOps.d.ts +33 -20
  75. package/dist/plus/integrations/providers/azureDevOps.js +109 -48
  76. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  77. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +16 -47
  78. package/dist/plus/integrations/providers/azureDevOpsServer.js +52 -91
  79. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  80. package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
  81. package/dist/plus/integrations/providers/models.d.ts +5 -0
  82. package/dist/plus/integrations/providers/models.js +14 -3
  83. package/dist/plus/integrations/providers/models.js.map +1 -1
  84. package/dist/plus/integrations/reads/drains.d.ts +2 -3
  85. package/dist/plus/integrations/reads/drains.js +4 -4
  86. package/dist/plus/integrations/reads/drains.js.map +1 -1
  87. package/dist/plus/integrations/reads/issues.js +7 -4
  88. package/dist/plus/integrations/reads/issues.js.map +1 -1
  89. package/dist/plus/integrations/reads/resolveRepository.js +5 -5
  90. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  91. package/package.json +1 -1
@@ -540,7 +540,8 @@ var BranchesGitSubProvider = class {
540
540
  }, ex));
541
541
  } finally {
542
542
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
543
- this.context.hooks?.repository?.onChanged?.(repoPath, mayWriteTracking(ref, options?.noTracking) ? ["config", "heads"] : ["heads"]);
543
+ if (mayWriteTracking(ref, options?.noTracking)) this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"], [`refs/heads/${name}`], { configConfinedToRefs: true });
544
+ else this.context.hooks?.repository?.onChanged?.(repoPath, ["heads"], [`refs/heads/${name}`]);
544
545
  }
545
546
  }
546
547
  async deleteLocalBranch(repoPath, names, options) {
@@ -554,11 +555,12 @@ var BranchesGitSubProvider = class {
554
555
  await this.git.run({ cwd: repoPath }, ...args);
555
556
  for (const branch of branches) await this.forgetDeletedBranch(repoPath, branch);
556
557
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
557
- this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"]);
558
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"], branches.map((b) => `refs/heads/${b}`), { configConfinedToRefs: true });
558
559
  } catch (ex) {
559
- if (await this.cleanupDeletedBranchMetadata(repoPath, branches)) {
560
+ const deleted = await this.cleanupDeletedBranchMetadata(repoPath, branches);
561
+ if (deleted.length) {
560
562
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
561
- this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"]);
563
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"], deleted.map((b) => `refs/heads/${b}`), { configConfinedToRefs: true });
562
564
  }
563
565
  if (ex instanceof BranchError) throw ex.update({
564
566
  action: options?.force ? "force delete" : "delete",
@@ -596,8 +598,8 @@ var BranchesGitSubProvider = class {
596
598
  * for the partial-failure path — one extra `for-each-ref` is cheap while already handling an error,
597
599
  * and keeps the success path free of it.
598
600
  *
599
- * Returns whether any of `names` is confirmed gone; `false` when the probe couldn't answer, so a
600
- * spurious notification is never fired on an unrelated failure.
601
+ * Returns those of `names` confirmed gone; none when the probe couldn't answer, so a spurious
602
+ * notification is never fired on an unrelated failure.
601
603
  */
602
604
  async cleanupDeletedBranchMetadata(repoPath, names) {
603
605
  try {
@@ -605,18 +607,18 @@ var BranchesGitSubProvider = class {
605
607
  cwd: repoPath,
606
608
  errors: "ignore"
607
609
  }, "for-each-ref", "--format=%(refname)", ...names.map((n) => `refs/heads/${n}`));
608
- if (result.completion.status !== "exited" || result.exitCode !== 0) return false;
610
+ if (result.completion.status !== "exited" || result.exitCode !== 0) return [];
609
611
  const prefix = "refs/heads/";
610
612
  const surviving = new Set(result.stdout.split("\n").map((l) => l.trim()).filter((l) => l.startsWith(prefix)).map((l) => l.substring(11)));
611
- let anyDeleted = false;
613
+ const deleted = [];
612
614
  for (const name of names) {
613
615
  if (surviving.has(name)) continue;
614
- anyDeleted = true;
616
+ deleted.push(name);
615
617
  await this.forgetDeletedBranch(repoPath, name);
616
618
  }
617
- return anyDeleted;
619
+ return deleted;
618
620
  } catch {
619
- return false;
621
+ return [];
620
622
  }
621
623
  }
622
624
  async deleteRemoteBranch(repoPath, names, remote) {
@@ -736,6 +738,26 @@ var BranchesGitSubProvider = class {
736
738
  const branches = new PageableResult((p) => this.getBranches(repoPath, p != null ? { paging: p } : void 0, cancellation));
737
739
  return getLocalBranchByUpstream(remoteBranchName, branches);
738
740
  }
741
+ async getPushTarget(repoPath, branch, cancellation) {
742
+ const records = await this.provider.refs.getRefs(repoPath, cancellation);
743
+ if (!records.length) return { known: false };
744
+ if (branch == null) {
745
+ const current = await this.getCurrentBranchReference(repoPath, cancellation);
746
+ if (current == null) return { known: false };
747
+ if (current.remote || isDetachedHead(current.name)) return {
748
+ known: true,
749
+ push: void 0,
750
+ upstream: void 0
751
+ };
752
+ branch = current.name;
753
+ }
754
+ const record = findRefRecord(records, branch.startsWith("refs/heads/") ? branch : `refs/heads/${branch}`);
755
+ return {
756
+ known: true,
757
+ push: record?.push ? toPushTargetRef(records, record.push) : void 0,
758
+ upstream: record?.upstream ? toPushTargetRef(records, record.upstream) : void 0
759
+ };
760
+ }
739
761
  /** Detects potential conflicts when applying commits onto a target branch (git rebase and cherry-pick) */
740
762
  async getPotentialApplyConflicts(repoPath, targetBranch, shas, options, cancellation) {
741
763
  if (!shas.length) return { status: "clean" };
@@ -1006,7 +1028,7 @@ var BranchesGitSubProvider = class {
1006
1028
  };
1007
1029
  if (createdFrom !== "HEAD") {
1008
1030
  if (options?.upstream) {
1009
- const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${createdFrom}@{u}`, priorityOpts);
1031
+ const upstream = await this.getUpstreamName(repoPath, createdFrom, priorityOpts, cancellation);
1010
1032
  if (upstream) return {
1011
1033
  branch: upstream,
1012
1034
  failed: false
@@ -1030,7 +1052,7 @@ var BranchesGitSubProvider = class {
1030
1052
  if (match?.length === 2) {
1031
1053
  let name = match[1];
1032
1054
  if (options?.upstream) {
1033
- const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`, priorityOpts);
1055
+ const upstream = await this.getUpstreamName(repoPath, name, priorityOpts, cancellation);
1034
1056
  if (upstream) return {
1035
1057
  branch: upstream,
1036
1058
  failed: false
@@ -1106,6 +1128,21 @@ var BranchesGitSubProvider = class {
1106
1128
  if (await this.isSelfRef(repoPath, name, branch, cancellation)) return void 0;
1107
1129
  return name;
1108
1130
  }
1131
+ getAheadOfBaseConfigKey(repoPath, cancellation) {
1132
+ return this.cache.getAheadOfBaseConfigKey(repoPath, async (checkoutPath, cacheable, signal) => {
1133
+ const result = await this.git.run({
1134
+ cwd: checkoutPath,
1135
+ cancellation: signal,
1136
+ expectedExitCodes: [1]
1137
+ }, "config", "--null", "--get-regexp", "^(branch\\..*\\.(remote|merge)|remote\\..*|init\\.defaultbranch)$");
1138
+ if (signal?.aborted) throw new CancellationError();
1139
+ if (result.completion.status !== "exited") {
1140
+ cacheable.invalidate();
1141
+ return;
1142
+ }
1143
+ return result.stdout;
1144
+ }, cancellation);
1145
+ }
1109
1146
  async getAheadOfBase(repoPath, branch, options, cancellation) {
1110
1147
  if (branch != null && isDetachedHead(branch)) branch = void 0;
1111
1148
  const dependsOn = new Set(branch != null ? [`refs/heads/${branch}`] : []);
@@ -1547,7 +1584,7 @@ var BranchesGitSubProvider = class {
1547
1584
  if (!candidate || candidate.startsWith("-")) return void 0;
1548
1585
  if (candidate === branch || candidate === `refs/heads/${branch}`) return void 0;
1549
1586
  addRefDependencies(dependsOn, candidate);
1550
- const upstreamName = this.provider.refs.getSymbolicReferenceName(repoPath, `${candidate}@{u}`, void 0, cancellation);
1587
+ const upstreamName = this.getUpstreamName(repoPath, candidate, void 0, cancellation);
1551
1588
  const getUpstreamFork = async () => {
1552
1589
  const upstream = await upstreamName;
1553
1590
  if (!upstream || upstream.startsWith("-")) return void 0;
@@ -1599,6 +1636,14 @@ var BranchesGitSubProvider = class {
1599
1636
  } : void 0;
1600
1637
  }
1601
1638
  /**
1639
+ * `<name>@{u}`, without asking git when the cached ref list shows `name` can't have one: a failed lookup isn't
1640
+ * cached, so asking it of a remote-tracking ref (`origin/main`, the usual default) re-spawns on every read.
1641
+ */
1642
+ async getUpstreamName(repoPath, name, options, cancellation) {
1643
+ if (!mayHaveUpstream(await this.provider.refs.getRefs(repoPath, cancellation), name)) return void 0;
1644
+ return this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`, options, cancellation);
1645
+ }
1646
+ /**
1602
1647
  * The base for a branch that is itself the default branch, with its tip: its own upstream, `upstream/<branch>`
1603
1648
  * when an `upstream` remote has it, else `<branch>@{u}`. Read from the cached ref and branch lists; only a
1604
1649
  * `<branch>` that isn't checked out spawns, for its `@{u}`. `undefined` when there is neither, or its ref is gone.
@@ -1757,7 +1802,7 @@ var BranchesGitSubProvider = class {
1757
1802
  }, ex));
1758
1803
  } finally {
1759
1804
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
1760
- this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"]);
1805
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"], [`refs/heads/${oldName}`, `refs/heads/${newName}`], { configConfinedToRefs: true });
1761
1806
  }
1762
1807
  }
1763
1808
  async setUpstreamBranch(repoPath, name, upstream) {
@@ -1785,7 +1830,7 @@ var BranchesGitSubProvider = class {
1785
1830
  }, ex));
1786
1831
  } finally {
1787
1832
  this.context.hooks?.cache?.onReset?.(repoPath, "branches");
1788
- this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"]);
1833
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "heads"], [`refs/heads/${name}`], { configConfinedToRefs: true });
1789
1834
  }
1790
1835
  }
1791
1836
  async storeBaseBranchName(repoPath, ref, base, options) {
@@ -1844,16 +1889,18 @@ __decorate([debug()], BranchesGitSubProvider.prototype, "deleteLocalBranch", nul
1844
1889
  __decorate([debug()], BranchesGitSubProvider.prototype, "deleteRemoteBranch", null);
1845
1890
  __decorate([debug()], BranchesGitSubProvider.prototype, "getBranchMergedStatus", null);
1846
1891
  __decorate([debug()], BranchesGitSubProvider.prototype, "getLocalBranchByUpstream", null);
1892
+ __decorate([trace({ exit: true })], BranchesGitSubProvider.prototype, "getPushTarget", null);
1847
1893
  __decorate([debug()], BranchesGitSubProvider.prototype, "getPotentialApplyConflicts", null);
1848
1894
  __decorate([debug()], BranchesGitSubProvider.prototype, "getPotentialMergeConflicts", null);
1849
1895
  __decorate([debug()], BranchesGitSubProvider.prototype, "getPotentialStashReapplyConflicts", null);
1850
1896
  __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getBaseBranchName", null);
1897
+ __decorate([trace()], BranchesGitSubProvider.prototype, "getAheadOfBaseConfigKey", null);
1851
1898
  __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getAheadOfBase", null);
1852
1899
  __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getAheadBehindCounts", null);
1853
1900
  __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getMergedBranches", null);
1854
1901
  __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getStoredMergeTargetBranchName", null);
1855
- __decorate([debug({ exit: true })], BranchesGitSubProvider.prototype, "getStoredDetectedMergeTargetBranchName", null);
1856
- __decorate([debug()], BranchesGitSubProvider.prototype, "getStoredUserMergeTargetBranchName", null);
1902
+ __decorate([trace({ exit: true })], BranchesGitSubProvider.prototype, "getStoredDetectedMergeTargetBranchName", null);
1903
+ __decorate([trace()], BranchesGitSubProvider.prototype, "getStoredUserMergeTargetBranchName", null);
1857
1904
  __decorate([trace()], BranchesGitSubProvider.prototype, "onCurrentBranchAccessed", null);
1858
1905
  __decorate([trace()], BranchesGitSubProvider.prototype, "onCurrentBranchModified", null);
1859
1906
  __decorate([trace()], BranchesGitSubProvider.prototype, "onCurrentBranchAgentActivity", null);
@@ -1870,19 +1917,14 @@ function parseSymbolicFullNames(stdout) {
1870
1917
  upstream: upstream || void 0
1871
1918
  };
1872
1919
  }
1873
- /** Each ref list {@link findRefTip} searched, by full name: one base read looks up many names in the same cached list */
1920
+ /** Each ref list {@link findRefTip} and {@link findRefRecord} searched, by full name: one base read looks up many names in the same cached list */
1874
1921
  const refRecordsByName = /* @__PURE__ */ new WeakMap();
1875
1922
  /**
1876
1923
  * The commit `name` resolves to among `records`, tried in git's own order for a short name (`refs/tags/` before
1877
1924
  * `refs/heads/` before `refs/remotes/`); annotated tags peel to their commit. `undefined` when no listed ref matches.
1878
1925
  */
1879
1926
  function findRefTip(records, name) {
1880
- let byName = refRecordsByName.get(records);
1881
- if (byName == null) {
1882
- byName = /* @__PURE__ */ new Map();
1883
- for (const record of records) if (!byName.has(record.name)) byName.set(record.name, record);
1884
- refRecordsByName.set(records, byName);
1885
- }
1927
+ const byName = getRefRecordsByName(records);
1886
1928
  for (const candidate of [
1887
1929
  name,
1888
1930
  `refs/${name}`,
@@ -1895,6 +1937,38 @@ function findRefTip(records, name) {
1895
1937
  if (record != null) return record.peeledObjectname || record.objectname;
1896
1938
  }
1897
1939
  }
1940
+ function getRefRecordsByName(records) {
1941
+ let byName = refRecordsByName.get(records);
1942
+ if (byName == null) {
1943
+ byName = /* @__PURE__ */ new Map();
1944
+ for (const record of records) if (!byName.has(record.name)) byName.set(record.name, record);
1945
+ refRecordsByName.set(records, byName);
1946
+ }
1947
+ return byName;
1948
+ }
1949
+ /** The record for the full ref name `fullName` in `records`, the cached ref list; no short-name resolution */
1950
+ function findRefRecord(records, fullName) {
1951
+ return getRefRecordsByName(records).get(fullName);
1952
+ }
1953
+ function toPushTargetRef(records, ref) {
1954
+ const record = findRefRecord(records, ref);
1955
+ return {
1956
+ ref,
1957
+ sha: record != null ? record.peeledObjectname || record.objectname : void 0
1958
+ };
1959
+ }
1960
+ /**
1961
+ * Whether `<name>@{u}` can resolve, judged from `records`, the cached ref list. git follows `@{u}` only from the
1962
+ * upstream configured for a branch of that short name (`branch.<name>.merge`), so a remote-tracking ref, a tag or a
1963
+ * full ref name (`refs/heads/main@{u}` is "no such branch") has none. A name that names a local branch, or no ref at
1964
+ * all (a deleted branch's leftover config still answers), is asked. An empty list is a failed enumeration (see
1965
+ * `getRefTip`), which says nothing either way.
1966
+ */
1967
+ function mayHaveUpstream(records, name) {
1968
+ if (!records.length || name === "HEAD") return true;
1969
+ if (findRefTip(records, `refs/heads/${name}`) != null) return true;
1970
+ return findRefTip(records, name) == null;
1971
+ }
1898
1972
  /**
1899
1973
  * Adds the full ref names a `.git/refs` watcher would report for `name`. A short name can't be told tag from local
1900
1974
  * from remote without a spawn, so it adds every form, including the tag git resolves it to first; a spurious one