/* The checkout backend. */
/* $Id: checkout.c,v 1.11 2003/09/06 10:23:50 pasky Exp $ */

/*
 * PaVS - Pasky's Version System, advanced version control system
 * Copyright (C) 2003  Petr Baudis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include <libpavs/backsel.h>
#include <librcs/revnum.h>
#include <librev/branch.h>
#include <librev/inode.h>
#include <librev/list.h>
#include <librev/revision.h>


int
pavs_checkout_file (char *srcfile, char *destdir, char *revision)
{
	struct rev_inode *inode;
	enum pavs_backend backend;
	struct rev_revision *headrev;
	struct rev_revision *rev;

	assert (srcfile && destdir);

	inode = rev_inode_init ();
	rev_inode_associate (inode);

	backend = rev_inode_attach_backend (inode, srcfile);
	if (backend < 0 || backend == PBE_NONE) {
		rev_inode_dissociate (inode);
		return backend == PBE_NONE ? 0 : -1;
	}

	if (rev_inode_load (inode) <= 0) {
		goto error;
	}

	/* XXX: Is this necessary? Well it is safe ;-). --pasky */
	if (rev_inode_cache (inode) <= 0) {
		goto error;
	}

	headrev = (struct rev_revision *)
		rev_list_last (((struct rev_branch *)
				rev_list_last(inode->forkrev->offsprings)
			       )->revs);
	if (revision) {
		struct rev_objid *r = rcs_revnum_lookup (inode, revision);

		if (! r || r->type != ROIT_REVISION)
			goto error;
		rev = r->data.revision;
		rev_revision_associate (rev);
		rev_objid_untie (r);
		free (r);
	} else {
		rev = headrev;
	}
	if (! rev) {
		goto error;
	}

	/* FIXME: And here we are quite RCS-specific since we rely on the fact
	 * that HEAD has dataobj associated. We should have some generic means
	 * to get dataobj of the revision we need. --pasky */

	/* Do we need to get dataobj to our rev? */

	if (rev != headrev && ! rev->dataobj
	    && rev_revision_propagate_dataobj (headrev) <= 0) {
		goto error;
	}

	if (! rev->dataobj) {
		goto error;
	}

	if (rev_dataobj_store (rev->dataobj, destdir) <= 0) {
		goto error;
	}

	rev_inode_dissociate (inode);
	return 1;

error:
	rev_inode_dissociate (inode);
	return -1;
}
