#ifndef LIBREV__BRANCH_H
#define LIBREV__BRANCH_H

/*
 * Copyright (c) 2003  Petr Baudis.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of the author nor the names of the product's
 *     contributors may be used to endorse or promote products
 *     derived from this software without specific prior written
 *     permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifdef __cplusplus
extern "C" {
#endif


#include <librev/librev.h>
#include <librev/list.h>
#include <librev/revision.h>

#include <time.h>


/* This header file contains the branch object ({struct rev_branch}).  This
 * object is used to stream revisions into a DAG. Each inode has to have at
 * least one (so-called "trunk") branch, as well as at least one revision in
 * each branch. HEAD branch is the last trunk branch, and HEAD revision is the
 * last branch revision. */


struct rev_inode;

rev_object (branch,
	/* Public attributes */


	/* Ordered linked list of branches with a common ancestor. */
	struct rev_list_item offspring; /* @parent->offsprings */

	/* The revision from which this branch was forked off. If this is a
	 * trunk branch, the revision this points at is a special dummy
	 * revision specifically crafted to act ONLY as a placeholder for the
	 * trunk revisions. This revision is not listed in any lists, it is
	 * in uninitialized zero state and ideally, it should be completely
	 * invisible even to the user. Such a revision can be recognized
	 * through a fact that its branch pointer is NULL. Use the
	 * rev_revision_is_dummy () macro. */
	/* {rev_branch_get_parent()},{rev_branch_set_parent()} */
	struct rev_revision *parent;

	/* The inode this branch belongs to. Note that the inode is superior
	 * object to branch, thus we don't increment inode's refcount. A
	 * branch always gets notified when inode is going away. */
	/* {rev_branch_get_inode()},{rev_branch_set_inode()} */
	struct rev_inode *inode;


	/* The history */

	/* Ordered linked list of revisions in the branch. First is the
	 * earliest, last is the newest. */
	struct rev_list_head revs; /* {struct rev_revision} */


	/* Identification */

	/* Number of this branch (unique in the frame of parent offsprings). */
	/* {rev_branch_get_number()},{rev_branch_set_number()} */
	int number;


	/* Backend data: */

	void *data; /* Backend's data. */

	struct rev_branch_dataops {
		/* Release obj->data. */
		void (*done) (struct rev_branch *obj);
	} *dataops;


	/* User data: */

	void *udata; /* User's data. */

	struct rev_branch_userops {
		/* Release obj->udata. */
		void (*done) (struct rev_branch *obj);
	} *userops;
);

/* Constructor */

/* This creates the branch, belonging to @inode, forked off from @parent. */
/* Returns the pointer on success, NULL otherwise. */
struct rev_branch *rev_branch_init (struct rev_inode *inode,
				struct rev_revision *parent);

/* This creates the branch, belonging to @inode, forked off from @parent. It
 * makes sure that it is added to a correct spot in the offsprings list. */
/* Returns the pointer on success, NULL otherwise. */
struct rev_branch *rev_branch_allocate (struct rev_inode *inode,
				struct rev_revision *parent, int number);


/* Action */

/* This looks up a revision of given number. */
/* Returns the revision structure pointer on success, NULL otherwise. */
struct rev_revision *rev_branch_find_revision (struct rev_branch *obj,
					      int number);


/* Attributes */

#include <assert.h>

/* This returns the inode. */
static inline struct rev_inode *
rev_branch_get_inode (struct rev_branch *obj)
{
	assert (obj);
	return obj->inode;
}

/* This sets the inode. */
void rev_branch_set_inode (struct rev_branch *obj, struct rev_inode *inode);

/* This returns the parent. */
static inline struct rev_revision *
rev_branch_get_parent (struct rev_branch *obj)
{
	assert (obj);
	return obj->parent;
}

/* This sets the parent. */
void rev_branch_set_parent (struct rev_branch *obj, struct rev_revision *rev);

/* This returns the number. */
static inline int
rev_branch_get_number (struct rev_branch *obj)
{
	assert (obj);
	return obj->number;
}

/* This sets the number. */
static inline void
rev_branch_set_number (struct rev_branch *obj, int number)
{
	assert (obj);
	obj->number = number;
}


#ifdef __cplusplus
}
#endif

#endif
