complete tree provider refactor
This commit is contained in:
parent
cbab380bb0
commit
c315c18b4e
|
@ -31,7 +31,8 @@
|
|||
"title": "Show as list"
|
||||
},
|
||||
{
|
||||
"command": "gitcommitfilter.compare"
|
||||
"command": "gitcommitfilter.compare",
|
||||
"title": "比较文件变化"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
|
|
|
@ -35,6 +35,10 @@ export class GitService {
|
|||
this._repoPath = workspaceFolders[0].uri.fsPath;
|
||||
}
|
||||
|
||||
get repoPath(): string {
|
||||
return this._repoPath;
|
||||
}
|
||||
|
||||
private transformFilter(filter: GitCommitFilter): string[] {
|
||||
const gitArgs: string[] = [];
|
||||
if(filter.committer) {
|
||||
|
@ -54,7 +58,8 @@ export class GitService {
|
|||
return gitArgs;
|
||||
}
|
||||
|
||||
getDateStr(d:Date) :string {
|
||||
getDateStr(d:Date|undefined) :string {
|
||||
if(!d) {return '';}
|
||||
return d.toLocaleDateString('zh-CN');
|
||||
}
|
||||
private defaultFilter(): string[] {
|
||||
|
@ -75,17 +80,11 @@ export class GitService {
|
|||
return result.toString().trim();
|
||||
}
|
||||
|
||||
public async getCommits(filter: string = ""): Promise<any[]> {
|
||||
const filterParts = filter.split(" ");
|
||||
let nFilter: string[] = [];
|
||||
filterParts.forEach((part) => {
|
||||
const t = part.split(":");
|
||||
const key = t[0];
|
||||
const v = t[1];
|
||||
if (key in GitFilter) {
|
||||
nFilter.push(`--${GitFilter[key]}=${v}`);
|
||||
}
|
||||
});
|
||||
public async getCommits(filter: GitCommitFilter = {}): Promise<any[]> {
|
||||
let nFilter :string[] = [];
|
||||
if(Object.keys(filter).length !== 0){
|
||||
nFilter = this.transformFilter(filter);
|
||||
}
|
||||
if(nFilter.length === 0){
|
||||
nFilter = this.defaultFilter();
|
||||
}
|
||||
|
@ -97,6 +96,9 @@ export class GitService {
|
|||
"--date=format:%Y-%m-%d",
|
||||
"--name-only",
|
||||
];
|
||||
if(filter.path) {
|
||||
gitArgs.push(filter.path);
|
||||
}
|
||||
|
||||
const that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -146,7 +148,7 @@ export class GitService {
|
|||
if(lines.length > 0){
|
||||
const commit = makeCommit(lines);
|
||||
if(commit){
|
||||
that.logger.info('push commit', commit.hash)
|
||||
that.logger.info('push commit', commit.hash);
|
||||
commits.push(commit);
|
||||
|
||||
}
|
||||
|
@ -154,11 +156,11 @@ export class GitService {
|
|||
lines = [];
|
||||
lines.push(nline);
|
||||
} else if (nline.startsWith("---") ) {
|
||||
continue
|
||||
continue;
|
||||
}else if( nline.trim() === ""){
|
||||
const commit = makeCommit(lines);
|
||||
if(commit){
|
||||
that.logger.info('push commit 2', commit.hash)
|
||||
that.logger.info('push commit 2', commit.hash);
|
||||
commits.push(commit);
|
||||
}
|
||||
lines = [];
|
||||
|
@ -174,7 +176,7 @@ export class GitService {
|
|||
const commit = makeCommit(lines);
|
||||
if(commit){
|
||||
|
||||
that.logger.info('push commit 3', commit.hash)
|
||||
that.logger.info('push commit 3', commit.hash);
|
||||
commits.push(commit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import path from "path";
|
||||
import { EventBus } from "./event-bus";
|
||||
import { GitService } from "./GitService";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
export class Commander {
|
||||
constructor(private _gitService: GitService, private eventBus: EventBus) {
|
||||
console.log("Commander");
|
||||
}
|
||||
|
||||
public async compare(commit: string, file: string) {
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||
if (!workspaceFolder) {
|
||||
vscode.window.showErrorMessage('Please open a workspace folder first');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const rawPrevCommit = await this._gitService.getPreviousCommit(commit);
|
||||
const previousCommitId = rawPrevCommit?.trim(); // 去除可能的换行符
|
||||
if (!previousCommitId) {
|
||||
vscode.window.showErrorMessage('Cannot find previous commit');
|
||||
return;
|
||||
}
|
||||
|
||||
// 编码处理
|
||||
const encodedCommit = encodeURIComponent(commit.trim());
|
||||
const encodedPrevCommit = encodeURIComponent(previousCommitId);
|
||||
const sanitizedWorkPath = workspaceFolder.replace(/\\/g, '/')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/ /g, " ");
|
||||
const sanitizedFilePath = file.replace(/\\/g, '/')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/ /g, " ");
|
||||
// 构造 URI
|
||||
const currentUri = this.makeUri(sanitizedFilePath, encodedCommit);
|
||||
|
||||
const previousUri = this.makeUri(sanitizedFilePath, encodedPrevCommit);
|
||||
|
||||
await vscode.commands.executeCommand(
|
||||
"vscode.diff",
|
||||
previousUri,
|
||||
currentUri,
|
||||
`Changes: ${path.basename(file)} (${previousCommitId.slice(0, 7)} → ${commit.slice(0, 7)})`
|
||||
);
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`Failed to open diff: ${error instanceof Error ? error.message : error}`);
|
||||
}
|
||||
}
|
||||
private makeUri(filePath: string, commit: string) {
|
||||
const repoPath = this._gitService.repoPath;
|
||||
const repoUri = vscode.Uri.file(repoPath);
|
||||
const fUri = vscode.Uri.joinPath(repoUri, filePath);
|
||||
const params = {
|
||||
path: fUri.fsPath,
|
||||
ref: commit
|
||||
}
|
||||
return fUri.with({ scheme: 'git', path: fUri.path, query: JSON.stringify(params) });
|
||||
}
|
||||
|
||||
public changeToList() {
|
||||
// set state to list
|
||||
vscode.commands.executeCommand('setContext', 'gitcommitfilter:viewState', 'list');
|
||||
this.eventBus.emit('changeView', 'list');
|
||||
}
|
||||
|
||||
public changeToTree() {
|
||||
// set state to tree
|
||||
vscode.commands.executeCommand('setContext', 'gitcommitfilter:viewState', 'tree');
|
||||
this.eventBus.emit('changeView', 'tree');
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ export class CommitListProvider implements vscode.TreeDataProvider<CommitItem> {
|
|||
private state:string = "list";
|
||||
private filter: any = {};
|
||||
private _commits: GitCommit[] = [];
|
||||
private _items: CommitItem[] = [];
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<CommitItem | undefined | void> = new vscode.EventEmitter<CommitItem | undefined | void>();
|
||||
readonly onDidChangeTreeData: vscode.Event<CommitItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||
|
||||
|
@ -18,17 +19,30 @@ export class CommitListProvider implements vscode.TreeDataProvider<CommitItem> {
|
|||
this.filter = filter;
|
||||
this.refresh();
|
||||
});
|
||||
this.event.on("refresh",()=>{
|
||||
this.event.on("changeView",(state)=>{
|
||||
this.state = state;
|
||||
this._makeCommitItems();
|
||||
this._onDidChangeTreeData.fire();
|
||||
});
|
||||
}
|
||||
|
||||
_makeCommitItems() {
|
||||
|
||||
this._items = this._commits.map(commit => {
|
||||
const item = new CommitItem(
|
||||
commit.msg+' -- '+commit.author+'@'+commit.hash+' '+ commit.date,
|
||||
vscode.TreeItemCollapsibleState.None,
|
||||
commit.hash||'',
|
||||
this.state,
|
||||
'',
|
||||
commit.files||[]
|
||||
);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
async refresh() {
|
||||
this._commits = await this._gitService.getCommits(this.filter);
|
||||
this._makeCommitItems();
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
|
@ -43,12 +57,9 @@ export class CommitListProvider implements vscode.TreeDataProvider<CommitItem> {
|
|||
|
||||
async getChildren(element?: CommitItem): Promise<CommitItem[]> {
|
||||
if (!element) {
|
||||
const commits = await this._gitService.getCommits("");
|
||||
return commits.map(commit => new CommitItem(`${commit.msg} -- ${commit.author}@${commit.hash} ${commit.date}`, vscode.TreeItemCollapsibleState.Expanded, commit.files));
|
||||
return this._items;
|
||||
// return commits.map(commit => new CommitItem(`${commit.msg} -- ${commit.author}@${commit.hash} ${commit.date}`, vscode.TreeItemCollapsibleState.Expanded, commit.files));
|
||||
}
|
||||
if (element.files) {
|
||||
return element.files.map(file => new CommitItem(this._showFullPath ? file : path.basename(file), vscode.TreeItemCollapsibleState.None, undefined, file));
|
||||
}
|
||||
return [];
|
||||
return element.children||[];
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ import * as path from "path";
|
|||
export class CommitItem extends vscode.TreeItem {
|
||||
public iconPath?: string | vscode.IconPath | undefined = 'file';
|
||||
public children?: CommitItem[];
|
||||
public command?: vscode.Command | undefined = undefined
|
||||
constructor(
|
||||
public readonly label:string,
|
||||
public state : vscode.TreeItemCollapsibleState,
|
||||
|
@ -54,6 +55,11 @@ export class CommitItem extends vscode.TreeItem {
|
|||
super(label, state);
|
||||
if(this.isFileItem()){
|
||||
this.tooltip = this.fpath;
|
||||
this.command = {
|
||||
command: 'gitcommitfilter.compare',
|
||||
title: '比较文件变化',
|
||||
arguments: [this.commitHash, this.fpath]
|
||||
};
|
||||
}
|
||||
if(this.isCommitItem()) {
|
||||
this.iconPath = 'git-commit';
|
||||
|
|
|
@ -2,6 +2,9 @@ import * as vscode from 'vscode';
|
|||
|
||||
import { GitService } from './GitService';
|
||||
import { GViewProvider } from './view.provider';
|
||||
import { EventBus } from './event-bus';
|
||||
import { CommitListProvider } from './commit-list.provider';
|
||||
import { Commander } from './commands';
|
||||
|
||||
function getGitApi(){
|
||||
|
||||
|
@ -22,9 +25,25 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
return;
|
||||
}
|
||||
const logger = vscode.window.createOutputChannel('GitCommitFilter',{log: true});
|
||||
const eventBus = new EventBus();
|
||||
const gitService = new GitService(gitPath,logger);
|
||||
|
||||
const commitlist = new CommitListProvider(gitService,eventBus)
|
||||
|
||||
const commander = new Commander(gitService,eventBus);
|
||||
context.subscriptions.push(vscode.commands.registerCommand('gitcommitfilter.showaslist', () => {
|
||||
commander.changeToList();
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('gitcommitfilter.showastree', () => {
|
||||
commander.changeToTree();
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('gitcommitfilter.compare', (commit, file) => {
|
||||
commander.compare(commit, file);
|
||||
}));
|
||||
//get view gitcommitfilter.commit-list
|
||||
const viewProvider = new GViewProvider(context, gitService,logger);
|
||||
const d= vscode.window.registerTreeDataProvider('gitcommitfilter.commit-list', commitlist);
|
||||
context.subscriptions.push(d);
|
||||
commitlist.refresh();
|
||||
|
||||
const activityBarIcon = vscode.window.registerWebviewViewProvider(GViewProvider.viewType, viewProvider);
|
||||
|
||||
|
@ -33,28 +52,3 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
export function deactivate() {}
|
||||
|
||||
// 实现TreeDataProvider接口
|
||||
class CommitTreeDataProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<vscode.TreeItem | undefined | void>();
|
||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | void> = this._onDidChangeTreeData.event;
|
||||
|
||||
private gitService: GitService;
|
||||
|
||||
constructor(gitService: GitService) {
|
||||
this.gitService = gitService;
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
|
||||
return element;
|
||||
}
|
||||
|
||||
getChildren(element?: vscode.TreeItem): vscode.ProviderResult<vscode.TreeItem[]> {
|
||||
if (element) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ export class GViewProvider implements vscode.WebviewViewProvider {
|
|||
) {
|
||||
webviewView.webview.options = { enableScripts: true };
|
||||
this._view = webviewView;
|
||||
webviewView.webview.html = this.generateHtml(webviewView);
|
||||
webviewView.webview.html = '';//this.generateHtml(webviewView);
|
||||
|
||||
// 添加事件监听器
|
||||
webviewView.webview.onDidReceiveMessage(
|
||||
|
@ -261,13 +261,13 @@ private async openDiff(commitId: string, filePath: string) {
|
|||
}
|
||||
|
||||
private async filterCommits(filterText: string) {
|
||||
if (this._view) {
|
||||
const commits = await this._gitService.getCommits(filterText);
|
||||
this._logger.info(`filteredCommits:, ${JSON.stringify(commits)}"`);
|
||||
this._view.webview.postMessage({
|
||||
command: "updateCommits",
|
||||
commits
|
||||
});
|
||||
}
|
||||
// if (this._view) {
|
||||
// const commits = await this._gitService.getCommits(filterText);
|
||||
// this._logger.info(`filteredCommits:, ${JSON.stringify(commits)}"`);
|
||||
// this._view.webview.postMessage({
|
||||
// command: "updateCommits",
|
||||
// commits
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue