<commit_before>var internals = {};

/**
 * RLP Encoding based on: https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP
 * This function takes in a data, convert it to buffer if not, and a length for recursion
 *
 * @param {Buffer,String,Integer,Array} data - will be converted to buffer
 * @returns {Buffer} - returns buffer of encoded data
 **/
internals.encode = exports.encode = function(input) {
    if (input instanceof Array) {
        var output = [];
        for (var i in input) {
            output.push(internals.encode(input[i]));
        }
        var buf = Buffer.concat(output);
        return Buffer.concat([internals.encodeLength(buf.length, 192), buf]);
    } else {
        input = internals.toBuffer(input);
        if (input.length == 1 && input[0] < 128) {
            return input;
        } else {
            return Buffer.concat([internals.encodeLength(input.length, 128), input]);
        }
    }
};

internals.encodeLength = function(len, offset) {
    if (len < 56) {
        return new Buffer([len + offset]);
    } else {
        var hexLength = internals.intToHex(len);
        var lLength = hexLength.length / 2;
        var firstByte = internals.intToHex(offset + 55 + lLength);
        return new Buffer(firstByte + hexLength, 'hex');
    }
};

/**
 * RLP Decoding based on: {@link https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP|RLP}
 *
 * @param {Buffer,String,Integer,Array} data - will be converted to buffer
 * @returns {Array} - returns decode Array of Buffers containg the original message
 **/
exports.decode = function(input) {
    var input = internals.toBuffer(input);
    return internals._decode(input).data;
};

internals._decode = function(input) {
    var firstByte = input[0];
    if (firstByte <= 0x7f) {
        //a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.
        return {
            data: input.slice(0, 1),
            remainder: input.slice(1)
        };
    } else if (firstByte <= 0xb7) {
        //string is 0-55 bytes long. A single byte with value 0x80 plus the length of the string followed by the string
        //The range of the first byte is [0x80, 0xb7]
        var length = firstByte - 0x7f,
            data;

        //set 0x80 null to 0
        if(firstByte === 0x80){
            data = new Buffer([0]);
        }else{
            data = input.slice(1, length);
        }
        return {
            data: data,
            remainder: input.slice(length)
        };
    } else if (firstByte <= 0xbf) {
        var llength = firstByte - 0xb6;
        var length = parseInt(input.slice(1, llength).toString('hex'), 16);
        return {
            data: input.slice(llength, length + llength),
            remainder: input.slice(length + llength)
        };
    } else if (firstByte <= 0xf7) {
        //a list between  0-55 bytes long
        var length = firstByte - 0xbf;
        var remainder = input.slice(1);
        var innerRemainder = input.slice(1, length);
        var decoded = [];
        while (innerRemainder.length) {
            var d = internals._decode(innerRemainder);
            decoded.push(d.data);
            innerRemainder = d.remainder;
        }

        return {
            data: decoded,
            remainder: input.slice(length)
        };

    } else {
        //a list  over 55 bytes long
        var llength = firstByte - 0xf6;
        var length = parseInt(input.slice(1, llength).toString('hex'), 16);
        var remainder = input.slice(llength);
        var innerRemainder = input.slice(llength, llength + length);
        var decoded = [];
        while (innerRemainder.length) {
            var d = internals._decode(innerRemainder);
            decoded.push(d.data);
            innerRemainder = d.remainder;
        }
        return {
            data: decoded,
            remainder: input.slice(llength + length)
        };
    }
};

internals.intToHex = function(i) {
    var hex = i.toString(16);
    if (hex.length % 2) {
        hex = '0' + hex;
    }
    return hex;
};

internals.toBuffer = function(input) {
    if (Buffer.isBuffer(input)) {
        if(input.length === 1 && input[0] === 0){
            return this.toBuffer(null);
        }else{
            return input;
        }
    } else if (input === null || input === 0 || input === undefined) {
        return new Buffer(0);
    } else if (!isNaN(input)) {
        var hex = internals.intToHex(input);
        return new Buffer(hex, 'hex');
    } else if (!Buffer.isBuffer(input)) {
        return new Buffer(input.toString());
    }
};
<commit_msg>cleanup code<commit_after>/**
 * RLP Encoding based on: https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP
 * This function takes in a data, convert it to buffer if not, and a length for recursion
 *
 * @param {Buffer,String,Integer,Array} data - will be converted to buffer
 * @returns {Buffer} - returns buffer of encoded data
 **/
var encode = exports.encode = function (input) {
  if (input instanceof Array) {
    var output = [];
    for (var i in input) {
      output.push(encode(input[i]));
    }
    var buf = Buffer.concat(output);
    return Buffer.concat([encodeLength(buf.length, 192), buf]);
  } else {
    input = toBuffer(input);
    if (input.length === 1 && input[0] < 128) {
      return input;
    } else {
      return Buffer.concat([encodeLength(input.length, 128), input]);
    }
  }
};

function encodeLength(len, offset) {
  if (len < 56) {
    return new Buffer([len + offset]);
  } else {
    var hexLength = intToHex(len);
    var lLength = hexLength.length / 2;
    var firstByte = intToHex(offset + 55 + lLength);
    return new Buffer(firstByte + hexLength, 'hex');
  }
}

/**
 * RLP Decoding based on: {@link https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP|RLP}
 *
 * @param {Buffer,String,Integer,Array} data - will be converted to buffer
 * @returns {Array} - returns decode Array of Buffers containg the original message
 **/
var decode = exports.decode = function (input) {
  input = toBuffer(input);
  return _decode(input).data;
};

function _decode (input) {
  var firstByte = input[0];
  if (firstByte <= 0x7f) {
    //a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.
    return {
      data: input.slice(0, 1),
      remainder: input.slice(1)
    };
  } else if (firstByte <= 0xb7) {
    //string is 0-55 bytes long. A single byte with value 0x80 plus the length of the string followed by the string
    //The range of the first byte is [0x80, 0xb7]
    var length = firstByte - 0x7f,
      data;

    //set 0x80 null to 0
    if (firstByte === 0x80) {
      data = new Buffer([0]);
    } else {
      data = input.slice(1, length);
    }
    return {
      data: data,
      remainder: input.slice(length)
    };
  } else if (firstByte <= 0xbf) {
    var llength = firstByte - 0xb6;
    var length = parseInt(input.slice(1, llength).toString('hex'), 16);
    return {
      data: input.slice(llength, length + llength),
      remainder: input.slice(length + llength)
    };
  } else if (firstByte <= 0xf7) {
    //a list between  0-55 bytes long
    var length = firstByte - 0xbf;
    var remainder = input.slice(1);
    var innerRemainder = input.slice(1, length);
    var decoded = [];
    while (innerRemainder.length) {
      var d = _decode(innerRemainder);
      decoded.push(d.data);
      innerRemainder = d.remainder;
    }

    return {
      data: decoded,
      remainder: input.slice(length)
    };

  } else {
    //a list  over 55 bytes long
    var llength = firstByte - 0xf6;
    var length = parseInt(input.slice(1, llength).toString('hex'), 16);
    var remainder = input.slice(llength);
    var innerRemainder = input.slice(llength, llength + length);
    var decoded = [];
    while (innerRemainder.length) {
      var d = _decode(innerRemainder);
      decoded.push(d.data);
      innerRemainder = d.remainder;
    }
    return {
      data: decoded,
      remainder: input.slice(llength + length)
    };
  }
}

function intToHex (i) {
  var hex = i.toString(16);
  if (hex.length % 2) {
    hex = '0' + hex;
  }
  return hex;
}

function toBuffer (input) {
  if (Buffer.isBuffer(input)) {
    if (input.length === 1 && input[0] === 0) {
      return this.toBuffer(null);
    } else {
      return input;
    }
  } else if (input === null || input === 0 || input === undefined) {
    return new Buffer(0);
  } else if (!isNaN(input)) {
    var hex = intToHex(input);
    return new Buffer(hex, 'hex');
  } else if (!Buffer.isBuffer(input)) {
    return new Buffer(input.toString());
  }
}
<|endoftext|>


<commit_before>var path = require('path')
var level = require('level')
var crypto = require('crypto')
var mkdirp = require('mkdirp')
var pumpify = require('pumpify')
var pump = require('pump')
var cuid = require('cuid')
var fs = require('fs')
var fuse = require('fuse-bindings')
var lexint = require('lexicographic-integer')
var union = require('sorted-union-stream')
var events = require('events')
var mknod = require('mknod')
var subleveldown = require('subleveldown')
var enumerate = require('level-enumerate')

var noop = function () {}
var ENOENT = new Error('ENOENT')
ENOENT.code = 'ENOENT'

