瀏覽代碼

Fixes compare with prev/next with renames (especially case only renames)

main
Eric Amodio 6 年之前
父節點
當前提交
32d683ce5e
共有 5 個檔案被更改,包括 68 行新增16 行删除
  1. +1
    -0
      CHANGELOG.md
  2. +13
    -2
      src/commands/diffWithNext.ts
  3. +4
    -5
      src/commands/diffWithPrevious.ts
  4. +9
    -2
      src/git/gitUri.ts
  5. +41
    -7
      src/gitService.ts

+ 1
- 0
CHANGELOG.md 查看文件

@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Fixes [#440](https://github.com/eamodio/vscode-gitlens/issues/436) - Searching for commits with an empty query yields to no results anymore
- Fixes issue where commands in the editor toolbar would flash unnecessarily when navigating history or switching tabs
- Fixes issue where the *Compare File with Previous Revision* command wouldn't work properly when the file had been renamed in some cases
- Fixes issue where the *Compare File with Next Revision* command wouldn't work properly when the file had been renamed in some cases
- Fixes issue where changed files count was wrong when the branch was behind the upstream
- Fixes issue where the *GitLens File History* explorer wasn't being updated automatically for working changes
- Fixes issue where the *Compare File with * Revision* commands in the editor toolbar would show and hide too often because of insignificant focus changes

+ 13
- 2
src/commands/diffWithNext.ts 查看文件

@ -54,13 +54,24 @@ export class DiffWithNextCommand extends ActiveEditorCommand {
return commands.executeCommand(Commands.DiffWith, diffArgs);
}
const log = await Container.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, {
let log = await Container.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, {
maxCount: sha !== undefined ? undefined : 2,
range: args.range!,
renames: true
});
if (log === undefined) {
return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
const fileName = await Container.git.findNextFileName(gitUri.repoPath!, gitUri.fsPath);
if (fileName !== undefined) {
log = await Container.git.getLogForFile(gitUri.repoPath, fileName, {
maxCount: sha !== undefined ? undefined : 2,
range: args.range!,
renames: true
});
}
if (log === undefined) {
return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
}
}
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());

+ 4
- 5
src/commands/diffWithPrevious.ts 查看文件

@ -77,7 +77,7 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
// Check for renames
log = await Container.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, {
maxCount: 4,
maxCount: 3,
ref: sha.substring(0, sha.length - 1),
renames: true
});
@ -86,10 +86,9 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare');
}
args.commit = Iterables.next(Iterables.skip(log.commits.values(), 2));
if (args.commit === undefined) {
args.commit = (sha && log.commits.get(sha)) || Iterables.first(log.commits.values());
}
args.commit =
Iterables.next(Iterables.skip(log.commits.values(), 1)) ||
Iterables.first(log.commits.values());
}
// If the sha is missing (i.e. working tree), check the file status

+ 9
- 2
src/git/gitUri.ts 查看文件

