Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Git history view to SCM package #26

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/git/src/browser/blame/blame-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { BlameDecorator } from './blame-decorator';
import { EditorManager, EditorKeybindingContexts, EditorWidget, EditorTextFocusContext, StrictEditorTextFocusContext } from '@theia/editor/lib/browser';
import { BlameManager } from './blame-manager';
import URI from '@theia/core/lib/common/uri';
import { EDITOR_CONTEXT_MENU_GIT } from '../git-contribution';
import { EDITOR_CONTEXT_MENU_SCM } from '@theia/scm/lib/browser/scm-contribution';

import debounce = require('lodash.debounce');

Expand Down Expand Up @@ -136,7 +136,7 @@ export class BlameContribution implements CommandContribution, KeybindingContrib
}

registerMenus(menus: MenuModelRegistry): void {
menus.registerMenuAction(EDITOR_CONTEXT_MENU_GIT, {
menus.registerMenuAction(EDITOR_CONTEXT_MENU_SCM, {
commandId: BlameCommands.TOGGLE_GIT_ANNOTATIONS.id,
});
}
Expand Down
20 changes: 14 additions & 6 deletions packages/git/src/browser/diff/git-diff-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FrontendApplication, AbstractViewContribution } from '@theia/core/lib/b
import { WidgetManager } from '@theia/core/lib/browser/widget-manager';
import { injectable, inject } from 'inversify';
import { GitDiffWidget, GIT_DIFF } from './git-diff-widget';
import { ScmService } from '@theia/scm/lib/browser/scm-service';
import { open, OpenerService } from '@theia/core/lib/browser';
import { NavigatorContextMenu } from '@theia/navigator/lib/browser/navigator-contribution';
import { UriCommandHandler, UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
Expand All @@ -27,8 +28,7 @@ import { FileSystem } from '@theia/filesystem/lib/common';
import { DiffUris } from '@theia/core/lib/browser/diff-uris';
import URI from '@theia/core/lib/common/uri';
import { GIT_RESOURCE_SCHEME } from '../git-resource';
import { Git } from '../../common';
import { GitRepositoryProvider } from '../git-repository-provider';
import { Git, Repository } from '../../common';

export namespace GitDiffCommands {
export const OPEN_FILE_DIFF: Command = {
Expand All @@ -49,7 +49,7 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>
@inject(FileSystem) protected readonly fileSystem: FileSystem,
@inject(OpenerService) protected openerService: OpenerService,
@inject(MessageService) protected readonly notifications: MessageService,
@inject(GitRepositoryProvider) protected readonly repositoryProvider: GitRepositoryProvider
@inject(ScmService) protected readonly scmService: ScmService
) {
super({
widgetId: GIT_DIFF,
Expand All @@ -69,8 +69,8 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>

registerCommands(commands: CommandRegistry): void {
commands.registerCommand(GitDiffCommands.OPEN_FILE_DIFF, this.newUriAwareCommandHandler({
isVisible: uri => !!this.repositoryProvider.findRepository(uri),
isEnabled: uri => !!this.repositoryProvider.findRepository(uri),
isVisible: uri => !!this.findGitRepository(uri),
isEnabled: uri => !!this.findGitRepository(uri),
execute: async fileUri => {
await this.quickOpenService.chooseTagsAndBranches(
async (fromRevision, toRevision) => {
Expand All @@ -96,11 +96,19 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>
}
}
}
}, this.repositoryProvider.findRepository(fileUri));
}, this.findGitRepository(fileUri));
}
}));
}

protected findGitRepository(uri: URI): Repository | undefined {
const repo = this.scmService.findRepository(uri);
if (repo && repo.provider.id === 'git') {
return { localUri: repo.provider.rootUri };
}
return undefined;
}

async showWidget(options: Git.Options.Diff): Promise<GitDiffWidget> {
const widget = await this.widget;
await widget.setContent(options);
Expand Down
54 changes: 36 additions & 18 deletions packages/git/src/browser/diff/git-diff-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ import { inject, injectable, postConstruct } from 'inversify';
import URI from '@theia/core/lib/common/uri';
import { StatefulWidget, SELECTED_CLASS, DiffUris } from '@theia/core/lib/browser';
import { EditorManager, EditorOpenerOptions, EditorWidget, DiffNavigatorProvider, DiffNavigator } from '@theia/editor/lib/browser';
import { ScmRepository } from '@theia/scm/lib/browser/scm-repository';
import { ScmService } from '@theia/scm/lib/browser/scm-service';
import { GitFileChange, GitFileStatus, Git, WorkingDirectoryStatus } from '../../common';
import { GitScmProvider, GitScmFileChange } from '../git-scm-provider';
import { GitWatcher } from '../../common';
import { GIT_RESOURCE_SCHEME } from '../git-resource';
import { GitNavigableListWidget } from '../git-navigable-list-widget';
import { ScmNavigableListWidget } from '@theia/scm/lib/browser/scm-navigable-list-widget';
import { GitFileChangeNode } from '../git-file-change-node';
import { GitRepositoryProvider } from '../git-repository-provider';
import { Message } from '@phosphor/messaging';
import * as React from 'react';

// tslint:disable:no-null-keyword

export const GIT_DIFF = 'git-diff';
@injectable()
export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> implements StatefulWidget {
export class GitDiffWidget extends ScmNavigableListWidget<GitFileChangeNode> implements StatefulWidget {

protected readonly GIT_DIFF_TITLE = 'Diff';

Expand All @@ -42,9 +46,11 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
protected listView?: GitDiffListContainer;

@inject(Git) protected readonly git: Git;
@inject(GitRepositoryProvider) protected readonly repositoryProvider: GitRepositoryProvider;
@inject(DiffNavigatorProvider) protected readonly diffNavigatorProvider: DiffNavigatorProvider;
@inject(EditorManager) protected readonly editorManager: EditorManager;
@inject(GitWatcher) protected readonly gitWatcher: GitWatcher;
@inject(ScmService) protected readonly sucmService: ScmService;

constructor() {
super();
Expand All @@ -55,6 +61,7 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
this.title.closable = true;
this.title.iconClass = 'theia-git-diff-icon';

this.addClass('theia-scm');
this.addClass('theia-git');
}

Expand All @@ -77,8 +84,10 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp

async setContent(options: Git.Options.Diff) {
this.options = options;
const repository = this.repositoryProvider.findRepositoryOrSelected(options);
if (repository) {
const scmRepository = this.findRepositoryOrSelected(options.uri);
if (scmRepository && scmRepository.provider.id === 'git') {
const provider = scmRepository.provider as GitScmProvider;
const repository = { localUri: scmRepository.provider.rootUri };
const fileChanges: GitFileChange[] = await this.git.diff(repository, {
range: options.range,
uri: options.uri
Expand All @@ -92,16 +101,25 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
this.relativePath(fileChangeUri.parent)
]);

const caption = this.computeCaption(fileChange);
const gitScmFileChange = new GitScmFileChange(fileChange, provider, options.range);
const caption = this.computeCaption(gitScmFileChange);
const statusCaption = gitScmFileChange.getStatusCaption();
fileChangeNodes.push({
...fileChange, icon, label, description, caption
...fileChange, icon, label, description, caption, statusCaption
});
}
this.fileChangeNodes = fileChangeNodes;
this.update();
}
}

protected findRepositoryOrSelected(uri?: string): ScmRepository | undefined {
if (uri) {
return this.scmService.findRepository(new URI(uri));
}
return this.scmService.selectedRepository;
}

storeState(): object {
const { fileChangeNodes, options } = this;
return {
Expand All @@ -125,10 +143,10 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
}

protected render(): React.ReactNode {
this.gitNodes = this.fileChangeNodes;
this.scmNodes = this.fileChangeNodes;
const commitishBar = this.renderDiffListHeader();
const fileChangeList = this.renderFileChangeList();
return <div className='git-diff-container'>{commitishBar}{fileChangeList}</div>;
return <div className='scm-diff-container'>{commitishBar}{fileChangeList}</div>;
}

protected renderDiffListHeader(): React.ReactNode {
Expand Down Expand Up @@ -237,7 +255,7 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
protected doAddGitDiffListKeyListeners(id: string) {
const container = document.getElementById(id);
if (container) {
this.addGitListNavigationKeyListeners(container);
this.addListNavigationKeyListeners(container);
}
}

Expand Down Expand Up @@ -265,7 +283,7 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
<div
title={change.caption}
className={'status staged ' + GitFileStatus[change.status].toLowerCase()}>
{this.getStatusCaption(change.status, true).charAt(0)}
{change.statusCaption ? change.statusCaption.charAt(0) : undefined}
</div>
</div>;
}
Expand All @@ -287,8 +305,8 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp
this.revealChange(selected);
}
});
} else if (this.gitNodes.length > 0) {
this.selectNode(this.gitNodes[0]);
} else if (this.scmNodes.length > 0) {
this.selectNode(this.scmNodes[0]);
this.openSelected();
}
}
Expand All @@ -315,19 +333,19 @@ export class GitDiffWidget extends GitNavigableListWidget<GitFileChangeNode> imp

