Skip to content

Commit

Permalink
feat: Added support to revert from explorer (close #606) (#608)
Browse files Browse the repository at this point in the history
  • Loading branch information
edgardmessias authored and JohnstonCode committed Jun 14, 2019
1 parent 3b7e74b commit 02c983b
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 51 deletions.
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,15 @@
"dark": "icons/dark/clean.svg"
}
},
{
"command": "svn.revertExplorer",
"title": "Revert with SVN",
"category": "SVN",
"icon": {
"light": "icons/light/clean.svg",
"dark": "icons/dark/clean.svg"
}
},
{
"command": "svn.revertAll",
"title": "Revert All Changes",
Expand Down Expand Up @@ -483,6 +492,10 @@
"command": "svn.revert",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
},
{
"command": "svn.revertExplorer",
"when": "false"
},
{
"command": "svn.update",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
Expand Down Expand Up @@ -902,6 +915,11 @@
"command": "svn.changelist",
"group": "9_svn",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
},
{
"command": "svn.revertExplorer",
"group": "7_modification",
"when": "config.svn.enabled && svnOpenRepositoryCount != 0"
}
]
},
Expand Down
2 changes: 2 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { Resolved } from "./commands/resolved";
import { Revert } from "./commands/revert";
import { RevertAll } from "./commands/revertAll";
import { RevertChange } from "./commands/revertChange";
import { RevertExplorer } from "./commands/revertExplorer";
import { RevertSelectedRanges } from "./commands/revertSelectedRanges";
import { SwitchBranch } from "./commands/switchBranch";
import { Update } from "./commands/update";
Expand Down Expand Up @@ -86,4 +87,5 @@ export function registerCommands(model: Model, disposables: Disposable[]) {
disposables.push(new OpenHeadFile());
disposables.push(new RevertAll());
disposables.push(new PickCommitMessage());
disposables.push(new RevertExplorer());
}
28 changes: 6 additions & 22 deletions src/commands/revert.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SourceControlResourceState, window } from "vscode";
import { SvnDepth } from "../common/types";
import { checkAndPromptDepth, confirmRevert } from "../input/revert";
import { Command } from "./command";

