gip-remote 1.2.3 → 1.2.5

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/index.js CHANGED
@@ -5,7 +5,7 @@ const z32 = require('z32')
5
5
  const def = require('./schema/hyperdb/index')
6
6
  const RemoteDrive = require('./lib/drive')
7
7
  const GitPearLink = require('./lib/link')
8
- const { parseCommit, walkTree } = require('./lib/git')
8
+ const { parseCommit, parseTag, walkTree } = require('./lib/git')
9
9
 
10
10
  class Remote extends ReadyResource {
11
11
  _swarm = null
@@ -22,7 +22,7 @@ class Remote extends ReadyResource {
22
22
  let config
23
23
  if (typeof this._link === 'string') {
24
24
  this._name = this._link
25
- config = {}
25
+ config = { core: store.get({ name: this._link }) }
26
26
  } else if (this._link.drive) {
27
27
  this._name = this._link.pathname?.split('/').slice(1)[0]
28
28
  config = { key: this._link.drive.key }
@@ -91,13 +91,18 @@ class Remote extends ReadyResource {
91
91
  }
92
92
 
93
93
  async getAllRefs() {
94
- const branches = this._db.find('@gip/branches')
95
94
  const refs = []
96
95
 
96
+ const branches = this._db.find('@gip/branches')
97
97
  for await (const b of branches) {
98
98
  refs.push({ ref: `refs/heads/${b.name}`, oid: b.commitOid })
99
99
  }
100
100
 
101
+ const tags = this._db.find('@gip/tags')
102
+ for await (const t of tags) {
103
+ refs.push({ ref: `refs/tags/${t.name}`, oid: t.oid })
104
+ }
105
+
101
106
  const headBranch = await this.getHead()
102
107
  if (headBranch) {
103
108
  const head = refs.find((r) => r.ref === `refs/heads/${headBranch}`)
@@ -129,36 +134,87 @@ class Remote extends ReadyResource {
129
134
  return true
130
135
  }
131
136
 
132
- // --- Push: store objects + index branch + files ---
137
+ async deleteTag(tagName) {
138
+ const tag = await this._db.get('@gip/tags', { name: tagName })
139
+ if (!tag) return false
140
+
141
+ await this._db.delete('@gip/tags', { name: tagName })
133
142
 
134
- async push(branchName, commitOid, objects) {
143
+ // Remove file records for this tag
144
+ const filesBranch = 'tags/' + tagName
145
+ const files = this._db.find('@gip/files', { branch: filesBranch })
146
+ for await (const file of files) {
147
+ await this._db.delete('@gip/files', { branch: filesBranch, path: file.path })
148
+ }
149
+
150
+ await this._db.flush()
151
+ return true
152
+ }
153
+
154
+ // --- Push: store objects + index branch/tag + files ---
155
+
156
+ async push(refName, oid, objects) {
135
157
  // 1. Store all git objects
136
- for (const [oid, obj] of objects) {
137
- const existing = await this.getObject(oid)
158
+ for (const [objOid, obj] of objects) {
159
+ const existing = await this.getObject(objOid)
138
160
  if (existing) continue
139
161
 
140
162
  await this._db.insert('@gip/objects', {
141
- oid,
163
+ oid: objOid,
142
164
  type: obj.type,
143
165
  size: obj.size,
144
166
  data: obj.data
145
167
  })
146
168
  }
147
169
 
148
- // 2. Parse commit metadata
149
- const commitObj = objects.get(commitOid)
150
- if (!commitObj) throw new Error('Commit object not found: ' + commitOid)
170
+ // 2. Dereference tag objects to find the commit
171
+ let resolvedOid = oid
172
+ let obj = objects.get(resolvedOid)
173
+ if (!obj) throw new Error('Object not found: ' + resolvedOid)
174
+
175
+ let tagMeta = null
176
+ while (obj.type === 'tag') {
177
+ const tag = parseTag(obj.data)
178
+ if (!tagMeta) tagMeta = tag
179
+ if (!tag.object) throw new Error('Tag has no object: ' + resolvedOid)
180
+ resolvedOid = tag.object
181
+ obj = objects.get(resolvedOid)
182
+ if (!obj) throw new Error('Object not found: ' + resolvedOid)
183
+ }
151
184
 
152
- const commit = parseCommit(commitObj.data)
153
- if (!commit.tree) throw new Error('Commit has no tree: ' + commitOid)
185
+ if (obj.type !== 'commit') {
186
+ throw new Error('Expected commit, got ' + obj.type + ': ' + resolvedOid)
187
+ }
188
+
189
+ const commit = parseCommit(obj.data)
190
+ if (!commit.tree) throw new Error('Commit has no tree: ' + resolvedOid)
154
191
 
155
192
  // 3. Walk tree to enumerate files
156
193
  const files = walkTree(objects, commit.tree, '')
157
194
 
158
- // 4. Insert file records
195
+ // 4a. Reconcile deletions — remove file records whose paths no longer
196
+ // exist in the new tree. Without this, files removed in a commit
197
+ // would persist in the index forever (only `deleteBranch` cleans
198
+ // them up, and only on full branch deletion). The drive view would
199
+ // keep showing ghost files; consumers iterating @gip/files would
200
+ // emit stale entries.
201
+ //
202
+ // We rebuild the new path set first, then sweep the existing
203
+ // records — O(N) in the size of the indexed tree, same order as
204
+ // the insert step that follows.
205
+ const newPaths = new Set(files.map((f) => f.path))
206
+ const existingFiles = this._db.find('@gip/files', { branch: refName })
207
+ for await (const file of existingFiles) {
208
+ if (!newPaths.has(file.path)) {
209
+ await this._db.delete('@gip/files', { branch: refName, path: file.path })
210
+ }
211
+ }
212
+
213
+ // 4b. Insert file records (idempotent w.r.t. (branch, path) — acts as
214
+ // upsert for paths whose blob/mode/metadata changed).
159
215
  for (const file of files) {
160
216
  await this._db.insert('@gip/files', {
161
- branch: branchName,
217
+ branch: refName,
162
218
  path: file.path,
163
219
  oid: file.oid,
164
220
  mode: file.mode,
@@ -169,21 +225,38 @@ class Remote extends ReadyResource {
169
225
  })
170
226
  }
171
227
 
172
- // 5. Insert branch record
173
- await this._db.insert('@gip/branches', {
174
- name: branchName,
175
- commitOid,
176
- treeOid: commit.tree,
177
- author: commit.author,
178
- message: commit.message,
179
- timestamp: commit.timestamp,
180
- objects: [...objects.keys()]
181
- })
228
+ const isTag = refName.startsWith('tags/')
229
+
230
+ if (isTag) {
231
+ // 5a. Insert tag record
232
+ const tagName = refName.slice(5) // strip 'tags/'
233
+ await this._db.insert('@gip/tags', {
234
+ name: tagName,
235
+ oid,
236
+ commitOid: resolvedOid,
237
+ treeOid: commit.tree,
238
+ tagger: tagMeta ? tagMeta.tagger : null,
239
+ message: tagMeta ? tagMeta.message : null,
240
+ timestamp: tagMeta ? tagMeta.timestamp : 0,
241
+ objects: [...objects.keys()]
242
+ })
243
+ } else {
244
+ // 5b. Insert branch record
245
+ await this._db.insert('@gip/branches', {
246
+ name: refName,
247
+ commitOid: oid,
248
+ treeOid: commit.tree,
249
+ author: commit.author,
250
+ message: commit.message,
251
+ timestamp: commit.timestamp,
252
+ objects: [...objects.keys()]
253
+ })
182
254
 
183
- // 6. Set HEAD to first branch pushed (like git init)
184
- const currentHead = await this.getHead()
185
- if (!currentHead) {
186
- await this._db.insert('@gip/head', { branch: branchName })
255
+ // 6. Set HEAD to first branch pushed (like git init)
256
+ const currentHead = await this.getHead()
257
+ if (!currentHead) {
258
+ await this._db.insert('@gip/head', { branch: refName })
259
+ }
187
260
  }
188
261
 
189
262
  // 7. Flush
@@ -192,29 +265,41 @@ class Remote extends ReadyResource {
192
265
 
193
266
  // --- Fetch support ---
194
267
 
195
- async getRefObjects(commitOid, onLoad) {
196
- const branches = this._db.find('@gip/branches')
197
- let branch = null
268
+ async getRefObjects(oid, onLoad) {
269
+ let record = null
198
270
 
271
+ // Check branches first
272
+ const branches = this._db.find('@gip/branches')
199
273
  for await (const b of branches) {
200
- if (b.commitOid === commitOid) {
201
- branch = b
274
+ if (b.commitOid === oid) {
275
+ record = b
202
276
  break
203
277
  }
204
278
  }
205
279
 
206
- if (!branch) return []
280
+ // Then check tags
281
+ if (!record) {
282
+ const tags = this._db.find('@gip/tags')
283
+ for await (const t of tags) {
284
+ if (t.oid === oid) {
285
+ record = t
286
+ break
287
+ }
288
+ }
289
+ }
290
+
291
+ if (!record) return []
207
292
 
208
293
  const results = []
209
- for (const oid of branch.objects) {
210
- const obj = await this.getObject(oid)
294
+ for (const objOid of record.objects) {
295
+ const obj = await this.getObject(objOid)
211
296
  if (!obj) continue
212
297
 
213
298
  // Empty blobs have null data after round-tripping through compact-encoding
214
299
  const data = obj.data || Buffer.alloc(0)
215
300
 
216
301
  if (onLoad) onLoad(obj.size)
217
- results.push({ ...obj, data, id: oid })
302
+ results.push({ ...obj, data, id: objOid })
218
303
  }
219
304
 
220
305
  return results
@@ -223,8 +308,16 @@ class Remote extends ReadyResource {
223
308
  // --- Drive ---
224
309
 
225
310
  async toDrive(branch) {
311
+ // Check branches first, then tags
226
312
  const b = await this._db.get('@gip/branches', { name: branch })
227
- if (!b) return null
313
+ if (!b) {
314
+ const t = await this._db.get('@gip/tags', { name: branch })
315
+ if (!t) return null
316
+ // For tags, files are stored under 'tags/<name>'
317
+ const drive = new RemoteDrive(this._db, { branch: 'tags/' + branch })
318
+ await drive.ready()
319
+ return drive
320
+ }
228
321
 
229
322
  const drive = new RemoteDrive(this._db, { branch })
230
323
  await drive.ready()
package/lib/git.js CHANGED
@@ -35,6 +35,37 @@ function parseCommit(data) {
35
35
  return result
36
36
  }
37
37
 
38
+ // --- Git tag parser ---
39
+
40
+ function parseTag(data) {
41
+ const text = data.toString('utf8')
42
+ const lines = text.split('\n')
43
+ const result = { object: null, type: null, tag: null, tagger: null, timestamp: 0, message: '' }
44
+
45
+ let i = 0
46
+ for (; i < lines.length; i++) {
47
+ const line = lines[i]
48
+ if (line === '') {
49
+ i++
50
+ break
51
+ }
52
+
53
+ if (line.startsWith('object ')) result.object = line.slice(7)
54
+ else if (line.startsWith('type ')) result.type = line.slice(5)
55
+ else if (line.startsWith('tag ')) result.tag = line.slice(4)
56
+ else if (line.startsWith('tagger ')) {
57
+ const match = line.match(/^tagger (.+) <.+> (\d+) [+-]\d+$/)
58
+ if (match) {
59
+ result.tagger = match[1]
60
+ result.timestamp = parseInt(match[2])
61
+ }
62
+ }
63
+ }
64
+
65
+ result.message = lines.slice(i).join('\n').trim()
66
+ return result
67
+ }
68
+
38
69
  // --- Tree walker: extracts all file paths from git tree objects ---
39
70
 
40
71
  function walkTree(objects, treeOid, prefix) {
@@ -136,4 +167,4 @@ async function toDisk(opts) {
136
167
  }
137
168
  }
138
169
 
139
- module.exports = { parseCommit, walkTree, toDisk }
170
+ module.exports = { parseCommit, parseTag, walkTree, toDisk }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gip-remote",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "Git+Pear remote DB for handling git data",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "offset": 0,
4
4
  "schema": [
5
5
  {
@@ -77,6 +77,19 @@
77
77
  "derived": false,
78
78
  "key": [],
79
79
  "trigger": null
80
+ },
81
+ {
82
+ "name": "tags",
83
+ "namespace": "gip",
84
+ "id": 6,
85
+ "type": 1,
86
+ "version": 3,
87
+ "versionField": null,
88
+ "indexes": [],
89
+ "schema": "@gip/tags",
90
+ "derived": false,
91
+ "key": ["name"],
92
+ "trigger": null
80
93
  }
81
94
  ]
82
95
  }
@@ -4,7 +4,7 @@
4
4
  const { IndexEncoder, c, b4a } = require('hyperdb/runtime')
5
5
  const { version, getEncoding, setVersion } = require('./messages.js')
6
6
 
7
- const versions = { schema: version, db: 2 }
7
+ const versions = { schema: version, db: 3 }
8
8
 
9
9
  // '@gip/repos' collection key
10
10
  const collection0_key = new IndexEncoder([IndexEncoder.STRING], { prefix: 0 })
@@ -386,7 +386,72 @@ const collection5 = {
386
386
  decodedVersion: 0
387
387
  }
388
388
 
389
- const collections = [collection0, collection1, collection2, collection3, collection5]
389
+ // '@gip/tags' collection key
390
+ const collection6_key = new IndexEncoder([IndexEncoder.STRING], { prefix: 6 })
391
+
392
+ function collection6_indexify(record) {
393
+ const a = record.name
394
+ return a === undefined ? [] : [a]
395
+ }
396
+
397
+ // '@gip/tags' value encoding
398
+ const collection6_enc = getEncoding('@gip/tags/hyperdb#6')
399
+
400
+ // '@gip/tags' reconstruction function
401
+ function collection6_reconstruct(schemaVersion, keyBuf, valueBuf) {
402
+ const key = collection6_key.decode(keyBuf)
403
+ setVersion(schemaVersion)
404
+ const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
405
+ const type = c.uint.decode(state)
406
+ if (type !== 0) throw new Error('Unknown collection type: ' + type)
407
+ collection6.decodedVersion = c.uint.decode(state)
408
+ const record = collection6_enc.decode(state)
409
+ record.name = key[0]
410
+ return record
411
+ }
412
+ // '@gip/tags' key reconstruction function
413
+ function collection6_reconstruct_key(keyBuf) {
414
+ const key = collection6_key.decode(keyBuf)
415
+ return {
416
+ name: key[0]
417
+ }
418
+ }
419
+
420
+ // '@gip/tags'
421
+ const collection6 = {
422
+ name: '@gip/tags',
423
+ id: 6,
424
+ version: 3,
425
+ encodeKey(record) {
426
+ const key = [record.name]
427
+ return collection6_key.encode(key)
428
+ },
429
+ encodeKeyRange({ gt, lt, gte, lte } = {}) {
430
+ return collection6_key.encodeRange({
431
+ gt: gt ? collection6_indexify(gt) : null,
432
+ lt: lt ? collection6_indexify(lt) : null,
433
+ gte: gte ? collection6_indexify(gte) : null,
434
+ lte: lte ? collection6_indexify(lte) : null
435
+ })
436
+ },
437
+ encodeValue(schemaVersion, collectionVersion, record) {
438
+ setVersion(schemaVersion)
439
+ const state = { start: 0, end: 2, buffer: null }
440
+ collection6_enc.preencode(state, record)
441
+ state.buffer = b4a.allocUnsafe(state.end)
442
+ state.buffer[state.start++] = 0
443
+ state.buffer[state.start++] = collectionVersion
444
+ collection6_enc.encode(state, record)
445
+ return state.buffer
446
+ },
447
+ trigger: null,
448
+ reconstruct: collection6_reconstruct,
449
+ reconstructKey: collection6_reconstruct_key,
450
+ indexes: [],
451
+ decodedVersion: 0
452
+ }
453
+
454
+ const collections = [collection0, collection1, collection2, collection3, collection5, collection6]
390
455
 
391
456
  const indexes = [index4]
392
457
 
@@ -404,6 +469,8 @@ function resolveCollection(name) {
404
469
  return collection3
405
470
  case '@gip/head':
406
471
  return collection5
472
+ case '@gip/tags':
473
+ return collection6
407
474
  default:
408
475
  return null
409
476
  }
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 2
2
+ // Schema Version: 3
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  const { c } = require('hyperschema/runtime')
8
8
 
9
- const VERSION = 2
9
+ const VERSION = 3
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -234,8 +234,63 @@ const encoding5 = {
234
234
  }
235
235
  }
236
236
 
237
- // @gip/repos/hyperdb#0
237
+ // @gip/tags.objects
238
+ const encoding6_7 = encoding1_6
239
+
240
+ // @gip/tags
238
241
  const encoding6 = {
242
+ preencode(state, m) {
243
+ c.string.preencode(state, m.name)
244
+ c.string.preencode(state, m.oid)
245
+ c.string.preencode(state, m.commitOid)
246
+ c.string.preencode(state, m.treeOid)
247
+ state.end++ // flags are fixed size
248
+
249
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
250
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
251
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
252
+ if (version >= 3 && m.objects) encoding6_7.preencode(state, m.objects)
253
+ },
254
+ encode(state, m) {
255
+ const flags =
256
+ (version >= 3 && m.tagger ? 1 : 0) |
257
+ (version >= 3 && m.message ? 2 : 0) |
258
+ (version >= 3 && m.timestamp ? 4 : 0) |
259
+ (version >= 3 && m.objects ? 8 : 0)
260
+
261
+ c.string.encode(state, m.name)
262
+ c.string.encode(state, m.oid)
263
+ c.string.encode(state, m.commitOid)
264
+ c.string.encode(state, m.treeOid)
265
+ c.uint8.encode(state, flags)
266
+
267
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
268
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
269
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
270
+ if (version >= 3 && m.objects) encoding6_7.encode(state, m.objects)
271
+ },
272
+ decode(state) {
273
+ const r0 = c.string.decode(state)
274
+ const r1 = c.string.decode(state)
275
+ const r2 = c.string.decode(state)
276
+ const r3 = c.string.decode(state)
277
+ const flags = c.uint8.decode(state)
278
+
279
+ return {
280
+ name: r0,
281
+ oid: r1,
282
+ commitOid: r2,
283
+ treeOid: r3,
284
+ tagger: version >= 3 && (flags & 1) !== 0 ? c.string.decode(state) : null,
285
+ message: version >= 3 && (flags & 2) !== 0 ? c.string.decode(state) : null,
286
+ timestamp: version >= 3 && (flags & 4) !== 0 ? c.uint.decode(state) : 0,
287
+ objects: version >= 3 && (flags & 8) !== 0 ? encoding6_7.decode(state) : null
288
+ }
289
+ }
290
+ }
291
+
292
+ // @gip/repos/hyperdb#0
293
+ const encoding7 = {
239
294
  preencode(state, m) {
240
295
  c.buffer.preencode(state, m.key)
241
296
  state.end++ // flags are fixed size
@@ -266,10 +321,10 @@ const encoding6 = {
266
321
  }
267
322
 
268
323
  // @gip/branches/hyperdb#1.objects
269
- const encoding7_6 = encoding1_6
324
+ const encoding8_6 = encoding1_6
270
325
 
271
326
  // @gip/branches/hyperdb#1
272
- const encoding7 = {
327
+ const encoding8 = {
273
328
  preencode(state, m) {
274
329
  c.string.preencode(state, m.commitOid)
275
330
  c.string.preencode(state, m.treeOid)
@@ -278,7 +333,7 @@ const encoding7 = {
278
333
  if (m.author) c.string.preencode(state, m.author)
279
334
  if (m.message) c.string.preencode(state, m.message)
280
335
  if (m.timestamp) c.uint.preencode(state, m.timestamp)
281
- if (m.objects) encoding7_6.preencode(state, m.objects)
336
+ if (m.objects) encoding8_6.preencode(state, m.objects)
282
337
  },
283
338
  encode(state, m) {
284
339
  const flags =
@@ -291,7 +346,7 @@ const encoding7 = {
291
346
  if (m.author) c.string.encode(state, m.author)
292
347
  if (m.message) c.string.encode(state, m.message)
293
348
  if (m.timestamp) c.uint.encode(state, m.timestamp)
294
- if (m.objects) encoding7_6.encode(state, m.objects)
349
+ if (m.objects) encoding8_6.encode(state, m.objects)
295
350
  },
296
351
  decode(state) {
297
352
  const r1 = c.string.decode(state)
@@ -305,13 +360,13 @@ const encoding7 = {
305
360
  author: (flags & 1) !== 0 ? c.string.decode(state) : null,
306
361
  message: (flags & 2) !== 0 ? c.string.decode(state) : null,
307
362
  timestamp: (flags & 4) !== 0 ? c.uint.decode(state) : 0,
308
- objects: (flags & 8) !== 0 ? encoding7_6.decode(state) : null
363
+ objects: (flags & 8) !== 0 ? encoding8_6.decode(state) : null
309
364
  }
310
365
  }
311
366
  }
312
367
 
313
368
  // @gip/files/hyperdb#2
314
- const encoding8 = {
369
+ const encoding9 = {
315
370
  preencode(state, m) {
316
371
  c.string.preencode(state, m.oid)
317
372
  c.string.preencode(state, m.mode)
@@ -354,7 +409,7 @@ const encoding8 = {
354
409
  }
355
410
 
356
411
  // @gip/objects/hyperdb#3
357
- const encoding9 = {
412
+ const encoding10 = {
358
413
  preencode(state, m) {
359
414
  encoding3.preencode(state, m.type)
360
415
  c.uint.preencode(state, m.size)
@@ -379,6 +434,58 @@ const encoding9 = {
379
434
  }
380
435
  }
381
436
 
437
+ // @gip/tags/hyperdb#6.objects
438
+ const encoding11_7 = encoding1_6
439
+
440
+ // @gip/tags/hyperdb#6
441
+ const encoding11 = {
442
+ preencode(state, m) {
443
+ c.string.preencode(state, m.oid)
444
+ c.string.preencode(state, m.commitOid)
445
+ c.string.preencode(state, m.treeOid)
446
+ state.end++ // flags are fixed size
447
+
448
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
449
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
450
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
451
+ if (version >= 3 && m.objects) encoding11_7.preencode(state, m.objects)
452
+ },
453
+ encode(state, m) {
454
+ const flags =
455
+ (version >= 3 && m.tagger ? 1 : 0) |
456
+ (version >= 3 && m.message ? 2 : 0) |
457
+ (version >= 3 && m.timestamp ? 4 : 0) |
458
+ (version >= 3 && m.objects ? 8 : 0)
459
+
460
+ c.string.encode(state, m.oid)
461
+ c.string.encode(state, m.commitOid)
462
+ c.string.encode(state, m.treeOid)
463
+ c.uint8.encode(state, flags)
464
+
465
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
466
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
467
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
468
+ if (version >= 3 && m.objects) encoding11_7.encode(state, m.objects)
469
+ },
470
+ decode(state) {
471
+ const r1 = c.string.decode(state)
472
+ const r2 = c.string.decode(state)
473
+ const r3 = c.string.decode(state)
474
+ const flags = c.uint8.decode(state)
475
+
476
+ return {
477
+ name: null,
478
+ oid: r1,
479
+ commitOid: r2,
480
+ treeOid: r3,
481
+ tagger: version >= 3 && (flags & 1) !== 0 ? c.string.decode(state) : null,
482
+ message: version >= 3 && (flags & 2) !== 0 ? c.string.decode(state) : null,
483
+ timestamp: version >= 3 && (flags & 4) !== 0 ? c.uint.decode(state) : 0,
484
+ objects: version >= 3 && (flags & 8) !== 0 ? encoding11_7.decode(state) : null
485
+ }
486
+ }
487
+ }
488
+
382
489
  function setVersion(v) {
383
490
  version = v
384
491
  }
@@ -416,14 +523,18 @@ function getEncoding(name) {
416
523
  return encoding4
417
524
  case '@gip/head':
418
525
  return encoding5
419
- case '@gip/repos/hyperdb#0':
526
+ case '@gip/tags':
420
527
  return encoding6
421
- case '@gip/branches/hyperdb#1':
528
+ case '@gip/repos/hyperdb#0':
422
529
  return encoding7
423
- case '@gip/files/hyperdb#2':
530
+ case '@gip/branches/hyperdb#1':
424
531
  return encoding8
425
- case '@gip/objects/hyperdb#3':
532
+ case '@gip/files/hyperdb#2':
426
533
  return encoding9
534
+ case '@gip/objects/hyperdb#3':
535
+ return encoding10
536
+ case '@gip/tags/hyperdb#6':
537
+ return encoding11
427
538
  default:
428
539
  throw new Error('Encoder not found ' + name)
429
540
  }
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 2
2
+ // Schema Version: 3
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  const { c } = require('hyperschema/runtime')
8
8
 
9
- const VERSION = 2
9
+ const VERSION = 3
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -234,6 +234,61 @@ const encoding5 = {
234
234
  }
235
235
  }
236
236
 
237
+ // @gip/tags.objects
238
+ const encoding6_7 = encoding1_6
239
+
240
+ // @gip/tags
241
+ const encoding6 = {
242
+ preencode(state, m) {
243
+ c.string.preencode(state, m.name)
244
+ c.string.preencode(state, m.oid)
245
+ c.string.preencode(state, m.commitOid)
246
+ c.string.preencode(state, m.treeOid)
247
+ state.end++ // flags are fixed size
248
+
249
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
250
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
251
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
252
+ if (version >= 3 && m.objects) encoding6_7.preencode(state, m.objects)
253
+ },
254
+ encode(state, m) {
255
+ const flags =
256
+ (version >= 3 && m.tagger ? 1 : 0) |
257
+ (version >= 3 && m.message ? 2 : 0) |
258
+ (version >= 3 && m.timestamp ? 4 : 0) |
259
+ (version >= 3 && m.objects ? 8 : 0)
260
+
261
+ c.string.encode(state, m.name)
262
+ c.string.encode(state, m.oid)
263
+ c.string.encode(state, m.commitOid)
264
+ c.string.encode(state, m.treeOid)
265
+ c.uint8.encode(state, flags)
266
+
267
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
268
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
269
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
270
+ if (version >= 3 && m.objects) encoding6_7.encode(state, m.objects)
271
+ },
272
+ decode(state) {
273
+ const r0 = c.string.decode(state)
274
+ const r1 = c.string.decode(state)
275
+ const r2 = c.string.decode(state)
276
+ const r3 = c.string.decode(state)
277
+ const flags = c.uint8.decode(state)
278
+
279
+ return {
280
+ name: r0,
281
+ oid: r1,
282
+ commitOid: r2,
283
+ treeOid: r3,
284
+ tagger: version >= 3 && (flags & 1) !== 0 ? c.string.decode(state) : null,
285
+ message: version >= 3 && (flags & 2) !== 0 ? c.string.decode(state) : null,
286
+ timestamp: version >= 3 && (flags & 4) !== 0 ? c.uint.decode(state) : 0,
287
+ objects: version >= 3 && (flags & 8) !== 0 ? encoding6_7.decode(state) : null
288
+ }
289
+ }
290
+ }
291
+
237
292
  function setVersion(v) {
238
293
  version = v
239
294
  }
@@ -271,6 +326,8 @@ function getEncoding(name) {
271
326
  return encoding4
272
327
  case '@gip/head':
273
328
  return encoding5
329
+ case '@gip/tags':
330
+ return encoding6
274
331
  default:
275
332
  throw new Error('Encoder not found ' + name)
276
333
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "schema": [
4
4
  {
5
5
  "name": "repos",
@@ -208,6 +208,62 @@
208
208
  "version": 2
209
209
  }
210
210
  ]
211
+ },
212
+ {
213
+ "name": "tags",
214
+ "namespace": "gip",
215
+ "compact": true,
216
+ "flagsPosition": 4,
217
+ "fields": [
218
+ {
219
+ "name": "name",
220
+ "required": true,
221
+ "type": "string",
222
+ "version": 3
223
+ },
224
+ {
225
+ "name": "oid",
226
+ "required": true,
227
+ "type": "string",
228
+ "version": 3
229
+ },
230
+ {
231
+ "name": "commitOid",
232
+ "required": true,
233
+ "type": "string",
234
+ "version": 3
235
+ },
236
+ {
237
+ "name": "treeOid",
238
+ "required": true,
239
+ "type": "string",
240
+ "version": 3
241
+ },
242
+ {
243
+ "name": "tagger",
244
+ "required": false,
245
+ "type": "string",
246
+ "version": 3
247
+ },
248
+ {
249
+ "name": "message",
250
+ "required": false,
251
+ "type": "string",
252
+ "version": 3
253
+ },
254
+ {
255
+ "name": "timestamp",
256
+ "required": false,
257
+ "type": "uint",
258
+ "version": 3
259
+ },
260
+ {
261
+ "name": "objects",
262
+ "array": true,
263
+ "type": "string",
264
+ "version": 3
265
+ }
266
+ ]
211
267
  }
212
268
  ]
213
269
  }