UNPKG

simple-breakpad-server

Version:
151 lines (134 loc) 4.18 kB
(function() { var COMPOSITE_INDEX, Sequelize, Symfile, cache, config, fs, options, path, schema, sequelize, streamToArray, symbolsPath; config = require('../config'); cache = require('./cache'); Sequelize = require('sequelize'); sequelize = require('./db'); fs = require('fs-promise'); path = require('path'); streamToArray = require('stream-to-array'); symbolsPath = config.getSymbolsPath(); COMPOSITE_INDEX = 'compositeIndex'; schema = { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, os: { type: Sequelize.STRING, unique: COMPOSITE_INDEX }, name: { type: Sequelize.STRING, unique: COMPOSITE_INDEX }, code: { type: Sequelize.STRING, unique: COMPOSITE_INDEX }, arch: { type: Sequelize.STRING, unique: COMPOSITE_INDEX }, contents: Sequelize.TEXT }; options = { indexes: [ { fields: ['created_at'] } ] }; Symfile = sequelize.define('symfiles', schema, options); Symfile.saveToDisk = function(symfile) { var symfileDir; symfileDir = path.join(symbolsPath, symfile.name, symfile.code); return fs.mkdirs(symfileDir).then(function() { var filePath, symbol_name; symbol_name = symfile.name; if (path.extname(symbol_name).toLowerCase() === '.pdb') { symbol_name = symbol_name.slice(0, -4); } symbol_name += '.sym'; filePath = path.join(symfileDir, symbol_name); return fs.writeFile(filePath, symfile.contents); }); }; Symfile.createFromRequest = function(req, callback) { var props, streamOps; props = {}; streamOps = []; req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype) { return streamOps.push(streamToArray(file).then(function(parts) { var buffers, i, j, part, ref; buffers = []; for (i = j = 0, ref = parts.length - 1; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) { part = parts[i]; buffers.push(part instanceof Buffer ? part : new Buffer(part)); } return Buffer.concat(buffers); }).then(function(buffer) { if (fieldname === 'symfile') { return props[fieldname] = buffer.toString(); } })); }); req.busboy.on('finish', function() { return Promise.all(streamOps).then(function() { var arch, code, contents, dec, header, msg, name, os; if (!'symfile' in props) { res.status(400); throw new Error('Form must include a "symfile" field'); } contents = props.symfile; header = contents.split('\n')[0].split(/\s+/); dec = header[0], os = header[1], arch = header[2], code = header[3], name = header[4]; if (dec !== 'MODULE') { msg = 'Could not parse header (expecting MODULE as first line)'; throw new Error(msg); } props = { os: os, arch: arch, code: code, name: name, contents: contents }; return sequelize.transaction(function(t) { var whereDuplicated; whereDuplicated = { where: { os: os, arch: arch, code: code, name: name } }; return Symfile.findOne(whereDuplicated, { transaction: t }).then(function(duplicate) { var p; p = duplicate != null ? duplicate.destroy({ transaction: t }) : Promise.resolve(); return p.then(function() { return Symfile.create(props, { transaction: t }).then(function(symfile) { return Symfile.saveToDisk(symfile).then(function() { cache.clear(); return callback(null, symfile); }); }); }); }); }); })["catch"](function(err) { return callback(err); }); }); return req.pipe(req.busboy); }; module.exports = Symfile; }).call(this);