mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) add more detail to /compare endpoint
Summary: * Extends `/api/docs/docId1/compare/docId2` endpoint with a `detail=1` option to include details of what changed in the document content. * Adds an `/api/docs/docId/compare?left=HASH&right=HASH` endpoint for comparing two versions of a single document. This is needed to implement the extension to `/api/docs/docId1/compare/docId2`. * Adds a `HashUtil` class to allow hash aliases like `HEAD` and `HEAD~`. Everything is a bit crude: * Changes are expressed as ActionSummary objects, which aren't fully fleshed out. * Extra data about formula columns is inserted in an inflexible way. This is extracted and cleaned up from https://phab.getgrist.com/D2600. Test Plan: added tests Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2614
This commit is contained in:
46
app/server/lib/HashUtil.ts
Normal file
46
app/server/lib/HashUtil.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { DocState } from 'app/common/UserAPI';
|
||||
|
||||
/**
|
||||
*
|
||||
* Helper class to support a small subset of git-style references for state hashes:
|
||||
* HEAD = the most recent state
|
||||
* [HASH]^1 = the parent of [HASH]
|
||||
* [HASH]~1 = the parent of [HASH]
|
||||
* [HASH]~2 = the grandparent of [HASH]
|
||||
* [HASH]^1^1 = the grandparent of [HASH]
|
||||
* [HASH]~3 = the great grandparent of [HASH]
|
||||
* For git, where commits have multiple parents, "~" refers to the first parent,
|
||||
* and "^1" also refers to the first parent. For grist, there are only first parents
|
||||
* (unless/until we start tracking history across merges).
|
||||
*
|
||||
*/
|
||||
export class HashUtil {
|
||||
|
||||
/**
|
||||
* To construct, provide a list of states, most recent first.
|
||||
*/
|
||||
constructor(private _state: DocState[]) {}
|
||||
|
||||
/**
|
||||
* Find the named hash in the list of states, allowing for aliases.
|
||||
* Returns an index into the list of states provided in constructor.
|
||||
*/
|
||||
public hashToOffset(hash: string): number {
|
||||
const parts = hash.split(/([~^][0-9]*)/);
|
||||
hash = parts.shift() || '';
|
||||
let offset = hash === 'HEAD' ? 0 : this._state.findIndex(state => state.h === hash);
|
||||
if (offset < 0) { throw new Error('Cannot read hash'); }
|
||||
for (const part of parts) {
|
||||
if (part === '^' || part === '^1') {
|
||||
offset++;
|
||||
} else if (part.startsWith('~')) {
|
||||
offset += parseInt(part.slice(1) || '1', 10);
|
||||
} else if (part === '') {
|
||||
// pass
|
||||
} else {
|
||||
throw new Error('cannot parse hash');
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user