CommandLineMergeTool.java

  1. /*
  2.  * Copyright (C) 2018-2022, Andre Bossert <andre.bossert@siemens.com>
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.diffmergetool;

  11. /**
  12.  * Pre-defined merge tools.
  13.  *
  14.  * Adds same merge tools as also pre-defined in C-Git see "git-core\mergetools\"
  15.  * see links to command line parameter description for the tools
  16.  *
  17.  * <pre>
  18.  * araxis
  19.  * bc
  20.  * bc3
  21.  * codecompare
  22.  * deltawalker
  23.  * diffmerge
  24.  * diffuse
  25.  * ecmerge
  26.  * emerge
  27.  * examdiff
  28.  * guiffy
  29.  * gvimdiff
  30.  * gvimdiff2
  31.  * gvimdiff3
  32.  * kdiff3
  33.  * kompare
  34.  * meld
  35.  * opendiff
  36.  * p4merge
  37.  * tkdiff
  38.  * tortoisemerge
  39.  * vimdiff
  40.  * vimdiff2
  41.  * vimdiff3
  42.  * winmerge
  43.  * xxdiff
  44.  * </pre>
  45.  *
  46.  */
  47. @SuppressWarnings("nls")
  48. public enum CommandLineMergeTool {
  49.     /**
  50.      * See: <a href=
  51.      * "https://www.araxis.com/merge/documentation-windows/command-line.en">https://www.araxis.com/merge/documentation-windows/command-line.en</a>
  52.      */
  53.     araxis("compare",
  54.             "-wait -merge -3 -a1 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"",
  55.             "-wait -2 \"$LOCAL\" \"$REMOTE\" \"$MERGED\"",
  56.             false),
  57.     /**
  58.      * See: <a href=
  59.      * "https://www.scootersoftware.com/v4help/index.html?command_line_reference.html">https://www.scootersoftware.com/v4help/index.html?command_line_reference.html</a>
  60.      */
  61.     bc("bcomp", "\"$LOCAL\" \"$REMOTE\" \"$BASE\" --mergeoutput=\"$MERGED\"",
  62.             "\"$LOCAL\" \"$REMOTE\" --mergeoutput=\"$MERGED\"",
  63.             false),
  64.     /**
  65.      * See: <a href=
  66.      * "https://www.scootersoftware.com/v4help/index.html?command_line_reference.html">https://www.scootersoftware.com/v4help/index.html?command_line_reference.html</a>
  67.      */
  68.     bc3("bcompare", bc),
  69.     /**
  70.      * See: <a href=
  71.      * "https://www.devart.com/codecompare/docs/index.html?merging_via_command_line.htm">https://www.devart.com/codecompare/docs/index.html?merging_via_command_line.htm</a>
  72.      */
  73.     codecompare("CodeMerge",
  74.             "-MF=\"$LOCAL\" -TF=\"$REMOTE\" -BF=\"$BASE\" -RF=\"$MERGED\"",
  75.             "-MF=\"$LOCAL\" -TF=\"$REMOTE\" -RF=\"$MERGED\"",
  76.             false),
  77.     /**
  78.      * See: <a href=
  79.      * "https://www.deltawalker.com/integrate/command-line">https://www.deltawalker.com/integrate/command-line</a>
  80.      * <p>
  81.      * Hint: $(pwd) command must be defined
  82.      * </p>
  83.      */
  84.     deltawalker("DeltaWalker",
  85.             "\"$LOCAL\" \"$REMOTE\" \"$BASE\" -pwd=\"$(pwd)\" -merged=\"$MERGED\"",
  86.             "\"$LOCAL\" \"$REMOTE\" -pwd=\"$(pwd)\" -merged=\"$MERGED\"",
  87.             true),
  88.     /**
  89.      * See: <a href=
  90.      * "https://sourcegear.com/diffmerge/webhelp/sec__clargs__diff.html">https://sourcegear.com/diffmerge/webhelp/sec__clargs__diff.html</a>
  91.      */
  92.     diffmerge("diffmerge", //$NON-NLS-1$
  93.             "--merge --result=\"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\"",
  94.             "--merge --result=\"$MERGED\" \"$LOCAL\" \"$REMOTE\"",
  95.             true),
  96.     /**
  97.      * See: <a href=
  98.      * "http://diffuse.sourceforge.net/manual.html#introduction-usage">http://diffuse.sourceforge.net/manual.html#introduction-usage</a>
  99.      * <p>
  100.      * Hint: check the ' | cat' for the call
  101.      * </p>
  102.      */
  103.     diffuse("diffuse", "\"$LOCAL\" \"$MERGED\" \"$REMOTE\" \"$BASE\"",
  104.             "\"$LOCAL\" \"$MERGED\" \"$REMOTE\"", false),
  105.     /**
  106.      * See: <a href=
  107.      * "http://www.elliecomputing.com/en/OnlineDoc/ecmerge_en/44205167.asp">http://www.elliecomputing.com/en/OnlineDoc/ecmerge_en/44205167.asp</a>
  108.      */
  109.     ecmerge("ecmerge",
  110.             "--default --mode=merge3 \"$BASE\" \"$LOCAL\" \"$REMOTE\" --to=\"$MERGED\"",
  111.             "--default --mode=merge2 \"$LOCAL\" \"$REMOTE\" --to=\"$MERGED\"",
  112.             false),
  113.     /**
  114.      * See: <a href=
  115.      * "https://www.gnu.org/software/emacs/manual/html_node/emacs/Overview-of-Emerge.html">https://www.gnu.org/software/emacs/manual/html_node/emacs/Overview-of-Emerge.html</a>
  116.      * <p>
  117.      * Hint: $(basename) command must be defined
  118.      * </p>
  119.      */
  120.     emerge("emacs",
  121.             "-f emerge-files-with-ancestor-command \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$(basename \"$MERGED\")\"",
  122.             "-f emerge-files-command \"$LOCAL\" \"$REMOTE\" \"$(basename \"$MERGED\")\"",
  123.             true),
  124.     /**
  125.      * See: <a href=
  126.      * "https://www.prestosoft.com/ps.asp?page=htmlhelp/edp/command_line_options">https://www.prestosoft.com/ps.asp?page=htmlhelp/edp/command_line_options</a>
  127.      */
  128.     examdiff("ExamDiff",
  129.             "-merge \"$LOCAL\" \"$BASE\" \"$REMOTE\" -o:\"$MERGED\" -nh",
  130.             "-merge \"$LOCAL\" \"$REMOTE\" -o:\"$MERGED\" -nh",
  131.             false),
  132.     /**
  133.      * See: <a href=
  134.      * "https://www.guiffy.com/help/GuiffyHelp/GuiffyCmd.html">https://www.guiffy.com/help/GuiffyHelp/GuiffyCmd.html</a>
  135.      */
  136.     guiffy("guiffy", "-s \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"",
  137.             "-m \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", true),
  138.     /**
  139.      * See: <a href=
  140.      * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
  141.      */
  142.     gvimdiff("gvim",
  143.             "-f -d -c '4wincmd w | wincmd J' \"$LOCAL\" \"$BASE\" \"$REMOTE\" \"$MERGED\"",
  144.             "-f -d -c 'wincmd l' \"$LOCAL\" \"$MERGED\" \"$REMOTE\"",
  145.             true),
  146.     /**
  147.      * See: <a href=
  148.      * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
  149.      */
  150.     gvimdiff2("gvim", "-f -d -c 'wincmd l' \"$LOCAL\" \"$MERGED\" \"$REMOTE\"",
  151.             "-f -d -c 'wincmd l' \"$LOCAL\" \"$MERGED\" \"$REMOTE\"", true),
  152.     /**
  153.      * See: <a href= "http://vimdoc.sourceforge.net/htmldoc/diff.html"></a>
  154.      */
  155.     gvimdiff3("gvim",
  156.             "-f -d -c 'hid | hid | hid' \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"",
  157.             "-f -d -c 'hid | hid' \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", true),
  158.     /**
  159.      * See: <a href=
  160.      * "http://kdiff3.sourceforge.net/doc/documentation.html">http://kdiff3.sourceforge.net/doc/documentation.html</a>
  161.      */
  162.     kdiff3("kdiff3",
  163.             "--auto --L1 \"$MERGED (Base)\" --L2 \"$MERGED (Local)\" --L3 \"$MERGED (Remote)\" -o \"$MERGED\" \"$BASE\" \"$LOCAL\" \"$REMOTE\"",
  164.             "--auto --L1 \"$MERGED (Local)\" --L2 \"$MERGED (Remote)\" -o \"$MERGED\" \"$LOCAL\" \"$REMOTE\"",
  165.             true),
  166.     /**
  167.      * See: <a href=
  168.      * "http://meldmerge.org/help/file-mode.html">http://meldmerge.org/help/file-mode.html</a>
  169.      * <p>
  170.      * Hint: use meld with output option only (new versions)
  171.      * </p>
  172.      */
  173.     meld("meld", "--output=\"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\"",
  174.             "\"$LOCAL\" \"$MERGED\" \"$REMOTE\"",
  175.             false),
  176.     /**
  177.      * See: <a href=
  178.      * "http://www.manpagez.com/man/1/opendiff/">http://www.manpagez.com/man/1/opendiff/</a>
  179.      * <p>
  180.      * Hint: check the ' | cat' for the call
  181.      * </p>
  182.      */
  183.     opendiff("opendiff",
  184.             "\"$LOCAL\" \"$REMOTE\" -ancestor \"$BASE\" -merge \"$MERGED\"",
  185.             "\"$LOCAL\" \"$REMOTE\" -merge \"$MERGED\"",
  186.             false),
  187.     /**
  188.      * See: <a href=
  189.      * "https://www.perforce.com/manuals/v15.1/cmdref/p4_merge.html">https://www.perforce.com/manuals/v15.1/cmdref/p4_merge.html</a>
  190.      * <p>
  191.      * Hint: check how to fix "no base present" / create_virtual_base problem
  192.      * </p>
  193.      */
  194.     p4merge("p4merge", "\"$BASE\" \"$REMOTE\" \"$LOCAL\" \"$MERGED\"",
  195.             "\"$REMOTE\" \"$LOCAL\" \"$MERGED\"", false),
  196.     /**
  197.      * See: <a href=
  198.      * "http://linux.math.tifr.res.in/manuals/man/tkdiff.html">http://linux.math.tifr.res.in/manuals/man/tkdiff.html</a>
  199.      */
  200.     tkdiff("tkdiff", "-a \"$BASE\" -o \"$MERGED\" \"$LOCAL\" \"$REMOTE\"",
  201.             "-o \"$MERGED\" \"$LOCAL\" \"$REMOTE\"",
  202.             true),
  203.     /**
  204.      * See: <a href=
  205.      * "https://tortoisegit.org/docs/tortoisegitmerge/tme-automation.html#tme-automation-basics">https://tortoisegit.org/docs/tortoisegitmerge/tme-automation.html#tme-automation-basics</a>
  206.      * <p>
  207.      * Hint: merge without base is not supported
  208.      * </p>
  209.      * <p>
  210.      * Hint: cannot diff
  211.      * </p>
  212.      */
  213.     tortoisegitmerge("tortoisegitmerge",
  214.             "-base \"$BASE\" -mine \"$LOCAL\" -theirs \"$REMOTE\" -merged \"$MERGED\"",
  215.             null, false),
  216.     /**
  217.      * See: <a href=
  218.      * "https://tortoisegit.org/docs/tortoisegitmerge/tme-automation.html#tme-automation-basics">https://tortoisegit.org/docs/tortoisegitmerge/tme-automation.html#tme-automation-basics</a>
  219.      * <p>
  220.      * Hint: merge without base is not supported
  221.      * </p>
  222.      * <p>
  223.      * Hint: cannot diff
  224.      * </p>
  225.      */
  226.     tortoisemerge("tortoisemerge",
  227.             "-base:\"$BASE\" -mine:\"$LOCAL\" -theirs:\"$REMOTE\" -merged:\"$MERGED\"",
  228.             null, false),
  229.     /**
  230.      * See: <a href=
  231.      * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
  232.      */
  233.     vimdiff("vim", gvimdiff),
  234.     /**
  235.      * See: <a href=
  236.      * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
  237.      */
  238.     vimdiff2("vim", gvimdiff2),
  239.     /**
  240.      * See: <a href=
  241.      * "http://vimdoc.sourceforge.net/htmldoc/diff.html">http://vimdoc.sourceforge.net/htmldoc/diff.html</a>
  242.      */
  243.     vimdiff3("vim", gvimdiff3),
  244.     /**
  245.      * See: <a href=
  246.      * "http://manual.winmerge.org/Command_line.html">http://manual.winmerge.org/Command_line.html</a>
  247.      * <p>
  248.      * Hint: check how 'mergetool_find_win32_cmd "WinMergeU.exe" "WinMerge"'
  249.      * works
  250.      * </p>
  251.      */
  252.     winmerge("WinMergeU",
  253.             "-u -e -dl Local -dr Remote \"$LOCAL\" \"$REMOTE\" \"$MERGED\"",
  254.             "-u -e -dl Local -dr Remote \"$LOCAL\" \"$REMOTE\" \"$MERGED\"",
  255.             false),
  256.     /**
  257.      * See: <a href=
  258.      * "http://furius.ca/xxdiff/doc/xxdiff-doc.html">http://furius.ca/xxdiff/doc/xxdiff-doc.html</a>
  259.      */
  260.     xxdiff("xxdiff",
  261.             "-X --show-merged-pane -R 'Accel.SaveAsMerged: \"Ctrl+S\"' -R 'Accel.Search: \"Ctrl+F\"' -R 'Accel.SearchForward: \"Ctrl+G\"' --merged-file \"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\"",
  262.             "-X -R 'Accel.SaveAsMerged: \"Ctrl+S\"' -R 'Accel.Search: \"Ctrl+F\"' -R 'Accel.SearchForward: \"Ctrl+G\"' --merged-file \"$MERGED\" \"$LOCAL\" \"$REMOTE\"",
  263.             false);

  264.     CommandLineMergeTool(String path, String parametersWithBase,
  265.             String parametersWithoutBase,
  266.             boolean exitCodeTrustable) {
  267.         this.path = path;
  268.         this.parametersWithBase = parametersWithBase;
  269.         this.parametersWithoutBase = parametersWithoutBase;
  270.         this.exitCodeTrustable = exitCodeTrustable;
  271.     }

  272.     CommandLineMergeTool(CommandLineMergeTool from) {
  273.         this(from.getPath(), from.getParameters(true),
  274.                 from.getParameters(false), from.isExitCodeTrustable());
  275.     }

  276.     CommandLineMergeTool(String path, CommandLineMergeTool from) {
  277.         this(path, from.getParameters(true), from.getParameters(false),
  278.                 from.isExitCodeTrustable());
  279.     }

  280.     private final String path;

  281.     private final String parametersWithBase;

  282.     private final String parametersWithoutBase;

  283.     private final boolean exitCodeTrustable;

  284.     /**
  285.      * @return path
  286.      */
  287.     public String getPath() {
  288.         return path;
  289.     }

  290.     /**
  291.      * @param withBase
  292.      *            return parameters with base present?
  293.      * @return parameters with or without base present
  294.      */
  295.     public String getParameters(boolean withBase) {
  296.         if (withBase) {
  297.             return parametersWithBase;
  298.         }
  299.         return parametersWithoutBase;
  300.     }

  301.     /**
  302.      * @return parameters
  303.      */
  304.     public boolean isExitCodeTrustable() {
  305.         return exitCodeTrustable;
  306.     }

  307.     /**
  308.      * @return true if command with base present is valid, false otherwise
  309.      */
  310.     public boolean canMergeWithoutBasePresent() {
  311.         return parametersWithoutBase != null;
  312.     }

  313. }