module.exports = function (home) {
  var that = {}

  var db = level(path.join(home, 'db'))
  var blobs = path.join(home, 'blobs')
  var mounts = path.join(home, 'mounts')

  var getId = enumerate(subleveldown(db, 'ids'))
  var files = subleveldown(db, 'files', {valueEncoding: 'json'})
  var parents = subleveldown(db, 'parents')

  var blobPath = function (hash) {
    return path.join(blobs, hash.slice(0, 2), hash.slice(2, 4), hash.slice(4))
  }

  var toIndexKey = function(name) {
    var depth = name.split('/').length - 1
    return lexint.pack(depth, 'hex') + '!' + name
  }

  that.add = function (layer, filename, stat, cb) {
    var key = layer + '!' + toIndexKey(filename)
    stat.ctime = stat.ctime || Date.now()
    stat.mtime = stat.mtime || Date.now()
    console.log('add', key)
    files.put(key, stat, cb)
  }

  that.get = function (layer, filename, cb) {
    var key = layer + '!' + toIndexKey(filename)
    console.log('get', key)
    files.get(key, cb)
  }

  that.del = function (layer, filename, cb) {
    var key = layer + '!' + toIndexKey(filename)
    files.del(key, cb)
  }

  that.createLayerStream = function (layer) {

  }

  that.createBlobReadStream = function (hash) {
    return fs.createReadStream(blobPath(hash))
  }

  that.createBlobWriteStream = function () {
    var sha = crypto.createHash('sha256')
    var tmp = path.join(os.tmpdir(), 'cauf-file-' + cuid())
    var ws = fs.createWriteStream(tmp)

    ws.on('finish', function () {
      stream.cork()
      stream.key = sha.digest('hex')
      var filename = blobPath(stream.key)
      mkdir(path.join(filename, '..'), function (err) {
        if (err) return stream.destroy(err)
        fs.rename(tmp, filename, function (err) {
          if (err) return stream.destroy(err)
          stream.uncork()
        })
      })
    })

    var stream = pumpify(through(write), ws)
    return stream
  }

  that.unmount = function (mnt, cb) {
    fuse.unmount(mnt, cb)
  }

  that.mount = function (mnt, opts) {
    if (!opts) opts = {}

    var mount = new events.EventEmitter()

    mount.id = null
    mount.writes = null
    mount.layers = null

    mount.unmount = function (cb) {
      that.unmount(mnt, cb)
    }

    var cow = function (name, cb) {
      that.get(mount.id, name, function (err, file) {
        if (file) return cb(null, file)

        console.log('copy-on-write for', mount.id, name)

        var copy = function (file) {
          var done = function (err) {
            if (err) return cb(err)

            var newFile = {
              mode: file ? file.mode : 33188,
              rdev: file && file.rdev,
              uid: file && file.uid,
              gid: file && file.gid,
              blob: newBlob
            }

            that.add(mount.id, name, newFile, function (err) {
              if (err) return cb(err)
              cb(null, newFile)
            })
          }

          mkdirp(path.join(newBlob, '..'), function (err) {
            if (err) return cb(err)
            if (!file) return done()
            if (file.rdev) return mknod(newBlob, file.mode, file.rdev, done) // special file
            pump(fs.createReadStream(file.blob), fs.createWriteStream(newBlob), done)
          })
        }

        var newBlob = path.join(mount.writes, name)
        var loop = function (i) {
          if (i < 0) return copy(null)
          that.get(mount.layers[i], name, function (err, file) {
            if (err) return loop(i - 1)
            copy(file.deleted ? null : file)
          })
        }

        loop(mount.layers.length - 2)
      })
    }

    var toCompareKey = function (data) {
      return data.key.slice(data.key.indexOf('!') + 1)
    }

    var createDirStream = function (layer, key) {
      return files.createReadStream({
        gt: layer + '!' + key,
        lt: layer + '!' + key + '\xff'
      })
    }

    var get = function (name, cb) {
      var loop = function (i) {
        if (i < 0) return cb(ENOENT)
        that.get(mount.layers[i], name, function (err, file) {
          if (err) return loop(i - 1)
          if (file.deleted) return cb(ENOENT)
          cb(null, file)
        })
      }

      loop(mount.layers.length - 1)
    }

    var del = function (name, cb) {
      var loop = function (i) {
        if (i < 0) return that.del(mount.id, name, cb)
        that.get(mount.layers[i], name, function (err, file) {
          if (err) return loop(i - 1)
          that.put(mount.id, name, {deleted: true}, cb)
        })
      }

      loop(mount.layers.length - 2)
    }

    var ready = function (root) {
      fuse.mount(mnt, {
        force: true,
        options: ['suid', 'dev'],
        getattr: function (name, cb) {
          if (name === '/') return cb(0, root)

          get(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))

            var onstat = function (_, st) {
              if (!st) st = root
              cb(0, {
                mode: file.mode,
                size: st.size,
                uid: file.uid || st.uid,
                gid: file.gid || st.gid,
                dev: file.dev || st.dev,
                nlink: file.nlink || st.nlink,
                rdev: file.rdev || st.rdev,
                blksize: file.blksize || st.blksize,
                blocks: file.blocks || st.blocks,
                ino: file.ino || st.ino,
                ctime: new Date(file.ctime || st.ctime.getTime()),
                mtime: new Date(file.mtime || st.mtime.getTime()),
                atime: file.atime || new Date()
              })
            }

            if (file.blob) fs.lstat(file.blob, onstat)
            else onstat(null, root)
          })
        },
        symlink: function (name, dst, cb) {
          cow(dst, function (err, file) { // cow is not needed - just use to get a file handle as it'll never cpy
            if (err) return cb(fuse.errno(err.code))
            fs.writeFile(file.blob, name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              that.add(mount.id, dst, {mode: 41453, blob: file.blob}, function (err) {
                if (err) return cb(fuse.errno(err.code))
                cb(0)
              })
            })
          })
        },
        readlink: function (name, cb) {
          get(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            fs.readFile(file.blob, 'utf-8', function (err, link) {
              if (err) return cb(fuse.errno(err.code))
              cb(0, link)
            })
          })
        },
        link: function (name, dst, cb) {
          // doesn't work
          // get(name, function (err, file) {
          //   if (err) return cb(fuse.errno(err.code))
          //   fs.link(file.blob, path.join(mount.writes, dst), function (err) {
          //     if (err) return cb(fuse.errno(err.code))
          //     that.add(mount.id, dst, file, function (err) {
          //       if (err) return cb(fuse.errno(err.code))
          //       cb(0)
          //     })
          //   })
          // })
          console.error('hardlinks not implemented yet')
          cb(fuse.EPERM)
        },
        readdir: function (name, cb) {
          if (!/\/$/.test(name)) name += '/'
          var key = toIndexKey(name)

          var result = []
          var stream = createDirStream(mount.layers[mount.layers.length - 1], key)
          for (var i = mount.layers.length - 2; i >= 0; i--) {
            stream = union(stream, createDirStream(mount.layers[i], key), toCompareKey)
          }

          stream.on('error', function (err) {
            cb(fuse.errno(err.code))
          })

          stream.on('data', function (data) {
            if (data.value.deleted) return
            result.push(data.key.slice(data.key.lastIndexOf('/') + 1)) // haxx
          })

          stream.on('end', function () {
            cb(null, result)
          })
        },
        mknod: function (name, mode, dev, cb) {
          console.log('calling mknod', name)
          var blob = path.join(mount.writes, name)
          mknod(blob, mode, dev, function (err) {
            if (err) return cb(fuse.errno(err.code))
            that.add(mount.id, name, {mode: mode, rdev: dev, blob: blob}, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        open: function (name, flags, cb) {
          var readonly = function () {
            get(name, function (err, file) {
              if (err) return cb(fuse.errno(err.code))
              if (file.rdev) return writeMaybe() // special file - always cow

              fs.open(file.blob, 'r', function (err, fd) {
                if (err) return cb(fuse.errno(err.code))
                cb(0, fd)
              })
            })
          }

          var writeMaybe = function () {
            cow(name, function (err, file) {
              if (err) return cb(fuse.errno(err))
              fs.open(file.blob, flags, function (err, fd) {
                if (err) return cb(fuse.errno(err))
                cb(0, fd)
              })
            })
          }

          if (flags === 0) readonly() // readonly
          else writeMaybe() // cow
        },
        read: function (name, fd, buf, len, offset, cb) {
          fs.read(fd, buf, 0, len, offset, function (err, bytes) {
            if (err) return cb(fuse.errno(err.code))
            cb(bytes)
          })
        },
        release: function (name, fd, cb) {
          fs.close(fd, function (err) {
            if (err) return cb(fuse.errno(err.code))
            cb(0)
          })
        },
        create: function (name, mode, cb) {
          var blob = path.join(mount.writes, name)
          mkdirp(path.join(blob, '..'), function (err) {
            if (err) return cb(fuse.errno(err.code))
            fs.open(blob, 'w', mode, function (err, fd) {
              if (err) return cb(fuse.errno(err.code))
              that.add(mount.id, name, {mode: mode, blob: blob}, function (err) {
                if (err) return cb(fuse.errno(err.code))
                cb(0, fd)
              })
            })
          })
        },
        write: function (name, fd, buf, len, offset, cb) {
          fs.write(fd, buf, 0, len, offset, function (err, bytes) {
            if (err) return cb(fuse.errno(err.code))
            cb(bytes)
          })
        },
        unlink: function (name, cb) {
          var blob = path.join(mount.writes, name)
          fs.unlink(blob, function () { // ignore error as this is just gc
            del(name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        mkdir: function (name, mode, cb) {
          that.add(mount.id, name, {mode: mode | 040000}, function (err) {
            if (err) return cb(fuse.errno(err.code))
            cb(0)
          })
        },
        rmdir: function (name, cb) {
          var blob = path.join(mount.writes, name)
          fs.rmdir(blob, function (err) { // ignore error as this is just gc
            del(name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        utimens: function (name, ctime, mtime, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.ctime = ctime.getTime()
            file.mtime = mtime.getTime()
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        chmod: function (name, mode, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.mode = mode
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        chown: function (name, uid, gid, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.uid = uid
            file.gid = gid
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        truncate: function (name, size, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err))
            fs.truncate(file.blob, size, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        }
      }, function (err) {
        if (err) mount.emit('error', err)
        else mount.emit('ready')
      })
    }

    var onid = function (err, id) {
      if (err) return mount.emit('error', err)

      mount.id = id.toString()
      mount.writes = path.join(mounts, mount.id)
      mount.layers = [].concat(opts.layers || [], mount.id)
      mount.mountpoint = mnt

      mkdirp(mnt, function (err) {
        if (err) return mount.emit('error', err)
        mkdirp(mount.writes, function (err) {
          if (err) return mount.emit('error', err)
          fs.stat(mnt, function (err, st) {
            if (err) return mount.emit('error', err)
            ready(st)
          })
        })
      })
    }

    if (opts.id) return onid(null, opts.id)
    getId(mnt, onid)

    return mount
  }

  return that
}
<commit_msg>add rename<commit_after>var path = require('path')
var level = require('level')
var crypto = require('crypto')
var mkdirp = require('mkdirp')
var pumpify = require('pumpify')
var pump = require('pump')
var cuid = require('cuid')
var fs = require('fs')
var fuse = require('fuse-bindings')
var lexint = require('lexicographic-integer')
var union = require('sorted-union-stream')
var events = require('events')
var mknod = require('mknod')
var subleveldown = require('subleveldown')
var enumerate = require('level-enumerate')

var noop = function () {}
var ENOENT = new Error('ENOENT')
ENOENT.code = 'ENOENT'

module.exports = function (home) {
  var that = {}

  var db = level(path.join(home, 'db'))
  var blobs = path.join(home, 'blobs')
  var mounts = path.join(home, 'mounts')

  var getId = enumerate(subleveldown(db, 'ids'))
  var files = subleveldown(db, 'files', {valueEncoding: 'json'})
  var parents = subleveldown(db, 'parents')

  var blobPath = function (hash) {
    return path.join(blobs, hash.slice(0, 2), hash.slice(2, 4), hash.slice(4))
  }

  var toIndexKey = function(name) {
    var depth = name.split('/').length - 1
    return lexint.pack(depth, 'hex') + '!' + name
  }

  that.add = function (layer, filename, stat, cb) {
    var key = layer + '!' + toIndexKey(filename)
    stat.ctime = stat.ctime || Date.now()
    stat.mtime = stat.mtime || Date.now()
    console.log('add', key)
    files.put(key, stat, cb)
  }

  that.get = function (layer, filename, cb) {
    var key = layer + '!' + toIndexKey(filename)
    console.log('get', key)
    files.get(key, cb)
  }

  that.del = function (layer, filename, cb) {
    var key = layer + '!' + toIndexKey(filename)
    files.del(key, cb)
  }

  that.createLayerStream = function (layer) {

  }

  that.createBlobReadStream = function (hash) {
    return fs.createReadStream(blobPath(hash))
  }

  that.createBlobWriteStream = function () {
    var sha = crypto.createHash('sha256')
    var tmp = path.join(os.tmpdir(), 'cauf-file-' + cuid())
    var ws = fs.createWriteStream(tmp)

    ws.on('finish', function () {
      stream.cork()
      stream.key = sha.digest('hex')
      var filename = blobPath(stream.key)
      mkdir(path.join(filename, '..'), function (err) {
        if (err) return stream.destroy(err)
        fs.rename(tmp, filename, function (err) {
          if (err) return stream.destroy(err)
          stream.uncork()
        })
      })
    })

    var stream = pumpify(through(write), ws)
    return stream
  }

  that.unmount = function (mnt, cb) {
    fuse.unmount(mnt, cb)
  }

  that.mount = function (mnt, opts) {
    if (!opts) opts = {}

    var mount = new events.EventEmitter()

    mount.id = null
    mount.writes = null
    mount.layers = null

    mount.unmount = function (cb) {
      that.unmount(mnt, cb)
    }

    var cow = function (name, cb) {
      that.get(mount.id, name, function (err, file) {
        if (file) return cb(null, file)

        console.log('copy-on-write for', mount.id, name)

        var copy = function (file) {
          var done = function (err) {
            if (err) return cb(err)

            var newFile = {
              mode: file ? file.mode : 33188,
              rdev: file && file.rdev,
              uid: file && file.uid,
              gid: file && file.gid,
              blob: newBlob
            }

            that.add(mount.id, name, newFile, function (err) {
              if (err) return cb(err)
              cb(null, newFile)
            })
          }

          mkdirp(path.join(newBlob, '..'), function (err) {
            if (err) return cb(err)
            if (!file) return done()
            if (file.rdev) return mknod(newBlob, file.mode, file.rdev, done) // special file
            pump(fs.createReadStream(file.blob), fs.createWriteStream(newBlob), done)
          })
        }

        var newBlob = path.join(mount.writes, name)
        var loop = function (i) {
          if (i < 0) return copy(null)
          that.get(mount.layers[i], name, function (err, file) {
            if (err) return loop(i - 1)
            copy(file.deleted ? null : file)
          })
        }

        loop(mount.layers.length - 2)
      })
    }

    var toCompareKey = function (data) {
      return data.key.slice(data.key.indexOf('!') + 1)
    }

    var createDirStream = function (layer, key) {
      return files.createReadStream({
        gt: layer + '!' + key,
        lt: layer + '!' + key + '\xff'
      })
    }

    var get = function (name, cb) {
      var loop = function (i) {
        if (i < 0) return cb(ENOENT)
        that.get(mount.layers[i], name, function (err, file) {
          if (err) return loop(i - 1)
          if (file.deleted) return cb(ENOENT)
          cb(null, file)
        })
      }

      loop(mount.layers.length - 1)
    }

    var del = function (name, cb) {
      var loop = function (i) {
        if (i < 0) return that.del(mount.id, name, cb)
        that.get(mount.layers[i], name, function (err, file) {
          if (err) return loop(i - 1)
          that.put(mount.id, name, {deleted: true}, cb)
        })
      }

      loop(mount.layers.length - 2)
    }

    var ready = function (root) {
      fuse.mount(mnt, {
        force: true,
        options: ['suid', 'dev'],
        getattr: function (name, cb) {
          if (name === '/') return cb(0, root)

          get(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))

            var onstat = function (_, st) {
              if (!st) st = root
              cb(0, {
                mode: file.mode,
                size: st.size,
                uid: file.uid || st.uid,
                gid: file.gid || st.gid,
                dev: file.dev || st.dev,
                nlink: file.nlink || st.nlink,
                rdev: file.rdev || st.rdev,
                blksize: file.blksize || st.blksize,
                blocks: file.blocks || st.blocks,
                ino: file.ino || st.ino,
                ctime: new Date(file.ctime || st.ctime.getTime()),
                mtime: new Date(file.mtime || st.mtime.getTime()),
                atime: file.atime || new Date()
              })
            }

            if (file.blob) fs.lstat(file.blob, onstat)
            else onstat(null, root)
          })
        },
        symlink: function (name, dst, cb) {
          cow(dst, function (err, file) { // cow is not needed - just use to get a file handle as it'll never cpy
            if (err) return cb(fuse.errno(err.code))
            fs.writeFile(file.blob, name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              that.add(mount.id, dst, {mode: 41453, blob: file.blob}, function (err) {
                if (err) return cb(fuse.errno(err.code))
                cb(0)
              })
            })
          })
        },
        readlink: function (name, cb) {
          get(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            fs.readFile(file.blob, 'utf-8', function (err, link) {
              if (err) return cb(fuse.errno(err.code))
              cb(0, link)
            })
          })
        },
        link: function (name, dst, cb) {
          // doesn't work
          // get(name, function (err, file) {
          //   if (err) return cb(fuse.errno(err.code))
          //   fs.link(file.blob, path.join(mount.writes, dst), function (err) {
          //     if (err) return cb(fuse.errno(err.code))
          //     that.add(mount.id, dst, file, function (err) {
          //       if (err) return cb(fuse.errno(err.code))
          //       cb(0)
          //     })
          //   })
          // })
          console.error('hardlinks not implemented yet')
          cb(fuse.EPERM)
        },
        rename: function (from, to, cb) {
          cow(from, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            var newBlob = path.join(mount.writes, to)
            fs.rename(file.blob, newBlob, function (err) {
              if (err) return cb(fuse.errno(err.code))
              file.blob = newBlob
              that.del(mount.id, from, function (err) {
                if (err) return cb(fuse.errno(err.code))
                that.add(mount.id, to, file, function (err) {
                  if (err) return cb(fuse.errno(err.code))
                  cb(0)
                })
              })
            })
          })
        },
        readdir: function (name, cb) {
          if (!/\/$/.test(name)) name += '/'
          var key = toIndexKey(name)

          var result = []
          var stream = createDirStream(mount.layers[mount.layers.length - 1], key)
          for (var i = mount.layers.length - 2; i >= 0; i--) {
            stream = union(stream, createDirStream(mount.layers[i], key), toCompareKey)
          }

          stream.on('error', function (err) {
            cb(fuse.errno(err.code))
          })

          stream.on('data', function (data) {
            if (data.value.deleted) return
            result.push(data.key.slice(data.key.lastIndexOf('/') + 1)) // haxx
          })

          stream.on('end', function () {
            cb(null, result)
          })
        },
        mknod: function (name, mode, dev, cb) {
          console.log('calling mknod', name)
          var blob = path.join(mount.writes, name)
          mknod(blob, mode, dev, function (err) {
            if (err) return cb(fuse.errno(err.code))
            that.add(mount.id, name, {mode: mode, rdev: dev, blob: blob}, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        open: function (name, flags, cb) {
          var readonly = function () {
            get(name, function (err, file) {
              if (err) return cb(fuse.errno(err.code))
              if (file.rdev) return writeMaybe() // special file - always cow

              fs.open(file.blob, 'r', function (err, fd) {
                if (err) return cb(fuse.errno(err.code))
                cb(0, fd)
              })
            })
          }

          var writeMaybe = function () {
            cow(name, function (err, file) {
              if (err) return cb(fuse.errno(err))
              fs.open(file.blob, flags, function (err, fd) {
                if (err) return cb(fuse.errno(err))
                cb(0, fd)
              })
            })
          }

          if (flags === 0) readonly() // readonly
          else writeMaybe() // cow
        },
        read: function (name, fd, buf, len, offset, cb) {
          fs.read(fd, buf, 0, len, offset, function (err, bytes) {
            if (err) return cb(fuse.errno(err.code))
            cb(bytes)
          })
        },
        release: function (name, fd, cb) {
          fs.close(fd, function (err) {
            if (err) return cb(fuse.errno(err.code))
            cb(0)
          })
        },
        create: function (name, mode, cb) {
          var blob = path.join(mount.writes, name)
          mkdirp(path.join(blob, '..'), function (err) {
            if (err) return cb(fuse.errno(err.code))
            fs.open(blob, 'w', mode, function (err, fd) {
              if (err) return cb(fuse.errno(err.code))
              that.add(mount.id, name, {mode: mode, blob: blob}, function (err) {
                if (err) return cb(fuse.errno(err.code))
                cb(0, fd)
              })
            })
          })
        },
        write: function (name, fd, buf, len, offset, cb) {
          fs.write(fd, buf, 0, len, offset, function (err, bytes) {
            if (err) return cb(fuse.errno(err.code))
            cb(bytes)
          })
        },
        unlink: function (name, cb) {
          var blob = path.join(mount.writes, name)
          fs.unlink(blob, function () { // ignore error as this is just gc
            del(name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        mkdir: function (name, mode, cb) {
          that.add(mount.id, name, {mode: mode | 040000}, function (err) {
            if (err) return cb(fuse.errno(err.code))
            cb(0)
          })
        },
        rmdir: function (name, cb) {
          var blob = path.join(mount.writes, name)
          fs.rmdir(blob, function (err) { // ignore error as this is just gc
            del(name, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        utimens: function (name, ctime, mtime, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.ctime = ctime.getTime()
            file.mtime = mtime.getTime()
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        chmod: function (name, mode, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.mode = mode
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        chown: function (name, uid, gid, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err.code))
            file.uid = uid
            file.gid = gid
            that.add(mount.id, name, file, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        },
        truncate: function (name, size, cb) {
          cow(name, function (err, file) {
            if (err) return cb(fuse.errno(err))
            fs.truncate(file.blob, size, function (err) {
              if (err) return cb(fuse.errno(err.code))
              cb(0)
            })
          })
        }
      }, function (err) {
        if (err) mount.emit('error', err)
        else mount.emit('ready')
      })
    }

    var onid = function (err, id) {
      if (err) return mount.emit('error', err)

      mount.id = id.toString()
      mount.writes = path.join(mounts, mount.id)
      mount.layers = [].concat(opts.layers || [], mount.id)
      mount.mountpoint = mnt

      mkdirp(mnt, function (err) {
        if (err) return mount.emit('error', err)
        mkdirp(mount.writes, function (err) {
          if (err) return mount.emit('error', err)
          fs.stat(mnt, function (err, st) {
            if (err) return mount.emit('error', err)
            ready(st)
          })
        })
      })
    }

    if (opts.id) return onid(null, opts.id)
    getId(mnt, onid)

    return mount
  }

  return that
}
<|endoftext|>


<commit_before>//*
class Player {
  constructor(x, y, id) {
    this.x = x;
    this.y = y;

    this.id = id;
  }
}

var limit = 14400;

var teams = [];
var sockets = [];
const repl = require('repl')
var io = require('socket.io')
for (var i = 5000; i <= 5010; i++) {
  io(i).on('connection', function (socket) {
    sockets.push(socket)
    socket.on('1', function(data){
      var id = 27

      name = data.name.length > 15 ? 'unknown' : data.name;

      socket.emit('id', {"teams":teams})
      socket.emit('1', id)
      socket.emit('mm', 0)
      socket.emit('3', [])

      var x = Math.random() * limit
      var y = Math.random() * limit

      var userteam = null;
      var last = 0;

      socket.emit("2",["a3Pm5dMzeKOjc5gvAJEF",id,name,x,7200,0,100,100,35,data.skin],true)
      socket.emit("5",[27,data.name,9001])//[5,"RIP",31988,45,"KADEJO503",23404,34,"winter wolf",4821,28,"Godenot",4500,33,"Arena Closer",3000,32,"LightTheif",2940,6,"CarlosKoS-_-16",2800,4,"GD desconhecido",2635,35,"jack black GD",2357,19,"AMIGO BOM",1623])
      socket.emit("6",[
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353,  4103, 13436,   0,    80, 2, null, -1,
        339,  2498, 14155,   0,    90, 2, null, -1])
      socket.emit("8",2.6,28)

      socket.on("ch",data=>{
        emit("ch", id, data)
      })

      socket.on("8", data => {
        console.log('CLAN CREATE REQUEST:', data);

        teams.push([{"sid":data,"owner":id}])
        var userteam = data;

        emit("st", data, true)
      });

      socket.on("3",function(data){
        if (data == null) {
          vx = vy = 0
          return
        } else if (x < 0 || x > limit || y < 0 || y > limit) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;

        }
        var speed = y > 2400 ? 60 * 0.8 : 60;

        vx = Math.cos(data) * speed
        vy = Math.sin(data) * speed

        x += vx;
        y += vy;

        socket.emit('a')
        socket.emit("3",[id,x,y,-2.26,-1,0,0,null,0,0,0,0])
      })

      socket.on("14",function(data){
        console.log('ping!!!', arguments)
      })
    })

    var emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg)
        socket.emit(...arg)
      } catch (e) {
        sockets.forEach(a => a.emit(...arg))
      }
    }
  });
}

repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a))
    } catch(e) {
      cb(e)
    }
  }
})

/*/

var proxy = require('socket.io-proxy');

var socket = proxy.connect('http://45.63.110.209/');

socket.on('connect', function () {
    console.log('Socket connected');
    socket.on('command', function (data) {
        console.log('Received data', data);
    });
    socket.on('id', function (data) {
        console.log(data);
    });
    socket.on('disconnect', function() {
        console.log('Socket disconnected');
    });
});//*/
<commit_msg>beatified<commit_after>class Player {
  constructor(x, y, id) {
    this.x = x;
    this.y = y;
    this.id = id;
  }
}
var limit = 14400;
var teams = [];
var sockets = [];
const repl = require('repl')
var io = require('socket.io')
for (var i = 5000; i <= 5010; i++) {
  io(i).on('connection', function (socket) {
    sockets.push(socket)
    socket.on('1', function (data) {
      var id = 27
      name = data.name.length > 15 ? 'unknown' : data.name;
      socket.emit('id', {
        "teams": teams
      })
      socket.emit('1', id)
      socket.emit('mm', 0)
      socket.emit('3', [])
      var x = Math.random() * limit
      var y = Math.random() * limit
      var userteam = null;
      var last = 0;
      socket.emit("2", ["a3Pm5dMzeKOjc5gvAJEF", id, name, x, 7200, 0, 100, 100, 35, data.skin], true)
      socket.emit("5", [27, data.name, 9001]) //[5,"RIP",31988,45,"KADEJO503",23404,34,"winter wolf",4821,28,"Godenot",4500,33,"Arena Closer",3000,32,"LightTheif",2940,6,"CarlosKoS-_-16",2800,4,"GD desconhecido",2635,35,"jack black GD",2357,19,"AMIGO BOM",1623])
      socket.emit("6", [
        29, 3115.1, 13592.9, 0, 109.2, 1, null, -1,
        353, 4103, 13436, 0, 80, 2, null, -1,
        339, 2498, 14155, 0, 90, 2, null, -1
      ])
      socket.emit("8", 2.6, 28)
      socket.on("ch", data => {
        emit("ch", id, data)
      })
      socket.on("8", data => {
        console.log('CLAN CREATE REQUEST:', data);
        teams.push([{
          "sid": data,
          "owner": id
        }])
        var userteam = data;
        emit("st", data, true)
      });
      socket.on("3", function (data) {
        if (data == null) {
          vx = vy = 0
          return
        } else if (x < 0 || x > limit || y < 0 || y > limit) {
          x = 7200;
          y = 7200;
        }
        if (y >= 6840 && y <= 7560) {
          x += 0.44;
        }
        var speed = y > 2400 ? 60 * 0.8 : 60;
        vx = Math.cos(data) * speed
        vy = Math.sin(data) * speed
        x += vx;
        y += vy;
        socket.emit('a')
        socket.emit("3", [id, x, y, -2.26, -1, 0, 0, null, 0, 0, 0, 0])
      })
      socket.on("14", function (data) {
        console.log('ping!!!', arguments)
      })
    })
    var emit = (...arg) => {
      try {
        socket.broadcast.emit(...arg)
        socket.emit(...arg)
      } catch (e) {
        sockets.forEach(a => a.emit(...arg))
      }
    }
  });
}
repl.start({
  eval: (a, _c, _f, cb) => {
    try {
      cb(null, eval(a))
    } catch (e) {
      cb(e)
    }
  }
})
<|endoftext|>


<commit_before>var mainApp = angular.module('myApp',[]);

mainApp.controller('myCtrl', ['$http', function($http){

	this.currentSection;
	this.currentSuggestions = [];
	this.currentRating;

	angular.element(document).ready(function() {
	})

	this.postTreeData(key, value) {
	}

	this.getTreeData(key) {
	/* get template
  	$http.get('someDataUrl').then(function(data){
    	this.value = data;
  	});
  	*/
	}

	this.changePage(value) {

	}

	// UI Functionality

	this.reateUp() {

	}

	this.rateDown() {

	}

	this.report() {

	}

	this.changeFont(size) {

	}

}])<commit_msg>Delete dupilcate index.js<commit_after><|endoftext|>


<commit_before>/**
 * Created by petersquicciarini on 3/9/17.
 */

const winston = require('winston');

if (!process.env.slackClientID || !process.env.slackClientSecret ||
  !process.env.ticketSystemUrl || !process.env.PORT || !process.env.mongoUri ||
  !process.env.escalationTeam) {
  winston.log('error', 'Please see README for required env vars.');
  process.exit();
}

const Botkit = require('botkit');
const mongoStorage = require('botkit-storage-mongo')({ mongoUri: process.env.mongoUri });
const url = require('url');
const quotes = require('./lib/quotes');
const freshservice = require('./lib/freshservice');
const request = require('request');

const connectionInfo = {
  slackClientID: process.env.slackClientID,
  slackClientSecret: process.env.slackClientSecret,
  ticketSystemUrl: process.env.ticketSystemUrl,
  ticketSystemAPIKey: process.env.ticketSystemAPIKey,
};
const controller = Botkit.slackbot({
  storage: mongoStorage,
}).configureSlackApp({
  clientId: connectionInfo.slackClientID,
  clientSecret: connectionInfo.slackClientSecret,
  scopes: ['bot', 'chat:write:bot', 'users:read', 'channels:read'],
});

controller.setupWebserver(process.env.PORT, () => {
  controller.createWebhookEndpoints(controller.webserver);
  controller.createHomepageEndpoint(controller.webserver);
  controller.createOauthEndpoints(controller.webserver, (err, req, res) => {
    if (err) {
      res.status(500).send(`ERROR: ${err}`);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
const activeBots = {};
function trackBot(bot) {
  activeBots[bot.config.token] = bot;
}

controller.on('create_bot', (bot) => {
  if (activeBots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM((err) => {
      if (!err) {
        trackBot(bot);
      }
    });
  }
});

controller.storage.teams.all((err, teams) => {
  if (err) {
    throw new Error(err);
  }
  // connect all teams with bots up to slack!
  Object.keys(teams).forEach((t) => {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM((startErr, bot) => {
        if (startErr) {
          winston.log('error', 'Could not connect to Slack RTM.');
        } else {
          trackBot(bot);
        }
      });
    }
  });
});
controller.on('rtm_open', () => {
  winston.log('info', '** The RTM api just connected!');
});
controller.on('rtm_close', (bot) => {
  winston.log('warn', '** The RTM api just closed');
  bot.startRTM((err) => {
    if (!err) {
      trackBot(bot);
    }
  });
});

// *** Begin Ticket Info/Link Handler *** //
controller.hears(['ticket ([0-9]+)'], ['ambient'], (bot, message) => {
  winston.log('info', 'Hazel heard a ticket # pattern. Crafting reply...');
  bot.api.channels.info({ channel: message.channel }, (err, info) => {
    if (err) {
      winston.log('error', 'Hazel could not get channel info.');
    } else {
      winston.log('debug', 'Hazel got the channel info.');
      if (info.channel.name === 'emg') {
        winston.log('info', 'We are in the EMG channel. Sending buttons...');
        const emgTicketReply = {
          username: 'hazel',
          icon_emoji: ':octopus:',
          text: "On Call Tech: Let everyone know you're taking care of it, and escalate if you need to:",
          attachments: [
            {
              fallback: "(Sorry. I couldn't make the cool buttons this time.)",
              callback_id: 'emgResponse',
              actions: [
                {
                  name: 'acceptEmg',
                  text: "I've got it.",
                  style: 'primary',
                  type: 'button',
                },
                {
                  name: 'escalateEmg',
                  text: 'I need to escalate!',
                  type: 'button',
                },
              ],
            },
          ],
        };
        bot.reply(message, emgTicketReply);
      } else {
        const ticketID = message.match[1];
        if (process.env.ticketSystemAPIKey) {
          bot.startTyping(message);
          winston.log('info', 'Looks like an API key for FreshService was provided. Will try to get ticket info...');
          const reqOptions = freshservice(connectionInfo.ticketSystemUrl, connectionInfo.ticketSystemAPIKey, 'GET', `${ticketID}.json`);
          request(reqOptions, (reqErr, res, body) => {
            winston.log('debug', 'Just sent request to FreshService.');
            if (err || res.statusCode !== 200) {
              winston.log('warning', 'Hazel could not get ticket info from FreshService. Sending link instead...');
              bot.reply(message, {
                text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                username: 'hazel',
                icon_emoji: ':octopus:',
              });
            } else {
              winston.log('debug', 'Got a good response from FreshService. Sending ticket stub...');
              const ticketInfoMessage = {
                username: 'hazel',
                icon_emoji: ':octopus:',
                attachments: [{
                  title: `Ticket ${ticketID}: ${body.helpdesk_ticket.subject}`,
                  title_link: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                  fields: [
                    {
                      title: 'Description',
                      value: `${body.helpdesk_ticket.description.substring(0, 300)}...`,
                      short: false,
                    },
                    {
                      title: 'Requester',
                      value: body.helpdesk_ticket.requester_name,
                      short: true,
                    },
                    {
                      title: 'Agent',
                      value: body.helpdesk_ticket.responder_name,
                      short: true,
                    },
                    {
                      title: 'Status',
                      value: body.helpdesk_ticket.status_name,
                      short: true,
                    },
                    {
                      title: 'Priority',
                      value: body.helpdesk_ticket.priority_name,
                      short: true,
                    },
                  ],
                }],
              };
              bot.reply(message, ticketInfoMessage);
            }
          });
        } else {
          winston.log('info', 'No API key provided, so just sending the URL to the ticket...');
          bot.reply(message, {
            text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
            username: 'hazel',
            icon_emoji: ':octopus:',
          });
        }
      }
    }
  });
});
// *** End Ticket Info/Link Handler *** //

// *** Begin Quote Handler *** //
controller.hears(['quote', 'proverb', 'wisdom'], ['direct_mention'], (bot, message) => {
  winston.log('info', 'Hazel heard someone mention her directly. Sending reply...');
  bot.reply(message, {
    username: 'hazel',
    icon_emoji: ':octopus:',
    text: quotes.getRandomQuote(),
  });
});
// *** End Quote Handler *** //

// *** Begin EMG Buttons Handler *** //
controller.on('interactive_message_callback', (bot, message) => {
  bot.api.users.info({ user: message.user }, (err, info) => {
    let buttonPresser = null;
    if (err) {
      winston.log('error', 'Could not get user name of button presser');
    } else {
      buttonPresser = info.user.name;
    }
    if (message.actions[0].name === 'acceptEmg') {
      bot.reply(message, {
        text: `<!everyone> ${buttonPresser || 'A tech'} is taking care of this emergency.`,
        username: 'hazel',
        icon_emoji: ':octopus:',
      });
    }
    if (message.actions[0].name === 'escalateEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: 'Tech needs to escalate!',
            text: '*Message sent to the escalation team for help.*',
            mrkdwn_in: ['text'],
          },
        ],
      });
      const escalationTeam = process.env.escalationTeam.split(/,\s?/);
      escalationTeam.forEach((person) => {
        bot.say({
          username: 'hazel',
          icon_emoji: ':octopus:',
          channel: `@${person}`,
          text: `${buttonPresser || 'The On Call Tech'} needs to escalate the emergency.`,
        });
      });
    }
  });
});
// *** End EMG Buttons Handler *** //
<commit_msg>added removal of Got It button after pressing<commit_after>/**
 * Created by petersquicciarini on 3/9/17.
 */

const winston = require('winston');

if (!process.env.slackClientID || !process.env.slackClientSecret ||
  !process.env.ticketSystemUrl || !process.env.PORT || !process.env.mongoUri ||
  !process.env.escalationTeam) {
  winston.log('error', 'Please see README for required env vars.');
  process.exit();
}

const Botkit = require('botkit');
const mongoStorage = require('botkit-storage-mongo')({ mongoUri: process.env.mongoUri });
const url = require('url');
const quotes = require('./lib/quotes');
const freshservice = require('./lib/freshservice');
const request = require('request');

const connectionInfo = {
  slackClientID: process.env.slackClientID,
  slackClientSecret: process.env.slackClientSecret,
  ticketSystemUrl: process.env.ticketSystemUrl,
  ticketSystemAPIKey: process.env.ticketSystemAPIKey,
};
const controller = Botkit.slackbot({
  storage: mongoStorage,
}).configureSlackApp({
  clientId: connectionInfo.slackClientID,
  clientSecret: connectionInfo.slackClientSecret,
  scopes: ['bot', 'chat:write:bot', 'users:read', 'channels:read'],
});

controller.setupWebserver(process.env.PORT, () => {
  controller.createWebhookEndpoints(controller.webserver);
  controller.createHomepageEndpoint(controller.webserver);
  controller.createOauthEndpoints(controller.webserver, (err, req, res) => {
    if (err) {
      res.status(500).send(`ERROR: ${err}`);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
const activeBots = {};
function trackBot(bot) {
  activeBots[bot.config.token] = bot;
}

controller.on('create_bot', (bot) => {
  if (activeBots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM((err) => {
      if (!err) {
        trackBot(bot);
      }
    });
  }
});

controller.storage.teams.all((err, teams) => {
  if (err) {
    throw new Error(err);
  }
  // connect all teams with bots up to slack!
  Object.keys(teams).forEach((t) => {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM((startErr, bot) => {
        if (startErr) {
          winston.log('error', 'Could not connect to Slack RTM.');
        } else {
          trackBot(bot);
        }
      });
    }
  });
});
controller.on('rtm_open', () => {
  winston.log('info', '** The RTM api just connected!');
});
controller.on('rtm_close', (bot) => {
  winston.log('warn', '** The RTM api just closed');
  bot.startRTM((err) => {
    if (!err) {
      trackBot(bot);
    }
  });
});

// *** Begin Ticket Info/Link Handler *** //
controller.hears(['ticket ([0-9]+)'], ['ambient'], (bot, message) => {
  winston.log('info', 'Hazel heard a ticket # pattern. Crafting reply...');
  bot.api.channels.info({ channel: message.channel }, (err, info) => {
    if (err) {
      winston.log('error', 'Hazel could not get channel info.');
    } else {
      winston.log('debug', 'Hazel got the channel info.');
      if (info.channel.name === 'emg') {
        winston.log('info', 'We are in the EMG channel. Sending buttons...');
        const emgTicketReply = {
          username: 'hazel',
          icon_emoji: ':octopus:',
          text: "On Call Tech: Let everyone know you're taking care of it, and escalate if you need to:",
          attachments: [
            {
              fallback: "(Sorry. I couldn't make the cool buttons this time.)",
              callback_id: 'emgResponse',
              actions: [
                {
                  name: 'acceptEmg',
                  text: "I've got it.",
                  style: 'primary',
                  type: 'button',
                },
                {
                  name: 'escalateEmg',
                  text: 'I need to escalate!',
                  type: 'button',
                },
              ],
            },
          ],
        };
        bot.reply(message, emgTicketReply);
      } else {
        const ticketID = message.match[1];
        if (process.env.ticketSystemAPIKey) {
          bot.startTyping(message);
          winston.log('info', 'Looks like an API key for FreshService was provided. Will try to get ticket info...');
          const reqOptions = freshservice(connectionInfo.ticketSystemUrl, connectionInfo.ticketSystemAPIKey, 'GET', `${ticketID}.json`);
          request(reqOptions, (reqErr, res, body) => {
            winston.log('debug', 'Just sent request to FreshService.');
            if (err || res.statusCode !== 200) {
              winston.log('warning', 'Hazel could not get ticket info from FreshService. Sending link instead...');
              bot.reply(message, {
                text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                username: 'hazel',
                icon_emoji: ':octopus:',
              });
            } else {
              winston.log('debug', 'Got a good response from FreshService. Sending ticket stub...');
              const ticketInfoMessage = {
                username: 'hazel',
                icon_emoji: ':octopus:',
                attachments: [{
                  title: `Ticket ${ticketID}: ${body.helpdesk_ticket.subject}`,
                  title_link: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                  fields: [
                    {
                      title: 'Description',
                      value: `${body.helpdesk_ticket.description.substring(0, 300)}...`,
                      short: false,
                    },
                    {
                      title: 'Requester',
                      value: body.helpdesk_ticket.requester_name,
                      short: true,
                    },
                    {
                      title: 'Agent',
                      value: body.helpdesk_ticket.responder_name,
                      short: true,
                    },
                    {
                      title: 'Status',
                      value: body.helpdesk_ticket.status_name,
                      short: true,
                    },
                    {
                      title: 'Priority',
                      value: body.helpdesk_ticket.priority_name,
                      short: true,
                    },
                  ],
                }],
              };
              bot.reply(message, ticketInfoMessage);
            }
          });
        } else {
          winston.log('info', 'No API key provided, so just sending the URL to the ticket...');
          bot.reply(message, {
            text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
            username: 'hazel',
            icon_emoji: ':octopus:',
          });
        }
      }
    }
  });
});
// *** End Ticket Info/Link Handler *** //

// *** Begin Quote Handler *** //
controller.hears(['quote', 'proverb', 'wisdom'], ['direct_mention'], (bot, message) => {
  winston.log('info', 'Hazel heard someone mention her directly. Sending reply...');
  bot.reply(message, {
    username: 'hazel',
    icon_emoji: ':octopus:',
    text: quotes.getRandomQuote(),
  });
});
// *** End Quote Handler *** //

// *** Begin EMG Buttons Handler *** //
controller.on('interactive_message_callback', (bot, message) => {
  bot.api.users.info({ user: message.user }, (err, info) => {
    let buttonPresser = null;
    if (err) {
      winston.log('error', 'Could not get user name of button presser');
    } else {
      buttonPresser = info.user.name;
    }
    if (message.actions[0].name === 'acceptEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: "(Sorry. I couldn't make the cool buttons this time.)",
            callback_id: 'emgResponse',
            actions: [
              {
                name: 'escalateEmg',
                text: 'I need to escalate!',
                type: 'button',
              },
            ],
          },
        ],
      });
      bot.reply(message, {
        text: `<!everyone> ${buttonPresser || 'A tech'} is taking care of this emergency.`,
        username: 'hazel',
        icon_emoji: ':octopus:',
      });
    }
    if (message.actions[0].name === 'escalateEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: 'Tech needs to escalate!',
            text: '*Message sent to the escalation team for help.*',
            mrkdwn_in: ['text'],
          },
        ],
      });
      const escalationTeam = process.env.escalationTeam.split(/,\s?/);
      escalationTeam.forEach((person) => {
        bot.say({
          username: 'hazel',
          icon_emoji: ':octopus:',
          channel: `@${person}`,
          text: `${buttonPresser || 'The On Call Tech'} needs to escalate the emergency.`,
        });
      });
    }
  });
});
// *** End EMG Buttons Handler *** //
<|endoftext|>


<commit_before>const url = require('url');
const request = require('request-promise-any');
const ethAddress = require('ethereum-address');
request.debug = true;

const DEFAULT_RPC_HOST = 'http://127.0.0.1:5001/';
const DEFAULT_API_VERSION = 1;

function RaidenNode(rpcHost = DEFAULT_RPC_HOST, apiVersion = DEFAULT_API_VERSION) {
  this.baseUrl = url.resolve(rpcHost, `/api/${apiVersion}`);
}

function getLocalNode() {
  return new RaidenNode();
}
RaidenNode.getLocalNode = getLocalNode;

function validateAmount(amount) {
  if (amount <= 0) throw new Error(`Deposit and transfer amounts must not be negative or zero (amount: ${amount})`);
}

function validateAddress(address) {
  if (!ethAddress.isAddress(address)) throw new Error(`Expected a valid ethereum address (got: ${address})`);
}

RaidenNode.prototype.raidenRequest = function(method, uri, ...options) {
  return request(Object.assign({
    method,
    uri,
    baseUrl: this.baseUrl,
    json: true,
    headers: {
      'content-type': 'application/json'
    },
  }, ...options));
}

RaidenNode.prototype.getAddress = function(options) {
  return this.raidenRequest('GET', '/address', options).then(data => data.our_address);
}

RaidenNode.prototype.registerToken = function(tokenAddress, options) {
  return this.raidenRequest('PUT', `/tokens/${tokenAddress}`, options).then(data => data.channel_manager_address);
}

RaidenNode.prototype.getRegisteredTokens = function(options) {
  return this.raidenRequest('GET', '/tokens', options);
}

RaidenNode.prototype.getTokenPartners = function(tokenAddress, options) {
  return this.raidenRequest('GET', `/tokens/${tokenAddress}/partners`, options).then(partners =>
    partners.map(data => ({
      partner_address: data.partner_address,
      channel_address: data.channel.split('/').pop(), // extract address from channel uri
    })));
}

RaidenNode.prototype.getChannel = function(channelAddress, options) {
  return this.raidenRequest('GET', `/channels/${channelAddress}`, options);
}

RaidenNode.prototype.getAllChannels = function(options) {
  return this.raidenRequest('GET', '/channels', options);
}

RaidenNode.prototype.openChannel = function(partnerAddress, tokenAddress, initialBalance, settleTimeout, revealTimeout, options) {
  return this.raidenRequest('PUT', '/channels', {
    body: Object.assign(
      {
        partner_address: partnerAddress,
        token_address: tokenAddress,
        balance: initialBalance,
      },
      settleTimeout ? { settle_timeout: settleTimeout } : {},
      revealTimeout ? { reveal_timeout: revealTimeout } : {}
    ),
  }, options);
}

RaidenNode.prototype.closeChannel = function(channelAddress, options) {
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { state: 'closed' } }, options);
}

