git ssb

0+

cel / pull-git-remote-helper



Commit 04c77cc71b341054c04792a9bc6c74aa4c18d225

Start implementing pack negotiation and encoding

Charles Lehner committed on 2/8/2016, 4:37:24 AM
Parent: b1ed4631de0942640e4c7591c2be9dbdf8e98240

Files changed

index.jschanged
pack.jschanged
test/git-remote-full.jschanged
test/run.jschanged
util.jschanged
index.jsView
@@ -70,30 +70,94 @@
7070 * agent=git/2.7.0 */
7171 var sendRefs = receivePackHeader([
7272 ], refSource, false)
7373
74+ var lines = packLineDecode(read, options)
75+ // var havesSink = pull.drain(console.error.bind(console, 'have:'))
76+ var readHave = lines.haves
77+ var acked
78+ var commonHash
79+ var sendPack
80+
81+ function haveObject(hash, cb) {
82+ cb(/* TODO */)
83+ }
84+
85+ function getObjects(commonObjId, cb) {
86+ console.error('get obj', commonObjId)
87+ cb(null, 0, function readObject(end, cb) {
88+ console.error('read obj', end)
89+ // cb(new Error('Not implemented'))
90+ cb(true)
91+ })
92+ }
93+
94+ // Packfile negotiation
7495 return packLineEncode(
7596 cat([
7697 sendRefs,
7798 pull.once(''),
7899 function (abort, cb) {
79100 if (abort) return
80- // read client wants
81- var lines = packLineDecode(read, options)
101+ if (acked) return cb(true)
102+ // read upload request (wants list) from client
82103 pull(
83104 lines.wants,
84105 onThroughEnd(wantsDone),
85106 wantSink
86107 )
108+
87109 function wantsDone(err) {
110+ console.error('wants done', err)
88111 if (err) return cb(err)
112+ // Read upload haves (haves list).
113+ // On first obj-id that we have, ACK
114+ // If we have none, NAK.
115+ // TODO: implement multi_ack_detailed
116+ readHave(null, function next(end, have) {
117+ ended = end
118+ if (end === true) {
119+ // found no common object
120+ acked = true
121+ cb(null, 'NAK')
122+ } else if (end)
123+ cb(end)
124+ else if (have.type != 'have')
125+ cb(new Error('Unknown have' + JSON.stringify(have)))
126+ else
127+ haveObject(have.hash, function (haveIt) {
128+ if (!haveIt)
129+ return readHave(null, next)
130+ commonHash = haveIt
131+ acked = true
132+ cb(null, 'ACK ' + have.hash)
133+ })
134+ })
135+ }
136+ /*
137+ function havesDone(err) {
138+ console.error('haves done', err)
139+ if (err) return cb(err)
140+ cb(true)
89141 pull(
90142 lines.passthrough,
91143 pull.drain(function (buf) {
92- console.error('got buf after wants', buf.toString('ascii'))
144+ console.error('got buf after wants', buf.length, buf.toString('ascii'))
93145 })
94146 )
95147 }
148+ */
149+ },
150+ function next(abort, cb) {
151+ if (abort) return cb(abort)
152+ // send pack file to client
153+ if (!sendPack)
154+ getObjects(commonHash, function (err, numObjects, readObject) {
155+ sendPack = pack.encode(numObjects, readObject)
156+ next(abort, cb)
157+ })
158+ else
159+ sendPack(abort, cb)
96160 }
97161 ])
98162 )
99163 }
@@ -105,10 +169,18 @@
105169 read(end, function (end, data) {
106170 if (ended = end) {
107171 cb(end)
108172 } else {
109- var len = data ? data.length + 5 : 0
110- cb(end, ('000' + len.toString(16)).substr(-4) + data + '\n')
173+ // console.error("data", data)
174+ if (data)
175+ data += '\n'
176+ else
177+ data = ''
178+ var len = data ? data.length + 4 : 0
179+ var hexLen = ('000' + len.toString(16)).substr(-4)
180+ var pkt = hexLen + data
181+ // console.error('>', JSON.stringify(pkt))
182+ cb(end, pkt)
111183 }
112184 })
113185 }
114186 }
@@ -122,8 +194,9 @@
122194 var readPrefix = b.chunks(4)
123195 var ended
124196
125197 function readPackLine(abort, cb) {
198+ if (ended) return cb(ended)
126199 readPrefix(abort, function (end, buf) {
127200 if (ended = end) return cb(end)
128201 var len = parseInt(buf, 16)
129202 if (!len)
@@ -135,8 +208,21 @@
135208 })
136209 })
137210 }
138211
212+ function readPackLineStr(abort, cb) {
213+ if (ended) return cb(ended)
214+ readPackLine(abort, function (end, buf) {
215+ if (ended = end) return cb(end)
216+ // trim newline
217+ var len = buf.length
218+ if (buf[len - 1] == 0xa)
219+ len--
220+ var line = buf.toString('ascii', 0, len)
221+ cb(null, line)
222+ })
223+ }
224+
139225 function readUpdate(abort, cb) {
140226 readPackLine(abort, function (end, line) {
141227 if (end) return cb(end)
142228 if (options.verbosity >= 2)
@@ -155,27 +241,50 @@
155241 })
156242 }
157243
158244 function readWant(abort, cb) {
245+ readPackLineStr(abort, function (end, line) {
246+ if (end) return cb(end)
247+ if (options.verbosity >= 2)
248+ console.error('line', line)
249+ // if (!line.length) return cb(true)
250+ if (!line.length || line == 'done') return cb(true)
251+ var args = split3(line)
252+ var caps = args[2]
253+ if (caps && options.verbosity >= 2)
254+ console.error('want capabilities:', caps)
255+ cb(null, {
256+ type: args[0],
257+ hash: args[1],
258+ })
259+ })
260+ }
261+
262+ /*
263+ function readWant(abort, cb) {
159264 readPackLine(abort, function (end, line) {
160265 if (end) return cb(end)
161266 if (options.verbosity >= 2)
162267 console.error('line', line.toString('ascii'))
163- if (!line.length || line == 'done') return cb(true)
268+ if (!line.length || line == 'done') {
269+ console.error('WANTS done', line, line.length)
270+ return cb(true)
271+ }
164272 var args = split3(line.toString('ascii'))
165273 var caps = args[2]
166274 if (caps && options.verbosity >= 2)
167275 console.error('want capabilities:', caps)
168276 cb(null, {
169277 type: args[0],
170- hash: args[1],
278+ hash: args[1].replace(/\n$/, ''),
171279 })
172280 })
173281 }
282+ */
174283
175284 b.packLines = readPackLine
176285 b.updates = readUpdate
177- b.wants = readWant
286+ b.wants = b.haves = readWant
178287
179288 return b
180289 }
181290
pack.jsView
@@ -2,11 +2,15 @@
22 var pull = require('pull-stream')
33 var toPull = require('stream-to-pull-stream')
44 var Inflate = require('pako/lib/inflate').Inflate
55 var createHash = require('./util').createHash
6+var cat = require('pull-cat')
67
78 exports.decode = decodePack
9+exports.encode = encodePack
810
11+var PACK_VERSION = 2
12+
913 var objectTypes = [
1014 'none', 'commit', 'tree', 'blob',
1115 'tag', 'unused', 'ofs-delta', 'ref-delta'
1216 ]
@@ -170,4 +174,29 @@
170174 }
171175
172176 return readObject
173177 }
178+
179+function encodePack(numObjects, readObject) {
180+ var ended
181+ var header = new Buffer(12)
182+ header.write('PACK')
183+ header.writeUInt32BE(PACK_VERSION, 4)
184+ header.writeUInt32BE(numObjects, 8)
185+ var checksum = createHash('sha1')
186+
187+ return pull.through(function (data) {
188+ console.error('> ' + data.length, data.toString())
189+ })(cat([
190+ checksum(cat([
191+ pull.once(header),
192+ function (abort, cb) {
193+ if (ended) return cb(ended)
194+ readObject(abort, function (end, type, length, read) {
195+ if (ended = end) return cb(end)
196+ console.error('TODO: encode object')
197+ })
198+ }
199+ ])),
200+ checksum.readDigest
201+ ]))
202+}
test/git-remote-full.jsView
@@ -21,9 +21,8 @@
2121 require('../')({
2222 prefix: 'foo',
2323 refSource: pull.values(refs),
2424 wantSink: pull.drain(function (want) {
25- console.error('got want', want)
2625 process.send({want: want})
2726 }),
2827 }),
2928 toPull(process.stdout, function (err) {
test/run.jsView
@@ -20,8 +20,12 @@
2020 full: 'full.js://'
2121 }
2222
2323 var tmpDir = mktemp.createDirSync(path.join(require('os').tmpdir(), 'XXXXXXX'))
24+tape.onFinish(function () {
25+ if (tmpDir)
26+ rimraf.sync(tmpDir)
27+})
2428
2529 function handleIpcMessage(t, cb) {
2630 return function (msg) {
2731 if (msg.error) {
@@ -149,17 +153,30 @@
149153 })
150154 })
151155 })
152156
153-tape('fetch', function (t) {
157+0 &&
158+tape('fetch when already up-to-date', function (t) {
154159 t.git('fetch', '-vv', remote.full, function (msg) {
155- t.notOk('should not get a message here', msg)
160+ t.notOk(msg, 'should not get a message here')
156161 }, function (code) {
157162 t.equals(code, 0, 'fetched')
158163 t.end()
159164 })
160165 })
161166
162-tape.onFinish(function () {
163- if (tmpDir)
164- rimraf.sync(tmpDir)
167+0 &&
168+tape('clone into new dir', function (t) {
169+ var dir = path.join(tmpDir, 'clonedir')
170+ t.plan(3)
171+ t.git('clone', '-vv', remote.full, dir, function (msg) {
172+ if (msg.want)
173+ t.deepEquals(msg.want, {
174+ type: 'want',
175+ hash: 'edb5b50e8019797925820007d318870f8c346726'
176+ }, 'got want')
177+ else
178+ t.notOk(msg, 'unexpected message')
179+ }, function (code) {
180+ t.equals(code, 0, 'cloned')
181+ })
165182 })
util.jsView
@@ -3,10 +3,15 @@
33
44 exports.createHash = function (type) {
55 var hash = crypto.createHash(type)
66 var hasher = pull.through(hash.update.bind(hash))
7+ var digest
78 hasher.hash = hash
89 hasher.digest = hash.digest.bind(hash)
10+ hasher.readDigest = function (abort, cb) {
11+ if (digest) cb(true)
12+ else cb(null, digest = hash.digest())
13+ }
914 return hasher
1015 }
1116
1217 exports.createGitObjectHash = function (objectType, objectLength) {

Built with git-ssb-web