View Javadoc
1   /*
2    * Copyright (C) 2009, Google Inc.
3    * Copyright (C) 2012, Research In Motion Limited and others
4    *
5    * This program and the accompanying materials are made available under the
6    * terms of the Eclipse Distribution License v. 1.0 which is available at
7    * https://www.eclipse.org/org/documents/edl-v10.php.
8    *
9    * SPDX-License-Identifier: BSD-3-Clause
10   */
11  
12  package org.eclipse.jgit.merge;
13  
14  import java.io.IOException;
15  
16  import org.eclipse.jgit.errors.IncorrectObjectTypeException;
17  import org.eclipse.jgit.errors.MissingObjectException;
18  import org.eclipse.jgit.lib.AnyObjectId;
19  import org.eclipse.jgit.lib.ObjectId;
20  import org.eclipse.jgit.lib.ObjectInserter;
21  import org.eclipse.jgit.lib.Repository;
22  import org.eclipse.jgit.revwalk.RevCommit;
23  import org.eclipse.jgit.revwalk.RevTree;
24  import org.eclipse.jgit.treewalk.AbstractTreeIterator;
25  import org.eclipse.jgit.treewalk.EmptyTreeIterator;
26  
27  /**
28   * A merge of 2 trees, using a common base ancestor tree.
29   */
30  public abstract class ThreeWayMerger extends Merger {
31  	private RevTree baseTree;
32  
33  	private ObjectId baseCommitId;
34  
35  	/**
36  	 * Create a new merge instance for a repository.
37  	 *
38  	 * @param local
39  	 *            the repository this merger will read and write data on.
40  	 */
41  	protected ThreeWayMerger(Repository local) {
42  		super(local);
43  	}
44  
45  	/**
46  	 * Create a new merge instance for a repository.
47  	 *
48  	 * @param local
49  	 *            the repository this merger will read and write data on.
50  	 * @param inCore
51  	 *            perform the merge in core with no working folder involved
52  	 */
53  	protected ThreeWayMerger(Repository local, boolean inCore) {
54  		this(local);
55  	}
56  
57  	/**
58  	 * Create a new in-core merge instance from an inserter.
59  	 *
60  	 * @param inserter
61  	 *            the inserter to write objects to.
62  	 * @since 4.8
63  	 */
64  	protected ThreeWayMerger(ObjectInserter inserter) {
65  		super(inserter);
66  	}
67  
68  	/**
69  	 * Set the common ancestor tree.
70  	 *
71  	 * @param id
72  	 *            common base treeish; null to automatically compute the common
73  	 *            base from the input commits during
74  	 *            {@link #merge(AnyObjectId...)}.
75  	 * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
76  	 *             the object is not a treeish.
77  	 * @throws org.eclipse.jgit.errors.MissingObjectException
78  	 *             the object does not exist.
79  	 * @throws java.io.IOException
80  	 *             the object could not be read.
81  	 */
82  	public void setBase(AnyObjectId id) throws MissingObjectException,
83  			IncorrectObjectTypeException, IOException {
84  		if (id != null) {
85  			baseTree = walk.parseTree(id);
86  		} else {
87  			baseTree = null;
88  		}
89  	}
90  
91  	/** {@inheritDoc} */
92  	@Override
93  	public boolean merge(AnyObjectId... tips) throws IOException {
94  		if (tips.length != 2)
95  			return false;
96  		return super.merge(tips);
97  	}
98  
99  	/** {@inheritDoc} */
100 	@Override
101 	public ObjectId getBaseCommitId() {
102 		return baseCommitId;
103 	}
104 
105 	/**
106 	 * Create an iterator to walk the merge base.
107 	 *
108 	 * @return an iterator over the caller-specified merge base, or the natural
109 	 *         merge base of the two input commits.
110 	 * @throws java.io.IOException
111 	 */
112 	protected AbstractTreeIterator mergeBase() throws IOException {
113 		if (baseTree != null) {
114 			return openTree(baseTree);
115 		}
116 		RevCommit baseCommit = (baseCommitId != null) ? walk
117 				.parseCommit(baseCommitId) : getBaseCommit(sourceCommits[0],
118 				sourceCommits[1]);
119 		if (baseCommit == null) {
120 			baseCommitId = null;
121 			return new EmptyTreeIterator();
122 		}
123 		baseCommitId = baseCommit.toObjectId();
124 		return openTree(baseCommit.getTree());
125 	}
126 }