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 * @return the full tracking branch name or <code>null</code> if it could 117 * not be determined 118 */ 119 public String getTrackingBranch() { 120 String remote = getRemoteOrDefault(); 121 String mergeRef = getMerge(); 122 if (remote == null || mergeRef == null) 123 return null; 124 125 if (isRemoteLocal()) 126 return mergeRef; 127 128 return findRemoteTrackingBranch(remote, mergeRef); 129 } 130 131 /** 132 * @return the full remote-tracking branch name or {@code null} if it could 133 * not be determined. If you also want local tracked branches use 134 * {@link #getTrackingBranch()} instead. 135 */ 136 public String getRemoteTrackingBranch() { 137 String remote = getRemoteOrDefault(); 138 String mergeRef = getMerge(); 139 if (remote == null || mergeRef == null) 140 return null; 141 142 return findRemoteTrackingBranch(remote, mergeRef); 143 } 144 145 /** 146 * @return {@code true} if the "remote" setting points to the local 147 * repository (with {@value #LOCAL_REPOSITORY}), false otherwise 148 * @since 3.5 149 */ 150 public boolean isRemoteLocal() { 151 return LOCAL_REPOSITORY.equals(getRemote()); 152 } 153 154 /** 155 * @return the remote this branch is configured to fetch from/push to, or 156 * {@code null} if not defined 157 * @since 3.5 158 */ 159 public String getRemote() { 160 return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION, 161 branchName, ConfigConstants.CONFIG_KEY_REMOTE); 162 } 163 164 /** 165 * @return the name of the upstream branch as it is called on the remote, or 166 * {@code null} if not defined 167 * @since 3.5 168 */ 169 public String getMerge() { 170 return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION, 171 branchName, ConfigConstants.CONFIG_KEY_MERGE); 172 } 173 174 /** 175 * @return {@code true} if the branch is configured to be rebased 176 * @since 3.5 177 */ 178 public boolean isRebase() { 179 return getRebaseMode() != BranchRebaseMode.NONE; 180 } 181 182 /** 183 * Retrieves the config value of branch.[name].rebase. 184 * 185 * @return the {@link BranchRebaseMode} 186 * @since 4.5 187 */ 188 public BranchRebaseMode getRebaseMode() { 189 return config.getEnum(BranchRebaseMode.values(), 190 ConfigConstants.CONFIG_BRANCH_SECTION, branchName, 191 ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE); 192 } 193 194 /** 195 * Finds the tracked remote tracking branch 196 * 197 * @param remote 198 * Remote name 199 * @param mergeRef 200 * merge Ref of the local branch tracking the remote tracking 201 * branch 202 * @return full remote tracking branch name or null 203 */ 204 private String findRemoteTrackingBranch(String remote, String mergeRef) { 205 RemoteConfig remoteConfig; 206 try { 207 remoteConfig = new RemoteConfig(config, remote); 208 } catch (URISyntaxException e) { 209 return null; 210 } 211 for (RefSpec refSpec : remoteConfig.getFetchRefSpecs()) { 212 if (refSpec.matchSource(mergeRef)) { 213 RefSpec expanded = refSpec.expandFromSource(mergeRef); 214 return expanded.getDestination(); 215 } 216 } 217 return null; 218 } 219 220 private String getRemoteOrDefault() { 221 String remote = getRemote(); 222 if (remote == null) 223 return Constants.DEFAULT_REMOTE_NAME; 224 else 225 return remote; 226 } 227 }