@dotinc/ogre 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.tap/processinfo/{21e0110c-397c-4c38-a84a-89c55de41e7e.json → 12fba5c1-f3d6-4b95-865b-9251ded2f6e3.json} +7 -6
- package/.tap/processinfo/{51b87298-fd44-42a9-b0f8-d4533e58fd1c.json → 38a3e28a-f045-4a32-bfc3-ca756e9457eb.json} +35 -34
- package/.tap/processinfo/{d1b618cb-a921-4f1c-ae4a-6bca359b5909.json → 594c45a4-6863-423e-9759-b092527c8ac4.json} +23 -22
- package/.tap/processinfo/{36da4059-ca5e-4b70-a993-7f99f94f7588.json → 671766c2-87ab-40cf-8051-2b74d41d0bc5.json} +7 -6
- package/.tap/processinfo/{75459f57-2341-476b-8576-587b93699d8b.json → a2952f0b-bb22-4fd6-a729-f9c500431030.json} +7 -6
- package/.tap/processinfo/{4aa37d99-4038-4033-9d38-beea00272892.json → cfca41ce-a29e-4cef-9564-b1f52749806b.json} +7 -6
- package/.tap/processinfo/{9656a0a0-72ab-4ea7-abb7-7415cd3842b4.json → d116ec0f-f197-434d-8a14-1f09a4b274ea.json} +23 -22
- package/.tap/test-results/src/branch.test.ts.tap +6 -6
- package/.tap/test-results/src/checkout.test.ts.tap +9 -9
- package/.tap/test-results/src/commit.test.ts.tap +18 -18
- package/.tap/test-results/src/merge.test.ts.tap +2 -2
- package/.tap/test-results/src/repository.test.ts.tap +23 -23
- package/.tap/test-results/src/tag.test.ts.tap +3 -3
- package/.tap/test-results/src/utils.test.ts.tap +7 -7
- package/CHANGELOG.md +13 -0
- package/lib/git2json.js +3 -4
- package/lib/repository.d.ts +1 -18
- package/lib/repository.js +39 -196
- package/lib/utils.d.ts +55 -0
- package/lib/utils.js +183 -2
- package/package.json +2 -2
- package/src/commit.test.ts +2 -1
- package/src/git2json.ts +6 -2
- package/src/repository.test.ts +2 -1
- package/src/repository.ts +28 -195
- package/src/utils.ts +194 -0
package/lib/repository.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Repository = void 0;
|
|
4
4
|
const fast_json_patch_1 = require("fast-json-patch");
|
|
5
5
|
const commit_1 = require("./commit");
|
|
6
|
-
const ref_1 = require("./ref");
|
|
7
6
|
const fflate_1 = require("fflate");
|
|
8
|
-
const
|
|
9
|
-
const headsRefPathPrefix = "refs/heads/";
|
|
10
|
-
const headValueRefPrefix = "ref: ";
|
|
11
|
-
exports.REFS_HEAD_KEY = "HEAD";
|
|
12
|
-
exports.REFS_MAIN_KEY = `${headsRefPathPrefix}main`;
|
|
7
|
+
const utils_1 = require("./utils");
|
|
13
8
|
/**
|
|
14
9
|
* A repository recording and managing the state transitions of an object
|
|
15
10
|
*/
|
|
@@ -25,10 +20,10 @@ class Repository {
|
|
|
25
20
|
this.refs =
|
|
26
21
|
(_c = (_b = options.history) === null || _b === void 0 ? void 0 : _b.refs) !== null && _c !== void 0 ? _c : new Map([
|
|
27
22
|
[
|
|
28
|
-
|
|
23
|
+
utils_1.REFS_HEAD_KEY,
|
|
29
24
|
{
|
|
30
|
-
name:
|
|
31
|
-
value: `ref: ${
|
|
25
|
+
name: utils_1.REFS_HEAD_KEY,
|
|
26
|
+
value: `ref: ${utils_1.REFS_MAIN_KEY}`,
|
|
32
27
|
},
|
|
33
28
|
],
|
|
34
29
|
]);
|
|
@@ -45,7 +40,7 @@ class Repository {
|
|
|
45
40
|
return this.remoteRefs;
|
|
46
41
|
}
|
|
47
42
|
moveTo(commit) {
|
|
48
|
-
const targetTree = treeToObject(commit.tree);
|
|
43
|
+
const targetTree = (0, utils_1.treeToObject)(commit.tree);
|
|
49
44
|
const patchToTarget = (0, fast_json_patch_1.compare)(this.data, targetTree);
|
|
50
45
|
if (!patchToTarget || patchToTarget.length < 1) {
|
|
51
46
|
return;
|
|
@@ -86,15 +81,15 @@ class Repository {
|
|
|
86
81
|
(0, fast_json_patch_1.applyPatch)(this.data, patch);
|
|
87
82
|
// const changed = patch.reduce(applyReducer, this.data);
|
|
88
83
|
}
|
|
89
|
-
reset(mode = "hard", shaish =
|
|
84
|
+
reset(mode = "hard", shaish = utils_1.REFS_HEAD_KEY) {
|
|
90
85
|
if (mode === "hard") {
|
|
91
86
|
(0, fast_json_patch_1.unobserve)(this.data, this.observer);
|
|
92
87
|
}
|
|
93
|
-
const [commit] = shaishToCommit(shaish, this.refs, this.commits);
|
|
88
|
+
const [commit] = (0, utils_1.shaishToCommit)(shaish, this.refs, this.commits);
|
|
94
89
|
this.moveTo(commit);
|
|
95
|
-
const refs = refsAtCommit(this.refs, commit);
|
|
90
|
+
const refs = (0, utils_1.refsAtCommit)(this.refs, commit);
|
|
96
91
|
// reset only moves heads and not tags
|
|
97
|
-
const moveableRefs = refs.filter((r) => r.name.startsWith(
|
|
92
|
+
const moveableRefs = refs.filter((r) => r.name.startsWith((0, utils_1.localHeadPathPrefix)()));
|
|
98
93
|
for (const ref of moveableRefs) {
|
|
99
94
|
this.moveRef(ref.name, commit);
|
|
100
95
|
}
|
|
@@ -103,16 +98,16 @@ class Repository {
|
|
|
103
98
|
}
|
|
104
99
|
}
|
|
105
100
|
branch() {
|
|
106
|
-
const currentHeadRef = this.refs.get(
|
|
101
|
+
const currentHeadRef = this.refs.get(utils_1.REFS_HEAD_KEY);
|
|
107
102
|
if (!currentHeadRef) {
|
|
108
103
|
throw new Error("unreachable: ref HEAD not available");
|
|
109
104
|
}
|
|
110
|
-
if (currentHeadRef.value.includes(headValueRefPrefix)) {
|
|
111
|
-
const refName = (0,
|
|
105
|
+
if (currentHeadRef.value.includes(utils_1.headValueRefPrefix)) {
|
|
106
|
+
const refName = (0, utils_1.cleanRefValue)(currentHeadRef.value);
|
|
112
107
|
if (this.refs.has(refName))
|
|
113
|
-
return
|
|
108
|
+
return (0, utils_1.getLastRefPathElement)(refName);
|
|
114
109
|
}
|
|
115
|
-
return
|
|
110
|
+
return utils_1.REFS_HEAD_KEY; // detached state
|
|
116
111
|
}
|
|
117
112
|
status() {
|
|
118
113
|
const commit = this.commitAtHead();
|
|
@@ -123,32 +118,32 @@ class Repository {
|
|
|
123
118
|
return this.diff(commit.hash);
|
|
124
119
|
}
|
|
125
120
|
diff(shaishFrom, shaishTo) {
|
|
126
|
-
const [cFrom] = shaishToCommit(shaishFrom, this.refs, this.commits);
|
|
121
|
+
const [cFrom] = (0, utils_1.shaishToCommit)(shaishFrom, this.refs, this.commits);
|
|
127
122
|
let target;
|
|
128
123
|
if (shaishTo) {
|
|
129
|
-
const [cTo] = shaishToCommit(shaishTo, this.refs, this.commits);
|
|
130
|
-
target = treeToObject(cTo.tree);
|
|
124
|
+
const [cTo] = (0, utils_1.shaishToCommit)(shaishTo, this.refs, this.commits);
|
|
125
|
+
target = (0, utils_1.treeToObject)(cTo.tree);
|
|
131
126
|
}
|
|
132
127
|
else {
|
|
133
128
|
target = this.data;
|
|
134
129
|
}
|
|
135
|
-
const targetTree = treeToObject(cFrom.tree);
|
|
130
|
+
const targetTree = (0, utils_1.treeToObject)(cFrom.tree);
|
|
136
131
|
return (0, fast_json_patch_1.compare)(targetTree, target);
|
|
137
132
|
}
|
|
138
133
|
checkout(shaish, createBranch) {
|
|
139
134
|
if (createBranch) {
|
|
140
|
-
(0,
|
|
141
|
-
let branchRef = (0,
|
|
135
|
+
(0, utils_1.validateBranchName)(shaish);
|
|
136
|
+
let branchRef = (0, utils_1.brancheNameToRef)(shaish);
|
|
142
137
|
const commit = this.commitAtHead();
|
|
143
138
|
if (commit) {
|
|
144
139
|
this.moveRef(branchRef, commit);
|
|
145
140
|
}
|
|
146
|
-
this.moveRef(
|
|
141
|
+
this.moveRef(utils_1.REFS_HEAD_KEY, branchRef);
|
|
147
142
|
}
|
|
148
143
|
else {
|
|
149
|
-
const [commit, isRef, refKey] = shaishToCommit(shaish, this.refs, this.commits);
|
|
144
|
+
const [commit, isRef, refKey] = (0, utils_1.shaishToCommit)(shaish, this.refs, this.commits);
|
|
150
145
|
this.moveTo(commit);
|
|
151
|
-
this.moveRef(
|
|
146
|
+
this.moveRef(utils_1.REFS_HEAD_KEY, isRef && refKey !== undefined ? refKey : commit);
|
|
152
147
|
}
|
|
153
148
|
}
|
|
154
149
|
async commit(message, author, amend) {
|
|
@@ -160,7 +155,7 @@ class Repository {
|
|
|
160
155
|
if (parent) {
|
|
161
156
|
if (amend) {
|
|
162
157
|
[parent] = parent.parent
|
|
163
|
-
? shaishToCommit(parent.parent, this.refs, this.commits)
|
|
158
|
+
? (0, utils_1.shaishToCommit)(parent.parent, this.refs, this.commits)
|
|
164
159
|
: [parent]; // we are the very first commit in the repository
|
|
165
160
|
}
|
|
166
161
|
}
|
|
@@ -203,13 +198,13 @@ class Repository {
|
|
|
203
198
|
}
|
|
204
199
|
else {
|
|
205
200
|
// move detached HEAD to new commit
|
|
206
|
-
this.moveRef(
|
|
201
|
+
this.moveRef(utils_1.REFS_HEAD_KEY, commit);
|
|
207
202
|
}
|
|
208
203
|
return sha;
|
|
209
204
|
}
|
|
210
205
|
// region Commit lookups
|
|
211
206
|
commitAtHead() {
|
|
212
|
-
return commitAtRefIn(
|
|
207
|
+
return (0, utils_1.commitAtRefIn)(utils_1.REFS_HEAD_KEY, this.refs, this.commits);
|
|
213
208
|
}
|
|
214
209
|
mustCommitAtHead() {
|
|
215
210
|
const commitHead = this.commitAtHead();
|
|
@@ -220,17 +215,17 @@ class Repository {
|
|
|
220
215
|
}
|
|
221
216
|
// endregion
|
|
222
217
|
createBranch(name) {
|
|
223
|
-
(0,
|
|
224
|
-
const branchRef = (0,
|
|
218
|
+
(0, utils_1.validateBranchName)(name);
|
|
219
|
+
const branchRef = (0, utils_1.brancheNameToRef)(name);
|
|
225
220
|
this.saveNewRef(branchRef, name);
|
|
226
221
|
return branchRef;
|
|
227
222
|
}
|
|
228
223
|
head() {
|
|
229
|
-
const ref = this.refs.get(
|
|
224
|
+
const ref = this.refs.get(utils_1.REFS_HEAD_KEY);
|
|
230
225
|
if (!ref) {
|
|
231
226
|
throw new Error(`unreachable: HEAD is not present`);
|
|
232
227
|
}
|
|
233
|
-
return (0,
|
|
228
|
+
return (0, utils_1.cleanRefValue)(ref.value);
|
|
234
229
|
}
|
|
235
230
|
// region History functions
|
|
236
231
|
collectCommits() {
|
|
@@ -276,7 +271,7 @@ class Repository {
|
|
|
276
271
|
// const srcHead = commitAtRefIn(REFS_HEAD, src.refs, src.commits)
|
|
277
272
|
throw new Error(`fatal: source type (${source instanceof Repository ? "Repository" : "History"}) not implemented`);
|
|
278
273
|
}
|
|
279
|
-
const [srcCommit] = shaishToCommit(source, this.refs, this.commits);
|
|
274
|
+
const [srcCommit] = (0, utils_1.shaishToCommit)(source, this.refs, this.commits);
|
|
280
275
|
const headCommit = this.mustCommitAtHead();
|
|
281
276
|
// no change
|
|
282
277
|
// *---* (master)
|
|
@@ -293,7 +288,7 @@ class Repository {
|
|
|
293
288
|
// *---*
|
|
294
289
|
// \
|
|
295
290
|
// *---*---* (master, foo)
|
|
296
|
-
const [isAncestor] = mapPath(headCommit, srcCommit, this.commits);
|
|
291
|
+
const [isAncestor] = (0, utils_1.mapPath)(headCommit, srcCommit, this.commits);
|
|
297
292
|
if (isAncestor) {
|
|
298
293
|
this.moveRef(this.head(), srcCommit);
|
|
299
294
|
this.moveTo(srcCommit);
|
|
@@ -316,9 +311,9 @@ class Repository {
|
|
|
316
311
|
// region Ref methods
|
|
317
312
|
moveRef(refName, value) {
|
|
318
313
|
let ref = this.refs.get(refName);
|
|
319
|
-
const val = typeof value === "string" ? (0,
|
|
314
|
+
const val = typeof value === "string" ? (0, utils_1.createHeadRefValue)(value) : value.hash;
|
|
320
315
|
if (!ref) {
|
|
321
|
-
ref = { name:
|
|
316
|
+
ref = { name: (0, utils_1.getLastRefPathElement)(refName), value: val };
|
|
322
317
|
}
|
|
323
318
|
else {
|
|
324
319
|
ref.value = val;
|
|
@@ -332,24 +327,24 @@ class Repository {
|
|
|
332
327
|
if (!headRef) {
|
|
333
328
|
throw new Error(`unreachable: HEAD not present`);
|
|
334
329
|
}
|
|
335
|
-
throw new Error(`fatal: not a valid object name: '${
|
|
330
|
+
throw new Error(`fatal: not a valid object name: '${(0, utils_1.getLastRefPathElement)(headRef)}'`);
|
|
336
331
|
}
|
|
337
332
|
this.refs.set(refKey, { name: name, value: headCommit.hash });
|
|
338
333
|
}
|
|
339
334
|
ref(reference) {
|
|
340
335
|
var _a;
|
|
341
336
|
const ref = (_a = this.refs.get(reference)) === null || _a === void 0 ? void 0 : _a.value;
|
|
342
|
-
return ref ? (0,
|
|
337
|
+
return ref ? (0, utils_1.cleanRefValue)(ref) : undefined;
|
|
343
338
|
}
|
|
344
339
|
// endregion
|
|
345
340
|
tag(tag) {
|
|
346
341
|
try {
|
|
347
|
-
(0,
|
|
342
|
+
(0, utils_1.validateRef)(tag);
|
|
348
343
|
}
|
|
349
344
|
catch (e) {
|
|
350
345
|
throw new Error(`fatal: '${tag}' is not a valid tag name`);
|
|
351
346
|
}
|
|
352
|
-
const tagRef = (0,
|
|
347
|
+
const tagRef = (0, utils_1.tagToRef)(tag);
|
|
353
348
|
try {
|
|
354
349
|
this.saveNewRef(tagRef, tag);
|
|
355
350
|
}
|
|
@@ -362,155 +357,3 @@ class Repository {
|
|
|
362
357
|
}
|
|
363
358
|
}
|
|
364
359
|
exports.Repository = Repository;
|
|
365
|
-
const treeToObject = (tree) => {
|
|
366
|
-
return JSON.parse((0, fflate_1.strFromU8)((0, fflate_1.decompressSync)(Buffer.from(tree, "base64"))));
|
|
367
|
-
};
|
|
368
|
-
const getLastItem = (thePath) => thePath.substring(thePath.lastIndexOf("/") + 1);
|
|
369
|
-
const mapPath = (from, to, commits) => {
|
|
370
|
-
let c = to;
|
|
371
|
-
while (c !== undefined) {
|
|
372
|
-
c = commits.find((parent) => parent.hash === (c === null || c === void 0 ? void 0 : c.parent));
|
|
373
|
-
if ((c === null || c === void 0 ? void 0 : c.hash) === from.hash) {
|
|
374
|
-
return [true];
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return [false];
|
|
378
|
-
};
|
|
379
|
-
/**
|
|
380
|
-
* Returns the commit to which the provided ref is pointing
|
|
381
|
-
* @param ref - needs to be in key format, e.g. refs/heads/... or refs/tags/...
|
|
382
|
-
* @param references
|
|
383
|
-
* @param commitsList
|
|
384
|
-
*/
|
|
385
|
-
const commitAtRefIn = (ref, references, commitsList) => {
|
|
386
|
-
const reference = references.get(ref);
|
|
387
|
-
if (!reference) {
|
|
388
|
-
throw new Error(`unreachable: '${ref}' is not present`);
|
|
389
|
-
}
|
|
390
|
-
let commitHash;
|
|
391
|
-
if (reference.value.includes(headValueRefPrefix)) {
|
|
392
|
-
const refKey = (0, exports.cleanRefValue)(reference.value);
|
|
393
|
-
const targetRef = references.get(refKey);
|
|
394
|
-
if (!targetRef) {
|
|
395
|
-
// target branch may not have been saved yet
|
|
396
|
-
return undefined;
|
|
397
|
-
}
|
|
398
|
-
commitHash = targetRef.value;
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
commitHash = reference.value;
|
|
402
|
-
}
|
|
403
|
-
for (const c of commitsList) {
|
|
404
|
-
if (c.hash === commitHash) {
|
|
405
|
-
return c;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return undefined;
|
|
409
|
-
};
|
|
410
|
-
const refsAtCommit = (references, commit) => {
|
|
411
|
-
const list = [];
|
|
412
|
-
for (const [name, ref] of references.entries()) {
|
|
413
|
-
if (ref.value === commit.hash) {
|
|
414
|
-
list.push(ref);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
return list;
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
* Accepts a shaish expression (e.g. refs (branches, tags), commitSha) and returns
|
|
421
|
-
* - a commit of type Commit
|
|
422
|
-
* - isRef boolean whether it is a direct reference
|
|
423
|
-
* - ref the key of the reference
|
|
424
|
-
*/
|
|
425
|
-
const shaishToCommit = (shaish, references, commitsList) => {
|
|
426
|
-
let sha = shaish;
|
|
427
|
-
let isRef = false;
|
|
428
|
-
let refKey = undefined;
|
|
429
|
-
// check for refs
|
|
430
|
-
for (const [name, ref] of references.entries()) {
|
|
431
|
-
// match on
|
|
432
|
-
if (ref.name === shaish || name === shaish) {
|
|
433
|
-
isRef = true;
|
|
434
|
-
refKey = name;
|
|
435
|
-
sha = ref.value;
|
|
436
|
-
if (sha.includes(headValueRefPrefix)) {
|
|
437
|
-
const cleanedRef = (0, exports.cleanRefValue)(sha);
|
|
438
|
-
const c = commitAtRefIn(cleanedRef, references, commitsList);
|
|
439
|
-
if (!c) {
|
|
440
|
-
throw new Error(`${cleanedRef} points to non-existing commit`);
|
|
441
|
-
}
|
|
442
|
-
return [c, isRef, refKey];
|
|
443
|
-
}
|
|
444
|
-
break;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
// check for partial sha matches
|
|
448
|
-
const found = commitsList.filter((c) => c.hash.indexOf(sha) > -1);
|
|
449
|
-
if (found.length === 0) {
|
|
450
|
-
throw new Error(`pathspec '${shaish}' did not match any known refs`);
|
|
451
|
-
}
|
|
452
|
-
// but sha should be specific enough to resolve to 1 commit
|
|
453
|
-
if (found.length > 1) {
|
|
454
|
-
throw new Error(`commit `);
|
|
455
|
-
}
|
|
456
|
-
return [found[0], isRef, refKey];
|
|
457
|
-
};
|
|
458
|
-
const createHeadRefValue = (refKey) => {
|
|
459
|
-
return `${headValueRefPrefix}${refKey}`;
|
|
460
|
-
};
|
|
461
|
-
exports.createHeadRefValue = createHeadRefValue;
|
|
462
|
-
const isTagRef = (refKey) => refKey.indexOf(tagRefPathPrefix) > -1;
|
|
463
|
-
exports.isTagRef = isTagRef;
|
|
464
|
-
const cleanRefValue = (ref) => ref.replace(headValueRefPrefix, "");
|
|
465
|
-
exports.cleanRefValue = cleanRefValue;
|
|
466
|
-
const brancheNameToRef = (name) => {
|
|
467
|
-
return `${headsRefPathPrefix}${name}`;
|
|
468
|
-
};
|
|
469
|
-
exports.brancheNameToRef = brancheNameToRef;
|
|
470
|
-
const tagToRef = (tag) => {
|
|
471
|
-
return `${tagRefPathPrefix}${tag}`;
|
|
472
|
-
};
|
|
473
|
-
exports.tagToRef = tagToRef;
|
|
474
|
-
const validateBranchName = (name) => {
|
|
475
|
-
if (!(0, ref_1.validBranch)(name)) {
|
|
476
|
-
throw new Error(`invalid ref name`);
|
|
477
|
-
}
|
|
478
|
-
};
|
|
479
|
-
exports.validateBranchName = validateBranchName;
|
|
480
|
-
const validateRef = (name, oneLevel = true) => {
|
|
481
|
-
if (!(0, ref_1.validRef)(name, oneLevel)) {
|
|
482
|
-
throw new Error(`invalid ref name`);
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
exports.validateRef = validateRef;
|
|
486
|
-
/**
|
|
487
|
-
* Prints the underlying changelog of a repository
|
|
488
|
-
* @param repository
|
|
489
|
-
*/
|
|
490
|
-
const printChangeLog = (repository) => {
|
|
491
|
-
console.log("----------------------------------------------------------");
|
|
492
|
-
console.log("Changelog");
|
|
493
|
-
console.log("----------------------------------------------------------");
|
|
494
|
-
const history = repository.getHistory();
|
|
495
|
-
const head = commitAtRefIn(repository.head(), history.refs, history.commits);
|
|
496
|
-
if (!head) {
|
|
497
|
-
throw new Error(`fatal: HEAD is not defined`);
|
|
498
|
-
}
|
|
499
|
-
let c = head;
|
|
500
|
-
while (c) {
|
|
501
|
-
console.log(`${c.hash} ${refsAtCommit(history.refs, c)
|
|
502
|
-
.map((r) => r.name)
|
|
503
|
-
.join(" ")}`);
|
|
504
|
-
for (const chg of c.changes) {
|
|
505
|
-
(0, exports.printChange)(chg);
|
|
506
|
-
}
|
|
507
|
-
c = history.commits.find((parent) => parent.hash === (c === null || c === void 0 ? void 0 : c.parent));
|
|
508
|
-
}
|
|
509
|
-
console.log("End of changelog");
|
|
510
|
-
console.log("----------------------------------------------------------");
|
|
511
|
-
};
|
|
512
|
-
exports.printChangeLog = printChangeLog;
|
|
513
|
-
const printChange = (chg) => {
|
|
514
|
-
console.log(` ${JSON.stringify(chg)}`);
|
|
515
|
-
};
|
|
516
|
-
exports.printChange = printChange;
|
package/lib/utils.d.ts
CHANGED
|
@@ -1 +1,56 @@
|
|
|
1
|
+
import { Commit } from "./commit";
|
|
2
|
+
import { Reference } from "./interfaces";
|
|
3
|
+
import { Operation } from "fast-json-patch";
|
|
4
|
+
import { RepositoryObject } from "./repository";
|
|
1
5
|
export declare const cleanAuthor: (author: string) => [name: string, email: string];
|
|
6
|
+
export declare const localRefPrefix = "refs/";
|
|
7
|
+
export declare const remoteRefPrefix = "refs/remotes/origin/";
|
|
8
|
+
export declare const tagRefPathPrefix = "tags/";
|
|
9
|
+
export declare const headsRefPathPrefix = "heads/";
|
|
10
|
+
export declare const headValueRefPrefix = "ref: ";
|
|
11
|
+
export declare const localHeadPathPrefix: () => string;
|
|
12
|
+
export declare const remoteHeadPathPrefix: () => string;
|
|
13
|
+
export declare const localTagPathPrefix: () => string;
|
|
14
|
+
export declare const remoteTagPathPrefix: () => string;
|
|
15
|
+
export declare const REFS_HEAD_KEY = "HEAD";
|
|
16
|
+
/**
|
|
17
|
+
* Should only be used in local context
|
|
18
|
+
*/
|
|
19
|
+
export declare const REFS_MAIN_KEY: string;
|
|
20
|
+
export declare const treeToObject: <T = any>(tree: string) => T;
|
|
21
|
+
export declare const mapPath: (from: Commit, to: Commit, commits: Commit[]) => [isAncestor: boolean];
|
|
22
|
+
/**
|
|
23
|
+
* Returns the commit to which the provided ref is pointing
|
|
24
|
+
* @param ref - needs to be in key format, e.g. refs/heads/... or refs/tags/...
|
|
25
|
+
* @param references
|
|
26
|
+
* @param commitsList
|
|
27
|
+
*/
|
|
28
|
+
export declare const commitAtRefIn: (ref: string, references: Map<string, Reference>, commitsList: Commit[]) => Commit | undefined;
|
|
29
|
+
export declare const refsAtCommit: (references: Map<string, Reference>, commit: Commit) => Reference[];
|
|
30
|
+
/**
|
|
31
|
+
* Accepts a shaish expression (e.g. refs (branches, tags), commitSha) and returns
|
|
32
|
+
* - a commit of type Commit
|
|
33
|
+
* - isRef boolean whether it is a direct reference
|
|
34
|
+
* - ref the key of the reference
|
|
35
|
+
*/
|
|
36
|
+
export declare const shaishToCommit: (shaish: string, references: Map<string, Reference>, commitsList: Commit[]) => [commit: Commit, isRef: boolean, ref: string | undefined];
|
|
37
|
+
export declare const createHeadRefValue: (refKey: string) => string;
|
|
38
|
+
export declare const isTagRef: (refKey: string) => boolean;
|
|
39
|
+
export declare const cleanRefValue: (ref: string) => string;
|
|
40
|
+
export declare const brancheNameToRef: (name: string) => string;
|
|
41
|
+
export declare const tagToRef: (tag: string) => string;
|
|
42
|
+
export declare const validateBranchName: (name: string) => void;
|
|
43
|
+
export declare const validateRef: (name: string, oneLevel?: boolean) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Prints the underlying changelog of a repository
|
|
46
|
+
* @param repository
|
|
47
|
+
*/
|
|
48
|
+
export declare const printChangeLog: <T extends {
|
|
49
|
+
[k: string]: any;
|
|
50
|
+
}>(repository: RepositoryObject<T>) => void;
|
|
51
|
+
export declare const printChange: (chg: Operation) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Should be called with a `/` delimited ref path. E.g. refs/heads/main
|
|
54
|
+
* @param thePath
|
|
55
|
+
*/
|
|
56
|
+
export declare const getLastRefPathElement: (thePath: string) => string;
|
package/lib/utils.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cleanAuthor = void 0;
|
|
4
|
-
|
|
3
|
+
exports.getLastRefPathElement = exports.printChange = exports.printChangeLog = exports.validateRef = exports.validateBranchName = exports.tagToRef = exports.brancheNameToRef = exports.cleanRefValue = exports.isTagRef = exports.createHeadRefValue = exports.shaishToCommit = exports.refsAtCommit = exports.commitAtRefIn = exports.mapPath = exports.treeToObject = exports.REFS_MAIN_KEY = exports.REFS_HEAD_KEY = exports.remoteTagPathPrefix = exports.localTagPathPrefix = exports.remoteHeadPathPrefix = exports.localHeadPathPrefix = exports.headValueRefPrefix = exports.headsRefPathPrefix = exports.tagRefPathPrefix = exports.remoteRefPrefix = exports.localRefPrefix = exports.cleanAuthor = void 0;
|
|
4
|
+
const fflate_1 = require("fflate");
|
|
5
|
+
const ref_1 = require("./ref");
|
|
5
6
|
const emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
|
|
6
7
|
const cleanAuthor = (author) => {
|
|
7
8
|
if (author === "") {
|
|
@@ -25,3 +26,183 @@ const cleanAuthor = (author) => {
|
|
|
25
26
|
return [author, ""];
|
|
26
27
|
};
|
|
27
28
|
exports.cleanAuthor = cleanAuthor;
|
|
29
|
+
exports.localRefPrefix = `refs/`;
|
|
30
|
+
exports.remoteRefPrefix = `refs/remotes/origin/`;
|
|
31
|
+
exports.tagRefPathPrefix = "tags/";
|
|
32
|
+
exports.headsRefPathPrefix = "heads/";
|
|
33
|
+
exports.headValueRefPrefix = "ref: ";
|
|
34
|
+
const localHeadPathPrefix = () => `${exports.localRefPrefix}${exports.headsRefPathPrefix}`;
|
|
35
|
+
exports.localHeadPathPrefix = localHeadPathPrefix;
|
|
36
|
+
const remoteHeadPathPrefix = () => `${exports.remoteRefPrefix}${exports.headsRefPathPrefix}`;
|
|
37
|
+
exports.remoteHeadPathPrefix = remoteHeadPathPrefix;
|
|
38
|
+
const localTagPathPrefix = () => `${exports.localRefPrefix}${exports.tagRefPathPrefix}`;
|
|
39
|
+
exports.localTagPathPrefix = localTagPathPrefix;
|
|
40
|
+
const remoteTagPathPrefix = () => `${exports.remoteRefPrefix}${exports.tagRefPathPrefix}`;
|
|
41
|
+
exports.remoteTagPathPrefix = remoteTagPathPrefix;
|
|
42
|
+
exports.REFS_HEAD_KEY = "HEAD";
|
|
43
|
+
/**
|
|
44
|
+
* Should only be used in local context
|
|
45
|
+
*/
|
|
46
|
+
exports.REFS_MAIN_KEY = `${(0, exports.localHeadPathPrefix)()}main`;
|
|
47
|
+
const treeToObject = (tree) => {
|
|
48
|
+
return JSON.parse((0, fflate_1.strFromU8)((0, fflate_1.decompressSync)(Buffer.from(tree, "base64"))));
|
|
49
|
+
};
|
|
50
|
+
exports.treeToObject = treeToObject;
|
|
51
|
+
const mapPath = (from, to, commits) => {
|
|
52
|
+
let c = to;
|
|
53
|
+
while (c !== undefined) {
|
|
54
|
+
c = commits.find((parent) => parent.hash === (c === null || c === void 0 ? void 0 : c.parent));
|
|
55
|
+
if ((c === null || c === void 0 ? void 0 : c.hash) === from.hash) {
|
|
56
|
+
return [true];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [false];
|
|
60
|
+
};
|
|
61
|
+
exports.mapPath = mapPath;
|
|
62
|
+
/**
|
|
63
|
+
* Returns the commit to which the provided ref is pointing
|
|
64
|
+
* @param ref - needs to be in key format, e.g. refs/heads/... or refs/tags/...
|
|
65
|
+
* @param references
|
|
66
|
+
* @param commitsList
|
|
67
|
+
*/
|
|
68
|
+
const commitAtRefIn = (ref, references, commitsList) => {
|
|
69
|
+
const reference = references.get(ref);
|
|
70
|
+
if (!reference) {
|
|
71
|
+
throw new Error(`unreachable: '${ref}' is not present`);
|
|
72
|
+
}
|
|
73
|
+
let commitHash;
|
|
74
|
+
if (reference.value.includes(exports.headValueRefPrefix)) {
|
|
75
|
+
const refKey = (0, exports.cleanRefValue)(reference.value);
|
|
76
|
+
const targetRef = references.get(refKey);
|
|
77
|
+
if (!targetRef) {
|
|
78
|
+
// target branch may not have been saved yet
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
commitHash = targetRef.value;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
commitHash = reference.value;
|
|
85
|
+
}
|
|
86
|
+
for (const c of commitsList) {
|
|
87
|
+
if (c.hash === commitHash) {
|
|
88
|
+
return c;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
};
|
|
93
|
+
exports.commitAtRefIn = commitAtRefIn;
|
|
94
|
+
const refsAtCommit = (references, commit) => {
|
|
95
|
+
const list = [];
|
|
96
|
+
for (const [name, ref] of references.entries()) {
|
|
97
|
+
if (ref.value === commit.hash) {
|
|
98
|
+
list.push(ref);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return list;
|
|
102
|
+
};
|
|
103
|
+
exports.refsAtCommit = refsAtCommit;
|
|
104
|
+
/**
|
|
105
|
+
* Accepts a shaish expression (e.g. refs (branches, tags), commitSha) and returns
|
|
106
|
+
* - a commit of type Commit
|
|
107
|
+
* - isRef boolean whether it is a direct reference
|
|
108
|
+
* - ref the key of the reference
|
|
109
|
+
*/
|
|
110
|
+
const shaishToCommit = (shaish, references, commitsList) => {
|
|
111
|
+
let sha = shaish;
|
|
112
|
+
let isRef = false;
|
|
113
|
+
let refKey = undefined;
|
|
114
|
+
// check for refs
|
|
115
|
+
for (const [name, ref] of references.entries()) {
|
|
116
|
+
// match on
|
|
117
|
+
if (ref.name === shaish || name === shaish) {
|
|
118
|
+
isRef = true;
|
|
119
|
+
refKey = name;
|
|
120
|
+
sha = ref.value;
|
|
121
|
+
if (sha.includes(exports.headValueRefPrefix)) {
|
|
122
|
+
const cleanedRef = (0, exports.cleanRefValue)(sha);
|
|
123
|
+
const c = (0, exports.commitAtRefIn)(cleanedRef, references, commitsList);
|
|
124
|
+
if (!c) {
|
|
125
|
+
throw new Error(`${cleanedRef} points to non-existing commit`);
|
|
126
|
+
}
|
|
127
|
+
return [c, isRef, refKey];
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// check for partial sha matches
|
|
133
|
+
const found = commitsList.filter((c) => c.hash.indexOf(sha) > -1);
|
|
134
|
+
if (found.length === 0) {
|
|
135
|
+
throw new Error(`pathspec '${shaish}' did not match any known refs`);
|
|
136
|
+
}
|
|
137
|
+
// but sha should be specific enough to resolve to 1 commit
|
|
138
|
+
if (found.length > 1) {
|
|
139
|
+
throw new Error(`commit `);
|
|
140
|
+
}
|
|
141
|
+
return [found[0], isRef, refKey];
|
|
142
|
+
};
|
|
143
|
+
exports.shaishToCommit = shaishToCommit;
|
|
144
|
+
const createHeadRefValue = (refKey) => {
|
|
145
|
+
return `${exports.headValueRefPrefix}${refKey}`;
|
|
146
|
+
};
|
|
147
|
+
exports.createHeadRefValue = createHeadRefValue;
|
|
148
|
+
const isTagRef = (refKey) => refKey.indexOf((0, exports.localTagPathPrefix)()) > -1;
|
|
149
|
+
exports.isTagRef = isTagRef;
|
|
150
|
+
const cleanRefValue = (ref) => ref.replace(exports.headValueRefPrefix, "");
|
|
151
|
+
exports.cleanRefValue = cleanRefValue;
|
|
152
|
+
const brancheNameToRef = (name) => {
|
|
153
|
+
return `${(0, exports.localHeadPathPrefix)()}${name}`;
|
|
154
|
+
};
|
|
155
|
+
exports.brancheNameToRef = brancheNameToRef;
|
|
156
|
+
const tagToRef = (tag) => {
|
|
157
|
+
return `${(0, exports.localTagPathPrefix)()}${tag}`;
|
|
158
|
+
};
|
|
159
|
+
exports.tagToRef = tagToRef;
|
|
160
|
+
const validateBranchName = (name) => {
|
|
161
|
+
if (!(0, ref_1.validBranch)(name)) {
|
|
162
|
+
throw new Error(`invalid ref name`);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
exports.validateBranchName = validateBranchName;
|
|
166
|
+
const validateRef = (name, oneLevel = true) => {
|
|
167
|
+
if (!(0, ref_1.validRef)(name, oneLevel)) {
|
|
168
|
+
throw new Error(`invalid ref name`);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
exports.validateRef = validateRef;
|
|
172
|
+
/**
|
|
173
|
+
* Prints the underlying changelog of a repository
|
|
174
|
+
* @param repository
|
|
175
|
+
*/
|
|
176
|
+
const printChangeLog = (repository) => {
|
|
177
|
+
console.log("----------------------------------------------------------");
|
|
178
|
+
console.log("Changelog");
|
|
179
|
+
console.log("----------------------------------------------------------");
|
|
180
|
+
const history = repository.getHistory();
|
|
181
|
+
const head = (0, exports.commitAtRefIn)(repository.head(), history.refs, history.commits);
|
|
182
|
+
if (!head) {
|
|
183
|
+
throw new Error(`fatal: HEAD is not defined`);
|
|
184
|
+
}
|
|
185
|
+
let c = head;
|
|
186
|
+
while (c) {
|
|
187
|
+
console.log(`${c.hash} ${(0, exports.refsAtCommit)(history.refs, c)
|
|
188
|
+
.map((r) => r.name)
|
|
189
|
+
.join(" ")}`);
|
|
190
|
+
for (const chg of c.changes) {
|
|
191
|
+
(0, exports.printChange)(chg);
|
|
192
|
+
}
|
|
193
|
+
c = history.commits.find((parent) => parent.hash === (c === null || c === void 0 ? void 0 : c.parent));
|
|
194
|
+
}
|
|
195
|
+
console.log("End of changelog");
|
|
196
|
+
console.log("----------------------------------------------------------");
|
|
197
|
+
};
|
|
198
|
+
exports.printChangeLog = printChangeLog;
|
|
199
|
+
const printChange = (chg) => {
|
|
200
|
+
console.log(` ${JSON.stringify(chg)}`);
|
|
201
|
+
};
|
|
202
|
+
exports.printChange = printChange;
|
|
203
|
+
/**
|
|
204
|
+
* Should be called with a `/` delimited ref path. E.g. refs/heads/main
|
|
205
|
+
* @param thePath
|
|
206
|
+
*/
|
|
207
|
+
const getLastRefPathElement = (thePath) => thePath.substring(thePath.lastIndexOf("/") + 1);
|
|
208
|
+
exports.getLastRefPathElement = getLastRefPathElement;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/dotindustries/ogre.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.8.0",
|
|
8
8
|
"description": "Git-like repository for in-memory object versioning",
|
|
9
9
|
"private": false,
|
|
10
10
|
"main": "lib/index.js",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"registry": "https://registry.npmjs.org/",
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "8745cba07d9dc502ee7b0fc595d660a5de58f64f"
|
|
41
41
|
}
|
package/src/commit.test.ts
CHANGED
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
testAuthor,
|
|
9
9
|
updateHeaderData,
|
|
10
10
|
} from "./test.utils";
|
|
11
|
-
import {
|
|
11
|
+
import { Repository } from "./repository";
|
|
12
|
+
import { printChangeLog } from "./utils";
|
|
12
13
|
|
|
13
14
|
test("baseline with 1 commit and zero changelog entries", async (t) => {
|
|
14
15
|
const [repo] = await getBaseline();
|
package/src/git2json.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { Commit } from "./commit";
|
|
2
2
|
import { History, Reference } from "./interfaces";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
cleanAuthor,
|
|
5
|
+
createHeadRefValue,
|
|
6
|
+
isTagRef,
|
|
7
|
+
REFS_HEAD_KEY,
|
|
8
|
+
} from "./utils";
|
|
5
9
|
|
|
6
10
|
const findRefs = (commit: Commit, refs: Map<string, Reference>) => {
|
|
7
11
|
const list = [];
|