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.Config;
53  import org.eclipse.jgit.lib.ObjectInserter;
54  import org.eclipse.jgit.lib.Repository;
55  
56  /**
57   * A method of combining two or more trees together to form an output tree.
58   * <p>
59   * Different strategies may employ different techniques for deciding which paths
60   * (and ObjectIds) to carry from the input trees into the final output tree.
61   */
62  public abstract class MergeStrategy {
63  	/** Simple strategy that sets the output tree to the first input tree. */
64  	public static final MergeStrategy OURS = new StrategyOneSided("ours", 0); //$NON-NLS-1$
65  
66  	/** Simple strategy that sets the output tree to the second input tree. */
67  	public static final MergeStrategy THEIRS = new StrategyOneSided("theirs", 1); //$NON-NLS-1$
68  
69  	/** Simple strategy to merge paths, without simultaneous edits. */
70  	public static final ThreeWayMergeStrategy SIMPLE_TWO_WAY_IN_CORE = new StrategySimpleTwoWayInCore();
71  
72  	/**
73  	 * Simple strategy to merge paths. It tries to merge also contents. Multiple
74  	 * merge bases are not supported
75  	 */
76  	public static final ThreeWayMergeStrategy RESOLVE = new StrategyResolve();
77  
78  	/**
79  	 * Recursive strategy to merge paths. It tries to merge also contents.
80  	 * Multiple merge bases are supported
81  	 * @since 3.0
82  	 */
83  	public static final ThreeWayMergeStrategy RECURSIVE = new StrategyRecursive();
84  
85  	private static final HashMap<String, MergeStrategy> STRATEGIES = new HashMap<>();
86  
87  	static {
88  		register(OURS);
89  		register(THEIRS);
90  		register(SIMPLE_TWO_WAY_IN_CORE);
91  		register(RESOLVE);
92  		register(RECURSIVE);
93  	}
94  
95  	/**
96  	 * Register a merge strategy so it can later be obtained by name.
97  	 *
98  	 * @param imp
99  	 *            the strategy to register.
100 	 * @throws java.lang.IllegalArgumentException
101 	 *             a strategy by the same name has already been registered.
102 	 */
103 	public static void register(MergeStrategy imp) {
104 		register(imp.getName(), imp);
105 	}
106 
107 	/**
108 	 * Register a merge strategy so it can later be obtained by name.
109 	 *
110 	 * @param name
111 	 *            name the strategy can be looked up under.
112 	 * @param imp
113 	 *            the strategy to register.
114 	 * @throws java.lang.IllegalArgumentException
115 	 *             a strategy by the same name has already been registered.
116 	 */
117 	public static synchronized void register(final String name,
118 			final MergeStrategy imp) {
119 		if (STRATEGIES.containsKey(name))
120 			throw new IllegalArgumentException(MessageFormat.format(
121 					JGitText.get().mergeStrategyAlreadyExistsAsDefault, name));
122 		STRATEGIES.put(name, imp);
123 	}
124 
125 	/**
126 	 * Locate a strategy by name.
127 	 *
128 	 * @param name
129 	 *            name of the strategy to locate.
130 	 * @return the strategy instance; null if no strategy matches the name.
131 	 */
132 	public static synchronized MergeStrategy get(String name) {
133 		return STRATEGIES.get(name);
134 	}
135 
136 	/**
137 	 * Get all registered strategies.
138 	 *
139 	 * @return the registered strategy instances. No inherit order is returned;
140 	 *         the caller may modify (and/or sort) the returned array if
141 	 *         necessary to obtain a reasonable ordering.
142 	 */
143 	public static synchronized MergeStrategy[] get() {
144 		final MergeStrategy[] r = new MergeStrategy[STRATEGIES.size()];
145 		STRATEGIES.values().toArray(r);
146 		return r;
147 	}
148 
149 	/**
150 	 * Get default name of this strategy implementation.
151 	 *
152 	 * @return default name of this strategy implementation.
153 	 */
154 	public abstract String getName();
155 
156 	/**
157 	 * Create a new merge instance.
158 	 *
159 	 * @param db
160 	 *            repository database the merger will read from, and eventually
161 	 *            write results back to.
162 	 * @return the new merge instance which implements this strategy.
163 	 */
164 	public abstract Merger newMerger(Repository db);
165 
166 	/**
167 	 * Create a new merge instance.
168 	 *
169 	 * @param db
170 	 *            repository database the merger will read from, and eventually
171 	 *            write results back to.
172 	 * @param inCore
173 	 *            the merge will happen in memory, working folder will not be
174 	 *            modified, in case of a non-trivial merge that requires manual
175 	 *            resolution, the merger will fail.
176 	 * @return the new merge instance which implements this strategy.
177 	 */
178 	public abstract Merger newMerger(Repository db, boolean inCore);
179 
180 	/**
181 	 * Create a new merge instance.
182 	 * <p>
183 	 * The merge will happen in memory, working folder will not be modified, in
184 	 * case of a non-trivial merge that requires manual resolution, the merger
185 	 * will fail.
186 	 *
187 	 * @param inserter
188 	 *            inserter to write results back to.
189 	 * @param config
190 	 *            repo config for reading diff algorithm settings.
191 	 * @return the new merge instance which implements this strategy.
192 	 * @since 4.8
193 	 */
194 	public abstract Merger newMerger(ObjectInserter inserter, Config config);
195 }