Browse Source

Fixes #430 - Use content provider instead of tmp files (for text docs)

main
Eric Amodio 6 years ago
parent
commit
0f2f79fca7
12 changed files with 57 additions and 139 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +2
    -2
      src/codelens/gitCodeLensProvider.ts
  3. +0
    -91
      src/codelens/gitRevisionCodeLensProvider.ts
  4. +8
    -11
      src/commands/common.ts
  5. +2
    -2
      src/commands/diffWithWorking.ts
  6. +11
    -1
      src/constants.ts
  7. +0
    -4
      src/container.ts
  8. +7
    -8
      src/git/gitUri.ts
  9. +6
    -6
      src/git/models/repository.ts
  10. +5
    -3
      src/gitContentProvider.ts
  11. +12
    -8
      src/gitService.ts
  12. +3
    -3
      src/trackers/documentTracker.ts

+ 1
- 0
CHANGELOG.md View File

@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Fixed
- Fixes [#405](https://github.com/eamodio/vscode-gitlens/issues/405) - Secondary, blank repository appears repeatedly in gitExplorer view
- Fixes [#430](https://github.com/eamodio/vscode-gitlens/issues/430) - File revisions can end up being parsed by language servers (causing errors and warnings, etc)
- Fixes issues with git log caching
### Removed

+ 2
- 2
src/codelens/gitCodeLensProvider.ts View File

@ -222,7 +222,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
gitUri.getFilename(),
SymbolKind.File,
'',
new Location(gitUri.fileUri(), new Range(0, 0, 0, blameRange.start.character))
new Location(gitUri.documentUri(), new Range(0, 0, 0, blameRange.start.character))
);
lenses.push(
new GitRecentChangeCodeLens(
@ -249,7 +249,7 @@ export class GitCodeLensProvider implements CodeLensProvider {
gitUri.getFilename(),
SymbolKind.File,
'',
new Location(gitUri.fileUri(), new Range(0, 1, 0, blameRange.start.character))
new Location(gitUri.documentUri(), new Range(0, 1, 0, blameRange.start.character))
);
lenses.push(
new GitAuthorsCodeLens(

+ 0
- 91
src/codelens/gitRevisionCodeLensProvider.ts View File

@ -1,91 +0,0 @@
'use strict';
import { CancellationToken, CodeLens, CodeLensProvider, DocumentSelector, Range, TextDocument, Uri } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs } from '../commands';
import { DocumentSchemes } from '../constants';
import { Container } from '../container';
import { GitCommit, GitUri } from '../gitService';
export class GitDiffWithWorkingCodeLens extends CodeLens {
constructor(
public readonly fileName: string,
public readonly commit: GitCommit,
range: Range
) {
super(range);
}
}
export class GitDiffWithPreviousCodeLens extends CodeLens {
constructor(
public readonly fileName: string,
public readonly commit: GitCommit,
range: Range
) {
super(range);
}
}
export class GitRevisionCodeLensProvider implements CodeLensProvider {
static selector: DocumentSelector = { scheme: DocumentSchemes.GitLensGit };
async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
const gitUri = GitUri.fromRevisionUri(document.uri);
const lenses: CodeLens[] = [];
const commit = await Container.git.getLogCommitForFile(gitUri.repoPath, gitUri.fsPath, {
ref: gitUri.sha,
firstIfNotFound: true
});
if (commit === undefined) return lenses;
if (commit.previousSha) {
lenses.push(new GitDiffWithPreviousCodeLens(commit.previousUri.fsPath, commit, new Range(0, 0, 0, 1)));
}
lenses.push(new GitDiffWithWorkingCodeLens(commit.uri.fsPath, commit, new Range(0, 1, 0, 2)));
return lenses;
}
resolveCodeLens(lens: CodeLens, token: CancellationToken): Thenable<CodeLens> {
if (lens instanceof GitDiffWithWorkingCodeLens) return this._resolveDiffWithWorkingTreeCodeLens(lens, token);
if (lens instanceof GitDiffWithPreviousCodeLens) return this._resolveGitDiffWithPreviousCodeLens(lens, token);
return Promise.reject<CodeLens>(undefined);
}
_resolveDiffWithWorkingTreeCodeLens(
lens: GitDiffWithWorkingCodeLens,
token: CancellationToken
): Thenable<CodeLens> {
lens.command = {
title: `Compare Revision (${lens.commit.shortSha}) with Working`,
command: Commands.DiffWithWorking,
arguments: [
Uri.file(lens.fileName),
{
commit: lens.commit,
line: lens.range.start.line
} as DiffWithWorkingCommandArgs
]
};
return Promise.resolve(lens);
}
_resolveGitDiffWithPreviousCodeLens(
lens: GitDiffWithPreviousCodeLens,
token: CancellationToken
): Thenable<CodeLens> {
lens.command = {
title: `Compare Revision (${lens.commit.shortSha}) with Previous (${lens.commit.previousShortSha})`,
command: Commands.DiffWithPrevious,
arguments: [
Uri.file(lens.fileName),
{
commit: lens.commit,
line: lens.range.start.line
} as DiffWithPreviousCommandArgs
]
};
return Promise.resolve(lens);
}
}

+ 8
- 11
src/commands/common.ts View File

@ -13,7 +13,7 @@ import {
window,
workspace
} from 'vscode';
import { BuiltInCommands, DocumentSchemes, ImageExtensions } from '../constants';
import { BuiltInCommands, DocumentSchemes, ImageMimetypes } from '../constants';
import { Container } from '../container';
import { GitBranch, GitCommit, GitRemote, GitUri } from '../gitService';
import { Logger } from '../logger';
@ -394,21 +394,18 @@ export async function openEditor(
const { rethrow, ...opts } = options;
try {
if (uri instanceof GitUri) {
uri = uri.fileUri({ noSha: true });
uri = uri.documentUri({ noSha: true });
}
// TODO: revist this
// This is a bit of an ugly hack, but I added it because there a bunch of call sites and toRevisionUri can't be easily made async because of its use in ctors
if (uri.scheme === DocumentSchemes.GitLensGit) {
if (uri.scheme === DocumentSchemes.GitLensGit && ImageMimetypes[path.extname(uri.fsPath)]) {
const gitUri = GitUri.fromRevisionUri(uri);
if (ImageExtensions.includes(path.extname(gitUri.fsPath))) {
const uri = await Container.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha);
if (uri !== undefined) {
await commands.executeCommand(BuiltInCommands.Open, uri);
return undefined;
}
const imageUri = await Container.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha);
if (imageUri !== undefined) {
await commands.executeCommand(BuiltInCommands.Open, imageUri);
}
return undefined;
}
const document = await workspace.openTextDocument(uri);

+ 2
- 2
src/commands/diffWithWorking.ts View File

@ -44,11 +44,11 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand {
repoPath: gitUri.repoPath,
lhs: {
sha: GitService.stagedUncommittedSha,
uri: gitUri.fileUri()
uri: gitUri.documentUri()
},
rhs: {
sha: '',
uri: gitUri.fileUri()
uri: gitUri.documentUri()
},
line: args.line,
showOptions: args.showOptions

+ 11
- 1
src/constants.ts View File

@ -109,7 +109,17 @@ export enum GlobalState {
GitLensVersion = 'gitlensVersion'
}
export const ImageExtensions = ['.png', '.gif', '.jpg', '.jpeg', '.webp', '.tif', '.tiff', '.bmp'];
export const ImageMimetypes: { [key: string]: string } = {
'.png': 'image/png',
'.gif': 'image/gif',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.jpe': 'image/jpeg',
'.webp': 'image/webp',
'.tif': 'image/tiff',
'.tiff': 'image/tiff',
'.bmp': 'image/bmp'
};
export enum WorkspaceState {
GitExplorerAutoRefresh = 'gitlens:gitExplorer:autoRefresh',

+ 0
- 4
src/container.ts View File

@ -3,7 +3,6 @@ import { Disposable, ExtensionContext, languages, workspace } from 'vscode';
import { FileAnnotationController } from './annotations/fileAnnotationController';
import { LineAnnotationController } from './annotations/lineAnnotationController';
import { CodeLensController } from './codelens/codeLensController';
import { GitRevisionCodeLensProvider } from './codelens/gitRevisionCodeLensProvider';
import { configuration, IConfig } from './configuration';
import { GitContentProvider } from './gitContentProvider';
import { GitService } from './gitService';
@ -69,9 +68,6 @@ export class Container {
context.subscriptions.push(
workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider())
);
context.subscriptions.push(
languages.registerCodeLensProvider(GitRevisionCodeLensProvider.selector, new GitRevisionCodeLensProvider())
);
}
private static _codeLensController: CodeLensController;

+ 7
- 8
src/git/gitUri.ts View File

@ -33,7 +33,6 @@ interface UriEx {
export class GitUri extends ((Uri as any) as UriEx) {
repoPath?: string;
sha?: string;
versionedPath?: string;
constructor(uri?: Uri);
@ -94,16 +93,16 @@ export class GitUri extends ((Uri as any) as UriEx) {
return this.sha && GitService.shortenSha(this.sha);
}
equals(uri: Uri | undefined) {
if (!UriComparer.equals(this, uri)) return false;
documentUri(options: { noSha?: boolean; useVersionedPath?: boolean } = {}) {
if (options.useVersionedPath && this.versionedPath !== undefined) return Uri.file(this.versionedPath);
return this.sha === (uri instanceof GitUri ? uri.sha : undefined);
return this.scheme === 'file' ? Uri.file(!options.noSha && this.sha ? this.path : this.fsPath) : this;
}
fileUri(options: { noSha?: boolean; useVersionedPath?: boolean } = {}) {
if (options.useVersionedPath && this.versionedPath !== undefined) return Uri.file(this.versionedPath);
equals(uri: Uri | undefined) {
if (!UriComparer.equals(this, uri)) return false;
return Uri.file(!options.noSha && this.sha ? this.path : this.fsPath);
return this.sha === (uri instanceof GitUri ? uri.sha : undefined);
}
getDirectory(relativeTo?: string): string {
@ -314,7 +313,7 @@ export class GitUri extends ((Uri as any) as UriEx) {
const parsed = path.parse(fileName);
return Uri.parse(
`${DocumentSchemes.GitLensGit}:${path.join(parsed.dir, parsed.name)}:${shortSha}${
`${DocumentSchemes.GitLensGit}:${path.join(parsed.dir, parsed.name)} (${shortSha})${
parsed.ext
}?${JSON.stringify(data)}`
);

+ 6
- 6
src/git/models/repository.ts View File

@ -218,13 +218,13 @@ export class Repository implements Disposable {
}
}
containsUri(uri: Uri) {
if (uri instanceof GitUri) {
uri = uri.repoPath !== undefined ? Uri.file(uri.repoPath) : uri.fileUri();
}
// containsUri(uri: Uri) {
// if (uri instanceof GitUri) {
// uri = uri.repoPath !== undefined ? Uri.file(uri.repoPath) : uri.documentUri();
// }
return this.folder === workspace.getWorkspaceFolder(uri);
}
// return this.folder === workspace.getWorkspaceFolder(uri);
// }
getBranch(): Promise<GitBranch | undefined> {
if (this._branch === undefined) {

+ 5
- 3
src/gitContentProvider.ts View File

@ -1,8 +1,7 @@
'use strict';
import * as path from 'path';
import { CancellationToken, TextDocumentContentProvider, Uri, window } from 'vscode';
import { CancellationToken, TextDocumentContentProvider, Uri, window, workspace } from 'vscode';
import { DocumentSchemes } from './constants';
import { Container } from './container';
import { GitService, GitUri } from './gitService';
import { Logger } from './logger';
@ -14,7 +13,10 @@ export class GitContentProvider implements TextDocumentContentProvider {
if (!gitUri.repoPath || gitUri.sha === GitService.deletedSha) return '';
try {
return await Container.git.getVersionedFileText(gitUri.repoPath, gitUri.fsPath, gitUri.sha || 'HEAD');
const document = await workspace.openTextDocument(
Uri.parse(`git:/${gitUri.fsPath}?${JSON.stringify({ path: gitUri.fsPath, ref: gitUri.sha || 'HEAD' })}`)
);
return document.getText();
}
catch (ex) {
Logger.error(ex, 'GitContentProvider', 'getVersionedFileText');

+ 12
- 8
src/gitService.ts View File

@ -18,7 +18,7 @@ import {
} from 'vscode';
import { GitExtension } from './@types/git';
import { configuration, IRemotesConfig } from './configuration';
import { CommandContext, DocumentSchemes, GlyphChars, setCommandContext } from './constants';
import { CommandContext, DocumentSchemes, GlyphChars, ImageMimetypes, setCommandContext } from './constants';
import { Container } from './container';
import {
CommitFormatting,
@ -1652,15 +1652,19 @@ export class GitService implements Disposable {
return undefined;
}
const file = await Git.getVersionedFile(repoPath, fileName, sha);
if (file === undefined) return undefined;
if (ImageMimetypes[path.extname(fileName)]) {
const file = await Git.getVersionedFile(repoPath, fileName, sha);
if (file === undefined) return undefined;
this._versionedUriCache.set(
GitUri.toKey(file),
new GitUri(Uri.file(fileName), { sha: sha, repoPath: repoPath!, versionedPath: file })
);
this._versionedUriCache.set(
GitUri.toKey(file),
new GitUri(Uri.file(fileName), { sha: sha, repoPath: repoPath!, versionedPath: file })
);
return Uri.file(file);
}
return Uri.file(file);
return GitUri.toRevisionUri(sha, fileName, repoPath!);
}
getVersionedFileText(repoPath: string, fileName: string, sha: string) {

+ 3
- 3
src/trackers/documentTracker.ts View File

@ -238,7 +238,7 @@ export class DocumentTracker implements Disposable {
private async _add(documentOrId: TextDocument | Uri): Promise<TrackedDocument<T>> {
if (documentOrId instanceof GitUri) {
try {
documentOrId = await workspace.openTextDocument(documentOrId.fileUri({ useVersionedPath: true }));
documentOrId = await workspace.openTextDocument(documentOrId.documentUri({ useVersionedPath: true }));
}
catch (ex) {
const msg = ex.toString();
@ -271,7 +271,7 @@ export class DocumentTracker implements Disposable {
private async _get(documentOrId: string | TextDocument | Uri) {
if (documentOrId instanceof GitUri) {
documentOrId = GitUri.toKey(documentOrId.fileUri({ useVersionedPath: true }));
documentOrId = GitUri.toKey(documentOrId.documentUri({ useVersionedPath: true }));
}
else if (typeof documentOrId === 'string' || documentOrId instanceof Uri) {
documentOrId = GitUri.toKey(documentOrId);
@ -366,7 +366,7 @@ class EmptyTextDocument implements TextDocument {
constructor(
public readonly gitUri: GitUri
) {
this.uri = gitUri.fileUri({ useVersionedPath: true });
this.uri = gitUri.documentUri({ useVersionedPath: true });
this.eol = EndOfLine.LF;
this.fileName = this.uri.fsPath;

Loading…
Cancel
Save