RaidenNode.prototype.settleChannel = function(channelAddress, options) {
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { state: 'settled' } }, options);
}

RaidenNode.prototype.deposit = function(channelAddress, amount, options) {
  validateAmount(amount);
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { balance: amount } }, options);
}

RaidenNode.prototype.joinNetwork = function(
  tokenAddress, depositAmount,
  numberOfChannels = 3, reserveDepositRatio = 0.4,
  options,
) {
  validateAmount(depositAmount);
  return this.raidenRequest('PUT', `/connections/${tokenAddress}`, {
    body: {
      funds: depositAmount,
      initial_channel_target: numberOfChannels,
      joinable_funds_target: reserveDepositRatio,
    },
  }, options);
}

RaidenNode.prototype.leaveNetwork = function(tokenAddress, onlyReceivingChannels = true, options) {
  return this.raidenRequest('DELETE', `/connections/${tokenAddress}`, { body: { only_receiving_channels: onlyReceivingChannels } }, options);
}

RaidenNode.prototype.sendTokens = function(tokenAddress, recipientAddress, amount, transferId, options) {
  validateAmount(amount);
  if (transferId && !Number.isInteger(transferId)) throw new Error('token transfer identifier must be an integer');
  return this.raidenRequest('POST', `/transfers/${tokenAddress}/${recipientAddress}`, {
    body: Object.assign({ amount }, transferId ? { identifier: transferId } : {}),
  }, options);
}