@ -1,6 +1,7 @@
'use strict';
import { Strings } from '../system';
import { Uri } from 'vscode';
import { UriComparer } from '../comparers';
import { DocumentSchemes, GlyphChars } from '../constants';
import { Container } from '../container';
import { GitCommit, GitService, IGitStatusFile } from '../gitService';
@ -93,6 +94,12 @@ 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;
return this.sha === (uri instanceof GitUri ? uri.sha : undefined);
}
fileUri(options: { noSha?: boolean; useVersionedPath?: boolean } = {}) {
if (options.useVersionedPath && this.versionedPath !== undefined) return Uri.file(this.versionedPath);
@ -265,8 +272,8 @@ export class GitUri extends ((Uri as any) as UriEx) {
static toKey(fileNameOrUri: string | Uri): string;
static toKey(fileNameOrUri: string | Uri): string {
return Strings.normalizePath(
typeof fileNameOrUri === 'string' ? fileNameOrUri : fileNameOrUri.fsPath
).toLowerCase();
(typeof fileNameOrUri === 'string' ? Uri.file(fileNameOrUri) : fileNameOrUri).fsPath
);
}
static toRevisionUri(uri: GitUri): Uri;

+ 41
- 7
src/gitService.ts 查看文件

@ -412,8 +412,39 @@ export class GitService extends Disposable {
return Git.checkout(uri.repoPath!, uri.fsPath, ref!);
}
private async fileExists(repoPath: string, fileName: string): Promise<boolean> {
return await new Promise<boolean>((resolve, reject) => fs.exists(path.resolve(repoPath, fileName), resolve));
private async fileExists(
repoPath: string,
fileName: string,
options: { ensureCase: boolean } = { ensureCase: false }
): Promise<boolean> {
const filePath = path.resolve(repoPath, fileName);
const exists = await new Promise<boolean>((resolve, reject) => fs.exists(filePath, resolve));
if (!options.ensureCase || !exists) return exists;
// Deal with renames in case only on case-insensative file systems
const normalizedRepoPath = path.normalize(repoPath);
return this.fileExistsWithCase(filePath, normalizedRepoPath, normalizedRepoPath.length);
}
private async fileExistsWithCase(filePath: string, repoPath: string, repoPathLength: number): Promise<boolean> {
const dir = path.dirname(filePath);
if (dir.length < repoPathLength) return false;
if (dir === repoPath) return true;
const filenames = await new Promise<string[]>((resolve, reject) =>
fs.readdir(dir, (err: NodeJS.ErrnoException, files: string[]) => {
if (err) {
reject(err);
}
else {
resolve(files);
}
})
);
if (filenames.indexOf(path.basename(filePath)) === -1) {
return false;
}
return this.fileExistsWithCase(dir, repoPath, repoPathLength);
}
async findNextCommit(repoPath: string, fileName: string, ref?: string): Promise<GitLogCommit | undefined> {
@ -438,7 +469,7 @@ export class GitService extends Disposable {
async findNextFileName(repoPath: string | undefined, fileName: string, ref?: string): Promise<string | undefined> {
[fileName, repoPath] = Git.splitPath(fileName, repoPath);
return (await this.fileExists(repoPath, fileName))
return (await this.fileExists(repoPath, fileName, { ensureCase: true }))
? fileName
: await this.findNextFileNameCore(repoPath, fileName, ref);
}
@ -486,7 +517,7 @@ export class GitService extends Disposable {
else {
const c = commitOrFileName;
repoPath = c.repoPath;
if (c.workingFileName && (await this.fileExists(repoPath, c.workingFileName))) {
if (c.workingFileName && (await this.fileExists(repoPath, c.workingFileName, { ensureCase: true }))) {
return [c.workingFileName, repoPath];
}
fileName = c.fileName;
@ -494,7 +525,7 @@ export class GitService extends Disposable {
// Keep walking up to the most recent commit for a given filename, until it exists on disk
while (true) {
if (await this.fileExists(repoPath, fileName)) return [fileName, repoPath];
if (await this.fileExists(repoPath, fileName, { ensureCase: true })) return [fileName, repoPath];
fileName = await this.findNextFileNameCore(repoPath, fileName);
if (fileName === undefined) return [undefined, undefined];
@ -1192,11 +1223,14 @@ export class GitService extends Disposable {
if (options.renames) {
key += `:follow`;
}
if (options.reverse) {
key += `:reverse`;
}
const doc = await Container.tracker.getOrAdd(
new GitUri(Uri.file(fileName), { repoPath: repoPath!, sha: options.ref })
);
if (this.UseCaching && options.range === undefined && !options.reverse) {
if (this.UseCaching && options.range === undefined) {
if (doc.state !== undefined) {
const cachedLog = doc.state.get<CachedLog>(key);
if (cachedLog !== undefined) {
@ -1258,7 +1292,7 @@ export class GitService extends Disposable {
const promise = this.getLogForFileCore(repoPath, fileName, options, doc, key);
if (doc.state !== undefined && options.range === undefined && !options.reverse) {
if (doc.state !== undefined && options.range === undefined) {
Logger.log(`Add log cache for '${doc.state.key}:${key}'`);
doc.state.set<CachedLog>(key, {

Loading…
取消
儲存