Path: blob/main/extensions/git/src/quickDiffProvider.ts
13383 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { FileType, l10n, LogOutputChannel, QuickDiffProvider, Uri, workspace } from 'vscode';6import { IRepositoryResolver, Repository } from './repository';7import { isDescendant, pathEquals } from './util';8import { toGitUri } from './uri';9import { Status } from './api/git.constants';1011export class GitQuickDiffProvider implements QuickDiffProvider {12readonly label = l10n.t('Git Local Changes (Working Tree)');1314constructor(15private readonly repository: Repository,16private readonly repositoryResolver: IRepositoryResolver,17private readonly logger: LogOutputChannel18) { }1920async provideOriginalResource(uri: Uri): Promise<Uri | undefined> {21this.logger.trace(`[Repository][provideOriginalResource] Resource: ${uri.toString()}`);2223if (uri.scheme !== 'file') {24this.logger.trace(`[Repository][provideOriginalResource] Resource is not a file: ${uri.scheme}`);25return undefined;26}2728// Ignore path that is inside the .git directory (ex: COMMIT_EDITMSG)29if (isDescendant(this.repository.dotGit.commonPath ?? this.repository.dotGit.path, uri.fsPath)) {30this.logger.trace(`[Repository][provideOriginalResource] Resource is inside .git directory: ${uri.toString()}`);31return undefined;32}3334// Ignore symbolic links35const stat = await workspace.fs.stat(uri);36if ((stat.type & FileType.SymbolicLink) !== 0) {37this.logger.trace(`[Repository][provideOriginalResource] Resource is a symbolic link: ${uri.toString()}`);38return undefined;39}4041// Ignore path that is not inside the current repository42if (this.repositoryResolver.getRepository(uri) !== this.repository) {43this.logger.trace(`[Repository][provideOriginalResource] Resource is not part of the repository: ${uri.toString()}`);44return undefined;45}4647// Ignore path that is inside a hidden repository48if (this.repository.isHidden === true) {49this.logger.trace(`[Repository][provideOriginalResource] Repository is hidden: ${uri.toString()}`);50return undefined;51}5253// Ignore path that is inside a merge group54if (this.repository.mergeGroup.resourceStates.some(r => pathEquals(r.resourceUri.fsPath, uri.fsPath))) {55this.logger.trace(`[Repository][provideOriginalResource] Resource is part of a merge group: ${uri.toString()}`);56return undefined;57}5859// Ignore path that is untracked60if (this.repository.untrackedGroup.resourceStates.some(r => pathEquals(r.resourceUri.path, uri.path)) ||61this.repository.workingTreeGroup.resourceStates.some(r => pathEquals(r.resourceUri.path, uri.path) && r.type === Status.UNTRACKED)) {62this.logger.trace(`[Repository][provideOriginalResource] Resource is untracked: ${uri.toString()}`);63return undefined;64}6566// Ignore path that is git ignored67const ignored = await this.repository.checkIgnore([uri.fsPath]);68if (ignored.size > 0) {69this.logger.trace(`[Repository][provideOriginalResource] Resource is git ignored: ${uri.toString()}`);70return undefined;71}7273const originalResource = toGitUri(uri, '', { replaceFileExtension: true });74this.logger.trace(`[Repository][provideOriginalResource] Original resource: ${originalResource.toString()}`);7576return originalResource;77}78}7980export class StagedResourceQuickDiffProvider implements QuickDiffProvider {81readonly label = l10n.t('Git Local Changes (Index)');8283constructor(84private readonly _repository: Repository,85private readonly logger: LogOutputChannel86) { }8788async provideOriginalResource(uri: Uri): Promise<Uri | undefined> {89this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Resource: ${uri.toString()}`);9091if (uri.scheme !== 'file') {92this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Resource is not a file: ${uri.scheme}`);93return undefined;94}9596// Ignore path that is inside a hidden repository97if (this._repository.isHidden === true) {98this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Repository is hidden: ${uri.toString()}`);99return undefined;100}101102// Ignore symbolic links103const stat = await workspace.fs.stat(uri);104if ((stat.type & FileType.SymbolicLink) !== 0) {105this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Resource is a symbolic link: ${uri.toString()}`);106return undefined;107}108109// Ignore resources that are not in the index group110if (!this._repository.indexGroup.resourceStates.some(r => pathEquals(r.resourceUri.fsPath, uri.fsPath))) {111this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Resource is not part of a index group: ${uri.toString()}`);112return undefined;113}114115const originalResource = toGitUri(uri, 'HEAD', { replaceFileExtension: true });116this.logger.trace(`[StagedResourceQuickDiffProvider][provideOriginalResource] Original resource: ${originalResource.toString()}`);117return originalResource;118}119}120121122