merge(1) uses an ed script internally to apply changes to merged files,
It fails to properly merge files which contain lines starting with a dot,
as in the following example:
Save these lines as file1:
./etc/signify/openbsd-66-base.pub
./etc/signify/openbsd-66-fw.pub
./etc/signify/openbsd-66-pkg.pub
./etc/signify/openbsd-66-syspatch.pub
./etc/signify/openbsd-67-base.pub
./etc/skel
./etc/skel/.ssh
Save these lines as file2:
./etc/signify/openbsd-66-base.pub
./etc/signify/openbsd-66-fw.pub
./etc/signify/openbsd-66-pkg.pub
./etc/signify/openbsd-66-syspatch.pub
./etc/skel
./etc/skel/.ssh
Save these lines as file3:
./etc/signify/openbsd-66-base.pub
./etc/signify/openbsd-66-fw.pub
./etc/signify/openbsd-66-pkg.pub
./etc/signify/openbsd-66-syspatch.pub
./etc/signify/openbsd-67-base.pub
./etc/signify/openbsd-67-pkg.pub
./etc/skel
./etc/skel/.ssh
Now run: merge -p file1 file2 file3
The output will be:
./etc/signify/openbsd-66-base.pub
./etc/signify/openbsd-66-fw.pub
./etc/signify/openbsd-66-pkg.pub
./etc/signify/openbsd-66-syspatch.pub
<<<<<<< 1
./etc/signify/openbsd-67-base.pub
=======
./etc/skel
./etc/skel/.ssh
No line with a 67 package key, and no trailing conflict marker!
They are missing because the built-in ed script interpreter considers
the leading dot on this line as a "dot on a line by itself" command:
./etc/signify/openbsd-67-pkg.pub
The code only checks for the existence of a leading dot on the line,
not whether the dot appears on a line by itself.
With the patch below, the merged result looks as expected:
./etc/signify/openbsd-66-base.pub
./etc/signify/openbsd-66-fw.pub
./etc/signify/openbsd-66-pkg.pub
./etc/signify/openbsd-66-syspatch.pub
<<<<<<< 1
./etc/signify/openbsd-67-base.pub
=======
./etc/signify/openbsd-67-base.pub
./etc/signify/openbsd-67-pkg.pub
>>>>>>> 3
./etc/skel
./etc/skel/.ssh
Problem found in Game of Trees, which uses diff3 code derived from merge(1).
ok?
diff e875c3a0682a8180b4f2b861af260412eca02c28 /usr/src
blob - 16cc1b29ff5f7ecd37951b7e464496f0f0b9d6fa
file + usr.bin/rcs/diff3.c
--- usr.bin/rcs/diff3.c
+++ usr.bin/rcs/diff3.c
@@ -496,7 +496,8 @@ ed_patch_lines(struct rcs_lines *dlines, struct rcs_li
if (lp == NULL)
errx(1, "ed_patch_lines");
- if (!memcmp(lp->l_line, ".", 1))
+ if (lp->l_len >= 2 &&
+ !memcmp(lp->l_line, ".", lp->l_len - 2))
break;
TAILQ_REMOVE(&(plines->l_lines), lp, l_list);