1 /* three-way file merge internals
2
3 Copyright (C) 2010-2020 Thien-Thi Nguyen
4 Copyright (C) 1991, 1992, 1993, 1994, 1995 Paul Eggert
5
6 This file is part of GNU RCS.
7
8 GNU RCS is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "base.h"
23 #include <string.h>
24 #include <stdlib.h>
25 #include "b-complain.h"
26 #include "b-divvy.h"
27 #include "b-fb.h"
28 #include "b-feph.h"
29 #include "b-fro.h"
30 #include "b-merger.h"
31
32 int
merge(bool tostdout,char const * edarg,struct symdef three_manifestations[3])33 merge (bool tostdout, char const *edarg, struct symdef three_manifestations[3])
34 /* Do ‘merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2’, where ‘tostdout’
35 specifies whether ‘-p’ is present, ‘edarg’ gives the editing type
36 (e.g. "-A", or null for the default), and lN and aN are taken from
37 three_manifestations[N].{meaningful,underlying}, respectively.
38 Return ‘DIFF_SUCCESS’ or ‘DIFF_FAILURE’. */
39 {
40 register int i;
41 FILE *f;
42 struct fro *rt;
43 char const *a[3], *t;
44 int s;
45
46 for (i = 3; 0 <= --i;)
47 {
48 char const *filename = FNAME (i);
49
50 /* If a filename begins with hyphen, prepend ‘./’. */
51 if ('-' == filename[0])
52 {
53 accf (PLEXUS, ".%c", SLASH);
54 a[i] = str_save (filename);
55 }
56 else
57 a[i] = filename;
58 }
59
60 if (!edarg)
61 edarg = "-E";
62
63 if (DIFF3_BIN)
64 {
65 t = NULL;
66 if (!tostdout)
67 t = maketemp (0);
68 s = run (-1, t, prog_diff3, edarg, "-am",
69 "-L", LABEL (0), "-L", LABEL (1), "-L", LABEL (2),
70 a[0], a[1], a[2], NULL);
71 if (DIFF_TROUBLE == s)
72 BOW_OUT ();
73 if (DIFF_FAILURE == s)
74 PWARN ("conflicts during merge");
75 if (t)
76 {
77 if (!(f = fopen_safer (FNAME (0), "w")))
78 fatal_sys (FNAME (0));
79 if (!(rt = fro_open (t, "r", NULL)))
80 fatal_sys (t);
81 fro_spew (rt, f);
82 fro_close (rt);
83 Ozclose (&f);
84 }
85 }
86 else
87 {
88 char const *d[2];
89
90 for (i = 0; i < 2; i++)
91 if (DIFF_TROUBLE == run (-1, d[i] = maketemp (i), prog_diff,
92 a[i], a[2], NULL))
93 PFATAL ("diff failed");
94 t = maketemp (2);
95 s = run (-1, t,
96 prog_diff3, edarg, d[0], d[1], a[0], a[1], a[2],
97 LABEL (0), LABEL (2), NULL);
98 if (s != DIFF_SUCCESS)
99 {
100 s = DIFF_FAILURE;
101 PWARN ("overlaps or other problems during merge");
102 }
103 if (!(f = fopen_safer (t, "a+")))
104 fatal_sys (t);
105 aputs (tostdout ? "1,$p\n" : "w\n", f);
106 rewind (f);
107 aflush (f);
108 if (run (fileno (f), NULL, ED, "-", a[0], NULL))
109 BOW_OUT ();
110 Ozclose (&f);
111 }
112
113 tempunlink ();
114 return s;
115 }
116
117 /* merger.c ends here */
118