Reimplementation of Pijul in C, for education, fun and absolutely no profit
#include <stdint.h>
#include <stdlib.h>

#include "common.h"
#include "scaffold.h"
#include "hash.h"
#include "vertex.h"
#include "atom.h"
#include "hunk.h"

const char *
hunk_basehunk_type_str(enum basehunktype hunk_type)
{
	switch (hunk_type) {
	case FILE_MOVE:
		return "file move";
	case FILE_DEL:
		return "file del";
	case FILE_UNDEL:
		return "file undel";
	case FILE_ADD:
		return "file add";
	case SOLVE_NAME_CONFLICT:
		return "solve name conflict";
	case UNSOLVE_NAME_CONFLICT:
		return "unsolve name conflict";
	case EDIT:
		return "edit";
	case REPLACEMENT:
		return "replacement";
	case SOLVE_ORDER_CONFLICT:
		return "solve order conflict";
	case UNSOLVE_ORDER_CONFLICT:
		return "unsolve order conflict";
	case RESURRECT_ZOMBIES:
		return "resurrect zombies";
	case ADD_ROOT:
		return "add root";
	case DEL_ROOT:
		return "del root";
	default:
		die("unknown hunk type: %u", hunk_type);
	}
}

void
hunklistinit(struct hunklist *hunklist, size_t len)
{
	hunklist->len = len;
	hunklist->entries = xmalloc(sizeof(struct basehunk) * len);
}

void
hunklistfree(struct hunklist *hunklist)
{
	size_t i;

	for (i = 0; i < hunklist->len; i++) {
		struct basehunk *b = &hunklist->entries[i];
		switch (b->hunktype) {
		case FILE_MOVE:
			atomfree(&b->filemove.del);
			atomfree(&b->filemove.add);
			free(b->filemove.path);
			break;
		case FILE_DEL:
			atomfree(&b->filedel.del);
			/* FIXME this is optional */
			atomfree(&b->filedel.contents);
			free(b->filedel.path);
			if (b->filedel.encoding)
				free(b->filedel.encoding);
			break;
		case FILE_UNDEL:
			atomfree(&b->fileundel.undel);
			/* FIXME this is optional */
			atomfree(&b->fileundel.contents);
			free(b->fileundel.path);
			if (b->fileundel.encoding)
				free(b->fileundel.encoding);
			break;
		case FILE_ADD:
			atomfree(&b->fileadd.addname);
			atomfree(&b->fileadd.addinode);
			/* FIXME this is optional */
			atomfree(&b->fileadd.contents);
			free(b->fileadd.path);
			if (b->fileadd.encoding)
				free(b->fileadd.encoding);
			break;
		case EDIT:
			atomfree(&b->edit.change);
			free(b->edit.local.path);
			if (b->edit.encoding)
				free(b->edit.encoding);
			break;
		case REPLACEMENT:
			atomfree(&b->replacement.change);
			atomfree(&b->replacement.replacement);
			free(b->replacement.local.path);
			if (b->replacement.encoding)
				free(b->replacement.encoding);
			break;
		case SOLVE_ORDER_CONFLICT:
			atomfree(&b->solveorderconflict.change);
			free(b->solveorderconflict.local.path);
			break;
		case UNSOLVE_ORDER_CONFLICT:
			atomfree(&b->unsolveorderconflict.change);
			free(b->unsolveorderconflict.local.path);
			break;
		case SOLVE_NAME_CONFLICT:
			atomfree(&b->solvenameconflict.name);
			free(b->solvenameconflict.path);
			break;
		case UNSOLVE_NAME_CONFLICT:
			atomfree(&b->unsolvenameconflict.name);
			free(b->unsolvenameconflict.path);
			break;
		case RESURRECT_ZOMBIES:
			atomfree(&b->resurrectzombies.change);
			free(b->resurrectzombies.local.path);
			if (b->resurrectzombies.encoding)
				free(b->resurrectzombies.encoding);
			break;
		case ADD_ROOT:
			atomfree(&b->addroot.name);
			atomfree(&b->addroot.inode);
			break;
		case DEL_ROOT:
			atomfree(&b->delroot.name);
			atomfree(&b->delroot.inode);
			break;
		}
	}
	free(hunklist->entries);
}