View Javadoc
1   /*
2    * Copyright (C) 2011, Robin Stocker <robin@nibor.org>
3    * Copyright (C) 2012, Matthias Sohn <matthias.sohn@sap.com>
4    * and other copyright owners as documented in the project's IP log.
5    *
6    * This program and the accompanying materials are made available
7    * under the terms of the Eclipse Distribution License v1.0 which
8    * accompanies this distribution, is reproduced below, and is
9    * available at http://www.eclipse.org/org/documents/edl-v10.php
10   *
11   * All rights reserved.
12   *
13   * Redistribution and use in source and binary forms, with or
14   * without modification, are permitted provided that the following
15   * conditions are met:
16   *
17   * - Redistributions of source code must retain the above copyright
18   *   notice, this list of conditions and the following disclaimer.
19   *
20   * - Redistributions in binary form must reproduce the above
21   *   copyright notice, this list of conditions and the following
22   *   disclaimer in the documentation and/or other materials provided
23   *   with the distribution.
24   *
25   * - Neither the name of the Eclipse Foundation, Inc. nor the
26   *   names of its contributors may be used to endorse or promote
27   *   products derived from this software without specific prior
28   *   written permission.
29   *
30   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43   */
44  
45  package org.eclipse.jgit.lib;
46  
47  import java.net.URISyntaxException;
48  
49  import org.eclipse.jgit.transport.RefSpec;
50  import org.eclipse.jgit.transport.RemoteConfig;
51  
52  /**
53   * Branch section of a Git configuration file.
54   */
55  public class BranchConfig {
56  
57  	/**
58  	 * The value that means "local repository" for {@link #getRemote()}:
59  	 * {@value}
60  	 *
61  	 * @since 3.5
62  	 */
63  	public static final String LOCAL_REPOSITORY = "."; //$NON-NLS-1$
64  
65  	private final Config config;
66  	private final String branchName;
67  
68  	/**
69  	 * Create a new branch config, which will read configuration from config
70  	 * about specified branch.
71  	 *
72  	 * @param config
73  	 *            the config to read from
74  	 * @param branchName
75  	 *            the short branch name of the section to read
76  	 */
77  	public BranchConfig(final Config config, String branchName) {
78  		this.config = config;
79  		this.branchName = branchName;
80  	}
81  
82  	/**
83  	 * @return the full tracking branch name or <code>null</code> if it could
84  	 *         not be determined
85  	 */
86  	public String getTrackingBranch() {
87  		String remote = getRemoteOrDefault();
88  		String mergeRef = getMerge();
89  		if (remote == null || mergeRef == null)
90  			return null;
91  
92  		if (isRemoteLocal())
93  			return mergeRef;
94  
95  		return findRemoteTrackingBranch(remote, mergeRef);
96  	}
97  
98  	/**
99  	 * @return the full remote-tracking branch name or {@code null} if it could
100 	 *         not be determined. If you also want local tracked branches use
101 	 *         {@link #getTrackingBranch()} instead.
102 	 */
103 	public String getRemoteTrackingBranch() {
104 		String remote = getRemoteOrDefault();
105 		String mergeRef = getMerge();
106 		if (remote == null || mergeRef == null)
107 			return null;
108 
109 		return findRemoteTrackingBranch(remote, mergeRef);
110 	}
111 
112 	/**
113 	 * @return {@code true} if the "remote" setting points to the local
114 	 *         repository (with {@value #LOCAL_REPOSITORY}), false otherwise
115 	 * @since 3.5
116 	 */
117 	public boolean isRemoteLocal() {
118 		return LOCAL_REPOSITORY.equals(getRemote());
119 	}
120 
121 	/**
122 	 * @return the remote this branch is configured to fetch from/push to, or
123 	 *         {@code null} if not defined
124 	 * @since 3.5
125 	 */
126 	public String getRemote() {
127 		return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
128 				branchName, ConfigConstants.CONFIG_KEY_REMOTE);
129 	}
130 
131 	/**
132 	 * @return the name of the upstream branch as it is called on the remote, or
133 	 *         {@code null} if not defined
134 	 * @since 3.5
135 	 */
136 	public String getMerge() {
137 		return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
138 				branchName, ConfigConstants.CONFIG_KEY_MERGE);
139 	}
140 
141 	/**
142 	 * @return {@code true} if the branch is configured to be rebased
143 	 * @since 3.5
144 	 */
145 	public boolean isRebase() {
146 		return config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION,
147 				branchName, ConfigConstants.CONFIG_KEY_REBASE, false);
148 	}
149 
150 	/**
151 	 * Finds the tracked remote tracking branch
152 	 *
153 	 * @param remote
154 	 *            Remote name
155 	 * @param mergeRef
156 	 *            merge Ref of the local branch tracking the remote tracking
157 	 *            branch
158 	 * @return full remote tracking branch name or null
159 	 */
160 	private String findRemoteTrackingBranch(String remote, String mergeRef) {
161 		RemoteConfig remoteConfig;
162 		try {
163 			remoteConfig = new RemoteConfig(config, remote);
164 		} catch (URISyntaxException e) {
165 			return null;
166 		}
167 		for (RefSpec refSpec : remoteConfig.getFetchRefSpecs()) {
168 			if (refSpec.matchSource(mergeRef)) {
169 				RefSpec expanded = refSpec.expandFromSource(mergeRef);
170 				return expanded.getDestination();
171 			}
172 		}
173 		return null;
174 	}
175 
176 	private String getRemoteOrDefault() {
177 		String remote = getRemote();
178 		if (remote == null)
179 			return Constants.DEFAULT_REMOTE_NAME;
180 		else
181 			return remote;
182 	}
183 }