function createTokenSwapBody(tokenSwap, isMaker) {
  const {
    makerToken, makerAmount, takerToken, takerAmount,
  } = tokenSwap;
  return isMaker ? {
    role: 'maker',
    sending_token: makerToken,
    sending_amount: makerAmount,
    receiving_token: takerToken,
    receiving_amount: takerAmount,
  } : {
    role: 'taker',
    sending_token: takerToken,
    sending_amount: takerAmount,
    receiving_token: makerToken,
    receiving_amount: makerAmount,
  };
}

RaidenNode.prototype.makeTokenSwap = function(tokenSwap, options) {
  const { identifier, takerAddress } = tokenSwap;
  return this.raidenRequest(
    'PUT',
    `/token_swaps/${takerAddress}/${identifier}`,
    { body: createTokenSwapBody(tokenSwap, true) },
    options,
  );
}

RaidenNode.prototype.takeTokenSwap = function(tokenSwap, options) {
  const { identifier, makerAddress } = tokenSwap;
  return this.raidenRequest(
    'PUT',
    `/token_swaps/${makerAddress}/${identifier}`,
    { body: createTokenSwapBody(tokenSwap, false) },
    options,
  );
}

function getEvents(node, eventUri, fromBlock = 0, options) {
  if (fromBlock < 0) throw new Error(`block number must not be negative (block: ${fromBlock}`);
  return node.raidenRequest('GET', url.resolve('/events', eventUri), fromBlock ? { qs: { from_block: fromBlock } } : {}, options);
}

