GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/rcs/rcsmerge.c Lines: 0 79 0.0 %
Date: 2016-12-06 Branches: 0 63 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rcsmerge.c,v 1.56 2015/11/02 16:45:21 nicm Exp $	*/
2
/*
3
 * Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. The name of the author may not be used to endorse or promote products
13
 *    derived from this software without specific prior written permission.
14
 *
15
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <err.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <unistd.h>
32
33
#include "rcsprog.h"
34
#include "diff.h"
35
36
int
37
rcsmerge_main(int argc, char **argv)
38
{
39
	int fd, ch, flags, kflag, status;
40
	char fpath[PATH_MAX], r1[RCS_REV_BUFSZ], r2[RCS_REV_BUFSZ];
41
	char *rev_str1, *rev_str2;
42
	RCSFILE *file;
43
	RCSNUM *rev1, *rev2;
44
	BUF *bp;
45
46
	flags = 0;
47
	status = D_ERROR;
48
	rev1 = rev2 = NULL;
49
	rev_str1 = rev_str2 = NULL;
50
51
	while ((ch = rcs_getopt(argc, argv, "AEek:p::q::r::TVx::z:")) != -1) {
52
		switch (ch) {
53
		case 'A':
54
			/*
55
			 * kept for compatibility
56
			 */
57
			break;
58
		case 'E':
59
			flags |= MERGE_EFLAG;
60
			flags |= MERGE_OFLAG;
61
			break;
62
		case 'e':
63
			flags |= MERGE_EFLAG;
64
			break;
65
		case 'k':
66
			kflag = rcs_kflag_get(rcs_optarg);
67
			if (RCS_KWEXP_INVAL(kflag)) {
68
				warnx("invalid RCS keyword substitution mode");
69
				(usage)();
70
			}
71
			break;
72
		case 'p':
73
			rcs_setrevstr2(&rev_str1, &rev_str2, rcs_optarg);
74
			flags |= PIPEOUT;
75
			break;
76
		case 'q':
77
			rcs_setrevstr2(&rev_str1, &rev_str2, rcs_optarg);
78
			flags |= QUIET;
79
			break;
80
		case 'r':
81
			rcs_setrevstr2(&rev_str1, &rev_str2,
82
			    rcs_optarg ? rcs_optarg : "");
83
			break;
84
		case 'T':
85
			/*
86
			 * kept for compatibility
87
			 */
88
			break;
89
		case 'V':
90
			printf("%s\n", rcs_version);
91
			exit(0);
92
		case 'x':
93
			/* Use blank extension if none given. */
94
			rcs_suffixes = rcs_optarg ? rcs_optarg : "";
95
			break;
96
		case 'z':
97
			timezone_flag = rcs_optarg;
98
			break;
99
		default:
100
			(usage)();
101
		}
102
	}
103
104
	argc -= rcs_optind;
105
	argv += rcs_optind;
106
107
	if (rev_str1 == NULL) {
108
		warnx("no base revision number given");
109
		(usage)();
110
	}
111
112
	if (argc < 1) {
113
		warnx("no input file");
114
		(usage)();
115
	}
116
117
	if (argc > 2 || (argc == 2 && argv[1] != NULL))
118
		warnx("warning: excess arguments ignored");
119
120
	if ((fd = rcs_choosefile(argv[0], fpath, sizeof(fpath))) < 0)
121
		err(status, "%s", fpath);
122
123
	if (!(flags & QUIET))
124
		(void)fprintf(stderr, "RCS file: %s\n", fpath);
125
126
	if ((file = rcs_open(fpath, fd, RCS_READ)) == NULL)
127
		return (status);
128
129
	if (strcmp(rev_str1, "") == 0) {
130
		rev1 = rcsnum_alloc();
131
		rcsnum_cpy(file->rf_head, rev1, 0);
132
	} else if ((rev1 = rcs_getrevnum(rev_str1, file)) == NULL)
133
		errx(D_ERROR, "invalid revision: %s", rev_str1);
134
135
	if (rev_str2 != NULL && strcmp(rev_str2, "") != 0) {
136
		if ((rev2 = rcs_getrevnum(rev_str2, file)) == NULL)
137
			errx(D_ERROR, "invalid revision: %s", rev_str2);
138
	} else {
139
		rev2 = rcsnum_alloc();
140
		rcsnum_cpy(file->rf_head, rev2, 0);
141
	}
142
143
	if (rcsnum_cmp(rev1, rev2, 0) == 0)
144
		goto out;
145
146
	if ((bp = rcs_diff3(file, argv[0], rev1, rev2, flags)) == NULL)
147
		errx(D_ERROR, "failed to merge");
148
149
	if (!(flags & QUIET)) {
150
		(void)rcsnum_tostr(rev1, r1, sizeof(r1));
151
		(void)rcsnum_tostr(rev2, r2, sizeof(r2));
152
153
		(void)fprintf(stderr, "Merging differences between %s and "
154
		    "%s into %s%s\n", r1, r2, argv[0],
155
		    (flags & PIPEOUT) ? "; result to stdout":"");
156
	}
157
158
	if (diff3_conflicts != 0)
159
		status = D_OVERLAPS;
160
	else
161
		status = 0;
162
163
	if (flags & PIPEOUT)
164
		buf_write_fd(bp, STDOUT_FILENO);
165
	else {
166
		/* XXX mode */
167
		if (buf_write(bp, argv[0], 0644) < 0)
168
			warnx("buf_write failed");
169
170
	}
171
172
	buf_free(bp);
173
174
out:
175
	rcs_close(file);
176
	rcsnum_free(rev1);
177
	rcsnum_free(rev2);
178
	return (status);
179
}
180
181
__dead void
182
rcsmerge_usage(void)
183
{
184
	fprintf(stderr,
185
	    "usage: rcsmerge [-EV] [-kmode] [-p[rev]] [-q[rev]]\n"
186
	    "                [-xsuffixes] [-ztz] -rrev file ...\n");
187
188
	exit(D_ERROR);
189
}