Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/common/agentHostSessionWorkspace.ts
13388 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Codicon } from '../../base/common/codicons.js';
7
import { match as matchGlob } from '../../base/common/glob.js';
8
import { extUri, basename } from '../../base/common/resources.js';
9
import { ThemeIcon } from '../../base/common/themables.js';
10
import { URI } from '../../base/common/uri.js';
11
import type { ISessionGitState } from '../../platform/agentHost/common/state/sessionState.js';
12
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
13
import { ISessionWorkspace } from '../services/sessions/common/session.js';
14
15
export interface IAgentHostSessionProjectSummary {
16
readonly uri: URI;
17
readonly displayName: string;
18
}
19
20
export interface IAgentHostSessionWorkspaceOptions {
21
readonly providerLabel?: string;
22
readonly fallbackIcon: ThemeIcon;
23
readonly requiresWorkspaceTrust: boolean;
24
readonly description?: string;
25
/**
26
* Group label used by the workspace picker to bucket the produced
27
* workspace into a top-level tab (e.g. `"Local"`, `"Remote"`).
28
*/
29
readonly group?: string;
30
/**
31
* Configured `git.branchProtection` glob patterns. Used to compute
32
* `baseBranchProtected` on the resulting repository.
33
*/
34
readonly branchProtectionPatterns?: readonly string[];
35
}
36
37
/**
38
* Returns true when `branchName` matches any of the configured
39
* `git.branchProtection` glob patterns.
40
*/
41
export function matchesAnyBranchProtectionPattern(branchName: string, patterns: readonly string[] | undefined): boolean {
42
if (!patterns) {
43
return false;
44
}
45
for (const pattern of patterns) {
46
const trimmed = pattern.trim();
47
if (trimmed && matchGlob(trimmed, branchName)) {
48
return true;
49
}
50
}
51
return false;
52
}
53
54
/**
55
* Reads `git.branchProtection` from configuration and normalizes the result
56
* into an array of trimmed, non-empty pattern strings.
57
*
58
* The `git.branchProtection` setting is `resource`-scoped, so the value can
59
* differ between workspace folders. Pass the session's working directory (or
60
* project URI as a fallback) as `resource` so we read the setting in the
61
* scope of the folder VS Code actually has loaded rather than the host
62
* window's active workspace.
63
*/
64
export function readBranchProtectionPatterns(configurationService: IConfigurationService, resource?: URI): readonly string[] {
65
const raw = configurationService.getValue<unknown>('git.branchProtection', { resource }) ?? [];
66
const list = Array.isArray(raw) ? raw : [raw];
67
return list
68
.map(p => typeof p === 'string' ? p.trim() : '')
69
.filter(p => p !== '');
70
}
71
72
export function agentHostSessionWorkspaceKey(workspace: ISessionWorkspace | undefined): string | undefined {
73
const repository = workspace?.repositories[0];
74
if (!workspace || !repository) {
75
return undefined;
76
}
77
return [
78
workspace.label,
79
extUri.getComparisonKey(repository.uri),
80
repository.workingDirectory ? extUri.getComparisonKey(repository.workingDirectory) : '',
81
repository.branchName ?? '',
82
repository.baseBranchName ?? '',
83
String(repository.baseBranchProtected ?? ''),
84
String(repository.hasGitHubRemote ?? ''),
85
repository.upstreamBranchName ?? '',
86
String(repository.incomingChanges ?? ''),
87
String(repository.outgoingChanges ?? ''),
88
String(repository.uncommittedChanges ?? ''),
89
].join('\n');
90
}
91
92
export function buildAgentHostSessionWorkspace(project: IAgentHostSessionProjectSummary | undefined, workingDirectory: URI | undefined, options: IAgentHostSessionWorkspaceOptions, gitState?: ISessionGitState): ISessionWorkspace | undefined {
93
const baseBranchName = gitState?.baseBranchName;
94
const baseBranchProtected = baseBranchName !== undefined
95
? matchesAnyBranchProtectionPattern(baseBranchName, options.branchProtectionPatterns)
96
: undefined;
97
const hasGitHubRemote = gitState?.hasGitHubRemote;
98
const upstreamBranchName = gitState?.upstreamBranchName;
99
const incomingChanges = gitState?.incomingChanges;
100
const outgoingChanges = gitState?.outgoingChanges;
101
const uncommittedChanges = gitState?.uncommittedChanges;
102
const branchName = gitState?.branchName;
103
const gitFields = { branchName, baseBranchName, baseBranchProtected, hasGitHubRemote, upstreamBranchName, incomingChanges, outgoingChanges, uncommittedChanges };
104
if (project) {
105
const repositoryWorkingDirectory = extUri.isEqual(workingDirectory, project.uri) ? undefined : workingDirectory;
106
return {
107
label: options.providerLabel ? `${project.displayName} [${options.providerLabel}]` : project.displayName,
108
description: options.description,
109
icon: Codicon.repo,
110
group: options.group,
111
repositories: [{ uri: project.uri, workingDirectory: repositoryWorkingDirectory, detail: undefined, ...gitFields }],
112
requiresWorkspaceTrust: options.requiresWorkspaceTrust,
113
};
114
}
115
116
if (!workingDirectory) {
117
return undefined;
118
}
119
120
const folderName = basename(workingDirectory) || workingDirectory.path;
121
return {
122
label: options.providerLabel ? `${folderName} [${options.providerLabel}]` : folderName,
123
description: options.description,
124
icon: options.fallbackIcon,
125
group: options.group,
126
repositories: [{ uri: workingDirectory, workingDirectory: undefined, detail: undefined, ...gitFields }],
127
requiresWorkspaceTrust: options.requiresWorkspaceTrust,
128
};
129
}
130
131