RaidenNode.prototype.getNetworkEvents = function(fromBlock, options) {
  return getEvents(this, '/network', fromBlock, options);
}

RaidenNode.prototype.getTokenEvents = function(tokenAddress, fromBlock, options) {
  return getEvents(this, `/tokens/${tokenAddress}`, fromBlock, options);
}

RaidenNode.prototype.getChannelEvents = function(channelAddress, fromBlock, options) {
  return getEvents(this, `/channels/${channelAddress}`, fromBlock, options);
}

module.exports = {
  RaidenNode,
  getLocalNode,
};
<commit_msg>Disable requests debugging<commit_after>const url = require('url');
const request = require('request-promise-any');
const ethAddress = require('ethereum-address');

const DEFAULT_RPC_HOST = 'http://127.0.0.1:5001/';
const DEFAULT_API_VERSION = 1;

function RaidenNode(rpcHost = DEFAULT_RPC_HOST, apiVersion = DEFAULT_API_VERSION) {
  this.baseUrl = url.resolve(rpcHost, `/api/${apiVersion}`);
}

function getLocalNode() {
  return new RaidenNode();
}
RaidenNode.getLocalNode = getLocalNode;

function validateAmount(amount) {
  if (amount <= 0) throw new Error(`Deposit and transfer amounts must not be negative or zero (amount: ${amount})`);
}

