aboutsummaryrefslogtreecommitdiff
path: root/lib/serve.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/serve.js')
-rw-r--r--lib/serve.js117
1 files changed, 117 insertions, 0 deletions
diff --git a/lib/serve.js b/lib/serve.js
index 8d3eeba..4e8c15d 100644
--- a/lib/serve.js
+++ b/lib/serve.js
@@ -119,6 +119,7 @@ Serve.prototype.go = function () {
else if (data.action === 'publish') self.publishJSON(next)
else if (data.action === 'vote') self.publishVote(next)
else if (data.action === 'contact') self.publishContact(next)
+ else if (data.action === 'want-blobs') self.wantBlobs(next)
else next()
}
@@ -172,6 +173,22 @@ Serve.prototype.publishContact = function (cb) {
this.publish(content, cb)
}
+Serve.prototype.wantBlobs = function (cb) {
+ var self = this
+ if (!self.data.blob_ids) return cb()
+ var ids = self.data.blob_ids.split(',')
+ if (!ids.every(u.isRef)) return cb(new Error('bad blob ids ' + ids.join(',')))
+ var done = multicb({pluck: 1})
+ ids.forEach(function (id) {
+ self.app.sbot.blobs.want(id, done())
+ })
+ done(function (err) {
+ if (err) return cb(err)
+ // self.note = h('div', 'wanted blobs: ' + ids.join(', ') + '.')
+ cb()
+ })
+}
+
Serve.prototype.publish = function (content, cb) {
var self = this
var done = multicb({pluck: 1, spread: true})
@@ -257,6 +274,7 @@ Serve.prototype.path = function (url) {
case '/emoji': return this.emoji(m[2])
case '/contacts': return this.contacts(m[2])
case '/about': return this.about(m[2])
+ case '/git': return this.git(m[2])
}
return this.respond(404, 'Not found')
}
@@ -1063,6 +1081,20 @@ function catchHTMLError() {
}
}
+function catchTextError() {
+ return function (read) {
+ var ended
+ return function (abort, cb) {
+ if (ended) return cb(ended)
+ read(abort, function (end, data) {
+ if (!end || end === true) return cb(end, data)
+ ended = true
+ cb(null, end.stack + '\n')
+ })
+ }
+ }
+}
+
function styles() {
return fs.readFileSync(path.join(__dirname, '../static/styles.css'), 'utf8')
}
@@ -1117,6 +1149,7 @@ Serve.prototype.wrapPage = function (title, searchQ) {
'published ',
self.app.render.msgLink(self.publishedMsg, done())
) : '',
+ // self.note,
content
)))
done(cb)
@@ -1245,6 +1278,65 @@ Serve.prototype.wrapUserFeed = function (isScrolled, id) {
})
}
+Serve.prototype.git = function (url) {
+ var m = /^\/?([^\/]*)\/?(.*)?$/.exec(url)
+ switch (m[1]) {
+ case 'commit': return this.gitCommit(m[2])
+ case 'tag': return this.gitCommit(m[2])
+ case 'raw': return this.gitRaw(m[2])
+ default: return this.respond(404, 'Not found')
+ }
+}
+
+Serve.prototype.gitRaw = function (rev) {
+ var self = this
+ if (!/[0-9a-f]{24}/.test(rev)) {
+ return pull(
+ pull.once('\'' + rev + '\' is not a git object id'),
+ self.respondSink(400, {'Content-Type': 'text/plain'})
+ )
+ }
+
+ var headMsgId = self.query.head
+ pull(
+ self.app.git.readObject({
+ id: rev,
+ headMsgId: headMsgId,
+ }),
+ catchTextError(),
+ self.respondSink(200, {'Content-type': 'text/plain'})
+ )
+}
+
+Serve.prototype.gitCommit = function (rev) {
+ var self = this
+ if (!/[0-9a-f]{24}/.test(rev)) {
+ return pull(
+ ph('div.error', 'rev is not a git object id'),
+ self.wrapPage('git'),
+ self.respondSink(400)
+ )
+ }
+
+ self.app.git.getCommit({
+ id: rev,
+ headMsgId: self.query.head,
+ }, function (err, commit) {
+ if (err && err.name === 'BlobNotFoundError')
+ return self.askWantBlobs(err.links)
+ if (err) return pull(
+ pull.once(u.renderError(err).outerHTML),
+ self.wrapPage('git object ' + rev),
+ self.respondSink(400)
+ )
+ pull(
+ pull.once(h('pre', self.app.render.linkify(commit.body)).outerHTML),
+ self.wrapPage('git object ' + rev),
+ self.respondSink(200)
+ )
+ })
+}
+
Serve.prototype.wrapPublic = function (opts) {
var self = this
return u.hyperwrap(function (thread, cb) {
@@ -1260,6 +1352,31 @@ Serve.prototype.wrapPublic = function (opts) {
})
}
+Serve.prototype.askWantBlobs = function (links) {
+ var self = this
+ pull(
+ ph('form', {action: '', method: 'post'}, [
+ ph('section', [
+ ph('h3', 'Missing blobs'),
+ ph('p', 'The application needs these blobs to continue:'),
+ ph('table', links.map(u.toLink).map(function (link) {
+ if (!u.isRef(link.link)) return
+ return ph('tr', [
+ ph('td', ph('code', link.link)),
+ ph('td', self.app.render.formatSize(link.size)),
+ ])
+ })),
+ ph('input', {type: 'hidden', name: 'action', value: 'want-blobs'}),
+ ph('input', {type: 'hidden', name: 'blob_ids',
+ value: links.map(u.linkDest).join(',')}),
+ ph('p', ph('input', {type: 'submit', value: 'Want Blobs'}))
+ ])
+ ]),
+ self.wrapPage('missing blobs'),
+ self.respondSink(409)
+ )
+}
+
Serve.prototype.wrapPrivate = function (opts) {
var self = this
return u.hyperwrap(function (thread, cb) {