View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * Copyright (C) 2009, Matthias Sohn <matthias.sohn@sap.com>
4    * Copyright (C) 2012, Research In Motion Limited
5    * and other copyright owners as documented in the project's IP log.
6    *
7    * This program and the accompanying materials are made available
8    * under the terms of the Eclipse Distribution License v1.0 which
9    * accompanies this distribution, is reproduced below, and is
10   * available at http://www.eclipse.org/org/documents/edl-v10.php
11   *
12   * All rights reserved.
13   *
14   * Redistribution and use in source and binary forms, with or
15   * without modification, are permitted provided that the following
16   * conditions are met:
17   *
18   * - Redistributions of source code must retain the above copyright
19   *   notice, this list of conditions and the following disclaimer.
20   *
21   * - Redistributions in binary form must reproduce the above
22   *   copyright notice, this list of conditions and the following
23   *   disclaimer in the documentation and/or other materials provided
24   *   with the distribution.
25   *
26   * - Neither the name of the Eclipse Foundation, Inc. nor the
27   *   names of its contributors may be used to endorse or promote
28   *   products derived from this software without specific prior
29   *   written permission.
30   *
31   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
32   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
33   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
36   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
43   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44   */
45  
46  package org.eclipse.jgit.merge;
47  
48  import java.text.MessageFormat;
49  import java.util.HashMap;
50  
51  import org.eclipse.jgit.internal.JGitText;
52  import org.eclipse.jgit.lib.Repository;
53  
54  /**
55   * A method of combining two or more trees together to form an output tree.
56   * <p>
57   * Different strategies may employ different techniques for deciding which paths
58   * (and ObjectIds) to carry from the input trees into the final output tree.
59   */
60  public abstract class MergeStrategy {
61  	/** Simple strategy that sets the output tree to the first input tree. */
62  	public static final MergeStrategy OURS = new StrategyOneSided("ours", 0); //$NON-NLS-1$
63  
64  	/** Simple strategy that sets the output tree to the second input tree. */
65  	public static final MergeStrategy THEIRS = new StrategyOneSided("theirs", 1); //$NON-NLS-1$
66  
67  	/** Simple strategy to merge paths, without simultaneous edits. */
68  	public static final ThreeWayMergeStrategy SIMPLE_TWO_WAY_IN_CORE = new StrategySimpleTwoWayInCore();
69  
70  	/**
71  	 * Simple strategy to merge paths. It tries to merge also contents. Multiple
72  	 * merge bases are not supported
73  	 */
74  	public static final ThreeWayMergeStrategy RESOLVE = new StrategyResolve();
75  
76  	/**
77  	 * Recursive strategy to merge paths. It tries to merge also contents.
78  	 * Multiple merge bases are supported
79  	 * @since 3.0
80  	 */
81  	public static final ThreeWayMergeStrategy RECURSIVE = new StrategyRecursive();
82  
83  	private static final HashMap<String, MergeStrategy> STRATEGIES = new HashMap<>();
84  
85  	static {
86  		register(OURS);
87  		register(THEIRS);
88  		register(SIMPLE_TWO_WAY_IN_CORE);
89  		register(RESOLVE);
90  		register(RECURSIVE);
91  	}
92  
93  	/**
94  	 * Register a merge strategy so it can later be obtained by name.
95  	 *
96  	 * @param imp
97  	 *            the strategy to register.
98  	 * @throws IllegalArgumentException
99  	 *             a strategy by the same name has already been registered.
100 	 */
101 	public static void register(final MergeStrategy imp) {
102 		register(imp.getName(), imp);
103 	}
104 
105 	/**
106 	 * Register a merge strategy so it can later be obtained by name.
107 	 *
108 	 * @param name
109 	 *            name the strategy can be looked up under.
110 	 * @param imp
111 	 *            the strategy to register.
112 	 * @throws IllegalArgumentException
113 	 *             a strategy by the same name has already been registered.
114 	 */
115 	public static synchronized void register(final String name,
116 			final MergeStrategy imp) {
117 		if (STRATEGIES.containsKey(name))
118 			throw new IllegalArgumentException(MessageFormat.format(
119 					JGitText.get().mergeStrategyAlreadyExistsAsDefault, name));
120 		STRATEGIES.put(name, imp);
121 	}
122 
123 	/**
124 	 * Locate a strategy by name.
125 	 *
126 	 * @param name
127 	 *            name of the strategy to locate.
128 	 * @return the strategy instance; null if no strategy matches the name.
129 	 */
130 	public static synchronized MergeStrategy get(final String name) {
131 		return STRATEGIES.get(name);
132 	}
133 
134 	/**
135 	 * Get all registered strategies.
136 	 *
137 	 * @return the registered strategy instances. No inherit order is returned;
138 	 *         the caller may modify (and/or sort) the returned array if
139 	 *         necessary to obtain a reasonable ordering.
140 	 */
141 	public static synchronized MergeStrategy[] get() {
142 		final MergeStrategy[] r = new MergeStrategy[STRATEGIES.size()];
143 		STRATEGIES.values().toArray(r);
144 		return r;
145 	}
146 
147 	/** @return default name of this strategy implementation. */
148 	public abstract String getName();
149 
150 	/**
151 	 * Create a new merge instance.
152 	 *
153 	 * @param db
154 	 *            repository database the merger will read from, and eventually
155 	 *            write results back to.
156 	 * @return the new merge instance which implements this strategy.
157 	 */
158 	public abstract Merger newMerger(Repository db);
159 
160 	/**
161 	 * Create a new merge instance.
162 	 *
163 	 * @param db
164 	 *            repository database the merger will read from, and eventually
165 	 *            write results back to.
166 	 * @param inCore
167 	 *            the merge will happen in memory, working folder will not be
168 	 *            modified, in case of a non-trivial merge that requires manual
169 	 *            resolution, the merger will fail.
170 	 * @return the new merge instance which implements this strategy.
171 	 */
172 	public abstract Merger newMerger(Repository db, boolean inCore);
173 }