Skip to content

Compatibility mode for Source Depot #48

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

Merged
merged 4 commits into from
Apr 8, 2017
Merged
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
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@
"type":"string",
"default":"none",
"description":"Configure a path to p4 or an alternate command if needed"
},
"perforce.compatibilityMode": {
"type": "string",
"default": "perforce",
"enum": [
"perforce",
"sourcedepot"
],
"description": "Specify if we should run in compatibility mode, currently support 'perforce' and 'sourcedepot'"
}
}
},
Expand Down
7 changes: 5 additions & 2 deletions src/ContentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ export class PerforceContentProvider {
private disposables: Disposable[] = [];
dispose(): void { this.disposables.forEach(d => d.dispose()); }

constructor() {
private compatibilityMode: string;

constructor(compatibilityMode: string) {
this.compatibilityMode = compatibilityMode;
this.disposables.push(
workspace.registerTextDocumentContentProvider('perforce', this),
);
}

public provideTextDocumentContent(uri: Uri): Promise<string> {
return Utils.isLoggedIn().then(value => {
return Utils.isLoggedIn(this.compatibilityMode).then(value => {
if (!value) {
return '';
}
Expand Down
7 changes: 5 additions & 2 deletions src/ScmProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Status } from './scm/Status';
import * as Path from 'path';

export class PerforceSCMProvider {
private compatibilityMode: string;

private disposables: Disposable[] = [];
dispose(): void {
this.disposables.forEach(d => d.dispose());
Expand Down Expand Up @@ -38,12 +40,13 @@ export class PerforceSCMProvider {
return 'idle'
}

constructor() {
constructor(compatibilityMode: string) {
this.compatibilityMode = compatibilityMode;
this.Initialize();
}

public Initialize() {
this._model = new Model();
this._model = new Model(this.compatibilityMode);
// Hook up the model change event to trigger our own event
this._model.onDidChange((groups: SourceControlResourceGroup[]) => this._onDidChange.fire(this));
this._model.Refresh();
Expand Down
25 changes: 8 additions & 17 deletions src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { PerforceService } from './PerforceService';

export namespace Utils
{
const ztagRegex = /^\.\.\.\s+(\w+)\s+(.+)/;

export function normalizePath(path: string): string
{
var normalizedPath = path;
Expand All @@ -29,14 +27,13 @@ export namespace Utils
return path.replace('%', '%25').replace('*', '%2A').replace('#', '%23').replace('@', '%40');
}

// process output from a p4 command executed with -ztag
function processZtag(output): Map<string, string> {
export function processInfo(output): Map<string, string> {
const map = new Map<string, string>();
const lines = output.trim().split('\n');

for (let i = 0, n = lines.length; i < n; ++i) {
// ... key value
const matches = lines[i].match(/\.\.\.\s(.[\w-]+)\s(.+)/);
// Property Name: Property Value
const matches = lines[i].match(/([^:]+): (.+)/);

if (matches) {
map.set(matches[1], matches[2]);
Expand All @@ -47,19 +44,13 @@ export namespace Utils
return map;
}

// Get a map containing the keys and values of the command
export function getZtag(command: string, file?: Uri | string, revision?: number, prefixArgs?: string): Promise<Map<string, string>> {
export function isLoggedIn(compatibilityMode: string) : Promise<boolean> {
return new Promise((resolve, reject) => {
getOutput(command, file, revision, prefixArgs, '-ztag').then(output => {
const map = processZtag(output);
resolve( map );
});
});

}
if(compatibilityMode === 'sourcedepot') {
resolve(true);
return;
}

export function isLoggedIn() : Promise<boolean> {
return new Promise((resolve, reject) => {
PerforceService.execute('login', (err, stdout, stderr) => {
if (err) {
resolve(false);
Expand Down
8 changes: 5 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

import { ExtensionContext } from 'vscode';
import { ExtensionContext, workspace } from 'vscode';

import { PerforceCommands } from './PerforceCommands';
import { PerforceContentProvider } from './ContentProvider';
Expand All @@ -9,10 +9,12 @@ import { PerforceSCMProvider } from './ScmProvider';
import { Display } from './Display';

export function activate(ctx: ExtensionContext) : void {
const compatibilityMode = workspace.getConfiguration('perforce').get('compatibilityMode', 'perforce');

//Register all commands
PerforceCommands.registerCommands();
Display.initialize();
ctx.subscriptions.push(new PerforceContentProvider());
ctx.subscriptions.push(new PerforceContentProvider(compatibilityMode));
ctx.subscriptions.push(new FileSystemListener());
ctx.subscriptions.push( new PerforceSCMProvider() );
ctx.subscriptions.push( new PerforceSCMProvider(compatibilityMode));
}
29 changes: 16 additions & 13 deletions src/scm/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class Model implements Disposable {
private _defaultGroup: SourceControlResourceGroup;
private _pendingGroups = new Map<number, { description: string, group: SourceControlResourceGroup }>();
private _shelvedGroups = new Map<number, { description: string, group: SourceControlResourceGroup }>();
private _compatibilityMode: string;

public get ResourceGroups(): SourceControlResourceGroup[] {
const result: SourceControlResourceGroup[] = [];
Expand All @@ -49,10 +50,12 @@ export class Model implements Disposable {
return result;
}

public constructor() {}
public constructor(compatibilityMode: string) {
this._compatibilityMode = compatibilityMode;
}

public async Sync(): Promise<void> {
const loggedin = await Utils.isLoggedIn();
const loggedin = await Utils.isLoggedIn(this._compatibilityMode);
if (!loggedin) {
return;
}
Expand All @@ -62,8 +65,7 @@ export class Model implements Disposable {

public async Refresh(): Promise<void> {
this.clean();

const loggedin = await Utils.isLoggedIn();
const loggedin = await Utils.isLoggedIn(this._compatibilityMode);
if (!loggedin) {
return;
}
Expand Down Expand Up @@ -190,7 +192,7 @@ export class Model implements Disposable {
}

public async ReopenFile(input: Resource): Promise<void> {
const loggedin = await Utils.isLoggedIn();
const loggedin = await Utils.isLoggedIn(this._compatibilityMode);
if (!loggedin) {
return;
}
Expand Down Expand Up @@ -241,13 +243,11 @@ export class Model implements Disposable {
}

private async updateInfo(): Promise<void> {
this._infos = await Utils.getZtag('info');

this._infos = await Utils.processInfo(await Utils.getOutput('info'));
}

private async updateStatus(): Promise<void> {

const loggedin = await Utils.isLoggedIn();
const loggedin = await Utils.isLoggedIn(this._compatibilityMode);
if (!loggedin) {
return;
}
Expand All @@ -259,7 +259,7 @@ export class Model implements Disposable {
this._defaultGroup = this._sourceControl.createResourceGroup('default', 'Default Changelist');
this._pendingGroups.clear(); // dispose ?

const pendingArgs = '-c ' + this._infos.get('clientName') + ' -s pending';
const pendingArgs = '-c ' + this._infos.get('Client name') + ' -s pending';
var output: string = await Utils.getOutput('changes', null, null, pendingArgs);
output.trim().split('\n').forEach( (value) => {
// Change num on date by user@client [status] description
Expand Down Expand Up @@ -310,10 +310,13 @@ export class Model implements Disposable {
const change = matches[4];
const type = matches[5];

const output: string = await Utils.getOutput('fstat', depotFile, null, '-T clientFile');
// fstat -T isn't supported in Source Depot
const output: string = await Utils.getOutput('fstat', depotFile, null);

const filteredOutput = output.trim().split('\n').filter((line) => line.startsWith('... clientFile '));

if (output.indexOf('... clientFile ') === 0) {
const clientFile = output.substring(15, output.indexOf('\n')).trim();
if (filteredOutput.length === 1) {
const clientFile = filteredOutput[0].substring(15).trim();
const uri = Uri.file(clientFile);
const resource: Resource = new Resource(uri, change, action);

Expand Down