Skip to content

Commit

Permalink
feat: Added Branches tree view (#729)
Browse files Browse the repository at this point in the history
  • Loading branch information
FractalBoy authored and JohnstonCode committed Nov 13, 2019
1 parent 4824881 commit cecd185
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 14 deletions.
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
"id": "itemlog",
"name": "File History",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
},
{
"id": "branchchanges",
"name": "Branch Changes",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
}
]
},
Expand Down Expand Up @@ -191,6 +196,20 @@
"category": "SVN",
"title": "Copy message to clipboard"
},
{
"command": "svn.branchchanges.openDiff",
"category": "SVN",
"title": "Open diff"
},
{
"command": "svn.branchchanges.refresh",
"category": "SVN",
"title": "Refresh branch changes",
"icon": {
"dark": "icons/dark/refresh.svg",
"light": "icons/light/refresh.svg"
}
},
{
"command": "svn.checkout",
"title": "Checkout",
Expand Down Expand Up @@ -592,6 +611,14 @@
"command": "svn.itemlog.copymsg",
"when": "false"
},
{
"command": "svn.branchchanges.openDiff",
"when": "false"
},
{
"command": "svn.branchchanges.refresh",
"when": "false"
},
{
"command": "svn.pickCommitMessage",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
Expand All @@ -617,6 +644,11 @@
"command": "svn.itemlog.refresh",
"when": "view == itemlog",
"group": "navigation"
},
{
"command": "svn.branchchanges.refresh",
"when": "view == branchchanges",
"group": "navigation"
}
],
"view/item/context": [
Expand Down
21 changes: 21 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ export interface ISvnInfo {
};
}

export interface ISvnPath {
props: PropStatus;
kind: SvnKindType;
item: Status;
_: string;
}

export interface ISvnPathChange {
oldPath: Uri;
newPath: Uri;
oldRevision: string;
newRevision: string;
props: PropStatus;
kind: SvnKindType;
item: Status;
repo: Uri;
}

