info-cvs
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]