Navigation Menu

Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Added Take Theirs and Keep Yours commands to UI
Browse files Browse the repository at this point in the history
User Story #884949
  • Loading branch information
jpricket committed Feb 15, 2017
1 parent 2a04264 commit 96fbf60
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 12 deletions.
42 changes: 40 additions & 2 deletions package.json
Expand Up @@ -77,7 +77,7 @@
},
{
"command": "tfvc.Undo",
"when": "scmProvider == tfvc",
"when": "scmProvider == tfvc && scmResourceGroup != conflicts",
"group": "1_modification@1"
},
{
Expand All @@ -90,9 +90,19 @@
"when": "scmProvider == tfvc && scmResourceGroup == included",
"group": "1_modification@2"
},
{
"command": "tfvc.ResolveTakeTheirs",
"when": "scmProvider == tfvc && scmResourceGroup == conflicts",
"group": "1_modification@1"
},
{
"command": "tfvc.ResolveKeepYours",
"when": "scmProvider == tfvc && scmResourceGroup == conflicts",
"group": "1_modification@2"
},
{
"command": "tfvc.Undo",
"when": "scmProvider == tfvc",
"when": "scmProvider == tfvc && scmResourceGroup != conflicts",
"group": "inline@1"
},
{
Expand All @@ -104,6 +114,16 @@
"command": "tfvc.Exclude",
"when": "scmProvider == tfvc && scmResourceGroup == included",
"group": "inline@2"
},
{
"command": "tfvc.ResolveTakeTheirs",
"when": "scmProvider == tfvc && scmResourceGroup == conflicts",
"group": "inline@1"
},
{
"command": "tfvc.ResolveKeepYours",
"when": "scmProvider == tfvc && scmResourceGroup == conflicts",
"group": "inline@2"
}
]
},
Expand Down Expand Up @@ -275,6 +295,24 @@
"dark": "resources/icons/dark/refresh.svg"
}
},
{
"command": "tfvc.ResolveKeepYours",
"title": "Resove: Keep Yours",
"category": "TFVC",
"icon": {
"light": "resources/icons/light/resolve-keepyours.svg",
"dark": "resources/icons/dark/resolve-keepyours.svg"
}
},
{
"command": "tfvc.ResolveTakeTheirs",
"title": "Resolve: Take Theirs",
"category": "TFVC",
"icon": {
"light": "resources/icons/light/resolve-taketheirs.svg",
"dark": "resources/icons/dark/resolve-taketheirs.svg"
}
},
{
"command": "tfvc.Sync",
"title": "Sync",
Expand Down
4 changes: 4 additions & 0 deletions resources/icons/dark/resolve-keepyours.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/icons/dark/resolve-taketheirs.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/icons/light/resolve-keepyours.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/icons/light/resolve-taketheirs.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/extension.ts
Expand Up @@ -8,6 +8,7 @@ import { commands, Disposable, ExtensionContext } from "vscode";
import { CommandNames, TfvcCommandNames } from "./helpers/constants";
import { ExtensionManager } from "./extensionmanager";
import { TfvcSCMProvider } from "./tfvc/tfvcscmprovider";
import { AutoResolveType } from "./tfvc/interfaces";

let _extensionManager: ExtensionManager;
let _scmProvider: TfvcSCMProvider;
Expand Down Expand Up @@ -62,6 +63,12 @@ export async function activate(context: ExtensionContext) {
}));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.Refresh, () => _extensionManager.Tfvc.TfvcRefresh()));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.ShowOutput, () => _extensionManager.Tfvc.TfvcShowOutput()));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.ResolveKeepYours, (...args) => {
_extensionManager.Tfvc.TfvcResolve(args ? args[0] : undefined, AutoResolveType.KeepYours);
}));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.ResolveTakeTheirs, (...args) => {
_extensionManager.Tfvc.TfvcResolve(args ? args[0] : undefined, AutoResolveType.TakeTheirs);
}));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.Checkin, () => _extensionManager.Tfvc.TfvcCheckin()));
context.subscriptions.push(commands.registerCommand(TfvcCommandNames.Sync, () => _extensionManager.Tfvc.TfvcSync()));
}
2 changes: 2 additions & 0 deletions src/helpers/constants.ts
Expand Up @@ -44,6 +44,8 @@ export class TfvcCommandNames {
static OpenDiff: string = TfvcCommandNames.CommandPrefix + "OpenDiff";
static OpenFile: string = TfvcCommandNames.CommandPrefix + "OpenFile";
static Refresh: string = TfvcCommandNames.CommandPrefix + "Refresh";
static ResolveKeepYours: string = TfvcCommandNames.CommandPrefix + "ResolveKeepYours";
static ResolveTakeTheirs: string = TfvcCommandNames.CommandPrefix + "ResolveTakeTheirs";
static ShowOutput: string = TfvcCommandNames.CommandPrefix + "ShowOutput";
static Status: string = TfvcCommandNames.CommandPrefix + "Status";
static Sync: string = TfvcCommandNames.CommandPrefix + "Sync";
Expand Down
10 changes: 10 additions & 0 deletions src/helpers/strings.ts
Expand Up @@ -67,6 +67,7 @@ export class Strings {
static UndoChanges: string = "Undo Changes";
static NoChangesToCheckin: string = "There are no changes to checkin. Changes must be added to the 'Included' section to be checked in.";
static AllFilesUpToDate: string = "All files are up to date.";
static CommandRequiresFileContext: string = "This command requires a file context and can only be executed from the TFVC viewlet window.";

// TFVC viewlet Strings
static ExcludedGroupName: string = "Excluded changes";
Expand All @@ -85,5 +86,14 @@ export class Strings {
static ConflictAlreadyDeleted: string = "ALREADY DELETED";
static ConflictAlreadyExists: string = "ALREADY EXISTS";
static ConflictDeletedLocally: string = "DELETED LOCALLY";

// TFVC AutoResolveType Strings
static AutoResolveTypeAutoMerge: string = "Auto Merge";
static AutoResolveTypeDeleteConflict: string = "Delete Conflict";
static AutoResolveTypeKeepYours: string = "Keep Yours";
static AutoResolveTypeKeepYoursRenameTheirs: string = "Keep Yours Rename Theirs";
static AutoResolveTypeOverwriteLocal: string = "Overwrite Local";
static AutoResolveTypeTakeTheirs: string = "Take Theirs";

}
/* tslint:enable:variable-name */
9 changes: 8 additions & 1 deletion src/tfvc/repository.ts
Expand Up @@ -8,14 +8,15 @@ import { TeamServerContext} from "../contexts/servercontext";
import { Logger } from "../helpers/logger";
import { ITfvcCommand, IExecutionResult } from "./interfaces";
import { Tfvc } from "./tfvc";
import { IArgumentProvider, IConflict, IItemInfo, IPendingChange, ISyncResults, IWorkspace } from "./interfaces";
import { AutoResolveType, IArgumentProvider, IConflict, IItemInfo, IPendingChange, ISyncResults, IWorkspace } from "./interfaces";
import { Add } from "./commands/add";
import { Checkin } from "./commands/checkin";
import { FindConflicts } from "./commands/findconflicts";
import { FindWorkspace } from "./commands/findworkspace";
import { GetInfo } from "./commands/getinfo";
import { GetFileContent } from "./commands/getfilecontent";
import { GetVersion } from "./commands/getversion";
import { ResolveConflicts } from "./commands/resolveconflicts";
import { Status } from "./commands/status";
import { Sync } from "./commands/sync";
import { Undo } from "./commands/undo";
Expand Down Expand Up @@ -96,6 +97,12 @@ export class Repository {
new Status(this._serverContext, ignoreFiles === undefined ? true : ignoreFiles));
}

public async ResolveConflicts(itemPaths: string[], autoResolveType: AutoResolveType): Promise<IConflict[]> {
Logger.LogDebug(`TFVC Repository.ResolveConflicts`);
return this.RunCommand<IConflict[]>(
new ResolveConflicts(this._serverContext, itemPaths, autoResolveType));
}

public async Sync(itemPaths: string[], recursive: boolean): Promise<ISyncResults> {
Logger.LogDebug(`TFVC Repository.Sync`);
return this.RunCommand<ISyncResults>(
Expand Down
42 changes: 34 additions & 8 deletions src/tfvc/tfvc-extension.ts
Expand Up @@ -19,7 +19,7 @@ import { TfvcSCMProvider } from "./tfvcscmprovider";
import { TfvcErrorCodes } from "./tfvcerror";
import { Repository } from "./repository";
import { UIHelper } from "./uihelper";
import { ICheckinInfo, IItemInfo, IPendingChange, ISyncResults } from "./interfaces";
import { AutoResolveType, ICheckinInfo, IItemInfo, IPendingChange, ISyncResults } from "./interfaces";
import { TfvcOutput } from "./tfvcoutput";

export class TfvcExtension {
Expand Down Expand Up @@ -134,6 +134,23 @@ export class TfvcExtension {
}
}

public async TfvcResolve(uri: Uri, autoResolveType: AutoResolveType): Promise<void> {
this.displayErrors(async () => {
if (uri) {
let localPath: string = TfvcSCMProvider.GetPathFromUri(uri);
const resolveTypeString: string = UIHelper.GetDisplayTextForAutoResolveType(autoResolveType);
const basename: string = path.basename(localPath);
const message: string = `Are you sure you want to resolve changes in ${basename} as ${resolveTypeString}?`;
if (await UIHelper.PromptForConfirmation(message, resolveTypeString)) {
await this._repo.ResolveConflicts([localPath], autoResolveType);
TfvcSCMProvider.Refresh();
}
} else {
this._manager.DisplayWarningMessage(Strings.CommandRequiresFileContext);
}
});
}

public async TfvcShowOutput(): Promise<void> {
TfvcOutput.Show();
}
Expand Down Expand Up @@ -202,14 +219,10 @@ export class TfvcExtension {
if (pathToUndo) {
const basename: string = path.basename(pathToUndo);
const message: string = `Are you sure you want to undo changes in ${basename}?`;
//TODO: use Modal api once vscode.d.ts exposes it (currently proposed)
const pick: string = await window.showWarningMessage(message, /*{ modal: true },*/ Strings.UndoChanges);
if (pick !== Strings.UndoChanges) {
return;
if (await UIHelper.PromptForConfirmation(message, Strings.UndoChanges)) {
this._manager.Telemetry.SendEvent(TfvcTelemetryEvents.Undo);
await this._repo.Undo([pathToUndo]);
}

this._manager.Telemetry.SendEvent(TfvcTelemetryEvents.Undo);
await this._repo.Undo([pathToUndo]);
}
} catch (err) {
this._manager.DisplayErrorMessage(err.message);
Expand Down Expand Up @@ -261,6 +274,19 @@ export class TfvcExtension {
}
}

private async displayErrors(funcToTry: () => Promise<void>): Promise<void> {
if (!this._manager.EnsureInitialized(RepositoryType.TFVC)) {
this._manager.DisplayErrorMessage();
return;
}

try {
await funcToTry();
} catch (err) {
this._manager.DisplayErrorMessage(err.message);
}
}

public async InitializeClients(repoType: RepositoryType): Promise<void> {
//We only need to initialize for Tfvc repositories
if (repoType !== RepositoryType.TFVC) {
Expand Down
21 changes: 20 additions & 1 deletion src/tfvc/uihelper.ts
Expand Up @@ -6,7 +6,7 @@

import { QuickPickItem, window, workspace } from "vscode";
import { Strings } from "../helpers/strings";
import { IPendingChange, ISyncResults, ISyncItemResult, SyncType } from "./interfaces";
import { AutoResolveType, IPendingChange, ISyncResults, ISyncItemResult, SyncType } from "./interfaces";
import { TfvcOutput } from "./tfvcoutput";

var path = require("path");
Expand Down Expand Up @@ -106,6 +106,18 @@ export class UIHelper {
}
}

public static GetDisplayTextForAutoResolveType(type: AutoResolveType): string {
switch (type) {
case AutoResolveType.AutoMerge: return Strings.AutoResolveTypeAutoMerge;
case AutoResolveType.DeleteConflict: return Strings.AutoResolveTypeDeleteConflict;
case AutoResolveType.KeepYours: return Strings.AutoResolveTypeKeepYours;
case AutoResolveType.KeepYoursRenameTheirs: return Strings.AutoResolveTypeKeepYoursRenameTheirs;
case AutoResolveType.OverwriteLocal: return Strings.AutoResolveTypeOverwriteLocal;
case AutoResolveType.TakeTheirs: return Strings.AutoResolveTypeTakeTheirs;
default: return Strings.AutoResolveTypeAutoMerge;
}
}

public static GetFileName(change: IPendingChange) {
if (change && change.localItem) {
var filename = path.parse(change.localItem).base;
Expand All @@ -122,4 +134,11 @@ export class UIHelper {

return change.localItem;
}

public static async PromptForConfirmation(message: string, okButtonText?: string): Promise<boolean> {
okButtonText = okButtonText ? okButtonText : "OK";
//TODO: use Modal api once vscode.d.ts exposes it (currently proposed)
const pick: string = await window.showWarningMessage(message, /*{ modal: true },*/ okButtonText);
return pick === okButtonText;
}
}

0 comments on commit 96fbf60

Please sign in to comment.