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 * Config values for branch.[name].rebase (and pull.rebase). 59 * 60 * @since 4.5 61 */ 62 public enum BranchRebaseMode implements Config.ConfigEnum { 63 64 /** Value for rebasing */ 65 REBASE("true"), //$NON-NLS-1$ 66 /** Value for rebasing preserving local merge commits */ 67 PRESERVE("preserve"), //$NON-NLS-1$ 68 /** Value for rebasing interactively */ 69 INTERACTIVE("interactive"), //$NON-NLS-1$ 70 /** Value for not rebasing at all but merging */ 71 NONE("false"); //$NON-NLS-1$ 72 73 private final String configValue; 74 75 private BranchRebaseMode(String configValue) { 76 this.configValue = configValue; 77 } 78 79 @Override 80 public String toConfigValue() { 81 return configValue; 82 } 83 84 @Override 85 public boolean matchConfigValue(String s) { 86 return configValue.equals(s); 87 } 88 } 89 90 /** 91 * The value that means "local repository" for {@link #getRemote()}: 92 * {@value} 93 * 94 * @since 3.5 95 */ 96 public static final String LOCAL_REPOSITORY = "."; //$NON-NLS-1$ 97 98 private final Config config; 99 private final String branchName; 100 101 /** 102 * Create a new branch config, which will read configuration from config 103 * about specified branch. 104 * 105 * @param config 106 * the config to read from 107 * @param branchName 108 * the short branch name of the section to read 109 */ 110 public BranchConfig(final Config config, String branchName) { 111 this.config = config; 112 this.branchName = branchName; 113 } 114 115 /** 116 * Get the full tracking branch name 117 * 118 * @return the full tracking branch name or <code>null</code> if it could 119 * not be determined 120 */ 121 public String getTrackingBranch() { 122 String remote = getRemoteOrDefault(); 123 String mergeRef = getMerge(); 124 if (remote == null || mergeRef == null) 125 return null; 126 127 if (isRemoteLocal()) 128 return mergeRef; 129 130 return findRemoteTrackingBranch(remote, mergeRef); 131 } 132 133 /** 134 * Get the full remote-tracking branch name 135 * 136 * @return the full remote-tracking branch name or {@code null} if it could 137 * not be determined. If you also want local tracked branches use 138 * {@link #getTrackingBranch()} instead. 139 */ 140 public String getRemoteTrackingBranch() { 141 String remote = getRemoteOrDefault(); 142 String mergeRef = getMerge(); 143 if (remote == null || mergeRef == null) 144 return null; 145 146 return findRemoteTrackingBranch(remote, mergeRef); 147 } 148 149 /** 150 * Whether the "remote" setting points to the local repository (with 151 * {@value #LOCAL_REPOSITORY}) 152 * 153 * @return {@code true} if the "remote" setting points to the local 154 * repository (with {@value #LOCAL_REPOSITORY}), false otherwise 155 * @since 3.5 156 */ 157 public boolean isRemoteLocal() { 158 return LOCAL_REPOSITORY.equals(getRemote()); 159 } 160 161 /** 162 * Get the remote this branch is configured to fetch from/push to 163 * 164 * @return the remote this branch is configured to fetch from/push to, or 165 * {@code null} if not defined 166 * @since 3.5 167 */ 168 public String getRemote() { 169 return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION, 170 branchName, ConfigConstants.CONFIG_KEY_REMOTE); 171 } 172 173 /** 174 * Get the name of the upstream branch as it is called on the remote 175 * 176 * @return the name of the upstream branch as it is called on the remote, or 177 * {@code null} if not defined 178 * @since 3.5 179 */ 180 public String getMerge() { 181 return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION, 182 branchName, ConfigConstants.CONFIG_KEY_MERGE); 183 } 184 185 /** 186 * Whether the branch is configured to be rebased 187 * 188 * @return {@code true} if the branch is configured to be rebased 189 * @since 3.5 190 */ 191 public boolean isRebase() { 192 return getRebaseMode() != BranchRebaseMode.NONE; 193 } 194 195 /** 196 * Retrieves the config value of branch.[name].rebase. 197 * 198 * @return the {@link org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode} 199 * @since 4.5 200 */ 201 public BranchRebaseMode getRebaseMode() { 202 return config.getEnum(BranchRebaseMode.values(), 203 ConfigConstants.CONFIG_BRANCH_SECTION, branchName, 204 ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE); 205 } 206 207 /** 208 * Finds the tracked remote tracking branch 209 * 210 * @param remote 211 * Remote name 212 * @param mergeRef 213 * merge Ref of the local branch tracking the remote tracking 214 * branch 215 * @return full remote tracking branch name or null 216 */ 217 private String findRemoteTrackingBranch(String remote, String mergeRef) { 218 RemoteConfig remoteConfig; 219 try { 220 remoteConfig = new RemoteConfig(config, remote); 221 } catch (URISyntaxException e) { 222 return null; 223 } 224 for (RefSpec refSpec : remoteConfig.getFetchRefSpecs()) { 225 if (refSpec.matchSource(mergeRef)) { 226 RefSpec expanded = refSpec.expandFromSource(mergeRef); 227 return expanded.getDestination(); 228 } 229 } 230 return null; 231 } 232 233 private String getRemoteOrDefault() { 234 String remote = getRemote(); 235 if (remote == null) 236 return Constants.DEFAULT_REMOTE_NAME; 237 else 238 return remote; 239 } 240 }