|
@ -16,7 +16,6 @@ import type { |
|
|
CloudWorkspaceData, |
|
|
CloudWorkspaceData, |
|
|
CloudWorkspaceProviderType, |
|
|
CloudWorkspaceProviderType, |
|
|
CloudWorkspaceRepositoryDescriptor, |
|
|
CloudWorkspaceRepositoryDescriptor, |
|
|
GetCloudWorkspaceRepositoriesResponse, |
|
|
|
|
|
GetWorkspacesResponse, |
|
|
GetWorkspacesResponse, |
|
|
LoadCloudWorkspacesResponse, |
|
|
LoadCloudWorkspacesResponse, |
|
|
LoadLocalWorkspacesResponse, |
|
|
LoadLocalWorkspacesResponse, |
|
@ -28,10 +27,10 @@ import type { |
|
|
WorkspacesResponse, |
|
|
WorkspacesResponse, |
|
|
} from './models'; |
|
|
} from './models'; |
|
|
import { |
|
|
import { |
|
|
|
|
|
CloudWorkspace, |
|
|
CloudWorkspaceProviderInputType, |
|
|
CloudWorkspaceProviderInputType, |
|
|
cloudWorkspaceProviderTypeToRemoteProviderId, |
|
|
cloudWorkspaceProviderTypeToRemoteProviderId, |
|
|
GKCloudWorkspace, |
|
|
|
|
|
GKLocalWorkspace, |
|
|
|
|
|
|
|
|
LocalWorkspace, |
|
|
WorkspaceAddRepositoriesChoice, |
|
|
WorkspaceAddRepositoriesChoice, |
|
|
WorkspaceType, |
|
|
WorkspaceType, |
|
|
} from './models'; |
|
|
} from './models'; |
|
@ -39,36 +38,16 @@ import { WorkspacesApi } from './workspacesApi'; |
|
|
import type { WorkspacesPathMappingProvider } from './workspacesPathMappingProvider'; |
|
|
import type { WorkspacesPathMappingProvider } from './workspacesPathMappingProvider'; |
|
|
|
|
|
|
|
|
export class WorkspacesService implements Disposable { |
|
|
export class WorkspacesService implements Disposable { |
|
|
private _cloudWorkspaces: GKCloudWorkspace[] | undefined = undefined; |
|
|
|
|
|
private _localWorkspaces: GKLocalWorkspace[] | undefined = undefined; |
|
|
|
|
|
private _workspacesApi: WorkspacesApi; |
|
|
|
|
|
private _workspacesPathProvider: WorkspacesPathMappingProvider; |
|
|
|
|
|
private _onDidChangeWorkspaces: EventEmitter<void> = new EventEmitter<void>(); |
|
|
private _onDidChangeWorkspaces: EventEmitter<void> = new EventEmitter<void>(); |
|
|
get onDidChangeWorkspaces(): Event<void> { |
|
|
get onDidChangeWorkspaces(): Event<void> { |
|
|
return this._onDidChangeWorkspaces.event; |
|
|
return this._onDidChangeWorkspaces.event; |
|
|
} |
|
|
} |
|
|
private _disposable: Disposable; |
|
|
|
|
|
|
|
|
|
|
|
// TODO@ramint Add error handling/logging when this is used.
|
|
|
|
|
|
private readonly _getCloudWorkspaceRepos: (workspaceId: string) => Promise<GetCloudWorkspaceRepositoriesResponse> = |
|
|
|
|
|
async (workspaceId: string) => { |
|
|
|
|
|
try { |
|
|
|
|
|
const workspaceRepos = await this._workspacesApi.getWorkspaceRepositories(workspaceId); |
|
|
|
|
|
const repoDescriptors = workspaceRepos?.data?.project?.provider_data?.repositories?.nodes; |
|
|
|
|
|
return { |
|
|
|
|
|
repositories: |
|
|
|
|
|
repoDescriptors != null |
|
|
|
|
|
? repoDescriptors.map(descriptor => ({ ...descriptor, workspaceId: workspaceId })) |
|
|
|
|
|
: [], |
|
|
|
|
|
repositoriesInfo: undefined, |
|
|
|
|
|
}; |
|
|
|
|
|
} catch { |
|
|
|
|
|
return { |
|
|
|
|
|
repositories: undefined, |
|
|
|
|
|
repositoriesInfo: 'Failed to load repositories for this workspace.', |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
private _cloudWorkspaces: CloudWorkspace[] | undefined; |
|
|
|
|
|
private _disposable: Disposable; |
|
|
|
|
|
private _localWorkspaces: LocalWorkspace[] | undefined; |
|
|
|
|
|
private _workspacesApi: WorkspacesApi; |
|
|
|
|
|
private _workspacesPathProvider: WorkspacesPathMappingProvider; |
|
|
|
|
|
|
|
|
constructor(private readonly container: Container, private readonly server: ServerConnection) { |
|
|
constructor(private readonly container: Container, private readonly server: ServerConnection) { |
|
|
this._workspacesApi = new WorkspacesApi(this.container, this.server); |
|
|
this._workspacesApi = new WorkspacesApi(this.container, this.server); |
|
@ -100,7 +79,7 @@ export class WorkspacesService implements Disposable { |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const cloudWorkspaces: GKCloudWorkspace[] = []; |
|
|
|
|
|
|
|
|
const cloudWorkspaces: CloudWorkspace[] = []; |
|
|
let workspaces: CloudWorkspaceData[] | undefined; |
|
|
let workspaces: CloudWorkspaceData[] | undefined; |
|
|
try { |
|
|
try { |
|
|
const workspaceResponse: WorkspacesResponse | undefined = excludeRepositories |
|
|
const workspaceResponse: WorkspacesResponse | undefined = excludeRepositories |
|
@ -137,12 +116,12 @@ export class WorkspacesService implements Disposable { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
cloudWorkspaces.push( |
|
|
cloudWorkspaces.push( |
|
|
new GKCloudWorkspace( |
|
|
|
|
|
|
|
|
new CloudWorkspace( |
|
|
|
|
|
this.container, |
|
|
workspace.id, |
|
|
workspace.id, |
|
|
workspace.name, |
|
|
workspace.name, |
|
|
workspace.organization?.id, |
|
|
workspace.organization?.id, |
|
|
workspace.provider as CloudWorkspaceProviderType, |
|
|
workspace.provider as CloudWorkspaceProviderType, |
|
|
this._getCloudWorkspaceRepos, |
|
|
|
|
|
repositories, |
|
|
repositories, |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
@ -160,12 +139,12 @@ export class WorkspacesService implements Disposable { |
|
|
|
|
|
|
|
|
// TODO@ramint: When we interact more with local workspaces, this should return more info about failures.
|
|
|
// TODO@ramint: When we interact more with local workspaces, this should return more info about failures.
|
|
|
private async loadLocalWorkspaces(): Promise<LoadLocalWorkspacesResponse> { |
|
|
private async loadLocalWorkspaces(): Promise<LoadLocalWorkspacesResponse> { |
|
|
const localWorkspaces: GKLocalWorkspace[] = []; |
|
|
|
|
|
|
|
|
const localWorkspaces: LocalWorkspace[] = []; |
|
|
const workspaceFileData: LocalWorkspaceData = |
|
|
const workspaceFileData: LocalWorkspaceData = |
|
|
(await this._workspacesPathProvider.getLocalWorkspaceData())?.workspaces || {}; |
|
|
(await this._workspacesPathProvider.getLocalWorkspaceData())?.workspaces || {}; |
|
|
for (const workspace of Object.values(workspaceFileData)) { |
|
|
for (const workspace of Object.values(workspaceFileData)) { |
|
|
localWorkspaces.push( |
|
|
localWorkspaces.push( |
|
|
new GKLocalWorkspace( |
|
|
|
|
|
|
|
|
new LocalWorkspace( |
|
|
workspace.localId, |
|
|
workspace.localId, |
|
|
workspace.name, |
|
|
workspace.name, |
|
|
workspace.repositories.map(repositoryPath => ({ |
|
|
workspace.repositories.map(repositoryPath => ({ |
|
@ -183,11 +162,11 @@ export class WorkspacesService implements Disposable { |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private getCloudWorkspace(workspaceId: string): GKCloudWorkspace | undefined { |
|
|
|
|
|
|
|
|
private getCloudWorkspace(workspaceId: string): CloudWorkspace | undefined { |
|
|
return this._cloudWorkspaces?.find(workspace => workspace.id === workspaceId); |
|
|
return this._cloudWorkspaces?.find(workspace => workspace.id === workspaceId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private getLocalWorkspace(workspaceId: string): GKLocalWorkspace | undefined { |
|
|
|
|
|
|
|
|
private getLocalWorkspace(workspaceId: string): LocalWorkspace | undefined { |
|
|
return this._localWorkspaces?.find(workspace => workspace.id === workspaceId); |
|
|
return this._localWorkspaces?.find(workspace => workspace.id === workspaceId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -217,6 +196,13 @@ export class WorkspacesService implements Disposable { |
|
|
return getWorkspacesResponse; |
|
|
return getWorkspacesResponse; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async getCloudWorkspaceRepositories(workspaceId: string): Promise<CloudWorkspaceRepositoryDescriptor[]> { |
|
|
|
|
|
// TODO@ramint Add error handling/logging when this is used.
|
|
|
|
|
|
const workspaceRepos = await this._workspacesApi.getWorkspaceRepositories(workspaceId); |
|
|
|
|
|
const descriptors = workspaceRepos?.data?.project?.provider_data?.repositories?.nodes; |
|
|
|
|
|
return descriptors?.map(d => ({ ...d, workspaceId: workspaceId })) ?? []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
resetWorkspaces(options?: { cloud?: boolean; local?: boolean }) { |
|
|
resetWorkspaces(options?: { cloud?: boolean; local?: boolean }) { |
|
|
if (options?.cloud ?? true) { |
|
|
if (options?.cloud ?? true) { |
|
|
this._cloudWorkspaces = undefined; |
|
|
this._cloudWorkspaces = undefined; |
|
@ -260,7 +246,9 @@ export class WorkspacesService implements Disposable { |
|
|
async locateAllCloudWorkspaceRepos(workspaceId: string, cancellation?: CancellationToken): Promise<void> { |
|
|
async locateAllCloudWorkspaceRepos(workspaceId: string, cancellation?: CancellationToken): Promise<void> { |
|
|
const workspace = this.getCloudWorkspace(workspaceId); |
|
|
const workspace = this.getCloudWorkspace(workspaceId); |
|
|
if (workspace == null) return; |
|
|
if (workspace == null) return; |
|
|
if (workspace.repositories == null || workspace.repositories.length === 0) return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const repoDescriptors = await workspace.getRepositoryDescriptors(); |
|
|
|
|
|
if (repoDescriptors == null || repoDescriptors.length === 0) return; |
|
|
|
|
|
|
|
|
const foundRepos = await this.getRepositoriesInParentFolder(cancellation); |
|
|
const foundRepos = await this.getRepositoriesInParentFolder(cancellation); |
|
|
if (foundRepos == null || foundRepos.length === 0 || cancellation?.isCancellationRequested) return; |
|
|
if (foundRepos == null || foundRepos.length === 0 || cancellation?.isCancellationRequested) return; |
|
@ -564,12 +552,12 @@ export class WorkspacesService implements Disposable { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this._cloudWorkspaces?.push( |
|
|
this._cloudWorkspaces?.push( |
|
|
new GKCloudWorkspace( |
|
|
|
|
|
|
|
|
new CloudWorkspace( |
|
|
|
|
|
this.container, |
|
|
createdProjectData.id, |
|
|
createdProjectData.id, |
|
|
createdProjectData.name, |
|
|
createdProjectData.name, |
|
|
createdProjectData.organization?.id, |
|
|
createdProjectData.organization?.id, |
|
|
createdProjectData.provider as CloudWorkspaceProviderType, |
|
|
createdProjectData.provider as CloudWorkspaceProviderType, |
|
|
this._getCloudWorkspaceRepos, |
|
|
|
|
|
[], |
|
|
[], |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
@ -780,10 +768,13 @@ export class WorkspacesService implements Disposable { |
|
|
}, |
|
|
}, |
|
|
): Promise<WorkspaceRepositoriesByName> { |
|
|
): Promise<WorkspaceRepositoriesByName> { |
|
|
const workspaceRepositoriesByName: WorkspaceRepositoriesByName = new Map<string, RepositoryMatch>(); |
|
|
const workspaceRepositoriesByName: WorkspaceRepositoriesByName = new Map<string, RepositoryMatch>(); |
|
|
const workspace: GKCloudWorkspace | GKLocalWorkspace | undefined = |
|
|
|
|
|
this.getCloudWorkspace(workspaceId) ?? this.getLocalWorkspace(workspaceId); |
|
|
|
|
|
|
|
|
|
|
|
if (workspace?.repositories == null || workspace.repositories.length === 0) return workspaceRepositoriesByName; |
|
|
|
|
|
|
|
|
const workspace = this.getLocalWorkspace(workspaceId) ?? this.getCloudWorkspace(workspaceId); |
|
|
|
|
|
if (workspace == null) return workspaceRepositoriesByName; |
|
|
|
|
|
|
|
|
|
|
|
const repoDescriptors = await workspace.getRepositoryDescriptors(); |
|
|
|
|
|
if (repoDescriptors == null || repoDescriptors.length === 0) return workspaceRepositoriesByName; |
|
|
|
|
|
|
|
|
const currentRepositories = options?.repositories ?? this.container.git.repositories; |
|
|
const currentRepositories = options?.repositories ?? this.container.git.repositories; |
|
|
|
|
|
|
|
|
const reposProviderMap = new Map<string, Repository>(); |
|
|
const reposProviderMap = new Map<string, Repository>(); |
|
@ -792,7 +783,7 @@ export class WorkspacesService implements Disposable { |
|
|
if (options?.cancellation?.isCancellationRequested) break; |
|
|
if (options?.cancellation?.isCancellationRequested) break; |
|
|
reposPathMap.set(normalizePath(repo.uri.fsPath.toLowerCase()), repo); |
|
|
reposPathMap.set(normalizePath(repo.uri.fsPath.toLowerCase()), repo); |
|
|
|
|
|
|
|
|
if (workspace instanceof GKCloudWorkspace) { |
|
|
|
|
|
|
|
|
if (workspace instanceof CloudWorkspace) { |
|
|
const remotes = await repo.getRemotes(); |
|
|
const remotes = await repo.getRemotes(); |
|
|
for (const remote of remotes) { |
|
|
for (const remote of remotes) { |
|
|
const remoteDescriptor = getRemoteDescriptor(remote); |
|
|
const remoteDescriptor = getRemoteDescriptor(remote); |
|
@ -805,7 +796,7 @@ export class WorkspacesService implements Disposable { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (const descriptor of workspace.repositories) { |
|
|
|
|
|
|
|
|
for (const descriptor of repoDescriptors) { |
|
|
let repoLocalPath = null; |
|
|
let repoLocalPath = null; |
|
|
let foundRepo = null; |
|
|
let foundRepo = null; |
|
|
|
|
|
|
|
@ -864,12 +855,14 @@ export class WorkspacesService implements Disposable { |
|
|
workspaceType: WorkspaceType, |
|
|
workspaceType: WorkspaceType, |
|
|
options?: { open?: boolean }, |
|
|
options?: { open?: boolean }, |
|
|
): Promise<void> { |
|
|
): Promise<void> { |
|
|
const workspace: GKCloudWorkspace | GKLocalWorkspace | undefined = |
|
|
|
|
|
|
|
|
const workspace = |
|
|
workspaceType === WorkspaceType.Cloud |
|
|
workspaceType === WorkspaceType.Cloud |
|
|
? this.getCloudWorkspace(workspaceId) |
|
|
? this.getCloudWorkspace(workspaceId) |
|
|
: this.getLocalWorkspace(workspaceId); |
|
|
: this.getLocalWorkspace(workspaceId); |
|
|
|
|
|
if (workspace == null) return; |
|
|
|
|
|
|
|
|
if (workspace?.repositories == null) return; |
|
|
|
|
|
|
|
|
const repoDescriptors = await workspace.getRepositoryDescriptors(); |
|
|
|
|
|
if (repoDescriptors == null) return; |
|
|
|
|
|
|
|
|
const workspaceRepositoriesByName = await this.resolveWorkspaceRepositoriesByName(workspaceId, { |
|
|
const workspaceRepositoriesByName = await this.resolveWorkspaceRepositoriesByName(workspaceId, { |
|
|
resolveFromPath: true, |
|
|
resolveFromPath: true, |
|
@ -889,7 +882,7 @@ export class WorkspacesService implements Disposable { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (workspaceFolderPaths.length < workspace.repositories.length) { |
|
|
|
|
|
|
|
|
if (workspaceFolderPaths.length < repoDescriptors.length) { |
|
|
const confirmation = await window.showWarningMessage( |
|
|
const confirmation = await window.showWarningMessage( |
|
|
`Some repositories in this workspace could not be located locally. Do you want to continue?`, |
|
|
`Some repositories in this workspace could not be located locally. Do you want to continue?`, |
|
|
{ modal: true }, |
|
|
{ modal: true }, |
|
|