[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Binary update and merge problem
From: |
Paul Sander |
Subject: |
Re: Binary update and merge problem |
Date: |
Mon, 9 Dec 2002 13:50:44 -0800 |
At the bottom of this message is a patch that I posted to this forum
over a year ago that implements a simple merge manager that relies on
consistent naming conventions to determine the type of data contained
in a file. It places a layer of abstraction over the merge tool and
allows the CVS admin to configure different merge tools based on the
type of data under source control.
The patch applies to CVS 1.11, so it might be a little out of date,
--- Forwarded mail from address@hidden
Walter Ghijsen wrote:
> I'm running into problems with merging binary files from one branch
> into another.
> Does anyone have any suggestions?
Yes. Don't merge binary files. CVS knows how to merge only text
files. Binary files you must handle on your own. What you probably
want to do is replace the main trunk version of the file with any
changed files on the developer branch, but you are the expert there.
You may need to devise a script for this. The handling of binary
files in CVS is very limited.
--- End of forwarded message from address@hidden
The following patch replaces the existing diff3-based merge algorithm
with the extensible one that I posted a while ago, with a slight
refinement. The patch modifies the update.c and rcscmds.c files as
needed to that end (while removing special -kb handling), and changes
a single diagnostic that becomes misleading in this context. It also
adds three Bourne Shell scripts: cvsmerge is the top-level wrapper
that matches the working file's name to a regular expression and invokes
an appropriate merge tool. cvsmerge.ascii invokes the usual diff3-based
merge. cvsmerge.binary performs a simple two-way selection, taking the
version that differs from the common ancestor and indicating a conflict
if both contributors have changed.
This is simple demonstration code and is suitable only for those
who are willing to try new things in a test environment. You must
modify the cvsmerge script to recognize the types of files at your
site. It would be prudent to add a match of last resort to the end
of the list to maintain backward compatibility by invoking cvsmerge.ascii.
Constructive feedback is welcome.
>--- End of forwarded message from address@hidden
Index: tools/cvs/src/cvsmerge
diff -c /dev/null tools/cvs/src/cvsmerge:1.1.2.1
*** /dev/null Sun Sep 16 01:05:14 2001
--- tools/cvs/src/cvsmerge Sun Sep 16 01:00:25 2001
***************
*** 0 ****
--- 1,36 ----
+ #!/bin/sh
+
+ # Usage: cvsmerge work ancestor contributor
+
+ me=`basename "$0"`
+
+ # The following table identifies the proper merge tool, based on the
+ # name of the working file.
+
+ cmd=`
+ cat <<EOF |
+ .*\.txt cvsmerge.ascii
+ .*\.gif cvsmerge.binary
+ .*\.jpg cvsmerge.binary
+ EOF
+
+ # The following code plucks out the proper tool from the table above
+ # and invokes it.
+
+ sed -e 's/^/^/' -e 's/ */$ /' |
+ awk '-F ' '
+ match(p1,$1) { print $2 }
+ ' "p1=$1" |
+ head -1
+ `
+
+ if [ "x$cmd" = "x" ]
+ then
+ echo "${me}: Failed to locate the proper merge tool" 1>&2
+ exit 2
+ fi
+
+ echo "${me}: Invoking $cmd $1 $2 $3" 1>&2
+ $cmd "$1" "$2" "$3"
+ exit $?
+
Index: tools/cvs/src/cvsmerge.ascii
diff -c /dev/null tools/cvs/src/cvsmerge.ascii:1.1.2.1
*** /dev/null Sun Sep 16 01:05:15 2001
--- tools/cvs/src/cvsmerge.ascii Sun Sep 16 01:00:26 2001
***************
*** 0 ****
--- 1,4 ----
+ #!/bin/sh
+
+ diff3 -E -am -L "$1" -L "$2" -L "$3" "$1" "$2" "$3"
+ exit $?
Index: tools/cvs/src/cvsmerge.binary
diff -c /dev/null tools/cvs/src/cvsmerge.binary:1.1.2.1
*** /dev/null Sun Sep 16 01:05:15 2001
--- tools/cvs/src/cvsmerge.binary Sun Sep 16 01:00:26 2001
***************
*** 0 ****
--- 1,72 ----
+ #!/bin/sh
+
+ # merge.binary: 2-way selection merge program
+
+ # Usage: merge.binary workfile ancestor contributor
+
+ me=`basename "$0"`
+
+ cmp "$1" "$2" > /dev/null
+ if [ $? = 0 ]
+ then
+ cmp "$2" "$3" > /dev/null
+ st=$?
+ if [ $st = 0 ]
+ then
+ # Files are identical, pick one
+ cat "$1"
+ if [ $? = 0 ]
+ then
+ exit 0
+ else
+ echo "${me}: Problem selecting workfile" 1>&2
+ exit 2
+ fi
+ elif [ $st = 1 ]
+ then
+ # $3 differs from $1 and $2, pick it
+ cat "$3"
+ if [ $? = 0 ]
+ then
+ exit 0
+ else
+ echo "${me}: Problem selecting contributor" 1>&2
+ exit 2
+ fi
+ else
+ echo "${me}: Problem comparing ancestor and contributor" 1>&2
+ exit 2
+ fi
+ else
+ cmp "$1" "$3" > /dev/null
+ st=$?
+ if [ $st = 0 ]
+ then
+ # $1 differs from $2 and $3, pick it
+ cat "$1"
+ if [ $? = 0 ]
+ then
+ exit 0
+ else
+ echo "${me}: Problem selecting workfile" 1>&2
+ exit 2
+ fi
+ else
+ # Conflict
+ echo "${me}: Conflict between $1 and contributor" 1>&2
+ echo "${me}: Leaving $1 intact for manual merge" 1>&2
+ cat "$1"
+ if [ $? = 0 ]
+ then
+ exit 1
+ else
+ echo "${me}: Problem selecting workfile" 1>&2
+ exit 2
+ fi
+ fi
+ fi
+
+ # Just in case
+ echo "${me}: Internal failure of binary selection merge" 1>&2
+ exit 2
+
Index: tools/cvs/src/rcscmds.c
diff -c tools/cvs/src/rcscmds.c:1.1.1.2 tools/cvs/src/rcscmds.c:1.1.1.2.4.1
*** tools/cvs/src/rcscmds.c:1.1.1.2 Sat Jan 8 23:38:27 2000
--- tools/cvs/src/rcscmds.c Sun Sep 16 01:00:27 2001
***************
*** 297,302 ****
--- 297,303 ----
/* Remember that the first word in the `call_diff_setup' string is used
now
only for diagnostic messages -- CVS no longer forks to run diff3. */
diffout = cvs_temp_name();
+ #if 0
call_diff_setup ("diff3");
call_diff_arg ("-E");
call_diff_arg ("-am");
***************
*** 313,318 ****
--- 314,328 ----
call_diff_arg (tmp2);
retval = call_diff3 (diffout);
+ #else
+ run_setup ("cvsmerge");
+
+ run_arg (workfile);
+ run_arg (tmp1);
+ run_arg (tmp2);
+
+ retval = run_exec(RUN_TTY,diffout,RUN_TTY,RUN_REALLY);
+ #endif
if (retval == 1)
cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);
Index: tools/cvs/src/update.c
diff -c tools/cvs/src/update.c:1.3 tools/cvs/src/update.c:1.3.4.1
*** tools/cvs/src/update.c:1.3 Mon Jan 10 00:57:50 2000
--- tools/cvs/src/update.c Sun Sep 16 01:00:27 2001
***************
*** 1897,1905 ****
--- 1897,1910 ----
copy_file (finfo->file, backup);
xchmod (finfo->file, 1);
+ #if 0
if (strcmp (vers->options, "-kb") == 0
|| wrap_merge_is_copy (finfo->file)
|| special_file_mismatch (finfo, NULL, vers->vn_rcs))
+ #else
+ if ( wrap_merge_is_copy (finfo->file)
+ || special_file_mismatch (finfo, NULL, vers->vn_rcs))
+ #endif
{
/* For binary files, a merge is always a conflict. Same for
files whose permissions or linkage do not match. We give the
***************
*** 2000,2007 ****
--- 2005,2018 ----
xcmp on the temporary files without much hassle, I think. */
if (!noexec && !xcmp (backup, finfo->file))
{
+ #if 0
cvs_output (finfo->fullname, 0);
cvs_output (" already contains the differences between ", 0);
+ #else
+ cvs_output ("If ",0);
+ cvs_output (finfo->fullname, 0);
+ cvs_output (" contains mergeable data, it may already contain the
differences between ",0);
+ #endif
cvs_output (vers->vn_user, 0);
cvs_output (" and ", 0);
cvs_output (vers->vn_rcs, 0);
***************
*** 2422,2430 ****
--- 2433,2446 ----
print. */
write_letter (finfo, 'U');
}
+ #if 0
else if (strcmp (options, "-kb") == 0
|| wrap_merge_is_copy (finfo->file)
|| special_file_mismatch (finfo, rev1, rev2))
+ #else
+ else if ( wrap_merge_is_copy (finfo->file)
+ || special_file_mismatch (finfo, rev1, rev2))
+ #endif
{
/* We are dealing with binary files, or files with a
permission/linkage mismatch, and real merging would