Comparing version 0.0.28 to 0.0.29
@@ -7,3 +7,3 @@ "use strict"; | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments)).next()); | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
@@ -10,0 +10,0 @@ }; |
@@ -0,1 +1,2 @@ | ||
import { Event } from "vscode-jsonrpc"; | ||
import { WorkspaceOp } from "../ot/workspace"; | ||
@@ -13,2 +14,6 @@ import { Client } from "./client"; | ||
} | ||
export interface SymbolicRefUpdateEvent extends RefIdentifier { | ||
newTarget: string; | ||
oldTarget?: string; | ||
} | ||
export declare class Handler { | ||
@@ -18,9 +23,13 @@ private remoteClient; | ||
private repos; | ||
private isDuringWatchCall; | ||
constructor(remoteClient: Client); | ||
register(connection: IConnection): void; | ||
attachWorkspace(refID: RefIdentifier, workspace: Workspace | null): Promise<void>; | ||
attachWorkspace(refID: RefIdentifier, workspace: Workspace): Promise<void>; | ||
repoWatch(params: RepoWatchParams): Thenable<void>; | ||
private symbolicRefUpdateEmitter; | ||
readonly onDidUpdateSymbolicRef: Event<SymbolicRefUpdateEvent>; | ||
private onRefUpdate(params); | ||
private onSymbolicRefUpdate(params); | ||
private getRepo(repoName); | ||
dispose(): void; | ||
} |
@@ -7,5 +7,6 @@ "use strict"; | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments)).next()); | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
const vscode_jsonrpc_1 = require("vscode-jsonrpc"); | ||
const client_1 = require("../ot/client"); | ||
@@ -17,2 +18,4 @@ const protocol_1 = require("./protocol"); | ||
this.repos = new Map(); | ||
this.isDuringWatchCall = false; | ||
this.symbolicRefUpdateEmitter = new vscode_jsonrpc_1.Emitter(); | ||
} | ||
@@ -22,6 +25,8 @@ register(connection) { | ||
connection.onNotification(protocol_1.RefUpdateDownstreamRequest.type, params => this.onRefUpdate(params)); | ||
connection.onRequest(protocol_1.RefUpdateSymbolicRequest.type, params => this.onSymbolicRefUpdate(params)); | ||
connection.onNotification(protocol_1.RefUpdateSymbolicRequest.type, params => this.onSymbolicRefUpdate(params)); | ||
} | ||
attachWorkspace(refID, workspace) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.getRepo(refID.repo).getRef(refID.ref).setWorkspace(workspace); | ||
yield this.getRepo(refID.repo).getRef(refID.ref).attachWorkspace(workspace); | ||
}); | ||
@@ -31,8 +36,23 @@ } | ||
return this.remoteClient.onReady().then(() => { | ||
return this.remoteClient.sendRequest(protocol_1.RepoWatchRequest.type, params); | ||
this.isDuringWatchCall = true; | ||
return this.remoteClient.sendRequest(protocol_1.RepoWatchRequest.type, params) | ||
.then(() => { this.isDuringWatchCall = false; }, (err) => { this.isDuringWatchCall = false; throw err; }); | ||
}); | ||
} | ||
get onDidUpdateSymbolicRef() { | ||
return this.symbolicRefUpdateEmitter.event; | ||
} | ||
onRefUpdate(params) { | ||
return this.getRepo(params.repo).onRefUpdateFromUpstream(params); | ||
} | ||
onSymbolicRefUpdate(params) { | ||
return this.getRepo(params.repo).onSymbolicRefUpdateFromUpstream(params, this.isDuringWatchCall).then(() => { | ||
this.symbolicRefUpdateEmitter.fire({ | ||
repo: params.repo, | ||
ref: params.ref, | ||
newTarget: params.target, | ||
oldTarget: params.oldTarget, | ||
}); | ||
}); | ||
} | ||
getRepo(repoName) { | ||
@@ -48,3 +68,3 @@ let repo = this.repos.get(repoName); | ||
} | ||
Handler.id = "ot"; | ||
Handler.id = "ot.handler"; | ||
exports.Handler = Handler; | ||
@@ -60,4 +80,3 @@ class RepoHandler { | ||
if (!ref) { | ||
ref = new RefHandler({ repo: this.repoName, ref: refName }, this.remoteClient, null); | ||
this.refs.set(refName, ref); | ||
throw new Error(`unknown ref: ${refName}`); | ||
} | ||
@@ -72,9 +91,77 @@ return ref; | ||
} | ||
ref = new RefHandler({ repo: this.repoName, ref: params.ref }, this.remoteClient, params.state || null); | ||
ref = new NonSymbolicRefHandler({ repo: this.repoName, ref: params.ref }, this.remoteClient, params.state || null); | ||
this.refs.set(params.ref, ref); | ||
} | ||
if (!(ref instanceof NonSymbolicRefHandler)) { | ||
throw new Error("not yet implemented: updating a ref from symbolic to non-symbolic"); | ||
} | ||
return ref.onUpdateFromUpstream(params); | ||
} | ||
onSymbolicRefUpdateFromUpstream(params, force) { | ||
let ref = this.refs.get(params.ref); | ||
if (!ref) { | ||
ref = new SymbolicRefHandler({ repo: params.repo, ref: params.ref }); | ||
this.refs.set(params.ref, ref); | ||
} | ||
if (!(ref instanceof SymbolicRefHandler)) { | ||
throw new Error("not yet implemented: updating a ref from symbolic to non-symbolic"); | ||
} | ||
return ref.onUpdateFromUpstream(params, this.refs, force); | ||
} | ||
} | ||
class RefHandler { | ||
class SymbolicRefHandler { | ||
constructor(refID) { | ||
this.refID = refID; | ||
} | ||
onUpdateFromUpstream(params, allRefs, force) { | ||
if (params.ack) { | ||
return Promise.resolve(void 0); | ||
} | ||
if (!force) { | ||
if (typeof this.target === "string" && !params.oldTarget) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: no oldTarget value sent`); | ||
} | ||
if (this.target !== params.oldTarget) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: wrong oldTarget value sent (${JSON.stringify(this.target)} != ${JSON.stringify(params.oldTarget)})`); | ||
} | ||
} | ||
const newTargetHandler = allRefs.get(params.target); | ||
if (!newTargetHandler) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: new target ref ${JSON.stringify(params.target)} does not exist`); | ||
} | ||
if (this.target === params.target) { | ||
return Promise.resolve(void 0); | ||
} | ||
this.target = params.target; | ||
const oldTargetHandler = this.targetHandler; | ||
this.targetHandler = newTargetHandler; | ||
if (this.workspace && oldTargetHandler !== newTargetHandler) { | ||
oldTargetHandler.detachWorkspace(); | ||
return this.targetHandler.attachWorkspace(this.workspace); | ||
} | ||
return Promise.resolve(void 0); | ||
} | ||
attachWorkspace(newWorkspace) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.workspace === newWorkspace) { | ||
console.log(`WARNING: NonSymbolicRefHandler(${JSON.stringify(this.refID)}): attachWorkspace called unnecessarily with this.workspace === newWorkspace`); | ||
return; | ||
} | ||
if (this.workspace) { | ||
this.detachWorkspace(); | ||
this.workspace = undefined; | ||
} | ||
this.workspace = newWorkspace; | ||
return this.targetHandler.attachWorkspace(newWorkspace); | ||
}); | ||
} | ||
detachWorkspace() { | ||
if (!this.workspace) { | ||
throw new Error("no workspace attached"); | ||
} | ||
this.targetHandler.detachWorkspace(); | ||
this.workspace = undefined; | ||
} | ||
} | ||
class NonSymbolicRefHandler { | ||
constructor(refID, remoteClient, state) { | ||
@@ -85,3 +172,2 @@ this.refID = refID; | ||
this.ot = new client_1.Client(); | ||
this.workspace = null; | ||
this.ot.send = (rev, op) => { | ||
@@ -110,22 +196,28 @@ this.remoteClient.onReady().then(() => { | ||
} | ||
setWorkspace(newWorkspace) { | ||
attachWorkspace(newWorkspace) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.workspace === newWorkspace) { | ||
console.log(`WARNING: NonSymbolicRefHandler(${JSON.stringify(this.refID)}): attachWorkspace called unnecessarily with this.workspace === newWorkspace`); | ||
} | ||
if (this.workspace) { | ||
this.workspace.onOp(undefined); | ||
this.workspace.onReset(undefined); | ||
this.detachWorkspace(); | ||
} | ||
this.workspace = newWorkspace; | ||
if (this.workspace) { | ||
this.ot.apply = (op) => this.workspace.apply(op); | ||
this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
yield this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
this.workspace.onOp(op => this.onWorkspaceOp(op)); | ||
this.workspace.onReset(newOp => this.onWorkspaceReset(newOp)); | ||
this.workspace.onWillSaveFile(params => this.onWorkspaceWillSaveFile(params)); | ||
} | ||
else { | ||
this.ot.apply = undefined; | ||
} | ||
this.ot.apply = (op) => this.workspace.apply(op); | ||
this.workspace.onOp(op => this.onWorkspaceOp(op)); | ||
this.workspace.onReset(newOp => this.onWorkspaceReset(newOp)); | ||
this.workspace.onWillSaveFile(params => this.onWorkspaceWillSaveFile(params)); | ||
this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
yield this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
}); | ||
} | ||
detachWorkspace() { | ||
if (!this.workspace) { | ||
throw new Error("no workspace attached"); | ||
} | ||
this.workspace.onOp(undefined); | ||
this.workspace.onReset(undefined); | ||
this.ot.apply = undefined; | ||
this.workspace = undefined; | ||
} | ||
onWorkspaceOp(op) { | ||
@@ -132,0 +224,0 @@ this.ot.record(op); |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
const assert = require("assert"); | ||
@@ -20,3 +28,3 @@ const client_1 = require("./client"); | ||
describe("Handler", () => { | ||
it("ref/update", () => { | ||
it("ref/update", () => __awaiter(this, void 0, void 0, function* () { | ||
const { server, serverOptions } = util_1.createTestServer(); | ||
@@ -50,4 +58,9 @@ server.onRequest("repo/watch", () => { | ||
client.registerHandler(handler_1.Handler.id, handler); | ||
handler.onRefUpdate({ | ||
repo: "repo", | ||
ref: "ref", | ||
state: { gitBase: "c", gitBranch: "d" }, | ||
}); | ||
const workspace = mockWorkspace(); | ||
handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
yield handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
return client.start().initialStart.then(() => { | ||
@@ -59,4 +72,4 @@ return handler.repoWatch({ repo: "repo", refspec: "*" }).then(() => { | ||
}, (err) => assert.ifError(err)); | ||
}); | ||
it("ack", () => { | ||
})); | ||
it("ack", () => __awaiter(this, void 0, void 0, function* () { | ||
const { server, serverOptions } = util_1.createTestServer(); | ||
@@ -66,4 +79,9 @@ const client = new client_1.Client(serverOptions, {}); | ||
client.registerHandler(handler_1.Handler.id, handler); | ||
handler.onRefUpdate({ | ||
repo: "repo", | ||
ref: "ref", | ||
state: { gitBase: "c", gitBranch: "d" }, | ||
}); | ||
const workspace = mockWorkspace(); | ||
handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
yield handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
let ok = false; | ||
@@ -82,4 +100,4 @@ handler.getRepo("repo").getRef("ref").ot.ack = () => { ok = true; }; | ||
}, (err) => assert.ifError(err)); | ||
}); | ||
})); | ||
}); | ||
//# sourceMappingURL=ot_test.js.map |
import { NotificationType, NotificationType0, RequestType, RequestType0 } from "vscode-jsonrpc"; | ||
import { WorkspaceOp } from "../ot/workspace"; | ||
export declare enum ErrorCode { | ||
ErrorCodeInvalid = 0, | ||
ErrorCodeNotInitialized = 1, | ||
ErrorCodeAlreadyInitialized = 2, | ||
ErrorCodeRepoNotExists = 3, | ||
ErrorCodeRefNotExists = 4, | ||
ErrorCodeRefExists = 5, | ||
ErrorCodeRefConflict = 6, | ||
ErrorCodeRemoteNotExists = 7, | ||
ErrorCodeInvalidConfig = 8, | ||
ErrorCodeSymbolicRefInvalid = 9, | ||
ErrorCodeWorkspaceNotExists = 10, | ||
ErrorCodeWorkspaceExists = 11, | ||
ErrorCodeWorkspaceIdentifierRequired = 12, | ||
ErrorCodeRefUpdateInvalid = 13, | ||
} | ||
export declare enum StatusType { | ||
@@ -9,3 +25,3 @@ StatusTypeError = 1, | ||
export interface ShowStatusParams { | ||
ref?: string; | ||
repo: string; | ||
message: string; | ||
@@ -104,3 +120,3 @@ type: StatusType; | ||
export interface RefInfo extends RefIdentifier, RefBaseInfo { | ||
rev: number; | ||
rev?: number; | ||
target?: string; | ||
@@ -176,2 +192,12 @@ watchers: string[]; | ||
} | ||
export interface RefUpdateSymbolicParams extends RefIdentifier { | ||
target: string; | ||
oldTarget?: string; | ||
ack?: boolean; | ||
} | ||
export interface RefUpdateSymbolicResult { | ||
} | ||
export declare namespace RefUpdateSymbolicRequest { | ||
const type: RequestType<RefUpdateSymbolicParams, RefUpdateSymbolicResult, void, void>; | ||
} | ||
export interface WorkspaceIdentifier { | ||
@@ -178,0 +204,0 @@ dir: string; |
"use strict"; | ||
const vscode_jsonrpc_1 = require("vscode-jsonrpc"); | ||
var ErrorCode; | ||
(function (ErrorCode) { | ||
ErrorCode[ErrorCode["ErrorCodeInvalid"] = 0] = "ErrorCodeInvalid"; | ||
ErrorCode[ErrorCode["ErrorCodeNotInitialized"] = 1] = "ErrorCodeNotInitialized"; | ||
ErrorCode[ErrorCode["ErrorCodeAlreadyInitialized"] = 2] = "ErrorCodeAlreadyInitialized"; | ||
ErrorCode[ErrorCode["ErrorCodeRepoNotExists"] = 3] = "ErrorCodeRepoNotExists"; | ||
ErrorCode[ErrorCode["ErrorCodeRefNotExists"] = 4] = "ErrorCodeRefNotExists"; | ||
ErrorCode[ErrorCode["ErrorCodeRefExists"] = 5] = "ErrorCodeRefExists"; | ||
ErrorCode[ErrorCode["ErrorCodeRefConflict"] = 6] = "ErrorCodeRefConflict"; | ||
ErrorCode[ErrorCode["ErrorCodeRemoteNotExists"] = 7] = "ErrorCodeRemoteNotExists"; | ||
ErrorCode[ErrorCode["ErrorCodeInvalidConfig"] = 8] = "ErrorCodeInvalidConfig"; | ||
ErrorCode[ErrorCode["ErrorCodeSymbolicRefInvalid"] = 9] = "ErrorCodeSymbolicRefInvalid"; | ||
ErrorCode[ErrorCode["ErrorCodeWorkspaceNotExists"] = 10] = "ErrorCodeWorkspaceNotExists"; | ||
ErrorCode[ErrorCode["ErrorCodeWorkspaceExists"] = 11] = "ErrorCodeWorkspaceExists"; | ||
ErrorCode[ErrorCode["ErrorCodeWorkspaceIdentifierRequired"] = 12] = "ErrorCodeWorkspaceIdentifierRequired"; | ||
ErrorCode[ErrorCode["ErrorCodeRefUpdateInvalid"] = 13] = "ErrorCodeRefUpdateInvalid"; | ||
})(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {})); | ||
var StatusType; | ||
@@ -80,2 +97,6 @@ (function (StatusType) { | ||
})(RefUpdateUpstreamRequest = exports.RefUpdateUpstreamRequest || (exports.RefUpdateUpstreamRequest = {})); | ||
var RefUpdateSymbolicRequest; | ||
(function (RefUpdateSymbolicRequest) { | ||
RefUpdateSymbolicRequest.type = new vscode_jsonrpc_1.RequestType("ref/updateSymbolic"); | ||
})(RefUpdateSymbolicRequest = exports.RefUpdateSymbolicRequest || (exports.RefUpdateSymbolicRequest = {})); | ||
; | ||
@@ -82,0 +103,0 @@ var WorkspaceAddRequest; |
{ | ||
"name": "libzap", | ||
"version": "0.0.28", | ||
"version": "0.0.29", | ||
"description": "JavaScript library for Zap", | ||
@@ -5,0 +5,0 @@ "license": "none", |
@@ -0,1 +1,3 @@ | ||
import { Emitter, Event } from "vscode-jsonrpc"; | ||
import { Client as OTClient } from "../ot/client"; | ||
@@ -5,3 +7,3 @@ import { WorkspaceOp } from "../ot/workspace"; | ||
import { IConnection } from "./connection"; | ||
import { RefIdentifier, RefState, RefUpdateUpstreamRequest, RefUpdateDownstreamRequest, RefUpdateDownstreamParams, RepoWatchParams, RepoWatchRequest, WorkspaceWillSaveFileParams, WorkspaceWillSaveFileRequest } from "./protocol"; | ||
import { RefIdentifier, RefState, RefUpdateUpstreamRequest, RefUpdateSymbolicParams, RefUpdateSymbolicRequest, RefUpdateDownstreamRequest, RefUpdateDownstreamParams, RepoWatchParams, RepoWatchRequest, WorkspaceWillSaveFileParams, WorkspaceWillSaveFileRequest } from "./protocol"; | ||
@@ -27,7 +29,22 @@ export interface Workspace { | ||
export interface SymbolicRefUpdateEvent extends RefIdentifier { | ||
newTarget: string; | ||
oldTarget?: string; | ||
} | ||
export class Handler { | ||
static readonly id: string = "ot"; | ||
static readonly id: string = "ot.handler"; | ||
private repos: Map<string, RepoHandler> = new Map(); // like refdb on the server | ||
/** | ||
* isDuringWatchCall is whether we have called repo/watch and have not | ||
* yet received the response from the server. If true, it means that | ||
* all ref updates should clobber our local state, since we are | ||
* updating them from the server's initial state. | ||
* | ||
* TODO(sqs): figure out how to merge changes if we made changes while offline | ||
*/ | ||
private isDuringWatchCall: boolean = false; | ||
constructor( | ||
@@ -41,6 +58,9 @@ private remoteClient: Client, | ||
connection.onNotification(RefUpdateDownstreamRequest.type, params => this.onRefUpdate(params)); | ||
connection.onRequest(RefUpdateSymbolicRequest.type, params => this.onSymbolicRefUpdate(params)); | ||
connection.onNotification(RefUpdateSymbolicRequest.type, params => this.onSymbolicRefUpdate(params)); | ||
} | ||
public async attachWorkspace(refID: RefIdentifier, workspace: Workspace | null): Promise<void> { | ||
await this.getRepo(refID.repo).getRef(refID.ref).setWorkspace(workspace); | ||
public async attachWorkspace(refID: RefIdentifier, workspace: Workspace): Promise<void> { | ||
await this.getRepo(refID.repo).getRef(refID.ref).attachWorkspace(workspace); | ||
} | ||
@@ -52,6 +72,13 @@ | ||
return this.remoteClient.onReady().then(() => { | ||
return this.remoteClient.sendRequest(RepoWatchRequest.type, params); | ||
this.isDuringWatchCall = true; | ||
return this.remoteClient.sendRequest(RepoWatchRequest.type, params) | ||
.then(() => { this.isDuringWatchCall = false; }, (err) => { this.isDuringWatchCall = false; throw err; }); | ||
}); | ||
} | ||
private symbolicRefUpdateEmitter: Emitter<SymbolicRefUpdateEvent> = new Emitter<SymbolicRefUpdateEvent>(); | ||
public get onDidUpdateSymbolicRef(): Event<SymbolicRefUpdateEvent> { | ||
return this.symbolicRefUpdateEmitter.event; | ||
} | ||
private onRefUpdate(params: RefUpdateDownstreamParams): Thenable<void> { | ||
@@ -61,2 +88,13 @@ return this.getRepo(params.repo).onRefUpdateFromUpstream(params); | ||
private onSymbolicRefUpdate(params: RefUpdateSymbolicParams): Thenable<void> { | ||
return this.getRepo(params.repo).onSymbolicRefUpdateFromUpstream(params, this.isDuringWatchCall).then(() => { | ||
this.symbolicRefUpdateEmitter.fire({ | ||
repo: params.repo, | ||
ref: params.ref, | ||
newTarget: params.target, | ||
oldTarget: params.oldTarget, | ||
}); | ||
}); | ||
} | ||
private getRepo(repoName: string): RepoHandler { | ||
@@ -85,4 +123,3 @@ let repo = this.repos.get(repoName); | ||
if (!ref) { | ||
ref = new RefHandler({ repo: this.repoName, ref: refName }, this.remoteClient, null); | ||
this.refs.set(refName, ref); | ||
throw new Error(`unknown ref: ${refName}`); | ||
} | ||
@@ -98,12 +135,93 @@ return ref; | ||
} | ||
ref = new RefHandler({ repo: this.repoName, ref: params.ref }, this.remoteClient, params.state || null); | ||
ref = new NonSymbolicRefHandler({ repo: this.repoName, ref: params.ref }, this.remoteClient, params.state || null); | ||
this.refs.set(params.ref, ref); | ||
} | ||
if (!(ref instanceof NonSymbolicRefHandler)) { | ||
throw new Error("not yet implemented: updating a ref from symbolic to non-symbolic"); | ||
} | ||
return ref.onUpdateFromUpstream(params); | ||
} | ||
public onSymbolicRefUpdateFromUpstream(params: RefUpdateSymbolicParams, force: boolean): Thenable<void> { | ||
let ref = this.refs.get(params.ref); | ||
if (!ref) { | ||
ref = new SymbolicRefHandler({ repo: params.repo, ref: params.ref }); | ||
this.refs.set(params.ref, ref); | ||
} | ||
if (!(ref instanceof SymbolicRefHandler)) { | ||
throw new Error("not yet implemented: updating a ref from symbolic to non-symbolic"); | ||
} | ||
return ref.onUpdateFromUpstream(params, this.refs, force); | ||
} | ||
} | ||
class RefHandler { | ||
interface RefHandler { | ||
attachWorkspace(workspace: Workspace): Promise<void>; | ||
detachWorkspace(): void; | ||
} | ||
class SymbolicRefHandler implements RefHandler { | ||
private target?: string; | ||
private targetHandler: RefHandler; | ||
private workspace?: Workspace; | ||
constructor( | ||
private refID: RefIdentifier, | ||
) { } | ||
onUpdateFromUpstream(params: RefUpdateSymbolicParams, allRefs: Map<string, RefHandler>, force: boolean): Thenable<void> { | ||
if (params.ack) { | ||
return Promise.resolve(void 0); | ||
} | ||
if (!force) { | ||
if (typeof this.target === "string" && !params.oldTarget) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: no oldTarget value sent`); | ||
} | ||
if (this.target !== params.oldTarget) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: wrong oldTarget value sent (${JSON.stringify(this.target)} != ${JSON.stringify(params.oldTarget)})`); | ||
} | ||
} | ||
const newTargetHandler = allRefs.get(params.target); | ||
if (!newTargetHandler) { | ||
throw new Error(`symbolic ref ${JSON.stringify(this.refID.ref)} update: new target ref ${JSON.stringify(params.target)} does not exist`); | ||
} | ||
if (this.target === params.target) { | ||
return Promise.resolve(void 0); // nothing to do | ||
} | ||
this.target = params.target; | ||
const oldTargetHandler = this.targetHandler; | ||
this.targetHandler = newTargetHandler; | ||
if (this.workspace && oldTargetHandler !== newTargetHandler) { | ||
oldTargetHandler.detachWorkspace(); | ||
return this.targetHandler.attachWorkspace(this.workspace); | ||
} | ||
return Promise.resolve(void 0); | ||
} | ||
public async attachWorkspace(newWorkspace: Workspace): Promise<void> { | ||
if (this.workspace === newWorkspace) { | ||
console.log(`WARNING: NonSymbolicRefHandler(${JSON.stringify(this.refID)}): attachWorkspace called unnecessarily with this.workspace === newWorkspace`); | ||
return; | ||
} | ||
if (this.workspace) { | ||
this.detachWorkspace(); | ||
this.workspace = undefined; | ||
} | ||
this.workspace = newWorkspace; | ||
return this.targetHandler.attachWorkspace(newWorkspace); | ||
} | ||
public detachWorkspace(): void { | ||
if (!this.workspace) { | ||
throw new Error("no workspace attached"); | ||
} | ||
this.targetHandler.detachWorkspace(); | ||
this.workspace = undefined; | ||
} | ||
} | ||
class NonSymbolicRefHandler implements RefHandler { | ||
private ot = new OTClient(); | ||
private workspace: Workspace | null = null; | ||
private workspace?: Workspace; | ||
@@ -138,23 +256,32 @@ constructor( | ||
public async setWorkspace(newWorkspace: Workspace | null): Promise<void> { | ||
// Remove listeners from old workspace. | ||
if (this.workspace) { | ||
this.workspace.onOp(undefined); | ||
this.workspace.onReset(undefined); | ||
public async attachWorkspace(newWorkspace: Workspace): Promise<void> { | ||
if (this.workspace === newWorkspace) { | ||
console.log(`WARNING: NonSymbolicRefHandler(${JSON.stringify(this.refID)}): attachWorkspace called unnecessarily with this.workspace === newWorkspace`); | ||
} | ||
this.workspace = newWorkspace; | ||
if (this.workspace) { | ||
// TODO(sqs): wait until workspace has been reset to apply ops | ||
this.ot.apply = (op) => this.workspace!.apply(op); | ||
this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
await this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
this.workspace.onOp(op => this.onWorkspaceOp(op)); | ||
this.workspace.onReset(newOp => this.onWorkspaceReset(newOp)); | ||
this.workspace.onWillSaveFile(params => this.onWorkspaceWillSaveFile(params)); | ||
} else { | ||
this.ot.apply = undefined; | ||
this.detachWorkspace(); | ||
} | ||
this.workspace = newWorkspace; | ||
this.ot.apply = (op) => this.workspace!.apply(op); | ||
this.workspace.onOp(op => this.onWorkspaceOp(op)); | ||
this.workspace.onReset(newOp => this.onWorkspaceReset(newOp)); | ||
this.workspace.onWillSaveFile(params => this.onWorkspaceWillSaveFile(params)); | ||
// TODO(sqs): wait until workspace has been reset to apply ops | ||
this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
await this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
} | ||
public detachWorkspace(): void { | ||
if (!this.workspace) { | ||
throw new Error("no workspace attached"); | ||
} | ||
this.workspace.onOp(undefined); | ||
this.workspace.onReset(undefined); | ||
this.ot.apply = undefined; | ||
this.workspace = undefined; | ||
} | ||
private onWorkspaceOp(op: WorkspaceOp): void { | ||
@@ -161,0 +288,0 @@ this.ot.record(op); |
@@ -24,3 +24,3 @@ import * as assert from "assert"; | ||
describe("Handler", () => { | ||
it("ref/update", () => { | ||
it("ref/update", async () => { | ||
const { server, serverOptions } = createTestServer(); | ||
@@ -56,4 +56,11 @@ | ||
// Create ref. | ||
(handler as any).onRefUpdate({ | ||
repo: "repo", | ||
ref: "ref", | ||
state: { gitBase: "c", gitBranch: "d" }, | ||
} as RefUpdateDownstreamParams); | ||
const workspace = mockWorkspace(); | ||
handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
await handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
@@ -68,3 +75,3 @@ return client.start().initialStart.then(() => { | ||
it("ack", () => { | ||
it("ack", async () => { | ||
const { server, serverOptions } = createTestServer(); | ||
@@ -76,4 +83,11 @@ | ||
// Create ref. | ||
(handler as any).onRefUpdate({ | ||
repo: "repo", | ||
ref: "ref", | ||
state: { gitBase: "c", gitBranch: "d" }, | ||
} as RefUpdateDownstreamParams); | ||
const workspace = mockWorkspace(); | ||
handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
await handler.attachWorkspace({ repo: "repo", ref: "ref" }, workspace); | ||
@@ -80,0 +94,0 @@ let ok = false; |
@@ -5,2 +5,24 @@ import { NotificationType, NotificationType0, RequestType, RequestType0 } from "vscode-jsonrpc"; | ||
/** | ||
* ErrorCode describes an error condition. | ||
* | ||
* NOTE: It should be kept in sync with the Go client/server implementation's ErrorCode list. | ||
*/ | ||
export enum ErrorCode { | ||
ErrorCodeInvalid = 0, | ||
ErrorCodeNotInitialized = 1, | ||
ErrorCodeAlreadyInitialized = 2, | ||
ErrorCodeRepoNotExists = 3, | ||
ErrorCodeRefNotExists = 4, | ||
ErrorCodeRefExists = 5, | ||
ErrorCodeRefConflict = 6, | ||
ErrorCodeRemoteNotExists = 7, | ||
ErrorCodeInvalidConfig = 8, | ||
ErrorCodeSymbolicRefInvalid = 9, | ||
ErrorCodeWorkspaceNotExists = 10, | ||
ErrorCodeWorkspaceExists = 11, | ||
ErrorCodeWorkspaceIdentifierRequired = 12, | ||
ErrorCodeRefUpdateInvalid = 13, | ||
} | ||
export enum StatusType { | ||
@@ -13,3 +35,3 @@ StatusTypeError = 1, | ||
export interface ShowStatusParams { | ||
ref?: string; // the current ref | ||
repo: string; // the repo that the status pertains to | ||
message: string; // the status text | ||
@@ -275,3 +297,3 @@ type: StatusType; // the status type | ||
export interface RefInfo extends RefIdentifier, RefBaseInfo { | ||
rev: number; | ||
rev?: number; | ||
target?: string; | ||
@@ -358,2 +380,14 @@ watchers: string[]; | ||
export interface RefUpdateSymbolicParams extends RefIdentifier { | ||
target: string; | ||
oldTarget?: string; | ||
ack?: boolean; | ||
} | ||
export interface RefUpdateSymbolicResult { } | ||
export namespace RefUpdateSymbolicRequest { | ||
export const type = new RequestType<RefUpdateSymbolicParams, RefUpdateSymbolicResult, void, void>("ref/updateSymbolic"); | ||
} | ||
// Workspace | ||
@@ -360,0 +394,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
249200
61
4806