diff options
| author | Chris Ball <chris@printf.net> | 2015-05-27 16:54:10 -0400 |
|---|---|---|
| committer | Chris Ball <chris@printf.net> | 2015-05-27 16:54:10 -0400 |
| commit | edf024a982457bc40862a66e4eda910ad4fff5b3 (patch) | |
| tree | e7a8cc24cf87f0a7b48edf7d72fca8b475c647c9 /git-remote-gittorrent | |
| parent | 59635ae30cb7982fbfad78aabe3f637b9e8adcae (diff) | |
Rename! gitswarm->gittorrent
Diffstat (limited to 'git-remote-gittorrent')
| -rwxr-xr-x | git-remote-gittorrent | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/git-remote-gittorrent b/git-remote-gittorrent new file mode 100755 index 0000000..a8bcb9d --- /dev/null +++ b/git-remote-gittorrent @@ -0,0 +1,132 @@ +#!/usr/bin/env node + +var Chalk = require('chalk') +var DHT = require('bittorrent-dht') +var exec = require('child_process').exec +var fs = require('fs') +var magnet = require('magnet-uri') +var spawn = require('child_process').spawn +var Swarm = require('bittorrent-swarm') +var ut_gittorrent = require('ut_gittorrent') +var WebTorrent = require('webtorrent') + +function die (error) { + console.error(error) + process.exit(1) +} + +// Gotta enable color manually because stdout isn't a tty. +var chalk = new Chalk.constructor({enabled: true}); + +var dht = new DHT({ + bootstrap: ['three.printf.net:6882'] +}) + +var url = process.argv[3] +var matches = url.match(/gittorrent:\/\/([a-f0-9]{40})\/(.*)/) +if (matches) { + var key = matches[1] + var reponame = matches[2] + dht.on('ready', function () { + var val = new Buffer(key, 'hex') + dht.get(val, function (err, res) { + if (err) { + return console.error(err) + } + var json = res.v.toString() + var repos = JSON.parse(json) + console.warn('\nMutable key ' + chalk.green(key) + ' returned:\n' + chalk.yellow(json)) + get_infohash(repos.repositories[reponame].master) + }) + }) +} else { + url = url.replace(/^gittorrent:/i, 'git:') + exec('git ls-remote ' + url + ' HEAD', function (err, stdout, stderr) { + if (err !== null) { + die(err) + } + var lines = stdout.split('\n') + if (lines.length !== 2) { + die("Didn't get back a single HEAD ref: " + lines) + } + var line = lines[0].split('\t') + var ref = line[0] + var head = line[1] + if (head !== 'HEAD') { + die("Couldn't parse the ref line: " + ref, head) + } + if (ref.length !== 40) { + die('Was expecting a 40-byte sha: ' + ref) + } + dht.on('ready', function () { + get_infohash(ref) + }) + }) +} + +function get_infohash (ref) { + // We use console.warn (stderr) because git ignores our writes to stdout. + console.warn('\nOkay, we want to get: ' + chalk.green(ref) + '\n') + + process.stdin.setEncoding('utf8') + process.stdin.on('readable', function () { + var chunk = process.stdin.read() + if (chunk === 'capabilities\n') { + process.stdout.write('fetch\n\n') + } + if (chunk === 'list\n') { + process.stdout.write(ref + ' refs/heads/master\n\n') + } + }) + process.stdout.on('error', function () { + // stdout was closed + }) + + var magnetUri = 'magnet:?xt=urn:btih:' + ref + var parsed = magnet(magnetUri) + dht.lookup(parsed.infoHash) + + dht.on('peer', function (addr, hash, from) { + swarm.addPeer(addr) + }) + + var swarm = new Swarm(parsed.infoHash, 'cafebabecafebabecafecafebabecafebabecafe') + swarm.on('wire', function (wire, addr) { + console.warn('Adding swarm peer: ' + chalk.green(addr) + '\n') + wire.use(ut_gittorrent()) + wire.ut_gittorrent.on('handshake', function () { + wire.ut_gittorrent.ask(parsed.infoHash) + }) + wire.ut_gittorrent.on('receivedTorrent', function (infoHash) { + var client = new WebTorrent({ + dht: { + bootstrap: ['three.printf.net:6882'] + }, + tracker: false + }) + client.download(infoHash, function (torrent) { + console.warn('Downloading git pack with infohash: ' + chalk.green(infoHash) + '\n') + torrent.on('done', function (done) { + var filename = torrent.storage.path + '/' + torrent.files[0].path + var unpack = spawn('git', ['index-pack', '--stdin', '-v', '--fix-thin']) + var stream = fs.createReadStream(filename) + stream.on('open', function () { + stream.pipe(unpack.stdin) + }) + unpack.stderr.pipe(process.stderr) + unpack.on('exit', function (code) { + var targetdir = process.env['GIT_DIR'] + var stream = fs.createWriteStream(targetdir + '/refs/heads/master') + stream.once('open', function (fd) { + stream.write(ref + '\n') + stream.end() + // These writes are actually necessary for git to finish checkout. + process.stdout.write('\n\n') + process.exit() + }) + }) + }) + }) + }) + }) +} |
