info-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Demo of extensible merge (was Re: giving up CVS)


From: Paul Sander
Subject: Demo of extensible merge (was Re: giving up CVS)
Date: Sun, 16 Sep 2001 01:20:52 -0700

>--- Forwarded mail from Greg Woods:

>>  CVS is perfectly capable of supporting even
>> unmergable file types with only minor changes to its logic, specifically
>> by adding an extensible mechanism to select the correct merge tool for the
>> data type at hand.

>So you seem to claim.  So far though you've only proposed the most
>superficial of functional specifications, and certainly there's been no
>appearance of running code to cloud the issue....

I call your bluff and raise you a nickel...

>> This is only true as long as CVS treats everything as text files.  There
>> is nothing holding us back from modifying CVS to accomodate non-text
>> files in a meaningful way and still retain the concurrent development
>> paradigm intact.

>Go for it.  I look forward to seeing your "Binary CVS" edition in the
>very near future!

>Hopefully with it you can steal away all the people who are currently
>abusing the original CVS by trying to use it to manage change in
>projects containing binary files.  Best wishes and good riddance!  ;-)

No need.  The following patch to CVS v1.11 seems to do exactly what
I promised.

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]