function validateAddress(address) {
  if (!ethAddress.isAddress(address)) throw new Error(`Expected a valid ethereum address (got: ${address})`);
}

RaidenNode.prototype.raidenRequest = function(method, uri, ...options) {
  return request(Object.assign({
    method,
    uri,
    baseUrl: this.baseUrl,
    json: true,
    headers: {
      'content-type': 'application/json'
    },
  }, ...options));
}

RaidenNode.prototype.getAddress = function(options) {
  return this.raidenRequest('GET', '/address', options).then(data => data.our_address);
}

RaidenNode.prototype.registerToken = function(tokenAddress, options) {
  return this.raidenRequest('PUT', `/tokens/${tokenAddress}`, options).then(data => data.channel_manager_address);
}

RaidenNode.prototype.getRegisteredTokens = function(options) {
  return this.raidenRequest('GET', '/tokens', options);
}

RaidenNode.prototype.getTokenPartners = function(tokenAddress, options) {
  return this.raidenRequest('GET', `/tokens/${tokenAddress}/partners`, options).then(partners =>
    partners.map(data => ({
      partner_address: data.partner_address,
      channel_address: data.channel.split('/').pop(), // extract address from channel uri
    })));
}

RaidenNode.prototype.getChannel = function(channelAddress, options) {
  return this.raidenRequest('GET', `/channels/${channelAddress}`, options);
}

RaidenNode.prototype.getAllChannels = function(options) {
  return this.raidenRequest('GET', '/channels', options);
}

RaidenNode.prototype.openChannel = function(partnerAddress, tokenAddress, initialBalance, settleTimeout, revealTimeout, options) {
  return this.raidenRequest('PUT', '/channels', {
    body: Object.assign(
      {
        partner_address: partnerAddress,
        token_address: tokenAddress,
        balance: initialBalance,
      },
      settleTimeout ? { settle_timeout: settleTimeout } : {},
      revealTimeout ? { reveal_timeout: revealTimeout } : {}
    ),
  }, options);
}

RaidenNode.prototype.closeChannel = function(channelAddress, options) {
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { state: 'closed' } }, options);
}

RaidenNode.prototype.settleChannel = function(channelAddress, options) {
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { state: 'settled' } }, options);
}

RaidenNode.prototype.deposit = function(channelAddress, amount, options) {
  validateAmount(amount);
  return this.raidenRequest('PATCH', `/channels/${channelAddress}`, { body: { balance: amount } }, options);
}

RaidenNode.prototype.joinNetwork = function(
  tokenAddress, depositAmount,
  numberOfChannels = 3, reserveDepositRatio = 0.4,
  options,
) {
  validateAmount(depositAmount);
  return this.raidenRequest('PUT', `/connections/${tokenAddress}`, {
    body: {
      funds: depositAmount,
      initial_channel_target: numberOfChannels,
      joinable_funds_target: reserveDepositRatio,
    },
  }, options);
}

RaidenNode.prototype.leaveNetwork = function(tokenAddress, onlyReceivingChannels = true, options) {
  return this.raidenRequest('DELETE', `/connections/${tokenAddress}`, { body: { only_receiving_channels: onlyReceivingChannels } }, options);
}

RaidenNode.prototype.sendTokens = function(tokenAddress, recipientAddress, amount, transferId, options) {
  validateAmount(amount);
  if (transferId && !Number.isInteger(transferId)) throw new Error('token transfer identifier must be an integer');
  return this.raidenRequest('POST', `/transfers/${tokenAddress}/${recipientAddress}`, {
    body: Object.assign({ amount }, transferId ? { identifier: transferId } : {}),
  }, options);
}

function createTokenSwapBody(tokenSwap, isMaker) {
  const {
    makerToken, makerAmount, takerToken, takerAmount,
  } = tokenSwap;
  return isMaker ? {
    role: 'maker',
    sending_token: makerToken,
    sending_amount: makerAmount,
    receiving_token: takerToken,
    receiving_amount: takerAmount,
  } : {
    role: 'taker',
    sending_token: takerToken,
    sending_amount: takerAmount,
    receiving_token: makerToken,
    receiving_amount: makerAmount,
  };
}

RaidenNode.prototype.makeTokenSwap = function(tokenSwap, options) {
  const { identifier, takerAddress } = tokenSwap;
  return this.raidenRequest(
    'PUT',
    `/token_swaps/${takerAddress}/${identifier}`,
    { body: createTokenSwapBody(tokenSwap, true) },
    options,
  );
}

RaidenNode.prototype.takeTokenSwap = function(tokenSwap, options) {
  const { identifier, makerAddress } = tokenSwap;
  return this.raidenRequest(
    'PUT',
    `/token_swaps/${makerAddress}/${identifier}`,
    { body: createTokenSwapBody(tokenSwap, false) },
    options,
  );
}

function getEvents(node, eventUri, fromBlock = 0, options) {
  if (fromBlock < 0) throw new Error(`block number must not be negative (block: ${fromBlock}`);
  return node.raidenRequest('GET', url.resolve('/events', eventUri), fromBlock ? { qs: { from_block: fromBlock } } : {}, options);
}

RaidenNode.prototype.getNetworkEvents = function(fromBlock, options) {
  return getEvents(this, '/network', fromBlock, options);
}

RaidenNode.prototype.getTokenEvents = function(tokenAddress, fromBlock, options) {
  return getEvents(this, `/tokens/${tokenAddress}`, fromBlock, options);
}

RaidenNode.prototype.getChannelEvents = function(channelAddress, fromBlock, options) {
  return getEvents(this, `/channels/${channelAddress}`, fromBlock, options);
}

module.exports = {
  RaidenNode,
  getLocalNode,
};
<|endoftext|>


<commit_before>var pkg = require("./package.json")
var MongoClient = require("mongodb").MongoClient
var params = require("commander")

params
  .version(pkg.version)
  .description(pkg.description)
  .option("-H, --host <address>", "DataBase host (127.0.0.1)", "127.0.0.1")
  .option("-P, --port <number>", "DataBase port (27017)", "27017")
  .option("-d, --db <name>", "DataBase name (logs)", "logs")
  .option("-c, --collection <name>", "DataBase collection name (logs)", "logs")
  .option("-u, --user <username>", "DataBase username (root)", "root")
  .option("-p, --pass <password>", "DataBase username password ()", "")
  .parse(process.argv)

var mongoOptions = "mongodb://"
  + (params.user && params.pass)
    ? "[" + params.user + ":" + params.pass + "]@"
    : ""
  + params.host
  + ":" + params.port
  + "/" + params.db

MongoClient.connect(mongoOptions, onConnection)

function onConnection(e, db) {

  if (e) {
    return handleError(e)
  }

  var collection = db.collection(params.collection)

  process.stdin.resume()
  process.stdin.setEncoding("utf8")
  process.stdin.on("data", function stdin(data) {

    var document = null

    try {
      document = JSON.parse(data)
    } catch (e) {
      document = {
        msg: data
      }
    }

    collection.insertOne(document, function insertOne(e) {
      if (e) {
        return handleError(e)
      }
    })

    process.stdout.write(JSON.stringify(document) + "\n")

  })
}

