/*
 *                       rcsmerge operation
 */
/*****************************************************************************
 *                       join 2 revisions with respect to a third
 *****************************************************************************
 *
 * Copyright (C) 1982 by Walter F. Tichy
 *                       Purdue University
 *                       Computer Science Department
 *                       West Lafayette, IN 47907
 *
 * All rights reserved. No part of this software may be sold or distributed
 * in any form or by any means without the prior written permission of the
 * author.
 * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
 */


/* $Log:	C.rcsmerge $
 * Revision 1.1  90/05/22  21:53:45  pmoore
 * Initial revision
 * 
 * Revision 4.3  87/10/18  10:38:02  narten
 * Updating version numbers. Changes relative to version 1.1
 * actually relative to 4.1
 *
 * Revision 1.3  87/09/24  14:00:31  narten
 * Sources now pass through lint (if you ignore printf/sprintf/fprintf
 * warnings)
 *
 * Revision 1.2  87/03/27  14:22:36  jenkins
 * Port to suns
 *
 * Revision 1.1  84/01/23  14:50:36  kcs
 * Initial revision
 *
 * Revision 4.1  83/03/28  11:14:57  wft
 * Added handling of default branch.
 *
 * Revision 3.3  82/12/24  15:29:00  wft
 * Added call to catchsig().
 *
 * Revision 3.2  82/12/10  21:32:02  wft
 * Replaced getdelta() with gettree(); improved error messages.
 *
 * Revision 3.1  82/11/28  19:27:44  wft
 * Initial revision.
 *
 */
#include "rcsbase.h"

/* Option processing */

#define OPTIONS "?pr:"

#define USAGE \
"Usage: rcsmerge [options] file...\n" \
"\n" \
"Options:\n" \
"    -p       Generate the merged revision on stdout\n" \
"    -r rev   Incorporate from <rev1> to <rev2> (-r can be specified twice)\n" \
"\n"

extern int nerror;		/* counter for errors                    */

char *RCSfilename;
char *workfilename;
char *basename;
char *temp1file, *temp2file;

int main(int argc, char **argv)
{
	int ch;
	char command[NCPPN + revlength + 40];
	int revnums;		/* counter for revision numbers given */
	int tostdout;
	char *rev1, *rev2;	/* revision numbers */
	char numericrev[revlength];	/* holds expanded revision number     */
	struct hshentry *gendeltas[hshsize];	/* stores deltas to be
						 * generated */
	struct hshentry *target;

	catchints();
	cmdid = "rcsmerge";
	revnums = 0;
	tostdout = false;

	while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
	{
		switch (ch)
		{
		case 'p':
			tostdout = true;
			break;

		case 'r':
			if (revnums == 0)
			{
				rev1 = optarg;
				revnums = 1;
			}
			else if (revnums == 1)
			{
				rev2 = optarg;
				revnums = 2;
			}
			else
				faterror("too many revision numbers");
			break;

		case '?':
		default:
			fputs(USAGE, stderr);
			exit (ch != '?');
		}
	}

	argv += optind;
	argc -= optind;

	if (argc < 1)
		faterror("No input file\n%s", USAGE);

	if (revnums < 1)
		faterror("no base revision number given");

	/* Expand the remaining elements of argv as wildcarded file names */
	wildcard_expand (&argc, &argv);

	/* now handle all filenames */
	if (pairfilenames(argc, argv, true, false) == 1)
	{

		if (argc > 2 || (argc == 2 && argv[1] != nil))
			warn("too many arguments");
		diagnose("RCS file: %s", RCSfilename);
		if (workfilestat.type != 1 || (workfilestat.attr & 0x01) == 0)
			faterror("Can't open %s", workfilename);

		if (!trysema(RCSfilename, false))
			goto end;	/* give up */

		gettree();	/* reads in the delta tree */

		if (Head == nil)
			faterror("no revisions present");

		if (!expandsym(rev1, numericrev))
			goto end;
		if ((target = genrevs(numericrev, (char *) nil, (char *) nil, (char *) nil, gendeltas)) == 0)
			goto end;
		rev1 = target->num;
		if (revnums == 1)	/* get default for rev2 */
			rev2 = Dbranch != nil ? Dbranch->num : Head->num;
		if (!expandsym(rev2, numericrev))
			goto end;
		if ((target = genrevs(numericrev, (char *) nil, (char *) nil, (char *) nil, gendeltas)) == 0)
			goto end;
		rev2 = target->num;

		temp1file = mktempfile("RcsMerge1");
		temp2file = mktempfile("RcsMerge2");

		diagnose("retrieving revision %s", rev1);
		VOID sprintf(command, "co -q -p -r%s %s > %s\n",
			         rev1, RCSfilename, temp1file);
		if (system(command))
		{
			faterror("co failed");
		}
		diagnose("retrieving revision %s", rev2);
		VOID sprintf(command, "co -q -p -r%s %s > %s\n",
			         rev2, RCSfilename, temp2file);
		if (system(command))
		{
			faterror("co failed");
		}
		diagnose("Merging differences between %s and %s into %s%s",
			 rev1, rev2, workfilename,
			 tostdout ? "; result to stdout" : "");

		VOID sprintf(command, "%s %s%s %s %s %s %s\n", MERGE, tostdout ? "-p " : "",
		    workfilename, temp1file, temp2file, workfilename, rev2);
		if (system(command))
		{
			faterror("merge failed");
		}
	}

end:
	VOID cleanup();
	return (nerror != 0);

}
