134 lines
3.6 KiB
JavaScript
134 lines
3.6 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
var bodec = require('bodec');
|
||
|
var treeMap = require('../lib/object-codec').treeMap;
|
||
|
|
||
|
module.exports = function (repo) {
|
||
|
var loadAs = repo.loadAs;
|
||
|
repo.loadAs = newLoadAs;
|
||
|
var saveAs = repo.saveAs;
|
||
|
repo.saveAs = newSaveAs;
|
||
|
|
||
|
function newLoadAs(type, hash, callback) {
|
||
|
if (!callback) return newLoadAs.bind(repo, type, hash);
|
||
|
var realType = type === "text" ? "blob":
|
||
|
type === "array" ? "tree" : type;
|
||
|
return loadAs.call(repo, realType, hash, onLoad);
|
||
|
|
||
|
function onLoad(err, body, hash) {
|
||
|
if (body === undefined) return callback(err);
|
||
|
if (type === "text") body = bodec.toUnicode(body);
|
||
|
if (type === "array") body = toArray(body);
|
||
|
return callback(err, body, hash);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function newSaveAs(type, body, callback) {
|
||
|
if (!callback) return newSaveAs.bind(repo, type, body);
|
||
|
type = type === "text" ? "blob":
|
||
|
type === "array" ? "tree" : type;
|
||
|
if (type === "blob") {
|
||
|
if (typeof body === "string") {
|
||
|
body = bodec.fromUnicode(body);
|
||
|
}
|
||
|
}
|
||
|
else if (type === "tree") {
|
||
|
body = normalizeTree(body);
|
||
|
}
|
||
|
else if (type === "commit") {
|
||
|
body = normalizeCommit(body);
|
||
|
}
|
||
|
else if (type === "tag") {
|
||
|
body = normalizeTag(body);
|
||
|
}
|
||
|
return saveAs.call(repo, type, body, callback);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
function toArray(tree) {
|
||
|
return Object.keys(tree).map(treeMap, tree);
|
||
|
}
|
||
|
|
||
|
function normalizeTree(body) {
|
||
|
var type = body && typeof body;
|
||
|
if (type !== "object") {
|
||
|
throw new TypeError("Tree body must be array or object");
|
||
|
}
|
||
|
var tree = {}, i, l, entry;
|
||
|
// If array form is passed in, convert to object form.
|
||
|
if (Array.isArray(body)) {
|
||
|
for (i = 0, l = body.length; i < l; i++) {
|
||
|
entry = body[i];
|
||
|
tree[entry.name] = {
|
||
|
mode: entry.mode,
|
||
|
hash: entry.hash
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
var names = Object.keys(body);
|
||
|
for (i = 0, l = names.length; i < l; i++) {
|
||
|
var name = names[i];
|
||
|
entry = body[name];
|
||
|
tree[name] = {
|
||
|
mode: entry.mode,
|
||
|
hash: entry.hash
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
return tree;
|
||
|
}
|
||
|
|
||
|
function normalizeCommit(body) {
|
||
|
if (!body || typeof body !== "object") {
|
||
|
throw new TypeError("Commit body must be an object");
|
||
|
}
|
||
|
if (!(body.tree && body.author && body.message)) {
|
||
|
throw new TypeError("Tree, author, and message are required for commits");
|
||
|
}
|
||
|
var parents = body.parents || (body.parent ? [ body.parent ] : []);
|
||
|
if (!Array.isArray(parents)) {
|
||
|
throw new TypeError("Parents must be an array");
|
||
|
}
|
||
|
var author = normalizePerson(body.author);
|
||
|
var committer = body.committer ? normalizePerson(body.committer) : author;
|
||
|
return {
|
||
|
tree: body.tree,
|
||
|
parents: parents,
|
||
|
author: author,
|
||
|
committer: committer,
|
||
|
message: body.message
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function normalizeTag(body) {
|
||
|
if (!body || typeof body !== "object") {
|
||
|
throw new TypeError("Tag body must be an object");
|
||
|
}
|
||
|
if (!(body.object && body.type && body.tag && body.tagger && body.message)) {
|
||
|
throw new TypeError("Object, type, tag, tagger, and message required");
|
||
|
}
|
||
|
return {
|
||
|
object: body.object,
|
||
|
type: body.type,
|
||
|
tag: body.tag,
|
||
|
tagger: normalizePerson(body.tagger),
|
||
|
message: body.message
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function normalizePerson(person) {
|
||
|
if (!person || typeof person !== "object") {
|
||
|
throw new TypeError("Person must be an object");
|
||
|
}
|
||
|
if (typeof person.name !== "string" || typeof person.email !== "string") {
|
||
|
throw new TypeError("Name and email are required for person fields");
|
||
|
}
|
||
|
return {
|
||
|
name: person.name,
|
||
|
email: person.email,
|
||
|
date: person.date || new Date()
|
||
|
};
|
||
|
}
|