function handleError(e) {
  if (e instanceof Error) {
    console.error(e)
  } else {
    console.error(new Error(e))
  }
  return
}
<commit_msg>Add process SIGINT handler<commit_after>var pkg = require("./package.json")
var MongoClient = require("mongodb").MongoClient
var params = require("commander")

params
  .version(pkg.version)
  .description(pkg.description)
  .option("-H, --host <address>", "DataBase host (127.0.0.1)", "127.0.0.1")
  .option("-P, --port <number>", "DataBase port (27017)", "27017")
  .option("-d, --db <name>", "DataBase name (logs)", "logs")
  .option("-c, --collection <name>", "DataBase collection name (logs)", "logs")
  .option("-u, --user <username>", "DataBase username (root)", "root")
  .option("-p, --pass <password>", "DataBase username password ()", "")
  .parse(process.argv)

var mongoOptions = "mongodb://"
  + (params.user && params.pass
      ? "[" + params.user + ":" + params.pass + "]@"
      : "")
  + params.host
  + ":" + params.port
  + "/" + params.db

MongoClient.connect(mongoOptions, onConnection)

function onConnection(e, db) {

  if (e) {
    return handleError(e)
  }

  var collection = db.collection(params.collection)

  process.on("SIGINT", function() {
    db.close(function() {
      process.exit()
    })
  })

  process.stdin.resume()
  process.stdin.setEncoding("utf8")
  process.stdin.on("data", function stdin(data) {

    var document = null

    try {
      document = JSON.parse(data)
    } catch (e) {
      document = {
        msg: data
      }
    }

    collection.insertOne(document, function insertOne(e) {
      if (e) {
        return handleError(e)
      }
    })

    process.stdout.write(JSON.stringify(document) + "\n")

  })
}

function handleError(e) {
  if (e instanceof Error) {
    console.error(e)
  } else {
    console.error(new Error(e))
  }
}
<|endoftext|>


<commit_before>module.exports = Synopsis;

var assert = require('assert');
var async = require('async');

var EventEmitter = require('events').EventEmitter;

var inherits = require('util').inherits;

inherits(Synopsis, EventEmitter);

function Synopsis(options) {
  if (!(this instanceof Synopsis)) {
    return new Synopsis(options);
  }

  var self = this;

  EventEmitter.call(this);

  assert(typeof options === 'object');

  var granularity = options.granularity || 5;

  var count = 0;

  var deltaCache = this.deltaCache = {};
  var differ = options.differ;
  var patcher = options.patcher;

  var store = options.store || (function() {
    var cache = [];
    return {
      get: function(key, cb) {
        return cb(null, cache[key]);
      },
      set: function(key, value, cb) {
        cache[key] = value;
        cb();
      }
    };
  })();

  function sum(index, cb) {
    if (typeof cb === 'undefined') {
      cb = index;
      index = count;
    }

    if (typeof index === 'undefined') {
      index = count;
    }

    if (index === 0) {
      return cb(null, options.start);
    }

    delta(0, index, function(err, d) {
      if (err) return cb(err);

      setImmediate(function() {
        cb(null, patcher(options.start, d));
      });
    });
  }

  function patch(delta, cb) {
    testNewPatch(delta, applyPatch);

    function applyPatch(err) {
      if (err) {
        return cb(err);
      }

      // TODO: make these two set operations atomic
      store.set(++ count + '-1', delta, function(err) {
        if (err) return cb(err);

        store.set('count', count, function(err) {
          if (err) return cb(err);

          updateAggregates(delta, function(err) {
            if (err) return cb(err);

            self.emit('patched', delta);

            cb();
          });
        });
      });
    }
  }

  function testNewPatch(patch, cb) {
    sum(function(err, s) {
      if (err) return cb(err);

      try {
        patcher(s, patch);
      } catch(e) {
        return cb(new Error('Invalid Patch ' + JSON.stringify(patch) + " to " + JSON.stringify(s)));
      }
      cb();
    });
  }

  function updateAggregates(delta, cb) {
    var scale = granularity;

    if (scale > count || count % scale !== 0) {
      return setImmediate(cb);
    }

    var after;
    sum(count - 1, function(err, prevSum) {
      if (err) return cb(err);

      after = patcher(prevSum, delta);

      async.whilst(function() {
        return scale <= count && count % scale === 0;
      }, function(next) {
        sum(count - scale, function(err, before) {
          if (err) return next(err);

          store.set(count + '-' + scale, differ(before, after), function(err) {
            if (err) return next(err);

            scale *= granularity;
            next();
          });
        });
      }, cb);
    });
  }

  function collectDeltas(idx1, idx2, cb) {
    var result = [];

    if (idx2 > count) return cb(new Error('index out of range: ' + idx2));
    if (idx1 > idx2) return cb(new Error('delta in incorrect order'));

    if (idx1 === idx2) return cb(null, []);

    var idx = idx2;

    async.whilst(function() {
      return idx > idx1;
    }, function(next) {
      if (idx === 0) {
        idx --;
        return next();
      } else if (idx % granularity !== 0) {
        store.get(idx -- + '-1', function(err, delta) {
          result.push(delta);
          return next();
        });
        return;
      }

      var deltaSize = idx - idx1;
      var deltaScale = Math.pow(granularity, Math.floor(Math.log(deltaSize)/Math.log(granularity)));

      var cached;

      async.doWhilst(function(next) {
        if (idx % deltaScale === 0) {
          store.get(idx + '-' + deltaScale, function(err, c) {
            if (c) {
              cached = c;
            } else {
              deltaScale /= granularity;
            }
            next();
          });
        } else {
          deltaScale /= granularity;
          next();
        }
      }, function() {
        return !cached && deltaScale > 1;
      }, function(err) {
        if (err) return next(err);
        if (cached) {
          result.push(cached);
          idx -= deltaScale;

          next();
        } else {
          store.get(idx -- + '-1', function(err, delta) {
            result.push(delta);
            next();
          });
        }
      });
    }, function(err) {
      cb(err, result.reverse());
    });
  }

  function delta(idx1, idx2, cb) {
    if (typeof cb === 'undefined') {
      cb = idx2;
      idx2 = count;
    }

    collectDeltas(idx1, idx2, function(err, deltas) {
      if (err) return cb(err);

      sum(idx1, function(err, start) {
        if (err) return cb(err);

        var result = start;

        deltas.forEach(function(delta) {
          result = patcher(result, delta);
        });

        cb(null, differ(start, result));
      });
    });
  }

  function size(cb) {
    if (count || count === 0) return cb(null, count);

    store.get('count', function(err, c) {
      if (err) return cb(err);

      count = c || 0;

      cb(null, count);
    });
  }

  size(function(err) {
    if (err) return debug('error', err);

    process.nextTick(function() {
      self.emit('ready');
    });
  });

  this.sum = sum;
  this.delta = delta;
  this.patch = patch;
  this.collectDeltas = collectDeltas;
  this.size = size;
}
<commit_msg>improving error message<commit_after>module.exports = Synopsis;

var assert = require('assert');
var async = require('async');

var EventEmitter = require('events').EventEmitter;

var inherits = require('util').inherits;

inherits(Synopsis, EventEmitter);

function Synopsis(options) {
  if (!(this instanceof Synopsis)) {
    return new Synopsis(options);
  }

  var self = this;

  EventEmitter.call(this);

  assert(typeof options === 'object');

  var granularity = options.granularity || 5;

  var count;

  var deltaCache = this.deltaCache = {};
  var differ = options.differ;
  var patcher = options.patcher;

  var store = options.store || (function() {
    var cache = [];
    return {
      get: function(key, cb) {
        return cb(null, cache[key]);
      },
      set: function(key, value, cb) {
        cache[key] = value;
        cb();
      }
    };
  })();

  function sum(index, cb) {
    if (typeof cb === 'undefined') {
      cb = index;
      index = count;
    }

    if (typeof index === 'undefined') {
      index = count;
    }

    if (index === 0) {
      return cb(null, options.start);
    }

    delta(0, index, function(err, d) {
      if (err) return cb(err);

      setImmediate(function() {
        cb(null, patcher(options.start, d));
      });
    });
  }

  function patch(delta, cb) {
    testNewPatch(delta, applyPatch);

    function applyPatch(err) {
      if (err) {
        return cb(err);
      }

      // TODO: make these two set operations atomic
      store.set(++ count + '-1', delta, function(err) {
        if (err) return cb(err);

        store.set('count', count, function(err) {
          if (err) return cb(err);

          updateAggregates(delta, function(err) {
            if (err) return cb(err);

            self.emit('patched', delta);

            cb();
          });
        });
      });
    }
  }

  function testNewPatch(patch, cb) {
    sum(function(err, s) {
      if (err) return cb(err);

      try {
        patcher(s, patch);
      } catch(e) {
        return cb(new Error('Invalid Patch ' + JSON.stringify(patch) + " to " + JSON.stringify(s)));
      }
      cb();
    });
  }

  function updateAggregates(delta, cb) {
    var scale = granularity;

    if (scale > count || count % scale !== 0) {
      return setImmediate(cb);
    }

    var after;
    sum(count - 1, function(err, prevSum) {
      if (err) return cb(err);

      after = patcher(prevSum, delta);

      async.whilst(function() {
        return scale <= count && count % scale === 0;
      }, function(next) {
        sum(count - scale, function(err, before) {
          if (err) return next(err);

          store.set(count + '-' + scale, differ(before, after), function(err) {
            if (err) return next(err);

            scale *= granularity;
            next();
          });
        });
      }, cb);
    });
  }

  function collectDeltas(idx1, idx2, cb) {
    var result = [];

    if (idx2 > count) return cb(new Error('index out of range: ' + idx2));
    if (idx1 > idx2) return cb(new Error('delta in incorrect order: ' + idx1 + ' > ' + idx2));

    if (idx1 === idx2) return cb(null, []);

    var idx = idx2;

    async.whilst(function() {
      return idx > idx1;
    }, function(next) {
      if (idx === 0) {
        idx --;
        return next();
      } else if (idx % granularity !== 0) {
        store.get(idx -- + '-1', function(err, delta) {
          result.push(delta);
          return next();
        });
        return;
      }

      var deltaSize = idx - idx1;
      var deltaScale = Math.pow(granularity, Math.floor(Math.log(deltaSize)/Math.log(granularity)));

      var cached;

      async.doWhilst(function(next) {
        if (idx % deltaScale === 0) {
          store.get(idx + '-' + deltaScale, function(err, c) {
            if (c) {
              cached = c;
            } else {
              deltaScale /= granularity;
            }
            next();
          });
        } else {
          deltaScale /= granularity;
          next();
        }
      }, function() {
        return !cached && deltaScale > 1;
      }, function(err) {
        if (err) return next(err);
        if (cached) {
          result.push(cached);
          idx -= deltaScale;

          next();
        } else {
          store.get(idx -- + '-1', function(err, delta) {
            result.push(delta);
            next();
          });
        }
      });
    }, function(err) {
      cb(err, result.reverse());
    });
  }

  function delta(idx1, idx2, cb) {
    if (typeof cb === 'undefined') {
      cb = idx2;
      idx2 = count;
    }

    collectDeltas(idx1, idx2, function(err, deltas) {
      if (err) return cb(err);

      sum(idx1, function(err, start) {
        if (err) return cb(err);

        var result = start;

        deltas.forEach(function(delta) {
          result = patcher(result, delta);
        });

        cb(null, differ(start, result));
      });
    });
  }

  function size(cb) {
    if (count || count === 0) return cb(null, count);

    store.get('count', function(err, c) {
      if (err) return cb(err);

      count = c || 0;

      cb(null, count);
    });
  }

  size(function(err) {
    if (err) return debug('error', err);

    process.nextTick(function() {
      self.emit('ready');
    });
  });

  this.sum = sum;
  this.delta = delta;
  this.patch = patch;
  this.collectDeltas = collectDeltas;
  this.size = size;
}
<|endoftext|>