export interface ISvnListItem {
kind: SvnKindType;
name: string;
Expand Down Expand Up @@ -91,6 +109,7 @@ export enum RepositoryState {
export enum Operation {
Add = "Add",
AddChangelist = "AddChangelist",
Changes = "Changes",
CleanUp = "CleanUp",
Commit = "Commit",
CurrentBranch = "CurrentBranch",
Expand Down Expand Up @@ -272,6 +291,8 @@ export interface ISvnLogEntryPath {
action: string;
/** "file" | "dir" e.g. */
kind: string;
copyfromPath?: string;
copyfromRev?: string;
}

/** produced by svn log */
Expand Down
33 changes: 33 additions & 0 deletions src/diffParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ISvnPath } from "./common/types";
import * as xml2js from "xml2js";
import { camelcase } from "./util";

export async function parseDiffXml(content: string): Promise<ISvnPath[]> {
return new Promise<ISvnPath[]>((resolve, reject) => {
xml2js.parseString(
content,
{
mergeAttrs: true,
explicitRoot: false,
explicitArray: false,
attrNameProcessors: [camelcase],
tagNameProcessors: [camelcase]
},
(err, result) => {
if (
err ||
!result.paths ||
!result.paths.path
) {
reject();
}

if (!Array.isArray(result.paths.path)) {
result.paths.path = [result.paths.path];
}

resolve(result.paths.path);
}
);
});
}
9 changes: 6 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import { Svn } from "./svn";
import { SvnContentProvider } from "./svnContentProvider";
import { SvnFinder } from "./svnFinder";
import SvnProvider from "./treeView/dataProviders/svnProvider";
import {
toDisposable
} from "./util";
import { toDisposable } from "./util";
import { BranchChangesProvider } from "./historyView/branchChangesProvider";

async function init(
_context: ExtensionContext,
Expand Down Expand Up @@ -53,6 +52,10 @@ async function init(
disposables.push(itemLogProvider);
window.registerTreeDataProvider("itemlog", itemLogProvider);

const branchChangesProvider = new BranchChangesProvider(model);
disposables.push(branchChangesProvider);
window.registerTreeDataProvider("branchchanges", branchChangesProvider);

disposables.push(new CheckActiveEditor(model));
disposables.push(new OpenRepositoryCount(model));

Expand Down
99 changes: 99 additions & 0 deletions src/historyView/branchChangesProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
TreeDataProvider,
Disposable,
TreeItem,
commands,
EventEmitter
} from "vscode";
import { Model } from "../model";
import { ISvnPathChange, Status } from "../common/types";
import { openDiff, getIconObject, openFileRemote } from "./common";
import { dispose } from "../util";

export class BranchChangesProvider
implements TreeDataProvider<ISvnPathChange>, Disposable {
private _dispose: Disposable[] = [];
private _onDidChangeTreeData = new EventEmitter<ISvnPathChange | undefined>();
public readonly onDidChangeTreeData = this._onDidChangeTreeData.event;

constructor(private model: Model) {
this._dispose.push(
commands.registerCommand(
"svn.branchchanges.openDiff",
this.openDiffCmd,
this
)
);

this._dispose.push(
commands.registerCommand(
"svn.branchchanges.refresh",
() => this._onDidChangeTreeData.fire(),
this
)
);

this.model.onDidChangeRepository(() => this._onDidChangeTreeData.fire());
}

dispose() {
dispose(this._dispose);
}

getTreeItem(element: ISvnPathChange): TreeItem | Thenable<TreeItem> {
let iconName: string = "";
if (element.item === Status.ADDED) {
iconName = "status-added";
} else if (element.item === Status.DELETED) {
iconName = "status-deleted";
} else if (element.item === Status.MODIFIED) {
iconName = "status-modified";
}

const iconPath = getIconObject(iconName);

return {
label: element.newPath.toString(),
command: {
command: "svn.branchchanges.openDiff",
title: "Open diff",
arguments: [element]
},
iconPath,
tooltip: `${element.oldPath}@r${element.oldRevision}${element.newPath}@r${element.newRevision}`
};
}

getChildren(element?: ISvnPathChange): Promise<ISvnPathChange[]> {
if (element !== undefined) {
return Promise.resolve([]);
}

const changes: Promise<ISvnPathChange[]>[] = [];

for (const repo of this.model.repositories) {
changes.push(repo.getChanges());
}

return Promise.all(changes).then(value =>
value.reduce((prev, curr) => prev.concat(curr), [])
);
}

public async openDiffCmd(element: ISvnPathChange) {
const repo = await this.model.getRemoteRepository(element.repo);

if (element.item === Status.MODIFIED) {
return openDiff(
repo,
element.oldPath,
element.oldRevision,
element.newRevision,
element.newPath
);
}
if (element.item === Status.ADDED) {
return openFileRemote(repo, element.newPath, element.newRevision);
}
}
}
11 changes: 6 additions & 5 deletions src/historyView/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,17 @@ async function downloadFile(

export async function openDiff(
repo: IRemoteRepository,
arg: Uri,
arg1: Uri,
r1: string,
r2: string
r2: string,
arg2?: Uri
) {
const uri1 = await downloadFile(repo, arg, r1);
const uri2 = await downloadFile(repo, arg, r2);
const uri1 = await downloadFile(repo, arg1, r1);
const uri2 = await downloadFile(repo, arg2 || arg1, r2);
const opts: TextDocumentShowOptions = {
preview: true
};
const title = `${path.basename(arg.path)} (${r1} : ${r2})`;
const title = `${path.basename(arg1.path)} (${r1} : ${r2})`;
return commands.executeCommand<void>("vscode.diff", uri1, uri2, title, opts);
}

Expand Down
7 changes: 6 additions & 1 deletion src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
RepositoryState,
Status,
SvnDepth,
SvnUriAction
SvnUriAction,
ISvnPathChange
} from "./common/types";
import { debounce, globalSequentialize, memoize, throttle } from "./decorators";
import { exists } from "./fs";
Expand Down Expand Up @@ -867,6 +868,10 @@ export class Repository implements IRemoteRepository {
);
}

public async getChanges(): Promise<ISvnPathChange[]> {
return this.run(Operation.Changes, () => this.repository.getChanges());
}

public async finishCheckout() {
return this.run(Operation.SwitchBranch, () =>
this.repository.finishCheckout()
Expand Down
Loading

0 comments on commit cecd185

Please sign in to comment.