git4idea: Implemented a better version of Compare with Latest revsion, now it compare...
[fedora-idea.git] / plugins / git4idea / src / git4idea / GitBranch.java
blob3a4ebe8b221cbc28d8bd67990280af560cc249aa
1 package git4idea;
2 /*
3 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
4 * with the License. You may obtain a copy of the License at:
6 * http://www.apache.org/licenses/LICENSE-2.0
8 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
9 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
10 * the specific language governing permissions and limitations under the License.
12 * Copyright 2007 Decentrix Inc
13 * Copyright 2007 Aspiro AS
14 * Copyright 2008 MQSoftware
15 * Copyright 2008 JetBrains s.r.o.
16 * Authors: gevession, Erlend Simonsen & Mark Scott
18 * This code was originally derived from the MKS & Mercurial IDEA VCS plugins
21 import com.intellij.openapi.project.Project;
22 import com.intellij.openapi.vcs.VcsException;
23 import com.intellij.openapi.vfs.VirtualFile;
24 import git4idea.commands.GitHandler;
25 import git4idea.commands.GitSimpleHandler;
26 import git4idea.config.GitConfigUtil;
27 import org.jetbrains.annotations.NonNls;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.StringTokenizer;
35 /**
36 * This data class represents a Git branch
38 public class GitBranch extends GitReference {
39 /**
40 * If true, the branch is remote
42 private final boolean myRemote;
43 /**
44 * If true, the branch is active
46 private final boolean myActive;
47 /**
48 * The name that specifies that git is on specific commit rather then on some branch ({@value})
50 @NonNls public static final String NO_BRANCH_NAME = "(no branch)";
51 /**
52 * Prefix for local branches ({@value})
54 @NonNls public static final String REFS_HEADS_PREFIX = "refs/heads/";
55 /**
56 * Prefix for remote branches ({@value})
58 @NonNls public static final String REFS_REMOTES_PREFIX = "refs/remotes/";
60 /**
61 * The constructor for the branch
63 * @param name the name of the branch
64 * @param active if true, the branch is active
65 * @param remote if true, the branch is remote
67 public GitBranch(@NotNull String name, boolean active, boolean remote) {
68 super(name);
69 myRemote = remote;
70 myActive = active;
73 /**
74 * @return true if the branch is remote
76 public boolean isRemote() {
77 return myRemote;
80 /**
81 * @return true if the branch is active
83 public boolean isActive() {
84 return myActive;
87 /**
88 * Get current branch
90 * @param project a project
91 * @param root a directory inside the repository
92 * @return the current branch or null if there is no current branch or if specific commit has been checked out
93 * @throws VcsException if there is a problem running git
95 @Nullable
96 public static GitBranch current(Project project, VirtualFile root) throws VcsException {
97 GitSimpleHandler h = new GitSimpleHandler(project, root, GitHandler.BRANCH);
98 h.setNoSSH(true);
99 h.setSilent(true);
100 for (StringTokenizer lines = new StringTokenizer(h.run(), "\n"); lines.hasMoreTokens();) {
101 String line = lines.nextToken();
102 if (line != null && line.startsWith("*")) {
103 //noinspection HardCodedStringLiteral
104 if (line.endsWith(NO_BRANCH_NAME)) {
105 return null;
107 else {
108 return new GitBranch(line.substring(2), true, false);
112 return null;
116 * List branches for the git root
118 * @param project the context project
119 * @param root the git root
120 * @param remote if true remote branches are listed
121 * @param local if true local branches are listed
122 * @param branches the collection used to store branches
123 * @throws VcsException if there is a problem with running git
125 public static void listAsStrings(final Project project,
126 final VirtualFile root,
127 final boolean remote,
128 final boolean local,
129 final Collection<String> branches) throws VcsException {
130 if (!local && !remote) {
131 // no need to run handler
132 return;
134 GitSimpleHandler handler = new GitSimpleHandler(project, root, GitHandler.BRANCH);
135 handler.setNoSSH(true);
136 handler.setSilent(true);
137 if (remote && local) {
138 handler.addParameters("-a");
140 else if (remote) {
141 handler.addParameters("-r");
143 for (String line : handler.run().split("\n")) {
144 if (line.length() == 0 || line.endsWith(NO_BRANCH_NAME)) {
145 continue;
147 branches.add(line.substring(2));
152 * {@inheritDoc}
154 @NotNull
155 public String getFullName() {
156 return (myRemote ? REFS_REMOTES_PREFIX : REFS_HEADS_PREFIX) + myName;
160 * Get tracked remote for the branch
162 * @param project the context project
163 * @param root the VCS root to investigate
164 * @return the remote name for tracked branch, "." meaning the current repository, or null if no branch is tracked
165 * @throws VcsException if there is a problem with running Git
167 @Nullable
168 public String getTrackedRemoteName(Project project, VirtualFile root) throws VcsException {
169 return GitConfigUtil.getValue(project, root, trackedRemoteKey());
173 * Get tracked the branch
175 * @param project the context project
176 * @param root the VCS root to investigate
177 * @return the name of tracked branch
178 * @throws VcsException if there is a problem with running Git
180 @Nullable
181 public String getTrackedBranchName(Project project, VirtualFile root) throws VcsException {
182 return GitConfigUtil.getValue(project, root, trackedBranchKey());
187 * List branches for the git root
189 * @param project the context project
190 * @param root the git root
191 * @param remote if true remote branches are listed
192 * @param local if true local branches are listed
193 * @param branches the collection used to store branches
194 * @throws VcsException if there is a problem with running git
196 public static void list(final Project project,
197 final VirtualFile root,
198 final boolean local,
199 final boolean remote,
200 final Collection<GitBranch> branches) throws VcsException {
201 ArrayList<String> temp = new ArrayList<String>();
202 if (local) {
203 listAsStrings(project, root, false, true, temp);
204 for (String b : temp) {
205 branches.add(new GitBranch(b, false, false));
207 temp.clear();
209 if (remote) {
210 listAsStrings(project, root, true, false, temp);
211 for (String b : temp) {
212 branches.add(new GitBranch(b, false, true));
218 * Set tracked branch
220 * @param project the context project
221 * @param root the git root
222 * @param remote the remote to track (null, for do not track anything, "." for local repository)
223 * @param branch the branch to track
225 public void setTrackedBranch(Project project, VirtualFile root, String remote, String branch) throws VcsException {
226 if (remote == null || branch == null) {
227 GitConfigUtil.unsetValue(project, root, trackedRemoteKey());
228 GitConfigUtil.unsetValue(project, root, trackedBranchKey());
230 else {
231 GitConfigUtil.setValue(project, root, trackedRemoteKey(), remote);
232 GitConfigUtil.setValue(project, root, trackedBranchKey(), branch);
237 * @return the key for the remote of the tracked branch
239 private String trackedBranchKey() {
240 return "branch." + getName() + ".merge";
244 * @return the key for the tracked branch
246 private String trackedRemoteKey() {
247 return "branch." + getName() + ".remote";
251 * Get tracked branch for the current branch
253 * @param project the project
254 * @param root the vcs root
255 * @return the tracked branch
256 * @throws VcsException if there is a problem with accessing configuration file
258 public GitBranch tracked(Project project, VirtualFile root) throws VcsException {
259 String remote = getTrackedRemoteName(project, root);
260 if (remote == null) {
261 return null;
263 String branch = getTrackedBranchName(project, root);
264 if (branch == null) {
265 return null;
267 branch = branch.substring(REFS_HEADS_PREFIX.length());
268 boolean remoteFlag;
269 if (!".".equals(remote)) {
270 branch = remote + "/" + branch;
271 remoteFlag = true;
273 else {
274 remoteFlag = false;
276 return new GitBranch(branch, false, remoteFlag);