<commit_before>'use strict';

var diff = require('diff');
var chalk = require('chalk');
var extend = require('lodash').extend;
var Template = require('template');
var Task = require('orchestrator');
var vfs = require('vinyl-fs');

var session = require('./lib/session');
var stack = require('./lib/stack');
var utils = require('./lib/utils/');
var init = require('./lib/init');

/**
 * Initialize `Verb`
 *
 * @param {Object} `context`
 * @api private
 */

function Verb() {
  Template.apply(this, arguments);
  Task.apply(this, arguments);
  this.session = session;
  init(this);
}

extend(Verb.prototype, Task.prototype);
Template.extend(Verb.prototype);

/**
 * Display a visual representation of the
 * difference between `a` and `b`
 */

Verb.prototype.diff = function(a, b, method) {
  method = method || 'diffJson';

  a = a || this.env;
  b = b || this.cache.data;
  diff[method](a, b).forEach(function (res) {
    var color = chalk.gray;
    if (res.added) {
      color = chalk.green;
    }
    if (res.removed) {
      color = chalk.red;
    }
    process.stderr.write(color(res.value));
  });
  console.log('\n');
};

/**
 * Run an array of tasks.
 *
 * ```js
 * verb.run(['foo', 'bar']);
 * ```
 *
 * @param {Array} `tasks`
 * @api private
 */

Verb.prototype.run = function() {
  var tasks = arguments.length ? arguments : ['default'];
  this.start.apply(this, tasks);
};

/**
 * Wrapper around Task._runTask to enable `sessions`
 *
 * @param  {Object} `task` Task to run
 * @api private
 */

Verb.prototype._runTask = function(task) {
  var verb = this;
  verb.session.run(function () {
    verb.session.set('task', task.name);
    Task.prototype._runTask.call(verb, task);
  });
};

/**
 * Glob patterns or filepaths to source files.
 *
 * ```js
 * verb.src('src/*.hbs', {layout: 'default'})
 * ```
 *
 * **Example usage**
 *
 * ```js
 * verb.task('site', function() {
 *   verb.src('src/*.hbs', {layout: 'default'})
 *     verb.dest('dist')
 * });
 * ```
 *
 * @param {String|Array} `glob` Glob patterns or file paths to source files.
 * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
 * @api public
 */

Verb.prototype.src = function(glob, opts) {
  return stack.src(this, glob, opts);
};

/**
 * Specify a destination for processed files.
 *
 * ```js
 * verb.dest('dist', {ext: '.xml'})
 * ```
 *
 * **Example usage**
 *
 * ```js
 * verb.task('sitemap', function() {
 *   verb.src('src/*.txt')
 *     verb.dest('dist', {ext: '.xml'})
 * });
 * ```
 *
 * @param {String|Function} `dest` File path or rename function.
 * @param {Object} `options` Options or locals to merge into the context and/or pass to `dest` plugins
 * @api public
 */

Verb.prototype.dest = function(dest, opts) {
  return stack.dest(this, dest, opts);
};

/**
 * Copy a `glob` of files to the specified `dest`.
 *
 * ```js
 * verb.task('assets', function() {
 *   verb.copy('assets/**', 'dist');
 * });
 * ```
 *
 * @param  {String|Array} `glob`
 * @param  {String|Function} `dest`
 * @return {Stream} Stream to allow doing additional work.
 */

Verb.prototype.copy = function(glob, dest) {
  return vfs.src(glob).pipe(vfs.dest(dest));
};

/**
 * The `files` property is session-context-specific
 * and returns the `files` collection being used in
 * the current `task`.
 *
 * @name assemble.files
 * @return {Object} Template files from current task.
 * @api public
 */

// Object.defineProperty(Verb.prototype, 'files', {
//   configurable: true,
//   enumerable: true,
//   get: function () {
//     var plural = this.inflections[this.gettask()];
//     return this.views[plural];
//   }
// });

/**
 * Define a Verb task.
 *
 * ```js
 * verb.task('docs', function() {
 *   verb.src(['.verb.md', 'docs/*.md'])
 *     .pipe(verb.dest('./'));
 * });
 * ```
 *
 * @param {String} `name`
 * @param {Function} `fn`
 * @api public
 */

Verb.prototype.task = Verb.prototype.add;

/**
 * Get the id from the current task.
 *
 * ```js
 * verb.gettask();
 * ```
 *
 * @return {String} `task` The currently running task.
 * @api public
 */

Verb.prototype.gettask = function() {
  var name = this.session.get('task');
  return typeof name != 'undefined'
    ? 'task_' + name
    : 'file';
};

/**
 * Re-run the specified task(s) when a file changes.
 *
 * ```js
 * verb.task('watch', function() {
 *   verb.watch('docs/*.md', ['docs']);
 * });
 * ```
 *
 * @param  {String|Array} `glob` Filepaths or glob patterns.
 * @param  {Function} `fn` Task(s) to watch.
 * @api public
 */

Verb.prototype.watch = function(glob, opts, fn) {
  if (Array.isArray(opts) || typeof opts === 'function') {
    fn = opts; opts = null;
  }

  if (!Array.isArray(fn)) vfs.watch(glob, opts, fn);
  return vfs.watch(glob, opts, function () {
    this.start.apply(this, fn);
  }.bind(this));
};

/**
 * Expose `verb.Verb`
 */

Verb.prototype.Verb = Verb;

/**
 * Expose `verb`
 */

module.exports = new Verb();
<commit_msg>expose `taskFiles` getter<commit_after>'use strict';

var diff = require('diff');
var chalk = require('chalk');
var extend = require('lodash').extend;
var Template = require('template');
var Task = require('orchestrator');
var vfs = require('vinyl-fs');

var session = require('./lib/session');
var stack = require('./lib/stack');
var init = require('./lib/init');

/**
 * Initialize `Verb`
 *
 * @param {Object} `context`
 * @api private
 */

function Verb() {
  Template.apply(this, arguments);
  Task.apply(this, arguments);
  this.session = session;
  init(this);
}

extend(Verb.prototype, Task.prototype);
Template.extend(Verb.prototype);

/**
 * Display a visual representation of the
 * difference between `a` and `b`
 */

Verb.prototype.diff = function(a, b, method) {
  method = method || 'diffJson';
  a = a || this.env;
  b = b || this.cache.data;
  diff[method](a, b).forEach(function (res) {
    var color = chalk.gray;
    if (res.added) {
      color = chalk.green;
    }
    if (res.removed) {
      color = chalk.red;
    }
    process.stderr.write(color(res.value));
  });
  console.log('\n');
};

/**
 * Run an array of tasks.
 *
 * ```js
 * verb.run(['foo', 'bar']);
 * ```
 *
 * @param {Array} `tasks`
 * @api private
 */

Verb.prototype.run = function() {
  var tasks = arguments.length ? arguments : ['default'];
  this.start.apply(this, tasks);
};

/**
 * Wrapper around Task._runTask to enable `sessions`
 *
 * @param  {Object} `task` Task to run
 * @api private
 */

Verb.prototype._runTask = function(task) {
  var verb = this;
  verb.session.run(function () {
    verb.session.set('task', task.name);
    Task.prototype._runTask.call(verb, task);
  });
};

/**
 * Glob patterns or filepaths to source files.
 *
 * ```js
 * verb.src('src/*.hbs', {layout: 'default'})
 * ```
 *
 * **Example usage**
 *
 * ```js
 * verb.task('site', function() {
 *   verb.src('src/*.hbs', {layout: 'default'})
 *     verb.dest('dist')
 * });
 * ```
 *
 * @param {String|Array} `glob` Glob patterns or file paths to source files.
 * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
 * @api public
 */

Verb.prototype.src = function(glob, opts) {
  return stack.src(this, glob, opts);
};

/**
 * Specify a destination for processed files.
 *
 * ```js
 * verb.dest('dist', {ext: '.xml'})
 * ```
 *
 * **Example usage**
 *
 * ```js
 * verb.task('sitemap', function() {
 *   verb.src('src/*.txt')
 *     verb.dest('dist', {ext: '.xml'})
 * });
 * ```
 *
 * @param {String|Function} `dest` File path or rename function.
 * @param {Object} `options` Options or locals to merge into the context and/or pass to `dest` plugins
 * @api public
 */

Verb.prototype.dest = function(dest, opts) {
  return stack.dest(this, dest, opts);
};

/**
 * Copy a `glob` of files to the specified `dest`.
 *
 * ```js
 * verb.task('assets', function() {
 *   verb.copy('assets/**', 'dist');
 * });
 * ```
 *
 * @param  {String|Array} `glob`
 * @param  {String|Function} `dest`
 * @return {Stream} Stream to allow doing additional work.
 */

Verb.prototype.copy = function(glob, dest) {
  return vfs.src(glob).pipe(vfs.dest(dest));
};

/**
 * Define a Verb task.
 *
 * ```js
 * verb.task('docs', function() {
 *   verb.src(['.verb.md', 'docs/*.md'])
 *     .pipe(verb.dest('./'));
 * });
 * ```
 *
 * @param {String} `name`
 * @param {Function} `fn`
 * @api public
 */

Verb.prototype.task = Verb.prototype.add;

/**
 * Get the id from the current task.
 *
 * ```js
 * verb.gettask();
 * ```
 *
 * @return {String} `task` The currently running task.
 * @api public
 */

Verb.prototype.gettask = function() {
  var name = this.session.get('task');
  return typeof name != 'undefined'
    ? 'task_' + name
    : 'file';
};

/**
 * The `taskFiles` property is session-context-specific and
 * returns the collection of files from the current `task`.
 *
 * @name .taskFiles
 * @return {Object} files from the current task.
 * @api public
 */

Object.defineProperty(Verb.prototype, 'taskFiles', {
  configurable: true,
  enumerable: true,
  get: function () {
    return this.views[this.inflections[this.gettask()]];
  }
});

/**
 * Re-run the specified task(s) when a file changes.
 *
 * ```js
 * verb.task('watch', function() {
 *   verb.watch('docs/*.md', ['docs']);
 * });
 * ```
 *
 * @param  {String|Array} `glob` Filepaths or glob patterns.
 * @param  {Function} `fn` Task(s) to watch.
 * @api public
 */

Verb.prototype.watch = function(glob, opts, fn) {
  if (Array.isArray(opts) || typeof opts === 'function') {
    fn = opts; opts = null;
  }
  if (!Array.isArray(fn)) vfs.watch(glob, opts, fn);
  return vfs.watch(glob, opts, function () {
    this.start.apply(this, fn);
  }.bind(this));
};

/**
 * Expose `verb.Verb`
 */

Verb.prototype.Verb = Verb;

/**
 * Expose `verb`
 */

module.exports = new Verb();
<|endoftext|>