Skip to content

Instantly share code, notes, and snippets.

@chrisdickinson
Last active December 15, 2015 16:38
Show Gist options
  • Save chrisdickinson/5290339 to your computer and use it in GitHub Desktop.
Save chrisdickinson/5290339 to your computer and use it in GitHub Desktop.
based on the newly released `git-list-pack` stream; this is an example of cloning repos from the browser. use `browserify client.js > bundle.js` to compile.
var shoe = require('shoe')
, fetch = require('git-fetch-pack')
, unpack = require('git-list-pack')
, through = require('through')
, Buffer = require('buffer').Buffer
// make a websocket connection to the
// server.
var conn = shoe('/git')
, client
// automatically clone plate.
client = fetch(
'git://github.com/chrisdickinson/plate.git'
, want
)
// we get a callback for each ref. say `true`
// if we want the ref, `false` if we don't.
function want(ref, ready) {
return ready(/heads/.test(ref.name))
}
client
.pipe(conn)
.pipe(parse())
.pipe(client)
// `pack` is a separate stream that
// emits binary packfile data.
client.pack.pipe(unpack()).on('data', function(obj) {
console.log(obj.offset, obj.num)
})
// parse turns our serialized objects
// back into js objects.
function parse() {
return through(function(data) {
// turn it back into a JS object + buffer data.
data = JSON.parse(data)
if(data.data !== null) {
data.data = new Buffer(data.data, 'base64')
}
this.queue(data)
})
}
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>test git</h1>
<script src="/bundle.js"></script>
</body>
</html>
var net = require('net')
, fs = require('fs')
var unpack = require('git-list-pack')
, concat = require('concat-stream')
, transport = require('git-transport-protocol')
, through = require('through')
var http = require('http')
, ecstatic = require('ecstatic')(__dirname)
, shoe = require('shoe')
, server
, sock
// serve up files.
server = http.createServer(ecstatic)
server.listen(9999)
// do websockets. install at `/git`.
sock = shoe(connect)
sock.install(server, '/git')
function connect(conn) {
// this runs whenever we get a new websocket connection.
var tcp = net.connect({host: 'github.com', port: 9418})
conn
.pipe(transport(tcp))
.pipe(translate())
.pipe(conn)
}
function translate() {
return through(function(data) {
// if there's data, base64 so we don't have any
// silly unicode issues. then queue
// up the stringified object.
data.data = data.data ? data.data.toString('base64') : null
this.queue(JSON.stringify(data))
})
}
@maks
Copy link

maks commented Apr 3, 2013

awesome work Chris!
doing a quick test...
works: git://github.com/maks/git-object-hash.git
fails: git://github.com/maks/testsite.git

can't really tell why though, adding logging into server,js in translate(through()) shows it stops on the first pkt-flush line on the failing repo - not sure if thats helpful?

@chrisdickinson
Copy link
Author

@maks thanks! that problem is interesting. I got testsite working by modifying the want function accept /(HEAD|heads)/ instead of just /heads/. you might check that?

I've run into intermittent bugs when cloning -- something is getting a sourceEnd oob in git-read-pkt-line. it's definitely a timing thing and is thus hard to reproduce, but I'm confident I'll have a solution soon.

@maks
Copy link

maks commented Apr 3, 2013

Doh! Didn't even think to look at the want function or log what it was getting passed in as a ref name.

@chrisdickinson sweet, that works! And its fixed it for a bunch of my other github repos that I tested yesterday and weren't working.

@maks
Copy link

maks commented Apr 3, 2013

@chrisdickinson actually I think it would be nice to clean this up a little bit, add package.json for the deps and put it into its own named repo as a sample or demo app of your modules. I'd be happy to do that if you like? I should have time this evening (I'm in GMT+1100)

@dignifiedquire
Copy link

I've created a repo while working with this stuff as @maks suggested. I've added a little bit stuff to the template and a write function to write stuff into the html. You can find it here: dignifiedquire/js-git-demo.

@chrisdickinson I've also tried to use git-objectify-pack with it to get real objects, but it fails with this stack trace:

Uncaught TypeError: Object [object Array] has no method 'copy' index.js:442
Buffer.concat index.js:442
hashify index.js:14
write index.js:35
stream.write index.js:25
ondata stream.js:17
EventEmitter.emit events.js:57
drain index.js:35
stream.queue.stream.push index.js:41
got_inflate index.js:185
should_break index.js:208
done index.js:102
check_adler index.js:87
i index.js:64
(anonymous function) zlib-browser.js:19
(anonymous function) browser.js:23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment