@gitkraken/core-gitlens 0.15.3 → 0.15.4
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/CHANGELOG.md +28 -1
- package/dist/git/cache.d.ts +24 -11
- package/dist/git/cache.js +44 -16
- package/dist/git/cache.js.map +1 -1
- package/dist/git/models/pullRequest.d.ts +7 -5
- package/dist/git/models/pullRequest.js.map +1 -1
- package/dist/git/models/reference.d.ts +8 -0
- package/dist/git/providers/branches.d.ts +43 -0
- package/dist/git/watching/changeEvent.d.ts +4 -2
- package/dist/git/watching/changeEvent.js +3 -1
- package/dist/git/watching/changeEvent.js.map +1 -1
- package/dist/git/watching/watchGroup.d.ts +3 -3
- package/dist/git/watching/watchGroup.js +1 -0
- package/dist/git/watching/watchGroup.js.map +1 -1
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git/watching/watchSession.d.ts +2 -1
- package/dist/git/watching/watchSession.js +3 -2
- package/dist/git/watching/watchSession.js.map +1 -1
- package/dist/git/watching/watcherPatterns.js +1 -0
- package/dist/git/watching/watcherPatterns.js.map +1 -1
- package/dist/git/watching/worktreeSummary.d.ts +19 -3
- package/dist/git/watching/worktreeSummary.js +107 -17
- package/dist/git/watching/worktreeSummary.js.map +1 -1
- package/dist/git-cli/parsers/refParser.js +2 -1
- package/dist/git-cli/parsers/refParser.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +8 -1
- package/dist/git-cli/providers/branches.js +84 -12
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts +32 -9
- package/dist/git-cli/providers/config.js +113 -24
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +29 -14
- package/dist/plus/integrations/models/gitHostIntegration.js +41 -19
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.d.ts +16 -16
- package/dist/plus/integrations/providers/azure/azure.js +45 -25
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.utils.d.ts +12 -0
- package/dist/plus/integrations/providers/azure/azure.utils.js +17 -1
- package/dist/plus/integrations/providers/azure/azure.utils.js.map +1 -1
- package/dist/plus/integrations/providers/azure/search.d.ts +4 -0
- package/dist/plus/integrations/providers/azure/search.js +46 -2
- package/dist/plus/integrations/providers/azure/search.js.map +1 -1
- package/dist/plus/integrations/providers/azure/workItemSearch.d.ts +11 -0
- package/dist/plus/integrations/providers/azure/workItemSearch.js +54 -0
- package/dist/plus/integrations/providers/azure/workItemSearch.js.map +1 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +2 -2
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js +19 -15
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +33 -20
- package/dist/plus/integrations/providers/azureDevOps.js +109 -48
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +16 -47
- package/dist/plus/integrations/providers/azureDevOpsServer.js +52 -91
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +5 -0
- package/dist/plus/integrations/providers/models.js +14 -3
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +2 -2
- package/dist/plus/integrations/reads/drains.js +4 -4
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/issues.js +7 -4
- package/dist/plus/integrations/reads/issues.js.map +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +5 -5
- package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Emitter } from "../../../utils/event.js";
|
|
2
2
|
import { IssueSearchCriteria } from "../../../git/models/issue.js";
|
|
3
|
-
import {
|
|
3
|
+
import { PullRequestSearchCriteria } from "../../../git/models/pullRequest.js";
|
|
4
4
|
import { Account } from "../../../git/models/author.js";
|
|
5
5
|
import { ProviderAuthenticationSession, TokenWithInfo } from "../authentication/models.js";
|
|
6
6
|
import { GitSelfManagedHostIntegrationId } from "../constants.js";
|
|
7
7
|
import { ProviderPullRequestCount, ProviderPullRequestSearchPage } from "../models/pullRequestReads.js";
|
|
8
|
-
import { ProviderAzureResource,
|
|
8
|
+
import { ProviderAzureResource, ProviderRepoInput, ProviderReposInput } from "./models.js";
|
|
9
9
|
import { AzureRepositoryDescriptor } from "./azure/models.js";
|
|
10
10
|
import { ProvidersApi } from "./providersApi.js";
|
|
11
11
|
import { ProviderIssueSearchPage, ProviderSearchCount } from "../models/issueReads.js";
|
|
12
|
+
import { RepositoryCoordinate } from "../models/gitHostIntegration.js";
|
|
12
13
|
import { IntegrationKey } from "../models/integration.js";
|
|
13
14
|
import { IntegrationConnectionChangeEvent } from "../integrationService.js";
|
|
14
15
|
import { IntegrationAuthenticationService } from "../authentication/integrationAuthenticationService.js";
|
|
@@ -45,11 +46,14 @@ export declare class AzureDevOpsServerIntegration extends AzureDevOpsIntegration
|
|
|
45
46
|
/** The base a request below `collection` appends to: the installation, whichever the address already ends in. */
|
|
46
47
|
protected collectionApiBaseUrl(session: ProviderAuthenticationSession, collection: string): string;
|
|
47
48
|
/**
|
|
48
|
-
* The collection names per credential and installation, `undefined` when they couldn't be read
|
|
49
|
+
* The collection names per credential and installation, `undefined` when they couldn't be read, and whether the
|
|
50
|
+
* address is then presumed to name a collection ({@link requestResourcesForUser}). Only a
|
|
49
51
|
* tie-breaker for {@link getRepositoryTarget}, so a failed read is kept (for {@link discoveryCacheTtl}) rather than
|
|
50
52
|
* retried on every repository read; a successful one comes from the organizations, which are kept for the session.
|
|
51
53
|
*/
|
|
52
54
|
private readonly _collectionNames;
|
|
55
|
+
/** The failures to read the collection an address names after its collection list answered with a 404. */
|
|
56
|
+
private readonly _collectionListRefusals;
|
|
53
57
|
/**
|
|
54
58
|
* Settles which segment of a remote's path is the collection before reading the repository. Behind a virtual
|
|
55
59
|
* directory a repository named after its project is also served as `{vdir}/{collection}/_git/{repo}`, which the
|
|
@@ -62,6 +66,8 @@ export declare class AzureDevOpsServerIntegration extends AzureDevOpsIntegration
|
|
|
62
66
|
/**
|
|
63
67
|
* The repository {@link getRepositoryTarget} reads `repo` as, and the base it reads it below: `undefined` when the
|
|
64
68
|
* connection doesn't serve its virtual directory (another installation's) or that directory isn't a valid one.
|
|
69
|
+
* `isCandidate` is whether `repo` can be project-less below the connection ({@link isAzureProjectlessCandidate} by
|
|
70
|
+
* default), given whether the connection is known to address a collection rather than the installation.
|
|
65
71
|
*/
|
|
66
72
|
private settleRepository;
|
|
67
73
|
/**
|
|
@@ -71,23 +77,10 @@ export declare class AzureDevOpsServerIntegration extends AzureDevOpsIntegration
|
|
|
71
77
|
* Only the coordinate is settled, and only to a repository the connection serves: each read places it below the
|
|
72
78
|
* connection itself, so one settling elsewhere reads as given and fails its own read rather than every coordinate's.
|
|
73
79
|
*/
|
|
74
|
-
protected resolveRepositoryCoordinates<T extends {
|
|
75
|
-
owner: string;
|
|
76
|
-
repo: string;
|
|
77
|
-
project?: string;
|
|
78
|
-
}>(session: ProviderAuthenticationSession, coordinates: readonly T[], cancellation?: AbortSignal): Promise<{
|
|
80
|
+
protected resolveRepositoryCoordinates<T extends RepositoryCoordinate>(session: ProviderAuthenticationSession, coordinates: readonly T[], cancellation?: AbortSignal): Promise<{
|
|
79
81
|
coordinates: readonly T[];
|
|
80
82
|
unsettled?: readonly boolean[];
|
|
81
83
|
}>;
|
|
82
|
-
/**
|
|
83
|
-
* The searches and counts take only `repos`: they re-read the collections and refuse a scope whose collection
|
|
84
|
-
* isn't one of them ({@link getSearchCollections}), and a scope read as parsed below a listed collection is what
|
|
85
|
-
* settling it would read ({@link resolveAzureProjectlessRepository}), so a miss there is not `unsettled`.
|
|
86
|
-
*/
|
|
87
|
-
protected resolveRepositoryInputs(session: ProviderAuthenticationSession, repos: readonly ProviderRepoInput[], cancellation?: AbortSignal): Promise<{
|
|
88
|
-
repos: ProviderRepoInput[];
|
|
89
|
-
unsettled?: readonly boolean[];
|
|
90
|
-
}>;
|
|
91
84
|
/**
|
|
92
85
|
* Never rejects. A credential refused the list leaves every path as parsed, as before discovery was asked; any other
|
|
93
86
|
* failure is `undefined`, so a read of a path it could have settled keeps a miss out of the caches (see
|
|
@@ -98,11 +91,13 @@ export declare class AzureDevOpsServerIntegration extends AzureDevOpsIntegration
|
|
|
98
91
|
/**
|
|
99
92
|
* Only the server level lists the collections: below one, Azure DevOps Server answers `projectCollections` with a
|
|
100
93
|
* 404 page. On that 404 an address that names a collection reads the collection's own connection data, whose
|
|
101
|
-
* `webApplicationRelativeDirectory` spells it, and reports it as the one collection visible there.
|
|
94
|
+
* `webApplicationRelativeDirectory` spells it, and reports it as the one collection visible there. When that read
|
|
95
|
+
* fails, the address is presumed to name a collection, which the failure carries (see {@link getCollectionNames}) for
|
|
96
|
+
* as long as the failed discovery is kept; connection data that answers for the server says it doesn't.
|
|
102
97
|
*/
|
|
103
98
|
protected requestResourcesForUser(session: ProviderAuthenticationSession, userId: string): Promise<ProviderAzureResource[] | undefined>;
|
|
104
99
|
/**
|
|
105
|
-
* The filtered work-item search
|
|
100
|
+
* The filtered work-item search snapshots matching ids with bounded WIQL queries, then reads details for each
|
|
106
101
|
* page's slice. See {@link resolveWorkItemSearchScope} for why a search never spans several collections.
|
|
107
102
|
*/
|
|
108
103
|
protected searchProviderIssuesPage(session: ProviderAuthenticationSession, options: {
|
|
@@ -196,34 +191,8 @@ export declare class AzureDevOpsServerIntegration extends AzureDevOpsIntegration
|
|
|
196
191
|
* user reads every project the account can see, the same breadth as the account-wide pull request read.
|
|
197
192
|
*/
|
|
198
193
|
private resolvePullRequestSearchFacets;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
* The current user's identity id in `collection`, read from the collection's own connection data, which is
|
|
202
|
-
* what Azure's creator and reviewer filters compare against. Cached per credential and collection, since it
|
|
203
|
-
* can't change for either.
|
|
204
|
-
*/
|
|
205
|
-
protected getFilterUserId(session: ProviderAuthenticationSession, collection: string): Promise<string | undefined>;
|
|
206
|
-
/**
|
|
207
|
-
* Resolved per collection, which a raw row names as its repository owner: a collection's pull requests carry the
|
|
208
|
-
* id {@link getFilterUserId} resolves there, never the server-level account's. A row that names no collection or
|
|
209
|
-
* has no author to match gets no viewer, nor does one in a collection whose id can't be read: its authorship
|
|
210
|
-
* stays unknown.
|
|
211
|
-
*/
|
|
212
|
-
getPullRequestViewers(pullRequests: readonly (ProviderPullRequest | PullRequest)[], connectionId?: string): Promise<({
|
|
213
|
-
id: string;
|
|
214
|
-
username?: string;
|
|
215
|
-
} | undefined)[]>;
|
|
216
|
-
/**
|
|
217
|
-
* Ignores `account`: it is the server-level one, which no collection's pull requests carry. A collection whose id
|
|
218
|
-
* can't be read resolves `undefined`, since authorship is optional enrichment and one collection's failed lookup
|
|
219
|
-
* must not fail the read or blank the others; it is asked once per read, as a miss isn't cached.
|
|
220
|
-
*/
|
|
221
|
-
protected getOrganizationViewers(session: ProviderAuthenticationSession, _account: {
|
|
222
|
-
id: string;
|
|
223
|
-
username?: string;
|
|
224
|
-
} | undefined): (collection: string) => Promise<{
|
|
225
|
-
id: string;
|
|
226
|
-
} | undefined>;
|
|
194
|
+
/** Reads the collection's own connection data, at the installation's address. */
|
|
195
|
+
protected requestOrganizationUserId(session: ProviderAuthenticationSession, collection: string): Promise<string | undefined>;
|
|
227
196
|
/** Every collection the account can see, or a refusal when discovery itself failed. */
|
|
228
197
|
private getSearchCollections;
|
|
229
198
|
/**
|
|
@@ -10,9 +10,10 @@ import "../constants.js";
|
|
|
10
10
|
import { toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
11
11
|
import { toTokenWithInfo } from "../authentication/models.js";
|
|
12
12
|
import { compareAzurePullRequestSearchPositions, getInvalidAzureSearchDate, isAzureWorkItemSearchFirstPage, parseAzurePullRequestSearchCursor, toAzurePullRequestSearchCursorKey, toAzurePullRequestSearchFilter, toAzurePullRequestSearchPosition, toAzureSearchPageSize } from "./azure/search.js";
|
|
13
|
-
import { fromProviderPullRequest, getProviderPullRequestIdentity,
|
|
13
|
+
import { fromProviderPullRequest, getProviderPullRequestIdentity, providersMetadata, toProviderPullRequestStates } from "./models.js";
|
|
14
|
+
import { getAzureRepositoryIdentity } from "./azure/azure.utils.js";
|
|
14
15
|
import { discoveryCacheTtl } from "./utils/discoveryCache.js";
|
|
15
|
-
import { AzureDevOpsIntegrationBase, findAzureRepositoryApiBaseUrl, getAzureRepositoryApiBaseUrl,
|
|
16
|
+
import { AzureDevOpsIntegrationBase, findAzureRepositoryApiBaseUrl, getAzureRepositoryApiBaseUrl, getAzureScopeVirtualDirectory, isAzureProjectlessCandidate, markMyGroupReviews, resolveAzureProjectlessRepository, sameAzureName, toAzureReviewerReads, uniqueAzureNames } from "./azureDevOps.js";
|
|
16
17
|
//#region ../plus/integrations/src/providers/azureDevOpsServer.ts
|
|
17
18
|
/**
|
|
18
19
|
* Whether `value` can stand as one route segment. Encoding keeps `.` and `..` as they are, and a URL resolves them
|
|
@@ -149,7 +150,8 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
149
150
|
});
|
|
150
151
|
}
|
|
151
152
|
/**
|
|
152
|
-
* The collection names per credential and installation, `undefined` when they couldn't be read
|
|
153
|
+
* The collection names per credential and installation, `undefined` when they couldn't be read, and whether the
|
|
154
|
+
* address is then presumed to name a collection ({@link requestResourcesForUser}). Only a
|
|
153
155
|
* tie-breaker for {@link getRepositoryTarget}, so a failed read is kept (for {@link discoveryCacheTtl}) rather than
|
|
154
156
|
* retried on every repository read; a successful one comes from the organizations, which are kept for the session.
|
|
155
157
|
*/
|
|
@@ -157,6 +159,8 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
157
159
|
capacity: 10,
|
|
158
160
|
createTTL: discoveryCacheTtl
|
|
159
161
|
});
|
|
162
|
+
/** The failures to read the collection an address names after its collection list answered with a 404. */
|
|
163
|
+
_collectionListRefusals = /* @__PURE__ */ new WeakSet();
|
|
160
164
|
/**
|
|
161
165
|
* Settles which segment of a remote's path is the collection before reading the repository. Behind a virtual
|
|
162
166
|
* directory a repository named after its project is also served as `{vdir}/{collection}/_git/{repo}`, which the
|
|
@@ -176,15 +180,18 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
176
180
|
/**
|
|
177
181
|
* The repository {@link getRepositoryTarget} reads `repo` as, and the base it reads it below: `undefined` when the
|
|
178
182
|
* connection doesn't serve its virtual directory (another installation's) or that directory isn't a valid one.
|
|
183
|
+
* `isCandidate` is whether `repo` can be project-less below the connection ({@link isAzureProjectlessCandidate} by
|
|
184
|
+
* default), given whether the connection is known to address a collection rather than the installation.
|
|
179
185
|
*/
|
|
180
|
-
async settleRepository(session, repo, cancellation) {
|
|
186
|
+
async settleRepository(session, repo, cancellation, isCandidate) {
|
|
181
187
|
const baseUrl = this.apiBaseUrlFor(session);
|
|
188
|
+
const candidate = isCandidate ?? ((belowCollection) => isAzureProjectlessCandidate(baseUrl, repo, belowCollection));
|
|
182
189
|
let unsettled = false;
|
|
183
|
-
if (
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
-
else unsettled = true;
|
|
190
|
+
if (candidate(false)) {
|
|
191
|
+
const discovery = this._collectionNames.getOrCreate(this.discoveryKey(session), () => this.getCollectionNames(session));
|
|
192
|
+
const { names, addressesCollection } = await (cancellation != null ? raceWithSignal(discovery, cancellation) : discovery);
|
|
193
|
+
if (names != null) repo = resolveAzureProjectlessRepository(repo, names);
|
|
194
|
+
else unsettled = candidate(addressesCollection === true);
|
|
188
195
|
}
|
|
189
196
|
return {
|
|
190
197
|
repo,
|
|
@@ -212,14 +219,21 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
212
219
|
name: `${c.project}/_git/${c.repo}`,
|
|
213
220
|
project: c.project,
|
|
214
221
|
virtualDirectory: virtualDirectory || void 0
|
|
215
|
-
}, cancellation);
|
|
216
|
-
return {
|
|
217
|
-
coordinate:
|
|
222
|
+
}, cancellation, (belowCollection) => getAzureScopeVirtualDirectory(baseUrl, c.owner, belowCollection) != null);
|
|
223
|
+
if (repo.owner === c.owner) return {
|
|
224
|
+
coordinate: c,
|
|
225
|
+
unsettled
|
|
226
|
+
};
|
|
227
|
+
return repoBaseUrl != null ? {
|
|
228
|
+
coordinate: {
|
|
218
229
|
...c,
|
|
219
230
|
owner: repo.owner,
|
|
220
231
|
project: repo.project
|
|
221
|
-
}
|
|
232
|
+
},
|
|
222
233
|
unsettled
|
|
234
|
+
} : {
|
|
235
|
+
coordinate: c,
|
|
236
|
+
unsettled: true
|
|
223
237
|
};
|
|
224
238
|
}));
|
|
225
239
|
return {
|
|
@@ -228,37 +242,20 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
228
242
|
};
|
|
229
243
|
}
|
|
230
244
|
/**
|
|
231
|
-
* The searches and counts take only `repos`: they re-read the collections and refuse a scope whose collection
|
|
232
|
-
* isn't one of them ({@link getSearchCollections}), and a scope read as parsed below a listed collection is what
|
|
233
|
-
* settling it would read ({@link resolveAzureProjectlessRepository}), so a miss there is not `unsettled`.
|
|
234
|
-
*/
|
|
235
|
-
async resolveRepositoryInputs(session, repos, cancellation) {
|
|
236
|
-
const { coordinates, unsettled } = await this.resolveRepositoryCoordinates(session, repos.map((r) => ({
|
|
237
|
-
...r,
|
|
238
|
-
owner: r.namespace,
|
|
239
|
-
repo: r.name
|
|
240
|
-
})), cancellation);
|
|
241
|
-
return {
|
|
242
|
-
repos: coordinates.map(({ owner, repo, ...r }) => ({
|
|
243
|
-
...r,
|
|
244
|
-
namespace: owner,
|
|
245
|
-
name: repo
|
|
246
|
-
})),
|
|
247
|
-
unsettled
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
245
|
* Never rejects. A credential refused the list leaves every path as parsed, as before discovery was asked; any other
|
|
252
246
|
* failure is `undefined`, so a read of a path it could have settled keeps a miss out of the caches (see
|
|
253
247
|
* `readRepository`).
|
|
254
248
|
*/
|
|
255
249
|
async getCollectionNames(session) {
|
|
256
250
|
try {
|
|
257
|
-
return (await this.getProviderResourcesForUser(session))?.map((r) => r.name);
|
|
251
|
+
return { names: (await this.getProviderResourcesForUser(session))?.map((r) => r.name) };
|
|
258
252
|
} catch (ex) {
|
|
259
|
-
if (ex instanceof AuthenticationError) return [];
|
|
253
|
+
if (ex instanceof AuthenticationError) return { names: [] };
|
|
260
254
|
_logger.debug(`${this.name}: collections at ${this.apiBaseUrlFor(session)} couldn't be read to place a repository path`, ex);
|
|
261
|
-
return
|
|
255
|
+
return {
|
|
256
|
+
names: void 0,
|
|
257
|
+
addressesCollection: this._collectionListRefusals.has(ex)
|
|
258
|
+
};
|
|
262
259
|
}
|
|
263
260
|
}
|
|
264
261
|
invalidateDiscoveryCaches() {
|
|
@@ -268,20 +265,29 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
268
265
|
/**
|
|
269
266
|
* Only the server level lists the collections: below one, Azure DevOps Server answers `projectCollections` with a
|
|
270
267
|
* 404 page. On that 404 an address that names a collection reads the collection's own connection data, whose
|
|
271
|
-
* `webApplicationRelativeDirectory` spells it, and reports it as the one collection visible there.
|
|
268
|
+
* `webApplicationRelativeDirectory` spells it, and reports it as the one collection visible there. When that read
|
|
269
|
+
* fails, the address is presumed to name a collection, which the failure carries (see {@link getCollectionNames}) for
|
|
270
|
+
* as long as the failed discovery is kept; connection data that answers for the server says it doesn't.
|
|
272
271
|
*/
|
|
273
272
|
async requestResourcesForUser(session, userId) {
|
|
274
273
|
try {
|
|
275
274
|
return await super.requestResourcesForUser(session, userId);
|
|
276
275
|
} catch (ex) {
|
|
277
276
|
if (!(ex instanceof RequestNotFoundError)) throw ex;
|
|
278
|
-
const
|
|
277
|
+
const azure = await this.authenticationService.apis.azure;
|
|
278
|
+
let addressed;
|
|
279
|
+
try {
|
|
280
|
+
addressed = await azure?.getAddressedCollection(this, toTokenWithInfo(this.id, session), this.apiBaseUrlFor(session));
|
|
281
|
+
} catch (collectionError) {
|
|
282
|
+
if (typeof collectionError === "object" && collectionError != null) this._collectionListRefusals.add(collectionError);
|
|
283
|
+
throw collectionError;
|
|
284
|
+
}
|
|
279
285
|
if (addressed == null) throw ex;
|
|
280
286
|
return [addressed];
|
|
281
287
|
}
|
|
282
288
|
}
|
|
283
289
|
/**
|
|
284
|
-
* The filtered work-item search
|
|
290
|
+
* The filtered work-item search snapshots matching ids with bounded WIQL queries, then reads details for each
|
|
285
291
|
* page's slice. See {@link resolveWorkItemSearchScope} for why a search never spans several collections.
|
|
286
292
|
*/
|
|
287
293
|
async searchProviderIssuesPage(session, options, cancellation) {
|
|
@@ -293,7 +299,8 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
293
299
|
return azure.searchWorkItemsPage(this, toTokenWithInfo(this.id, session), scope.collection, {
|
|
294
300
|
baseUrl: this.collectionApiBaseUrl(session, scope.collection),
|
|
295
301
|
criteria: options.criteria,
|
|
296
|
-
projectNames: scope.projectNames
|
|
302
|
+
projectNames: scope.projectNames,
|
|
303
|
+
workflowProjectNames: scope.projects.map((p) => p.name),
|
|
297
304
|
resolveProject: (name) => scope.projects.find((p) => sameAzureName(p.name, name)),
|
|
298
305
|
cursor: options.cursor,
|
|
299
306
|
pageSize: options.pageSize
|
|
@@ -316,7 +323,8 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
316
323
|
return azure.countWorkItems(this, tokenWithInfo, scope.collection, {
|
|
317
324
|
baseUrl: this.collectionApiBaseUrl(session, scope.collection),
|
|
318
325
|
criteria: s.criteria,
|
|
319
|
-
projectNames: scope.projectNames
|
|
326
|
+
projectNames: scope.projectNames,
|
|
327
|
+
workflowProjectNames: scope.projects.map((p) => p.name)
|
|
320
328
|
}, cancellation);
|
|
321
329
|
}));
|
|
322
330
|
}
|
|
@@ -625,55 +633,9 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
625
633
|
project: p
|
|
626
634
|
}));
|
|
627
635
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
* what Azure's creator and reviewer filters compare against. Cached per credential and collection, since it
|
|
632
|
-
* can't change for either.
|
|
633
|
-
*/
|
|
634
|
-
getFilterUserId(session, collection) {
|
|
635
|
-
const baseUrl = this.collectionApiBaseUrl(session, collection);
|
|
636
|
-
return this._collectionUserIds.getOrCreate(JSON.stringify([
|
|
637
|
-
session.accessToken,
|
|
638
|
-
baseUrl,
|
|
639
|
-
collection.toLowerCase()
|
|
640
|
-
]), async (cacheable) => {
|
|
641
|
-
const user = await (await this.authenticationService.apis.azure)?.getCurrentUserOnServer(this, toTokenWithInfo(this.id, session), `${baseUrl}/${encodeURIComponent(collection)}`);
|
|
642
|
-
if (user?.id == null) cacheable.invalidate();
|
|
643
|
-
return user?.id;
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
/**
|
|
647
|
-
* Resolved per collection, which a raw row names as its repository owner: a collection's pull requests carry the
|
|
648
|
-
* id {@link getFilterUserId} resolves there, never the server-level account's. A row that names no collection or
|
|
649
|
-
* has no author to match gets no viewer, nor does one in a collection whose id can't be read: its authorship
|
|
650
|
-
* stays unknown.
|
|
651
|
-
*/
|
|
652
|
-
async getPullRequestViewers(pullRequests, connectionId) {
|
|
653
|
-
const session = await this.resolveReadSessionOrThrow(connectionId, void 0);
|
|
654
|
-
if (session == null) return pullRequests.map(() => void 0);
|
|
655
|
-
const viewerFor = this.getOrganizationViewers(session, void 0);
|
|
656
|
-
return Promise.all(pullRequests.map((pr) => {
|
|
657
|
-
const collection = isNativePullRequest(pr) ? void 0 : pr.repository?.owner?.login;
|
|
658
|
-
return collection && pr.author != null ? viewerFor(collection) : Promise.resolve(void 0);
|
|
659
|
-
}));
|
|
660
|
-
}
|
|
661
|
-
/**
|
|
662
|
-
* Ignores `account`: it is the server-level one, which no collection's pull requests carry. A collection whose id
|
|
663
|
-
* can't be read resolves `undefined`, since authorship is optional enrichment and one collection's failed lookup
|
|
664
|
-
* must not fail the read or blank the others; it is asked once per read, as a miss isn't cached.
|
|
665
|
-
*/
|
|
666
|
-
getOrganizationViewers(session, _account) {
|
|
667
|
-
const viewers = /* @__PURE__ */ new Map();
|
|
668
|
-
return (collection) => {
|
|
669
|
-
const key = collection.toLowerCase();
|
|
670
|
-
let viewer = viewers.get(key);
|
|
671
|
-
if (viewer == null) {
|
|
672
|
-
viewer = this.getFilterUserId(session, collection).then((id) => id != null ? { id } : void 0, () => void 0);
|
|
673
|
-
viewers.set(key, viewer);
|
|
674
|
-
}
|
|
675
|
-
return viewer;
|
|
676
|
-
};
|
|
636
|
+
/** Reads the collection's own connection data, at the installation's address. */
|
|
637
|
+
async requestOrganizationUserId(session, collection) {
|
|
638
|
+
return (await (await this.authenticationService.apis.azure)?.getCurrentUserOnServer(this, toTokenWithInfo(this.id, session), `${this.collectionApiBaseUrl(session, collection)}/${encodeURIComponent(collection)}`))?.id;
|
|
677
639
|
}
|
|
678
640
|
/** Every collection the account can see, or a refusal when discovery itself failed. */
|
|
679
641
|
async getSearchCollections(session) {
|
|
@@ -723,7 +685,6 @@ var AzureDevOpsServerIntegration = class extends AzureDevOpsIntegrationBase {
|
|
|
723
685
|
super.providerOnDisconnect();
|
|
724
686
|
this._pullRequestSearches.clear();
|
|
725
687
|
this._latestPullRequestSearches.clear();
|
|
726
|
-
this._collectionUserIds.clear();
|
|
727
688
|
this._collectionNames.clear();
|
|
728
689
|
}
|
|
729
690
|
async _requestForCurrentUser(session) {
|