Comparing version 0.0.47 to 0.0.48
import { EditOps } from "./textDoc"; | ||
export interface WorkspaceOp { | ||
save?: string[]; | ||
copy?: { | ||
@@ -9,3 +10,2 @@ [file: string]: string; | ||
}; | ||
save?: string[]; | ||
create?: string[]; | ||
@@ -12,0 +12,0 @@ delete?: string[]; |
@@ -13,21 +13,21 @@ "use strict"; | ||
const parts = []; | ||
if (op.copy) { | ||
if (op.copy && !emptyMap(op.copy)) { | ||
parts.push(`copy(${mapToString(op.copy, undefined)})`); | ||
} | ||
if (op.rename) { | ||
if (op.rename && !emptyMap(op.rename)) { | ||
parts.push(`rename(${mapToString(op.rename, undefined)})`); | ||
} | ||
if (op.save) { | ||
if (op.save && !emptyArray(op.save)) { | ||
parts.push(`save(${op.save.join(" ")})`); | ||
} | ||
if (op.create) { | ||
if (op.create && !emptyArray(op.create)) { | ||
parts.push(`create(${op.create.join(" ")})`); | ||
} | ||
if (op.delete) { | ||
if (op.delete && !emptyArray(op.delete)) { | ||
parts.push(`delete(${op.delete.join(" ")})`); | ||
} | ||
if (op.edit) { | ||
if (op.edit && !emptyEdit(op.edit)) { | ||
parts.push(`edit(${mapToString(op.edit, maxLengthPerItem)})`); | ||
} | ||
if (op.sel) { | ||
if (op.sel && !emptySel(op.sel)) { | ||
parts.push(`sel(${mapToString(op.sel, maxLengthPerItem)})`); | ||
@@ -181,65 +181,73 @@ } | ||
function opExists(op, path) { | ||
let [copiedFrom, copiedTo, renamedFrom, renamedTo, created, deleted, truncated, edited, selected, savedTo] = Array(10).fill(false); | ||
if (op.copy) { | ||
copiedFrom = includes(values(op.copy), path); | ||
copiedTo = includes(Object.keys(op.copy), path); | ||
if (op.sel && op.sel[path]) { | ||
return [true, true]; | ||
} | ||
if (op.rename) { | ||
renamedFrom = includes(Object.keys(op.rename), path); | ||
renamedTo = includes(values(op.rename), path); | ||
if (op.edit && op.edit[path]) { | ||
return [true, true]; | ||
} | ||
if (op.create) { | ||
created = includes(op.create, path); | ||
if (op.truncate && includes(op.truncate, path)) { | ||
return [true, true]; | ||
} | ||
if (op.delete) { | ||
deleted = includes(op.delete, path); | ||
if (op.delete && includes(op.delete, path)) { | ||
return [false, true]; | ||
} | ||
if (op.truncate) { | ||
truncated = includes(op.truncate, path); | ||
if (op.create && includes(op.create, path)) { | ||
return [true, true]; | ||
} | ||
if (op.edit) { | ||
edited = includes(Object.keys(op.edit), path); | ||
if (op.rename && includes(values(op.rename), path)) { | ||
return [true, true]; | ||
} | ||
if (op.sel) { | ||
selected = includes(Object.keys(op.sel), path); | ||
if (op.rename && includes(Object.keys(op.rename), path)) { | ||
return [false, true]; | ||
} | ||
if (op.save) { | ||
if (isFilePath(path)) { | ||
const b = fileToBufferPath(path); | ||
savedTo = includes(op.save, b); | ||
} | ||
if (op.copy && includes(values(op.copy), path)) { | ||
return [true, true]; | ||
} | ||
const exists = copiedFrom || copiedTo || renamedTo || created || truncated || edited || selected || savedTo && !(renamedFrom || deleted); | ||
const known = copiedFrom || copiedTo || renamedFrom || renamedTo || created || deleted || truncated || savedTo || edited || selected; | ||
return [exists, known]; | ||
if (op.copy && includes(Object.keys(op.copy), path)) { | ||
return [true, true]; | ||
} | ||
if (op.save && includes(op.save, path)) { | ||
return [false, true]; | ||
} | ||
if (op.save && isFilePath(path) && includes(op.save, fileToBufferPath(path))) { | ||
return [true, true]; | ||
} | ||
return [false, false]; | ||
} | ||
exports.opExists = opExists; | ||
function opExisted(op, path) { | ||
let [copiedFrom, copiedTo, renamedFrom, renamedTo, created, deleted, truncated, edited, selected] = Array(9).fill(false); | ||
if (op.copy) { | ||
copiedFrom = includes(values(op.copy), path); | ||
copiedTo = includes(Object.keys(op.copy), path); | ||
if (op.save && isFilePath(path) && includes(op.save, fileToBufferPath(path))) { | ||
return [true, true]; | ||
} | ||
if (op.rename) { | ||
renamedFrom = includes(Object.keys(op.rename), path); | ||
renamedTo = includes(values(op.rename), path); | ||
if (op.save && includes(op.save, path)) { | ||
return [false, false]; | ||
} | ||
if (op.create) { | ||
created = includes(op.create, path); | ||
if (op.copy && includes(Object.keys(op.copy), path)) { | ||
return [false, true]; | ||
} | ||
if (op.delete) { | ||
deleted = includes(op.delete, path); | ||
if (op.copy && includes(values(op.copy), path)) { | ||
return [true, true]; | ||
} | ||
if (op.truncate) { | ||
truncated = includes(op.truncate, path); | ||
if (op.rename && includes(Object.keys(op.rename), path)) { | ||
return [true, true]; | ||
} | ||
if (op.edit) { | ||
edited = includes(Object.keys(op.edit), path); | ||
if (op.rename && includes(values(op.rename), path)) { | ||
return [false, true]; | ||
} | ||
if (op.sel) { | ||
selected = includes(Object.keys(op.sel), path); | ||
if (op.create && includes(op.create, path)) { | ||
return [false, true]; | ||
} | ||
const existed = copiedFrom || renamedFrom || deleted || truncated || edited || selected && !(renamedTo || copiedTo || created); | ||
const known = copiedFrom || copiedTo || renamedFrom || renamedTo || created || deleted || truncated || edited || selected; | ||
return [existed, known]; | ||
if (op.delete && includes(op.delete, path)) { | ||
return [true, true]; | ||
} | ||
if (op.truncate && includes(op.truncate, path)) { | ||
return [true, true]; | ||
} | ||
if (op.edit && op.edit[path]) { | ||
return [true, true]; | ||
} | ||
if (op.sel && op.sel[path]) { | ||
return [true, true]; | ||
} | ||
return [false, false]; | ||
} | ||
@@ -252,2 +260,55 @@ exports.opExisted = opExisted; | ||
const renamedTo = (op.rename ? invert(op.rename) : {}); | ||
const composeSave = (op, b) => { | ||
op.save = op.save || []; | ||
if (emptySave(b)) { | ||
return; | ||
} | ||
for (const s of b) { | ||
const d = bufferToFilePath(s); | ||
const [exists, known] = opExists(op, s); | ||
if (known && !exists) { | ||
throw new Error(`save from: file ${s} does not exist`); | ||
} | ||
if (op.edit && op.edit[d]) { | ||
delete op.edit[d]; | ||
} | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
if (op.delete && includes(op.delete, d)) { | ||
op.delete = without(op.delete, d); | ||
} | ||
if (op.truncate && includes(op.truncate, d)) { | ||
op.truncate = without(op.truncate, d); | ||
} | ||
const truncated = Boolean(op.truncate && includes(op.truncate, s)); | ||
if (truncated) { | ||
op.truncate.push(d); | ||
} | ||
if (renamedTo[d]) { | ||
const r = renamedTo[d]; | ||
delete op.rename[r]; | ||
op.delete = op.delete || []; | ||
op.delete.push(r); | ||
} | ||
if (op.copy && op.copy[s]) { | ||
const cs = op.copy[s]; | ||
if (isFilePath(cs) && isBufferPath(s) && stripFileOrBufferPathPrefix(cs) === stripFileOrBufferPathPrefix(s)) { | ||
delete op.copy[s]; | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
continue; | ||
} | ||
} | ||
if (op.create && includes(op.create, d)) { | ||
op.create = without(op.create, d); | ||
} | ||
if (!truncated) { | ||
op.save.push(s); | ||
} | ||
} | ||
}; | ||
const composeCopy = (op, b) => { | ||
@@ -294,11 +355,2 @@ op.copy = op.copy || {}; | ||
} | ||
if (isFilePath(s) && isFilePath(d)) { | ||
const sb = fileToBufferPath(s); | ||
const db = fileToBufferPath(d); | ||
if (op.save && op.save.indexOf(sb) !== -1) { | ||
op.save.push(db); | ||
op.copy[db] = sb; | ||
delete op.copy[d]; | ||
} | ||
} | ||
} | ||
@@ -359,70 +411,5 @@ } | ||
} | ||
if (isFilePath(s)) { | ||
const sb = fileToBufferPath(s); | ||
const db = fileToBufferPath(d); | ||
if (op.save && includes(op.save, sb)) { | ||
op.save.push(db); | ||
op.copy = op.copy || {}; | ||
op.copy[db] = sb; | ||
op.delete = op.delete || []; | ||
op.delete.push(s); | ||
delete op.rename[s]; | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
const composeSave = (op, b) => { | ||
op.save = op.save || []; | ||
if (emptySave(b)) { | ||
return; | ||
} | ||
for (const s of b) { | ||
const d = bufferToFilePath(s); | ||
const [exists, known] = opExists(op, s); | ||
if (known && !exists) { | ||
throw new Error(`save from: file ${s} does not exist`); | ||
} | ||
if (op.edit && op.edit[d]) { | ||
delete op.edit[d]; | ||
} | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
} | ||
if (op.delete && includes(op.delete, d)) { | ||
op.delete = without(op.delete, d); | ||
} | ||
if (op.truncate && includes(op.truncate, d)) { | ||
op.truncate = without(op.truncate, d); | ||
} | ||
const truncated = Boolean(op.truncate && includes(op.truncate, s)); | ||
if (truncated) { | ||
op.truncate.push(d); | ||
} | ||
if (renamedTo[d]) { | ||
const r = renamedTo[d]; | ||
delete op.rename[r]; | ||
op.delete = op.delete || []; | ||
op.delete.push(r); | ||
} | ||
if (op.copy && op.copy[s]) { | ||
const cs = op.copy[s]; | ||
if (isFilePath(cs) && isBufferPath(s) && stripFileOrBufferPathPrefix(cs) === stripFileOrBufferPathPrefix(s)) { | ||
delete op.copy[s]; | ||
op.save = without(op.save, s); | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
continue; | ||
} | ||
} | ||
if (op.create && includes(op.create, d)) { | ||
op.create = without(op.create, d); | ||
} | ||
if (!truncated) { | ||
op.save.push(s); | ||
} | ||
} | ||
}; | ||
const bDelete = new Set(b.delete); | ||
@@ -586,5 +573,5 @@ const noDelete = new Set(); | ||
}; | ||
composeSave(op, b.save); | ||
composeCopy(op, b); | ||
composeRename(op, b); | ||
composeSave(op, b.save); | ||
composeCreate(op, b.create); | ||
@@ -596,2 +583,14 @@ composeDelete(op, b.delete); | ||
op.head = b.head || a.head; | ||
if (op.save) { | ||
const toRemove = []; | ||
for (const s of op.save) { | ||
const d = bufferToFilePath(s); | ||
if (op.delete && includes(op.delete, d)) { | ||
toRemove.push(s); | ||
} | ||
} | ||
for (const r of toRemove) { | ||
op.save = without(op.save, r); | ||
} | ||
} | ||
if (op.copy) { | ||
@@ -624,14 +623,2 @@ for (const d of Object.keys(op.copy)) { | ||
} | ||
if (op.save) { | ||
const toRemove = []; | ||
for (const s of op.save) { | ||
const d = bufferToFilePath(s); | ||
if (op.delete && includes(op.delete, d)) { | ||
toRemove.push(s); | ||
} | ||
} | ||
for (const r of toRemove) { | ||
op.save = without(op.save, r); | ||
} | ||
} | ||
return normalize(op); | ||
@@ -687,2 +674,21 @@ } | ||
}; | ||
const transformSave = (x, y, z) => { | ||
if (!x.save) { | ||
x.save = []; | ||
} | ||
if (!y.save) { | ||
y.save = []; | ||
} | ||
z.save = z.save || []; | ||
for (const s of x.save) { | ||
if (y.save && includes(y.save, s)) { | ||
continue; | ||
} | ||
const [existed, known] = opExisted(y, s); | ||
if (!existed && known) { | ||
throw new Error(`save: ${s} does not exist`); | ||
} | ||
z.save.push(s); | ||
} | ||
}; | ||
const yCopyFrom = invertBy(y.copy || {}); | ||
@@ -771,17 +777,2 @@ const newFileSrc = {}; | ||
}; | ||
const transformSave = (x, y, z) => { | ||
if (!x.save) { | ||
x.save = []; | ||
} | ||
if (!y.save) { | ||
y.save = []; | ||
} | ||
z.save = z.save || []; | ||
for (const s of x.save) { | ||
if (y.save && includes(y.save, s)) { | ||
continue; | ||
} | ||
z.save.push(s); | ||
} | ||
}; | ||
const transformCreate = (x, y, z) => { | ||
@@ -870,13 +861,9 @@ if (!x.create) { | ||
let edit = x.edit[f]; | ||
if (y.rename && y.rename[f]) { | ||
const [exists, known] = opExists(y, y.rename[f]); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${f} does not exist`); | ||
} | ||
let yd = y.rename && y.rename[f] ? y.rename[f] : f; | ||
if (y.save && includes(y.save, f)) { | ||
yd = bufferToFilePath(f); | ||
} | ||
else { | ||
const [exists, known] = opExists(y, f); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${f} does not exist`); | ||
} | ||
const [exists, known] = opExists(y, yd); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${yd} does not exist`); | ||
} | ||
@@ -918,6 +905,22 @@ if (yCopyFrom[f]) { | ||
z.edit[d] = transformEditOps(copyHACK(x.edit[f] || []), copyHACK(y.edit[d] || []), primary); | ||
delete z.edit[f]; | ||
} | ||
if (x.save && includes(x.save, f)) { | ||
z.edit[d] = y.edit[d]; | ||
if (x.copy && x.copy[f]) { | ||
z.edit[f] = x.edit[f]; | ||
} | ||
} | ||
if (y.edit && y.edit[d]) { | ||
let z1 = transformEditOps(copyHACK(z.edit[f] || []), copyHACK(y.edit[d] || []), primary); | ||
if (!y.save || !includes(y.save, f)) { | ||
z1 = textDoc_1.composeEdits(copyHACK(y.edit[d]), z1); | ||
} | ||
if (z1 && !emptyArray(z1)) { | ||
z.edit[f] = z1; | ||
} | ||
else { | ||
delete z.edit[f]; | ||
} | ||
} | ||
} | ||
@@ -929,5 +932,18 @@ } | ||
if (x.save && includes(x.save, s)) { | ||
z.edit[f] = transformEditOps(copyHACK(x.edit[f] || []), copyHACK(y.edit[s] || []), primary); | ||
const z1 = transformEditOps(copyHACK(z.edit[f] || []), copyHACK(y.edit[f] || []), primary); | ||
z.edit[f] = textDoc_1.composeEdits(copyHACK(y.edit[f] || []), z1); | ||
let z1 = transformEditOps(copyHACK(x.edit[f] || []), copyHACK((y.edit && y.edit[s]) || []), primary); | ||
if (!y.edit || !y.edit[s]) { | ||
z1 = transformEditOps(z1, copyHACK((y.edit && y.edit[f]) || []), primary); | ||
} | ||
if (!y.save || !includes(y.save, s)) { | ||
z1 = textDoc_1.composeEdits(copyHACK((y.edit && y.edit[f]) || []), z1); | ||
} | ||
z.edit[f] = z1; | ||
if (x.copy && x.copy[s]) { | ||
if (y.edit && y.edit[f]) { | ||
z.edit[s] = transformEditOps(copyHACK(x.edit[s] || []), copyHACK(y.edit[f]), primary); | ||
} | ||
if (!y.save || !includes(y.save, s)) { | ||
z.edit[s] = textDoc_1.composeEdits(copyHACK(y.edit[f] || []), copyHACK(z.edit[s] || [])); | ||
} | ||
} | ||
} | ||
@@ -958,5 +974,5 @@ } | ||
const z = {}; | ||
transformSave(x, y, z); | ||
transformCopy(x, y, z); | ||
transformRename(x, y, z); | ||
transformSave(x, y, z); | ||
transformCreate(x, y, z); | ||
@@ -963,0 +979,0 @@ transformDelete(x, y, z); |
@@ -24,2 +24,3 @@ import { CancellationToken, Disposable, Event, GenericNotificationHandler, GenericRequestHandler, Logger, Message, MessageReader, MessageType as RPCMessageType, MessageWriter, NotificationHandler, NotificationHandler0, NotificationType, NotificationType0, RequestHandler, RequestHandler0, RequestType, RequestType0, ResponseError, Trace } from "vscode-jsonrpc"; | ||
export declare enum State { | ||
Initial = 0, | ||
Stopped = 1, | ||
@@ -26,0 +27,0 @@ Running = 2, |
@@ -12,2 +12,3 @@ "use strict"; | ||
(function (State) { | ||
State[State["Initial"] = 0] = "Initial"; | ||
State[State["Stopped"] = 1] = "Stopped"; | ||
@@ -34,2 +35,3 @@ State[State["Running"] = 2] = "Running"; | ||
this.configuration = clientOptions.configuration || {}; | ||
this.stateChangeEmitter = new vscode_jsonrpc_1.Emitter(); | ||
this.state = ClientState.Initial; | ||
@@ -45,3 +47,2 @@ this.connectionPromise = undefined; | ||
this.telemetryEmitter = new vscode_jsonrpc_1.Emitter(); | ||
this.stateChangeEmitter = new vscode_jsonrpc_1.Emitter(); | ||
this.tracer = { | ||
@@ -65,3 +66,6 @@ log: (message, data) => { | ||
getPublicState() { | ||
if (this.state === ClientState.Running) { | ||
if (this.state === ClientState.Initial) { | ||
return State.Initial; | ||
} | ||
else if (this.state === ClientState.Running) { | ||
return State.Running; | ||
@@ -68,0 +72,0 @@ } |
@@ -33,2 +33,3 @@ import { Event } from "vscode-jsonrpc"; | ||
attachWorkspace(refID: RefIdentifier, workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void>; | ||
resetWorkspaceRefState(refID: RefIdentifier, workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void>; | ||
private repoWatch(params); | ||
@@ -35,0 +36,0 @@ queryRefInfo(refID: RefIdentifier): Thenable<RefInfoResult>; |
@@ -48,2 +48,7 @@ "use strict"; | ||
} | ||
resetWorkspaceRefState(refID, workspace, mergeStrategy) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this.getRepo(refID.repo).getRef(refID.ref).resetWorkspaceRefState(workspace, mergeStrategy); | ||
}); | ||
} | ||
repoWatch(params) { | ||
@@ -177,2 +182,5 @@ return this.remoteClient.onReady().then(() => { | ||
} | ||
resetWorkspaceRefState(workspace, mergeStrategy) { | ||
return this.targetHandler.resetWorkspaceRefState(workspace, mergeStrategy); | ||
} | ||
} | ||
@@ -240,2 +248,23 @@ class NonSymbolicRefHandler { | ||
} | ||
resetWorkspaceRefState(workspace, mergeStrategy) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
switch (mergeStrategy) { | ||
case MergeStrategy.LocalClobbersRemote: | ||
this.state = yield this.remoteClient.sendRequest(protocol_1.WorkspaceResetRequest.type, { | ||
dir: this.refID.repo, | ||
ref: this.refID.ref, | ||
bufferFiles: workspace.allBufferFiles(), | ||
}); | ||
yield this.ot.reset(this.state.history); | ||
break; | ||
case MergeStrategy.RemoteClobbersLocal: | ||
yield this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
yield workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
break; | ||
default: | ||
return Promise.reject(new Error(`unknown merge strategy: ${mergeStrategy}`)); | ||
} | ||
return Promise.resolve(void 0); | ||
}); | ||
} | ||
attachWorkspace(newWorkspace, mergeStrategy) { | ||
@@ -258,18 +287,3 @@ return __awaiter(this, void 0, void 0, function* () { | ||
this.workspace.onWillSaveFile(params => this.onWorkspaceWillSaveFile(params)); | ||
switch (mergeStrategy) { | ||
case MergeStrategy.LocalClobbersRemote: | ||
this.state = yield this.remoteClient.sendRequest(protocol_1.WorkspaceResetRequest.type, { | ||
dir: this.refID.repo, | ||
ref: this.refID.ref, | ||
bufferFiles: this.workspace.allBufferFiles(), | ||
}); | ||
yield this.ot.reset(this.state.history); | ||
break; | ||
case MergeStrategy.RemoteClobbersLocal: | ||
yield this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
yield this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
break; | ||
default: | ||
return Promise.reject(new Error(`unknown merge strategy: ${mergeStrategy} `)); | ||
} | ||
yield this.resetWorkspaceRefState(this.workspace, mergeStrategy); | ||
return Promise.resolve(void 0); | ||
@@ -276,0 +290,0 @@ }); |
{ | ||
"name": "libzap", | ||
"version": "0.0.47", | ||
"version": "0.0.48", | ||
"description": "JavaScript library for Zap", | ||
@@ -5,0 +5,0 @@ "license": "none", |
@@ -444,3 +444,3 @@ // Code generated by ot/gen/gen-ts.go; DO NOT EDIT! | ||
}, | ||
"copy save-edited file": { | ||
"copy save-edited fileC": { | ||
"a": { | ||
@@ -450,2 +450,5 @@ "save": [ | ||
], | ||
"copy": { | ||
"#f1": "/f1" | ||
}, | ||
"edit": { | ||
@@ -463,9 +466,9 @@ "#f1": [ | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"copy": { | ||
"#f2": "#f1" | ||
"#f1": "/f1", | ||
"/f2": "/f1" | ||
}, | ||
"save": [ | ||
"#f1", | ||
"#f2" | ||
], | ||
"edit": { | ||
@@ -490,11 +493,11 @@ "#f1": [ | ||
"want": { | ||
"save": [ | ||
"#f" | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"save": [ | ||
"#f" | ||
] | ||
} | ||
} | ||
}, | ||
"copy saved file": { | ||
"copy saved fileC": { | ||
"a": { | ||
@@ -511,9 +514,8 @@ "save": [ | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"copy": { | ||
"#f2": "#f1" | ||
}, | ||
"save": [ | ||
"#f1", | ||
"#f2" | ||
] | ||
"/f2": "/f1" | ||
} | ||
} | ||
@@ -1508,8 +1510,8 @@ }, | ||
"a": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"rename": { | ||
"/f1": "/f2" | ||
}, | ||
"save": [ | ||
"#f1" | ||
] | ||
} | ||
}, | ||
@@ -1944,2 +1946,33 @@ "b": { | ||
} | ||
}, | ||
"wantErr": true | ||
}, | ||
"edit saved-copied buffer": { | ||
"a": { | ||
"save": [ | ||
"#f1" | ||
] | ||
}, | ||
"b": { | ||
"copy": { | ||
"#f1": "/f1" | ||
}, | ||
"edit": { | ||
"#f1": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"copy": { | ||
"#f1": "/f1" | ||
}, | ||
"edit": { | ||
"#f1": [ | ||
"x" | ||
] | ||
} | ||
} | ||
@@ -2118,3 +2151,3 @@ }, | ||
}, | ||
"rename saved file": { | ||
"rename saved fileC": { | ||
"a": { | ||
@@ -2131,11 +2164,8 @@ "save": [ | ||
"want": { | ||
"copy": { | ||
"#f2": "#f1" | ||
}, | ||
"save": [ | ||
"#f2" | ||
"#f1" | ||
], | ||
"delete": [ | ||
"/f1" | ||
] | ||
"rename": { | ||
"/f1": "/f2" | ||
} | ||
} | ||
@@ -2453,8 +2483,8 @@ }, | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"copy": { | ||
"/f2": "/f1" | ||
}, | ||
"save": [ | ||
"#f1" | ||
] | ||
} | ||
} | ||
@@ -2503,3 +2533,3 @@ }, | ||
}, | ||
"save created-edited file": { | ||
"save created-edited fileC": { | ||
"a": { | ||
@@ -2525,5 +2555,2 @@ "create": [ | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
], | ||
"/f": [ | ||
@@ -2552,3 +2579,3 @@ "x" | ||
}, | ||
"save edited buffer": { | ||
"save edited bufferC": { | ||
"a": { | ||
@@ -2571,5 +2598,2 @@ "edit": { | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
], | ||
"/f": [ | ||
@@ -2599,3 +2623,3 @@ "x" | ||
}, | ||
"save renamed and edited buffer": { | ||
"save renamed and edited bufferC": { | ||
"a": { | ||
@@ -2624,5 +2648,2 @@ "rename": { | ||
"edit": { | ||
"#f2": [ | ||
"x" | ||
], | ||
"/f2": [ | ||
@@ -2666,8 +2687,8 @@ "x" | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"rename": { | ||
"/f1": "/f2" | ||
}, | ||
"save": [ | ||
"#f1" | ||
] | ||
} | ||
} | ||
@@ -2727,4 +2748,10 @@ }, | ||
}, | ||
"save-edit edited buffer": { | ||
"save-copy-edit x2C": { | ||
"a": { | ||
"save": [ | ||
"#f" | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
@@ -2740,2 +2767,5 @@ "#f": [ | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
@@ -2752,2 +2782,5 @@ "#f": [ | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
@@ -2763,3 +2796,3 @@ "#f": [ | ||
}, | ||
"save-edit file with edited buffer": { | ||
"save-edit edited bufferC": { | ||
"a": { | ||
@@ -2776,4 +2809,7 @@ "edit": { | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"/f": [ | ||
"#f": [ | ||
1, | ||
@@ -2788,7 +2824,40 @@ "y" | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
"xy" | ||
], | ||
"/f": [ | ||
"x" | ||
] | ||
} | ||
} | ||
}, | ||
"save-edit file with edited bufferC": { | ||
"a": { | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"b": { | ||
"save": [ | ||
"#f" | ||
], | ||
"edit": { | ||
"/f": [ | ||
1, | ||
"y" | ||
] | ||
} | ||
}, | ||
"want": { | ||
"save": [ | ||
"#f" | ||
], | ||
"edit": { | ||
"/f": [ | ||
"xy" | ||
@@ -2799,3 +2868,3 @@ ] | ||
}, | ||
"save-rename edited buffer": { | ||
"save-rename edited bufferC": { | ||
"a": { | ||
@@ -2809,22 +2878,19 @@ "edit": { | ||
"b": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"rename": { | ||
"/f1": "/f2" | ||
}, | ||
} | ||
}, | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
] | ||
}, | ||
"want": { | ||
], | ||
"rename": { | ||
"/f1": "/f2" | ||
}, | ||
"save": [ | ||
"#f1" | ||
], | ||
"edit": { | ||
"#f1": [ | ||
"/f2": [ | ||
"x" | ||
], | ||
"/f1": [ | ||
"x" | ||
] | ||
@@ -3329,10 +3395,4 @@ } | ||
}, | ||
"want": { | ||
"save": [ | ||
"#f1" | ||
], | ||
"truncate": [ | ||
"#f1" | ||
] | ||
} | ||
"want": {}, | ||
"wantErr": true | ||
}, | ||
@@ -3609,2 +3669,38 @@ "truncate saved file": { | ||
}, | ||
"copy, edit buffer implying existing dest": { | ||
"a": { | ||
"copy": { | ||
"#f": "/f" | ||
} | ||
}, | ||
"b": { | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"a1": {}, | ||
"b1": {}, | ||
"wantErr": true, | ||
"commutative": true | ||
}, | ||
"copy, edit implying existing dest": { | ||
"a": { | ||
"copy": { | ||
"/f2": "/f1" | ||
} | ||
}, | ||
"b": { | ||
"edit": { | ||
"/f2": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"a1": {}, | ||
"b1": {}, | ||
"wantErr": true, | ||
"commutative": true | ||
}, | ||
"copy-edit(src)-edit(dest), edit": { | ||
@@ -3708,2 +3804,78 @@ "a": { | ||
}, | ||
"copy-edit, copy-edit": { | ||
"a": { | ||
"copy": { | ||
"/f2": "/f1" | ||
}, | ||
"edit": { | ||
"/f2": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"b": { | ||
"copy": { | ||
"/f2": "/f1" | ||
}, | ||
"edit": { | ||
"/f2": [ | ||
"y" | ||
] | ||
} | ||
}, | ||
"a1": { | ||
"edit": { | ||
"/f2": [ | ||
"x", | ||
1 | ||
] | ||
} | ||
}, | ||
"b1": { | ||
"edit": { | ||
"/f2": [ | ||
1, | ||
"y" | ||
] | ||
} | ||
} | ||
}, | ||
"copy-edit, copy-edit of buffer": { | ||
"a": { | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"b": { | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"y" | ||
] | ||
} | ||
}, | ||
"a1": { | ||
"edit": { | ||
"#f": [ | ||
"x", | ||
1 | ||
] | ||
} | ||
}, | ||
"b1": { | ||
"edit": { | ||
"#f": [ | ||
1, | ||
"y" | ||
] | ||
} | ||
} | ||
}, | ||
"copy-edit, edit": { | ||
@@ -4568,2 +4740,18 @@ "a": { | ||
}, | ||
"save, copy destC": { | ||
"a": { | ||
"save": [ | ||
"#f" | ||
] | ||
}, | ||
"b": { | ||
"copy": { | ||
"#f": "/f" | ||
} | ||
}, | ||
"a1": {}, | ||
"b1": {}, | ||
"wantErr": true, | ||
"commutative": true | ||
}, | ||
"save, create dest": { | ||
@@ -4585,3 +4773,3 @@ "a": { | ||
}, | ||
"save, edit": { | ||
"save, editC": { | ||
"a": { | ||
@@ -4606,5 +4794,2 @@ "save": [ | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
], | ||
"/f": [ | ||
@@ -4617,3 +4802,3 @@ "x" | ||
}, | ||
"save-edit buffer and file, edit file": { | ||
"save-edit buffer and file, edit fileC": { | ||
"a": { | ||
@@ -4623,2 +4808,5 @@ "save": [ | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
@@ -4644,5 +4832,8 @@ "#f": [ | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
"xz" | ||
], | ||
@@ -4656,2 +4847,6 @@ "/f": [ | ||
"edit": { | ||
"#f": [ | ||
1, | ||
"z" | ||
], | ||
"/f": [ | ||
@@ -4664,3 +4859,3 @@ 1, | ||
}, | ||
"save-edit buffer, edit file": { | ||
"save-edit buffer and file, save-edit bufferC": { | ||
"a": { | ||
@@ -4670,5 +4865,11 @@ "save": [ | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
], | ||
"/f": [ | ||
"y" | ||
] | ||
@@ -4678,4 +4879,56 @@ } | ||
"b": { | ||
"save": [ | ||
"#f" | ||
], | ||
"edit": { | ||
"/f": [ | ||
"z" | ||
] | ||
} | ||
}, | ||
"a1": { | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x", | ||
1 | ||
], | ||
"/f": [ | ||
"y", | ||
1 | ||
] | ||
} | ||
}, | ||
"b1": { | ||
"edit": { | ||
"#f": [ | ||
1, | ||
"z" | ||
], | ||
"/f": [ | ||
1, | ||
"z" | ||
] | ||
} | ||
} | ||
}, | ||
"save-edit buffer, edit fileC": { | ||
"a": { | ||
"save": [ | ||
"#f" | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
] | ||
} | ||
}, | ||
"b": { | ||
"edit": { | ||
"/f": [ | ||
"y" | ||
@@ -4689,5 +4942,8 @@ ] | ||
], | ||
"copy": { | ||
"#f": "/f" | ||
}, | ||
"edit": { | ||
"#f": [ | ||
"x" | ||
"xy" | ||
], | ||
@@ -4701,2 +4957,6 @@ "/f": [ | ||
"edit": { | ||
"#f": [ | ||
1, | ||
"y" | ||
], | ||
"/f": [ | ||
@@ -4708,3 +4968,3 @@ "y" | ||
}, | ||
"save-edit file, edit buffer": { | ||
"save-edit file, edit bufferC": { | ||
"a": { | ||
@@ -4740,5 +5000,2 @@ "save": [ | ||
"edit": { | ||
"#f": [ | ||
"y" | ||
], | ||
"/f": [ | ||
@@ -4751,3 +5008,3 @@ 1, | ||
}, | ||
"save-edit file, edit file": { | ||
"save-edit file, edit fileC": { | ||
"a": { | ||
@@ -4754,0 +5011,0 @@ "save": [ |
@@ -13,5 +13,5 @@ import * as cloneDeep from "lodash/cloneDeep"; | ||
export interface WorkspaceOp { | ||
save?: string[]; | ||
copy?: { [file: string]: string }; | ||
rename?: { [file: string]: string }; | ||
save?: string[]; | ||
create?: string[]; | ||
@@ -39,21 +39,21 @@ delete?: string[]; | ||
const parts: string[] = []; | ||
if (op.copy) { | ||
if (op.copy && !emptyMap(op.copy)) { | ||
parts.push(`copy(${mapToString(op.copy, undefined)})`); | ||
} | ||
if (op.rename) { | ||
if (op.rename && !emptyMap(op.rename)) { | ||
parts.push(`rename(${mapToString(op.rename, undefined)})`); | ||
} | ||
if (op.save) { | ||
if (op.save && !emptyArray(op.save)) { | ||
parts.push(`save(${op.save.join(" ")})`); | ||
} | ||
if (op.create) { | ||
if (op.create && !emptyArray(op.create)) { | ||
parts.push(`create(${op.create.join(" ")})`); | ||
} | ||
if (op.delete) { | ||
if (op.delete && !emptyArray(op.delete)) { | ||
parts.push(`delete(${op.delete.join(" ")})`); | ||
} | ||
if (op.edit) { | ||
if (op.edit && !emptyEdit(op.edit)) { | ||
parts.push(`edit(${mapToString(op.edit, maxLengthPerItem)})`); | ||
} | ||
if (op.sel) { | ||
if (op.sel && !emptySel(op.sel)) { | ||
parts.push(`sel(${mapToString(op.sel, maxLengthPerItem)})`); | ||
@@ -87,3 +87,3 @@ } | ||
function emptyArray(v?: string[]): v is undefined { | ||
function emptyArray(v?: any[]): v is undefined { | ||
return v === undefined || (typeof v.length === "number" && v.length === 0); | ||
@@ -193,67 +193,29 @@ } | ||
export function opExists(op: WorkspaceOp, path: string): [boolean, boolean] { | ||
let [copiedFrom, copiedTo, renamedFrom, renamedTo, created, deleted, truncated, edited, selected, savedTo] = Array(10).fill(false); | ||
if (op.copy) { | ||
copiedFrom = includes(values(op.copy), path); | ||
copiedTo = includes(Object.keys(op.copy), path); | ||
} | ||
if (op.rename) { | ||
renamedFrom = includes(Object.keys(op.rename), path); | ||
renamedTo = includes(values(op.rename), path); | ||
} | ||
if (op.create) { | ||
created = includes(op.create, path); | ||
} | ||
if (op.delete) { | ||
deleted = includes(op.delete, path); | ||
} | ||
if (op.truncate) { | ||
truncated = includes(op.truncate, path); | ||
} | ||
if (op.edit) { | ||
edited = includes(Object.keys(op.edit), path); | ||
} | ||
if (op.sel) { | ||
selected = includes(Object.keys(op.sel), path); | ||
} | ||
if (op.save) { | ||
if (isFilePath(path)) { | ||
const b = fileToBufferPath(path); | ||
savedTo = includes(op.save, b); | ||
} | ||
} | ||
const exists = copiedFrom || copiedTo || renamedTo || created || truncated || edited || selected || savedTo && !(renamedFrom || deleted); | ||
const known = copiedFrom || copiedTo || renamedFrom || renamedTo || created || deleted || truncated || savedTo || edited || selected; | ||
return [exists, known]; | ||
if (op.sel && op.sel[path]) { return [true, true]; } | ||
if (op.edit && op.edit[path]) { return [true, true]; } | ||
if (op.truncate && includes(op.truncate, path)) { return [true, true]; } | ||
if (op.delete && includes(op.delete, path)) { return [false, true]; } | ||
if (op.create && includes(op.create, path)) { return [true, true]; } | ||
if (op.rename && includes(values(op.rename), path)) { return [true, true]; } | ||
if (op.rename && includes(Object.keys(op.rename), path)) { return [false, true]; } | ||
if (op.copy && includes(values(op.copy), path)) { return [true, true]; } | ||
if (op.copy && includes(Object.keys(op.copy), path)) { return [true, true]; } | ||
if (op.save && includes(op.save, path)) { return [false, true]; } | ||
if (op.save && isFilePath(path) && includes(op.save, fileToBufferPath(path))) { return [true, true]; } | ||
return [false, false]; | ||
} | ||
export function opExisted(op: WorkspaceOp, path: string): [boolean, boolean] { | ||
let [copiedFrom, copiedTo, renamedFrom, renamedTo, created, deleted, truncated, edited, selected] = Array(9).fill(false); | ||
if (op.copy) { | ||
copiedFrom = includes(values(op.copy), path); | ||
copiedTo = includes(Object.keys(op.copy), path); | ||
} | ||
if (op.rename) { | ||
renamedFrom = includes(Object.keys(op.rename), path); | ||
renamedTo = includes(values(op.rename), path); | ||
} | ||
if (op.create) { | ||
created = includes(op.create, path); | ||
} | ||
if (op.delete) { | ||
deleted = includes(op.delete, path); | ||
} | ||
if (op.truncate) { | ||
truncated = includes(op.truncate, path); | ||
} | ||
if (op.edit) { | ||
edited = includes(Object.keys(op.edit), path); | ||
} | ||
if (op.sel) { | ||
selected = includes(Object.keys(op.sel), path); | ||
} | ||
const existed = copiedFrom || renamedFrom || deleted || truncated || edited || selected && !(renamedTo || copiedTo || created); | ||
const known = copiedFrom || copiedTo || renamedFrom || renamedTo || created || deleted || truncated || edited || selected; | ||
return [existed, known]; | ||
if (op.save && isFilePath(path) && includes(op.save, fileToBufferPath(path))) { return [true, true]; } | ||
if (op.save && includes(op.save, path)) { return [false, false]; } | ||
if (op.copy && includes(Object.keys(op.copy), path)) { return [false, true]; } | ||
if (op.copy && includes(values(op.copy), path)) { return [true, true]; } | ||
if (op.rename && includes(Object.keys(op.rename), path)) { return [true, true]; } | ||
if (op.rename && includes(values(op.rename), path)) { return [false, true]; } | ||
if (op.create && includes(op.create, path)) { return [false, true]; } | ||
if (op.delete && includes(op.delete, path)) { return [true, true]; } | ||
if (op.truncate && includes(op.truncate, path)) { return [true, true]; } | ||
if (op.edit && op.edit[path]) { return [true, true]; } | ||
if (op.sel && op.sel[path]) { return [true, true]; } | ||
return [false, false]; | ||
} | ||
@@ -271,2 +233,57 @@ | ||
// tslint:disable-next-line no-shadowed-variable | ||
const composeSave = (op: WorkspaceOp, b: FileSaves | undefined): void => { | ||
op.save = op.save || []; | ||
if (emptySave(b)) { return; } | ||
for (const s of b) { | ||
const d = bufferToFilePath(s); | ||
const [exists, known] = opExists(op, s); | ||
if (known && !exists) { | ||
throw new Error(`save from: file ${s} does not exist`); | ||
} | ||
if (op.edit && op.edit[d]) { | ||
delete op.edit[d]; | ||
} | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
if (op.delete && includes(op.delete, d)) { | ||
op.delete = without(op.delete, d); | ||
} | ||
if (op.truncate && includes(op.truncate, d)) { | ||
op.truncate = without(op.truncate, d); | ||
} | ||
const truncated = Boolean(op.truncate && includes(op.truncate, s)); | ||
if (truncated) { | ||
op.truncate!.push(d); | ||
} | ||
if (renamedTo[d]) { | ||
const r = renamedTo[d]; | ||
delete op.rename![r]; | ||
op.delete = op.delete || []; | ||
op.delete.push(r); | ||
} | ||
if (op.copy && op.copy[s]) { | ||
const cs = op.copy[s]; | ||
if (isFilePath(cs) && isBufferPath(s) && stripFileOrBufferPathPrefix(cs) === stripFileOrBufferPathPrefix(s)) { | ||
delete op.copy[s]; | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
continue; | ||
} | ||
} | ||
if (op.create && includes(op.create, d)) { | ||
op.create = without(op.create, d); | ||
} | ||
if (!truncated) { | ||
op.save.push(s); | ||
} | ||
} | ||
}; | ||
// tslint:disable-next-line no-shadowed-variable | ||
const composeCopy = (op: WorkspaceOp, b: WorkspaceOp): void => { | ||
@@ -313,12 +330,2 @@ op.copy = op.copy || {}; | ||
} | ||
if (isFilePath(s) && isFilePath(d)) { | ||
const sb = fileToBufferPath(s); | ||
const db = fileToBufferPath(d); | ||
if (op.save && op.save.indexOf(sb) !== -1) { | ||
op.save.push(db); | ||
op.copy[db] = sb; | ||
delete op.copy[d]; | ||
} | ||
} | ||
} | ||
@@ -386,15 +393,2 @@ } | ||
} | ||
if (isFilePath(s)) { | ||
const sb = fileToBufferPath(s); | ||
const db = fileToBufferPath(d); | ||
if (op.save && includes(op.save, sb)) { | ||
op.save.push(db); | ||
op.copy = op.copy || {}; | ||
op.copy[db] = sb; | ||
op.delete = op.delete || []; | ||
op.delete.push(s); | ||
delete op.rename[s]; | ||
} | ||
} | ||
} | ||
@@ -404,57 +398,2 @@ } | ||
// tslint:disable-next-line no-shadowed-variable | ||
const composeSave = (op: WorkspaceOp, b: FileSaves | undefined): void => { | ||
op.save = op.save || []; | ||
if (emptySave(b)) { return; } | ||
for (const s of b) { | ||
const d = bufferToFilePath(s); | ||
const [exists, known] = opExists(op, s); | ||
if (known && !exists) { | ||
throw new Error(`save from: file ${s} does not exist`); | ||
} | ||
if (op.edit && op.edit[d]) { | ||
delete op.edit[d]; | ||
} | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
} | ||
if (op.delete && includes(op.delete, d)) { | ||
op.delete = without(op.delete, d); | ||
} | ||
if (op.truncate && includes(op.truncate, d)) { | ||
op.truncate = without(op.truncate, d); | ||
} | ||
const truncated = Boolean(op.truncate && includes(op.truncate, s)); | ||
if (truncated) { | ||
op.truncate!.push(d); | ||
} | ||
if (renamedTo[d]) { | ||
const r = renamedTo[d]; | ||
delete op.rename![r]; | ||
op.delete = op.delete || []; | ||
op.delete.push(r); | ||
} | ||
if (op.copy && op.copy[s]) { | ||
const cs = op.copy[s]; | ||
if (isFilePath(cs) && isBufferPath(s) && stripFileOrBufferPathPrefix(cs) === stripFileOrBufferPathPrefix(s)) { | ||
delete op.copy[s]; | ||
op.save = without(op.save, s); | ||
if (op.edit && op.edit[s]) { | ||
op.edit[d] = op.edit[s]; | ||
delete op.edit[s]; | ||
} | ||
continue; | ||
} | ||
} | ||
if (op.create && includes(op.create, d)) { | ||
op.create = without(op.create, d); | ||
} | ||
if (!truncated) { | ||
op.save.push(s); | ||
} | ||
} | ||
}; | ||
const bDelete = new Set<string>(b.delete); | ||
@@ -608,5 +547,5 @@ const noDelete = new Set<string>(); | ||
composeSave(op, b.save); | ||
composeCopy(op, b); | ||
composeRename(op, b); | ||
composeSave(op, b.save); | ||
composeCreate(op, b.create); | ||
@@ -620,2 +559,14 @@ composeDelete(op, b.delete); | ||
// Simplify. | ||
if (op.save) { | ||
const toRemove: string[] = []; | ||
for (const s of op.save) { | ||
const d = bufferToFilePath(s); | ||
if (op.delete && includes(op.delete, d)) { | ||
toRemove.push(s); | ||
} | ||
} | ||
for (const r of toRemove) { | ||
op.save = without(op.save, r); | ||
} | ||
} | ||
if (op.copy) { | ||
@@ -648,14 +599,2 @@ for (const d of Object.keys(op.copy)) { | ||
} | ||
if (op.save) { | ||
const toRemove: string[] = []; | ||
for (const s of op.save) { | ||
const d = bufferToFilePath(s); | ||
if (op.delete && includes(op.delete, d)) { | ||
toRemove.push(s); | ||
} | ||
} | ||
for (const r of toRemove) { | ||
op.save = without(op.save, r); | ||
} | ||
} | ||
return normalize(op); | ||
@@ -714,2 +653,20 @@ }; | ||
// tslint:disable-next-line no-shadowed-variable | ||
const transformSave = (x: WorkspaceOp, y: WorkspaceOp, z: WorkspaceOp): void => { | ||
if (!x.save) { x.save = []; } | ||
if (!y.save) { y.save = []; } | ||
z.save = z.save || []; | ||
for (const s of x.save) { | ||
if (y.save && includes(y.save, s)) { | ||
continue; | ||
} | ||
const [existed, known] = opExisted(y, s); | ||
if (!existed && known) { | ||
throw new Error(`save: ${s} does not exist`); | ||
} | ||
z.save.push(s); | ||
} | ||
}; | ||
const yCopyFrom = invertBy(y.copy || {}) as { [key: string]: string[] }; | ||
@@ -793,17 +750,2 @@ const newFileSrc = {} as { [key: string]: string }; | ||
// tslint:disable-next-line no-shadowed-variable | ||
const transformSave = (x: WorkspaceOp, y: WorkspaceOp, z: WorkspaceOp): void => { | ||
if (!x.save) { x.save = []; } | ||
if (!y.save) { y.save = []; } | ||
z.save = z.save || []; | ||
for (const s of x.save) { | ||
if (y.save && includes(y.save, s)) { | ||
continue; | ||
} | ||
z.save.push(s); | ||
} | ||
}; | ||
// tslint:disable-next-line no-shadowed-variable | ||
const transformCreate = (x: WorkspaceOp, y: WorkspaceOp, z: WorkspaceOp): void => { | ||
@@ -887,13 +829,11 @@ if (!x.create) { x.create = []; } | ||
if (y.rename && y.rename[f]) { | ||
const [exists, known] = opExists(y, y.rename[f]); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${f} does not exist`); | ||
} | ||
} else { | ||
const [exists, known] = opExists(y, f); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${f} does not exist`); | ||
} | ||
// Follow renames and saves to derive the new filename. | ||
let yd = y.rename && y.rename[f] ? y.rename[f] : f; | ||
if (y.save && includes(y.save, f)) { | ||
yd = bufferToFilePath(f); | ||
} | ||
const [exists, known] = opExists(y, yd); | ||
if (known && !exists) { | ||
throw new Error(`edit: file ${yd} does not exist`); | ||
} | ||
@@ -935,6 +875,21 @@ if (yCopyFrom[f]) { | ||
z.edit[d] = transformEditOps(copyHACK(x.edit[f] || []), copyHACK(y.edit[d] || []), primary); | ||
delete z.edit[f]; | ||
} | ||
if (x.save && includes(x.save, f)) { | ||
z.edit[d] = y.edit[d]; | ||
if (x.copy && x.copy[f]) { | ||
z.edit[f] = x.edit[f]; | ||
} | ||
} | ||
if (y.edit && y.edit[d]) { | ||
let z1 = transformEditOps(copyHACK(z.edit[f] || []), copyHACK(y.edit[d] || []), primary); | ||
if (!y.save || !includes(y.save, f)) { | ||
z1 = composeEdits(copyHACK(y.edit[d]), z1); | ||
} | ||
if (z1 && !emptyArray(z1)) { | ||
z.edit[f] = z1; | ||
} else { | ||
delete z.edit[f]; | ||
} | ||
} | ||
} | ||
@@ -947,5 +902,21 @@ } | ||
if (x.save && includes(x.save, s)) { | ||
z.edit[f] = transformEditOps(copyHACK(x.edit[f] || []), copyHACK(y.edit[s] || []), primary); | ||
const z1 = transformEditOps(copyHACK(z.edit[f] || []), copyHACK(y.edit[f] || []), primary); | ||
z.edit[f] = composeEdits(copyHACK(y.edit[f] || []), z1); | ||
let z1 = transformEditOps(copyHACK(x.edit[f] || []), copyHACK((y.edit && y.edit[s]) || []), primary); | ||
if (!y.edit || !y.edit[s]) { | ||
z1 = transformEditOps(z1, copyHACK((y.edit && y.edit[f]) || []), primary); | ||
} | ||
if (!y.save || !includes(y.save, s)) { | ||
z1 = composeEdits(copyHACK((y.edit && y.edit[f]) || []), z1); | ||
} | ||
z.edit[f] = z1; | ||
if (x.copy && x.copy[s]) { | ||
if (y.edit && y.edit[f]) { | ||
z.edit[s] = transformEditOps(copyHACK(x.edit[s] || []), copyHACK(y.edit[f]), primary); | ||
} | ||
if (!y.save || !includes(y.save, s)) { | ||
z.edit[s] = composeEdits(copyHACK(y.edit[f] || []), copyHACK(z.edit[s] || [])); | ||
} | ||
} | ||
} | ||
@@ -975,5 +946,5 @@ } | ||
const z: WorkspaceOp = {}; | ||
transformSave(x, y, z); | ||
transformCopy(x, y, z); | ||
transformRename(x, y, z); | ||
transformSave(x, y, z); | ||
transformCreate(x, y, z); | ||
@@ -980,0 +951,0 @@ transformDelete(x, y, z); |
@@ -37,2 +37,3 @@ import * as is from "../util/is"; | ||
export enum State { | ||
Initial = 0, | ||
Stopped = 1, | ||
@@ -95,2 +96,3 @@ Running = 2, | ||
this.stateChangeEmitter = new Emitter<StateChangeEvent>(); | ||
this.state = ClientState.Initial; | ||
@@ -108,3 +110,2 @@ this.connectionPromise = undefined; | ||
this.telemetryEmitter = new Emitter<any>(); | ||
this.stateChangeEmitter = new Emitter<StateChangeEvent>(); | ||
this.tracer = { | ||
@@ -131,3 +132,5 @@ log: (message: string, data?: string) => { | ||
private getPublicState(): State { | ||
if (this.state === ClientState.Running) { | ||
if (this.state === ClientState.Initial) { | ||
return State.Initial; | ||
} else if (this.state === ClientState.Running) { | ||
return State.Running; | ||
@@ -134,0 +137,0 @@ } else { |
@@ -87,2 +87,6 @@ import { Emitter, Event } from "vscode-jsonrpc"; | ||
public async resetWorkspaceRefState(refID: RefIdentifier, workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void> { | ||
return this.getRepo(refID.repo).getRef(refID.ref).resetWorkspaceRefState(workspace, mergeStrategy); | ||
} | ||
/** | ||
@@ -181,2 +185,3 @@ * repoWatch starts watching a repo. It removes any previous watch | ||
interface RefHandler { | ||
resetWorkspaceRefState(workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void>; | ||
attachWorkspace(workspace: Workspace, mergeStrategy?: MergeStrategy): Promise<void>; | ||
@@ -244,2 +249,6 @@ detachWorkspace(): void; | ||
} | ||
public resetWorkspaceRefState(workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void> { | ||
return this.targetHandler.resetWorkspaceRefState(workspace, mergeStrategy); | ||
} | ||
} | ||
@@ -315,2 +324,24 @@ | ||
public async resetWorkspaceRefState(workspace: Workspace, mergeStrategy: MergeStrategy): Promise<void> { | ||
switch (mergeStrategy) { | ||
case MergeStrategy.LocalClobbersRemote: | ||
this.state = await this.remoteClient.sendRequest(WorkspaceResetRequest.type, { | ||
dir: this.refID.repo, | ||
ref: this.refID.ref, | ||
bufferFiles: workspace.allBufferFiles(), | ||
} as WorkspaceResetParams); | ||
await this.ot.reset(this.state!.history); | ||
break; | ||
case MergeStrategy.RemoteClobbersLocal: | ||
await this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
await workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
break; | ||
default: | ||
return Promise.reject(new Error(`unknown merge strategy: ${mergeStrategy}`)); | ||
} | ||
return Promise.resolve(void 0); | ||
} | ||
public async attachWorkspace(newWorkspace: Workspace, mergeStrategy: MergeStrategy): Promise<void> { | ||
@@ -336,21 +367,4 @@ this.mergeStrategy = mergeStrategy; | ||
switch (mergeStrategy) { | ||
case MergeStrategy.LocalClobbersRemote: | ||
// TODO(sqs): because this uses workspace/reset, it only works for vscode (not web), but that is OK because we only want this merge strategy's behavior on vscode. | ||
this.state = await this.remoteClient.sendRequest(WorkspaceResetRequest.type, { | ||
dir: this.refID.repo, | ||
ref: this.refID.ref, | ||
bufferFiles: this.workspace.allBufferFiles(), | ||
} as WorkspaceResetParams); | ||
await this.ot.reset(this.state!.history); | ||
break; | ||
await this.resetWorkspaceRefState(this.workspace, mergeStrategy); | ||
case MergeStrategy.RemoteClobbersLocal: | ||
await this.ot.reset(this.state && this.state.history ? this.state.history : []); | ||
await this.workspace.reset(this.state && this.state.history ? this.state.history : []); | ||
break; | ||
default: | ||
return Promise.reject(new Error(`unknown merge strategy: ${mergeStrategy} `)); | ||
} | ||
return Promise.resolve(void 0); | ||
@@ -357,0 +371,0 @@ } |
Sorry, the diff of this file is too big to display
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
581061
17513