Differences between revisions 5 and 14 (spanning 9 versions)
Revision 5 as of 2005-08-26 01:31:43
Size: 2238
Editor: waste
Comment:
Revision 14 as of 2009-07-24 14:15:18
Size: 2309
Comment:
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
[http://www.gnu.org/software/emacs/ Emacs] is bundled with an elisp program called Ediff which purpose is to help developers to visually apply patches. One of the various ediff commands is well suited to three way merging and can be used as a merger program with ["Mercurial"]. [[http://www.gnu.org/software/emacs/|Emacs]] is bundled with an elisp program called Ediff which purpose is to help developers to visually apply patches. One of the various ediff commands is well suited to three way merging and can be used as a [[MergeProgram|merger program]] with [[Mercurial]].
Line 7: Line 7:
So to use [http://www.gnu.org/software/emacs/ Emacs] as ["Mercurial"] merger program, dump the following content into a file in your PATH (don't forget to turn on the execute bit): So to use [[http://www.gnu.org/software/emacs/|Emacs]] as [[Mercurial]] merger program, dump the following content into a file in your PATH (don't forget to turn on the execute bit):
Line 10: Line 10:
 
  set -e # bail out quickly on failure
    
  LOCAL=$1
  BASE=$2
  OTHER=$3
   
   set -e # bail out quickly on failure
   
   LOCAL="$1"
   BASE="$2"
   OTHER="$3"
Line 17: Line 17:
  BACKUP=$LOCAL.orig
 
    Rm ()
  {
        if [ -f $BACKUP ]; then
            rm -f $BACKUP
        else
            :
        fi
    
}
   BACKUP="$LOCAL.orig"
   
   Restore ()
   {
       cp "$BACKUP" "$LOCAL"
   }
Line 28: Line 24:
    Restore ()
  {
        cp $BACKUP $LOCAL
    }
   ExitOK ()
   {
       exit $?
   }
Line 33: Line 29:
    ExitOK ()
    {
        Rm
        Exit $?
    }
   # Back up our file
   cp "$LOCAL" "$BACKUP"
Line 39: Line 32:
    # Back up our file
    cp $LOCAL $BACKUP
   # Attempt to do a non-interactive merge
   if which merge > /dev/null 2>&1 ; then
       if merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null; then
           # success!
           ExitOK
       fi
       Restore
   elif which diff3 > /dev/null 2>&1 ; then
       if diff3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" ; then
           # success
           ExitOK
       fi
       Restore
   fi
Line 42: Line 47:
    # Attempt to do a non-interactive merge
    if which merge > /dev/null 2>&1 ; then
        if merge $LOCAL $BASE $OTHER 2> /dev/null; then
            # success!
            ExitOK
        fi
        Restore
    elif which diff3 > /dev/null 2>&1 ; then
        if diff3 -m $BACKUP $BASE $OTHER > $LOCAL ; then
            # success
            ExitOK
        fi
        Restore
    fi
   if emacs -q --no-site-file --eval "(ediff-merge-with-ancestor \"$BACKUP\" \"$OTHER\" \"$BASE\" nil \"$LOCAL\")"
   then
       ExitOK
   fi
Line 57: Line 52:
    if emacs -q --no-site-file --eval "(ediff-merge-with-ancestor \"$BACKUP\" \"$OTHER\" \"$BASE\" nil \"$LOCAL\")"
    then
        ExitOK
    fi
   echo "emacs-merge: failed to merge files"
   exit 1
Line 62: Line 55:
    echo "emacs-merge: failed to merge files"
    exit 1
   # End of file
}}}
Line 65: Line 58:
    # End of file ''Considering Mercurial is now able to premerge before running the merge tool and even does it by default (see hgrc(5)), I feel that attempts of merge
with merge and diff3 are not needed anymore.''
Line 67: Line 61:
}}}
Line 74: Line 67:
Don't forget to add an entry in your hgrc file (either ~/.hgrc or the local working copy .hg/hgrc) to point ["Mercurial"] at your merge command (let's call it emacs-merge) Don't forget to add an entry in your hgrc file (either ~/.hgrc or the local working copy .hg/hgrc) to point [[Mercurial]] at your merge command (let's call it emacs-merge)
Line 77: Line 70:
  merge = emacs-merge    merge = emacs-merge

Using Emacs as a merger program

Emacs is bundled with an elisp program called Ediff which purpose is to help developers to visually apply patches. One of the various ediff commands is well suited to three way merging and can be used as a merger program with Mercurial.

Wrapping Emacs+Ediff call in a script

So to use Emacs as Mercurial merger program, dump the following content into a file in your PATH (don't forget to turn on the execute bit):

   #!/bin/sh
   
   set -e # bail out quickly on failure
   
   LOCAL="$1"
   BASE="$2"
   OTHER="$3"

   BACKUP="$LOCAL.orig"
   
   Restore ()
   {
       cp "$BACKUP" "$LOCAL" 
   }

   ExitOK ()
   {
       exit $?
   }

   # Back up our file
   cp "$LOCAL" "$BACKUP"

   # Attempt to do a non-interactive merge
   if which merge > /dev/null 2>&1 ; then
       if merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null; then
           # success!
           ExitOK 
       fi
       Restore
   elif which diff3 > /dev/null 2>&1 ; then
       if diff3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" ; then
           # success
           ExitOK
       fi
       Restore
   fi

   if emacs -q --no-site-file --eval "(ediff-merge-with-ancestor \"$BACKUP\" \"$OTHER\" \"$BASE\" nil \"$LOCAL\")" 
   then       
       ExitOK
   fi

   echo "emacs-merge: failed to merge files"
   exit 1

   # End of file

Considering Mercurial is now able to premerge before running the merge tool and even does it by default (see hgrc(5)), I feel that attempts of merge with merge and diff3 are not needed anymore.

How the script works

This script tries first to automatically merge the files using the RCS merge program or the diff3 program. If the automatic merger fails merging the files because of a conflict or, neither merge nor diff3 are available on the system, then emacs is launched to let the developer resolve the conflicts.

Enabling the script usage

Don't forget to add an entry in your hgrc file (either ~/.hgrc or the local working copy .hg/hgrc) to point Mercurial at your merge command (let's call it emacs-merge)

MergingWithEmacs (last edited 2015-08-18 22:49:33 by mpm)