'use strict'

const commit = require('./commit')
const object = require('./object')


function buildTree (commitHash) {
	function traverseCommit (hash) {
		const { parent, tree } = commit.retrieve(hash)

		return {
			type: 'commit',
			hash,
			tree: traverseTree(tree),
			parent: parent && traverseCommit(parent)
		}
	}

	function traverseTree (hash) {
		const nodes = object.retrieveTree(hash)

		const children = nodes.map(
			({ type, hash }) =>
				type === 'tree'
					? traverseTree(hash)
					: { type: 'blob', hash }
		)

		return {
			type: 'tree',
			children,
		}
	}

	return traverseCommit(commitHash)
}

function collectUntil (start, endHash) {
	const hashes = new Set()

	function traverseCommit ({ hash, tree, parent }) {
		if (hash === endHash) { return }

		hashes.add(hash)

		traverseTree(tree)

		if (parent) {
			traverseCommit(parent)
		}
	}

	function traverseTree ({ hash, type, children }) {
		hashes.add(hash)

		if (type === 'blob') { return }

		children.forEach(traverseTree)
	}

	traverseCommit(start)

	return hashes
}

function diffSets (a, b) {
	const diff = []

	a.forEach((aElement) => {
		if (!b.has(aElement)) {
			diff.push(aElement)
		}
	})

	return diff
}

function findCommit (start, needleHash) {
	if (start.hash === needleHash) {
		return start
	}

	if (start.parent) {
		findCommit(start.parent)
	}
}

function computeDelta (ancestorHash, descendantHash) {
	const ancestorTree = buildTree(ancestorHash)

	const ancestorObjects = collectUntil(ancestorTree, descendantHash)
	const descendantObjects = collectUntil(findCommit(ancestorTree, descendantHash))

	return diffSets(ancestorObjects, descendantObjects)
}

module.exports = {
	computeDelta,
}
@@ -554,16 +554,25 @@
 'tree',%0A
+%09%09%09hash,%0A
 %09%09%09child
@@ -1244,16 +1244,49 @@
 Hash) %7B%0A
+%09if (!start) %7B%0A%09%09return null%0A%09%7D%0A%0A
 %09if (sta
@@ -1335,30 +1335,15 @@
 %7D%0A%0A%09
-if (start.parent) %7B%0A%09%09
+return 
 find
@@ -1361,20 +1361,29 @@
 t.parent
-)%0A%09%7D
+, needleHash)
 %0A%7D%0A%0Afunc
@@ -1401,16 +1401,32 @@
 eDelta (
+descendantHash, 
 ancestor
@@ -1429,18 +1429,50 @@
 storHash
-, 
+) %7B%0A%09const descendant = buildTree(
 descenda
@@ -1474,26 +1474,25 @@
 cendantHash)
- %7B
+%0A
 %0A%09const ance
@@ -1499,25 +1499,34 @@
 stor
-Tree = buildTree(
+ = findCommit(descendant, 
 ance
@@ -1543,24 +1543,26 @@
 %0A%09const 
-ancestor
+descendant
 Objects 
@@ -1580,33 +1580,30 @@
 til(
-ancestorTree, descendantH
+descendant, ancestor.h
 ash)
@@ -1606,34 +1606,32 @@
 ash)%0A%09const 
-descendant
+ancestor
 Objects = co
@@ -1645,95 +1645,69 @@
 til(
-findCommit(ancestorTree, descendantHash))%0A%0A%09return diffSets(ancestorObjects, descendant
+ancestor, null)%0A%0A%09return diffSets(descendantObjects, ancestor
 Obje

Fix objects delta logic