protected selectNextNode() {
const idx = this.indexOfSelected;
if (idx >= 0 && idx < this.gitNodes.length - 1) {
this.selectNode(this.gitNodes[idx + 1]);
} else if (this.gitNodes.length > 0 && (idx === -1 || idx === this.gitNodes.length - 1)) {
this.selectNode(this.gitNodes[0]);
if (idx >= 0 && idx < this.scmNodes.length - 1) {
this.selectNode(this.scmNodes[idx + 1]);
} else if (this.scmNodes.length > 0 && (idx === -1 || idx === this.scmNodes.length - 1)) {
this.selectNode(this.scmNodes[0]);
}
}

protected selectPreviousNode() {
const idx = this.indexOfSelected;
if (idx > 0) {
this.selectNode(this.gitNodes[idx - 1]);
this.selectNode(this.scmNodes[idx - 1]);
} else if (idx === 0) {
this.selectNode(this.gitNodes[this.gitNodes.length - 1]);
this.selectNode(this.scmNodes[this.scmNodes.length - 1]);
}
}

Expand Down
4 changes: 1 addition & 3 deletions packages/git/src/browser/git-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import URI from '@theia/core/lib/common/uri';
import { Command, CommandContribution, CommandRegistry, DisposableCollection, MenuContribution, MenuModelRegistry, Mutable, MenuAction } from '@theia/core';
import { DiffUris, Widget } from '@theia/core/lib/browser';
import { TabBarToolbarContribution, TabBarToolbarRegistry, TabBarToolbarItem } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { EDITOR_CONTEXT_MENU, EditorContextMenu, EditorManager, EditorOpenerOptions, EditorWidget } from '@theia/editor/lib/browser';
import { EditorContextMenu, EditorManager, EditorOpenerOptions, EditorWidget } from '@theia/editor/lib/browser';
import { Git, GitFileChange, GitFileStatus } from '../common';
import { GitRepositoryTracker } from './git-repository-tracker';
import { GitAction, GitQuickOpenService } from './git-quick-open-service';
Expand All @@ -29,8 +29,6 @@ import { GitErrorHandler } from '../browser/git-error-handler';
import { ScmWidget } from '@theia/scm/lib/browser/scm-widget';
import { ScmResource, ScmCommand } from '@theia/scm/lib/browser/scm-provider';

export const EDITOR_CONTEXT_MENU_GIT = [...EDITOR_CONTEXT_MENU, '3_git'];

export namespace GIT_COMMANDS {
export const CLONE = {
id: 'git.clone',
Expand Down
1 change: 1 addition & 0 deletions packages/git/src/browser/git-file-change-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface GitFileChangeNode extends GitFileChange {
readonly label: string;
readonly description: string;
readonly caption?: string;
readonly statusCaption?: string;
readonly extraIconClassName?: string;
readonly commitSha?: string;
selected?: boolean;
Expand Down
11 changes: 10 additions & 1 deletion packages/git/src/browser/git-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import { GitCommitMessageValidator } from './git-commit-message-validator';
import { GitSyncService } from './git-sync-service';
import { GitErrorHandler } from './git-error-handler';
import { GitScmProvider } from './git-scm-provider';
import { GitHistorySupport } from './history/git-history-support';
import { ScmHistorySupport } from '@theia/scm/lib/browser/history/scm-history-widget';

export default new ContainerModule(bind => {
bindGitPreferences(bind);
Expand All @@ -64,9 +66,16 @@ export default new ContainerModule(bind => {
bind(GitResourceResolver).toSelf().inSingletonScope();
bind(ResourceResolver).toService(GitResourceResolver);

bind(GitScmProvider.Factory).toFactory(GitScmProvider.createFactory);
bind(GitScmProvider.ContainerFactory).toFactory(GitScmProvider.createFactory);
bind(GitRepositoryProvider).toSelf().inSingletonScope();
bind(GitQuickOpenService).toSelf().inSingletonScope();
bind(GitScmProvider.ScmTypeContainer).toDynamicValue(({ container }) => {
const child = container.createChild();
child.bind(GitScmProvider).toSelf().inTransientScope();
child.bind(GitHistorySupport).toSelf().inTransientScope();
child.bind(ScmHistorySupport).toService(GitHistorySupport);
return child;
}).inSingletonScope();

bind(LabelProviderContribution).to(GitUriLabelProviderContribution).inSingletonScope();
bind(NavigatorTreeDecorator).to(GitDecorator).inSingletonScope();
Expand Down
2 changes: 1 addition & 1 deletion packages/git/src/browser/git-repository-provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('GitRepositoryProvider', () => {
testContainer.bind(FileSystemWatcher).toConstantValue(mockFileSystemWatcher);
testContainer.bind(StorageService).toConstantValue(mockStorageService);
testContainer.bind(ScmService).toSelf().inSingletonScope();
testContainer.bind(GitScmProvider.Factory).toFactory(GitScmProvider.createFactory);
testContainer.bind(GitScmProvider.ContainerFactory).toFactory(GitScmProvider.createFactory);
testContainer.bind(ScmContextKeyService).toSelf().inSingletonScope();
testContainer.bind(ContextKeyService).toSelf().inSingletonScope();
testContainer.bind(GitCommitMessageValidator).toSelf().inSingletonScope();
Expand Down
34 changes: 6 additions & 28 deletions packages/git/src/browser/git-repository-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service
import { FileSystem } from '@theia/filesystem/lib/common';
import { Emitter, Event } from '@theia/core/lib/common/event';
import { StorageService } from '@theia/core/lib/browser/storage-service';
import URI from '@theia/core/lib/common/uri';
import { FileSystemWatcher } from '@theia/filesystem/lib/browser/filesystem-watcher';
import { Git, Repository } from '../common';
import { GitCommitMessageValidator } from './git-commit-message-validator';
Expand All @@ -40,8 +39,8 @@ export class GitRepositoryProvider {
protected readonly selectedRepoStorageKey = 'theia-git-selected-repository';
protected readonly allRepoStorageKey = 'theia-git-all-repositories';

@inject(GitScmProvider.Factory)
protected readonly scmProviderFactory: GitScmProvider.Factory;
@inject(GitScmProvider.ContainerFactory)
protected readonly scmProviderFactory: GitScmProvider.ContainerFactory;

@inject(GitCommitMessageValidator)
protected readonly commitMessageValidator: GitCommitMessageValidator;
Expand Down Expand Up @@ -123,29 +122,6 @@ export class GitRepositoryProvider {
return repositories;
}

findRepository(uri: URI): Repository | undefined {
const reposSorted = this.allRepositories.sort(Repository.sortComparator);
return reposSorted.find(repo => new URI(repo.localUri).isEqualOrParent(uri));
}

findRepositoryOrSelected(arg: URI | string | { uri?: string | URI } | undefined): Repository | undefined {
let uri: URI | string | undefined;
if (arg) {
if (arg instanceof URI || typeof arg === 'string') {
uri = arg;
} else if (typeof arg === 'object' && 'uri' in arg && arg.uri) {
uri = arg.uri;
}
if (uri) {
if (typeof uri === 'string') {
uri = new URI(uri);
}
return this.findRepository(uri);
}
}
return this.selectedRepository;
}

async refresh(options?: GitRefreshOptions): Promise<void> {
const repositories: Repository[] = [];
const refreshing: Promise<void>[] = [];
Expand Down Expand Up @@ -186,7 +162,8 @@ export class GitRepositoryProvider {
}

protected registerScmProvider(repository: Repository): void {
const provider = this.scmProviderFactory({ repository });
const providerContainer = this.scmProviderFactory({ repository });
const provider = providerContainer.get(GitScmProvider);
this.scmService.registerScmProvider(provider, {
input: {
placeholder: 'Message (press {0} to commit)',
Expand All @@ -196,7 +173,8 @@ export class GitRepositoryProvider {
message: issue.message,
type: issue.status
};
}
},
providerContainer
}
});
}
Expand Down
Loading