export class Revert extends Command {
Expand All @@ -10,33 +10,17 @@ export class Revert extends Command {
public async execute(...resourceStates: SourceControlResourceState[]) {
const selection = await this.getResourceStates(resourceStates);

if (selection.length === 0) {
if (selection.length === 0 || !(await confirmRevert())) {
return;
}

const yes = "Yes I'm sure";
const answer = await window.showWarningMessage(
"Are you sure? This will wipe all local changes.",
{ modal: true },
yes
);
const uris = selection.map(resource => resource.resourceUri);
const depth = await checkAndPromptDepth(uris);

if (answer !== yes) {
if (!depth) {
return;
}

const picks: any[] = [];

for (const depth in SvnDepth) {
if (SvnDepth.hasOwnProperty(depth)) {
picks.push({ label: depth, description: SvnDepth[depth] });
}
}

const placeHolder = "Select revert depth";
const pick = await window.showQuickPick(picks, { placeHolder });
const uris = selection.map(resource => resource.resourceUri);

await this.runByRepository(uris, async (repository, resources) => {
if (!repository) {
return;
Expand All @@ -45,7 +29,7 @@ export class Revert extends Command {
const paths = resources.map(resource => resource.fsPath);

try {
await repository.revert(paths, pick.label);
await repository.revert(paths, depth);
} catch (error) {
console.log(error);
window.showErrorMessage("Unable to revert");
Expand Down
28 changes: 6 additions & 22 deletions src/commands/revertAll.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SourceControlResourceGroup, window } from "vscode";
import { SvnDepth } from "../common/types";
import { checkAndPromptDepth, confirmRevert } from "../input/revert";
import { Command } from "./command";

export class RevertAll extends Command {
Expand All @@ -10,33 +10,17 @@ export class RevertAll extends Command {
public async execute(resourceGroup: SourceControlResourceGroup) {
const resourceStates = resourceGroup.resourceStates;

if (resourceStates.length === 0) {
if (resourceStates.length === 0 || !(await confirmRevert())) {
return;
}

const yes = "Yes I'm sure";
const answer = await window.showWarningMessage(
"Are you sure? This will wipe all local changes.",
{ modal: true },
yes
);
const uris = resourceStates.map(resource => resource.resourceUri);
const depth = await checkAndPromptDepth(uris);

if (answer !== yes) {
if (!depth) {
return;
}

const picks: any[] = [];

for (const depth in SvnDepth) {
if (SvnDepth.hasOwnProperty(depth)) {
picks.push({ label: depth, description: SvnDepth[depth] });
}
}

const placeHolder = "Select revert depth";
const pick = await window.showQuickPick(picks, { placeHolder });
const uris = resourceStates.map(resource => resource.resourceUri);

await this.runByRepository(uris, async (repository, resources) => {
if (!repository) {
return;
Expand All @@ -45,7 +29,7 @@ export class RevertAll extends Command {
const paths = resources.map(resource => resource.fsPath);

try {
await repository.revert(paths, pick.label);
await repository.revert(paths, depth);
} catch (error) {
console.log(error);
window.showErrorMessage("Unable to revert");
Expand Down
41 changes: 41 additions & 0 deletions src/commands/revertExplorer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Uri, window } from "vscode";
import { checkAndPromptDepth, confirmRevert } from "../input/revert";
import { Command } from "./command";

export class RevertExplorer extends Command {
constructor() {
super("svn.revertExplorer");
}

public async execute(_mainUri?: Uri, allUris?: Uri[]) {
if (!allUris) {
return;
}

const uris = allUris;
if (uris.length === 0 || !(await confirmRevert())) {
return;
}

const depth = await checkAndPromptDepth(uris);

if (!depth) {
return;
}

await this.runByRepository(uris, async (repository, resources) => {
if (!repository) {
return;
}

const paths = resources.map(resource => resource.fsPath);

try {
await repository.revert(paths, depth);
} catch (error) {
console.log(error);
window.showErrorMessage("Unable to revert");
}
});
}
}
64 changes: 64 additions & 0 deletions src/input/revert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Uri, window } from "vscode";
import { SvnDepth } from "../common/types";
import { lstat } from "../fs";

export async function confirmRevert() {
const yes = "Yes I'm sure";
const answer = await window.showWarningMessage(
"Are you sure? This will wipe all local changes.",
{ modal: true },
yes
);

if (answer !== yes) {
return false;
}

return true;
}

export async function promptDepth() {
const picks: any[] = [];

for (const depth in SvnDepth) {
if (SvnDepth.hasOwnProperty(depth)) {
picks.push({ label: depth, description: SvnDepth[depth] });
}
}

const placeHolder = "Select revert depth";
const pick = await window.showQuickPick(picks, { placeHolder });
if (!pick) {
return undefined;
}
return pick.label;
}

export async function checkAndPromptDepth(
uris: Uri[],
defaultDepth: keyof typeof SvnDepth = "empty"
) {
// Without uris, force prompt
let hasDirectory = uris.length === 0;

for (const uri of uris) {
if (uri.scheme !== "file") {
continue;
}
try {
const stat = await lstat(uri.fsPath);
if (stat.isDirectory()) {
hasDirectory = true;
break;
}
} catch (error) {
// ignore
}
}

if (hasDirectory) {
return await promptDepth();
}

return defaultDepth;
}
6 changes: 4 additions & 2 deletions src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,10 @@ export class Repository implements IRemoteRepository {
);
}

public async revert(files: string[], depth: SvnDepth) {
return this.run(Operation.Revert, () => this.repository.revert(files, depth));
public async revert(files: string[], depth: keyof typeof SvnDepth) {
return this.run(Operation.Revert, () =>
this.repository.revert(files, depth)
);
}

public async info(path: string) {
Expand Down
18 changes: 13 additions & 5 deletions src/svnRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ export class Repository {
filePath = file;
}

const isChild = uri.scheme === "file" && isDescendant(this.workspaceRoot, uri.fsPath);
const isChild =
uri.scheme === "file" && isDescendant(this.workspaceRoot, uri.fsPath);

let target: string = filePath;

Expand All @@ -194,7 +195,10 @@ export class Repository {

if (revision) {
args.push("-r", revision);
if (isChild && !["BASE", "COMMITTED", "PREV"].includes(revision.toUpperCase())) {
if (
isChild &&
!["BASE", "COMMITTED", "PREV"].includes(revision.toUpperCase())
) {
const info = await this.getInfo();
target = info.url + "/" + target.replace(/\\/g, "/");
// TODO move to SvnRI
Expand Down Expand Up @@ -292,9 +296,13 @@ export class Repository {

const matches = result.stdout.match(/Committed revision (.*)\./i);
if (matches && matches[0]) {
const sendedFiles = (result.stdout.match(/(Sending|Adding|Deleting)\s+/g) || []).length;
const sendedFiles = (
result.stdout.match(/(Sending|Adding|Deleting)\s+/g) || []
).length;

const filesMessage = `${sendedFiles} ${sendedFiles === 1 ? "file" : "files"} commited`;
const filesMessage = `${sendedFiles} ${
sendedFiles === 1 ? "file" : "files"
} commited`;

return `${filesMessage}: revision ${matches[1]}.`;
}
Expand Down Expand Up @@ -453,7 +461,7 @@ export class Repository {
return true;
}

public async revert(files: string[], depth: SvnDepth) {
public async revert(files: string[], depth: keyof typeof SvnDepth) {
files = files.map(file => this.removeAbsolutePath(file));
const result = await this.exec(["revert", "--depth", depth, ...files]);
return result.stdout;
Expand Down

0 comments on commit 02c983b

Please sign in to comment.