"use strict";
var nodeFs = require("fs");
var nodePath = require("path");
var mkdirp = require("mkdirp");

// Implements the fs interface required by js-git/fs-db
var fs = module.exports = {};

fs.readFile = readFile;
fs.readChunk = readChunk;
fs.writeFile = writeFile;
fs.readDir = readDir;

// Reads all bytes for given path.
// => binary
// => undefined if file does not exist
function readFile(path, callback) {
  nodeFs.readFile(path, function (err, binary) {
    if (err) {
      if (err.code === "ENOENT") {
        callback();
      } else {
        callback(err);
      }
    } else {
      callback(null, binary);
    }
  });
}

// Reads bytes from inclusive [start, end) exclusive for given path.
// => binary
// => undefined if file does not exist
function readChunk(path, start, end, callback) {
  var stream = nodeFs.createReadStream(path, {
    start: start,
    end: end - 1
  });
  var chunks = [];
  stream.on("readable", function () {
    var chunk = stream.read();
    if (chunk === null) {
      callback(null, Buffer.concat(chunks));
    } else {
      chunks.push(chunk);
    }
  });
  stream.on("error", function (err) {
    if (err.code === "ENOENT") {
      callback();
    } else {
      callback(err);
    }
  });
}

// Writes all bytes over file at given path.
// Creates all necessary parent directories.
// => undefined
function writeFile(path, binary, callback) {
  mkdirp(nodePath.dirname(path), function (err) {
    if (err) {
      callback(err);
    } else {
      nodeFs.writeFile(path, binary, callback);
    }
  });
}

// Reads all entry names for a given path.
// All names are relative to the directory itself, not fully qualified paths.
// => array<name>
// => undefined if directory does not exist
function readDir(path, callback) {
  nodeFs.readdir(path, function (err, names) {
    if (err) {
      if (err.code === "ENOENT") {
        callback();
      } else {
        callback(err);
      }
    } else {
      callback(null, names);
    }
  });
}

@@ -802,16 +802,91 @@
 back) %7B%0A
+  if (end %3C 0) %7B%0A    return readLastChunk(path, start, end, callback);%0A  %7D%0A
   var st
@@ -1313,16 +1313,1218 @@
  %7D);%0A%7D%0A%0A
+// Node.js readable streams do not support reading from a position to the end%0A// of the file, but we can roll our own using the lower-level fs.open and%0A// fs.read on a file descriptor, which allows read to seek.%0Afunction readLastChunk(path, start, end, callback) %7B%0A  nodeFs.open(path, %22r%22, function (err, fd) %7B%0A    if (err) %7B%0A      if (err.code === %22EACCES%22) %7B%0A        callback();%0A      %7D else %7B%0A        callback(err);%0A      %7D%0A    %7D%0A    var buffer = new Buffer(4096);%0A    var length = 0;%0A    read();%0A    // Only the first read needs to seek.%0A    // All subsequent reads will continue from the end of the previous.%0A    start = null;%0A%0A    function read() %7B%0A      if (buffer.length - length === 0) %7B%0A        grow();%0A      %7D%0A      nodeFs.read(fd, buffer, length, buffer.length - length, start, onread);%0A    %7D%0A%0A    function onread(err, bytesRead) %7B%0A      if (err) %7B%0A        callback(err);%0A      %7D%0A      length += bytesRead;%0A      if (bytesRead === 0) %7B%0A        callback(null, buffer.slice(0, buffer.length + end));%0A      %7D else %7B%0A        read();%0A      %7D%0A    %7D%0A%0A    function grow() %7B%0A      var newBuffer = new Buffer(buffer.length * 2);%0A      buffer.copy(newBuffer);%0A      buffer = newBuffer;%0A    %7D%0A  %7D);%0A%7D%0A%0A
 // Write

Support negative end index for readChunk