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
;
36 * This data class represents a Git branch
38 public class GitBranch
extends GitReference
{
40 * If true, the branch is remote
42 private final boolean myRemote
;
44 * If true, the branch is active
46 private final boolean myActive
;
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)";
52 * Prefix for local branches ({@value})
54 @NonNls public static final String REFS_HEADS_PREFIX
= "refs/heads/";
56 * Prefix for remote branches ({@value})
58 @NonNls public static final String REFS_REMOTES_PREFIX
= "refs/remotes/";
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
) {
74 * @return true if the branch is remote
76 public boolean isRemote() {
81 * @return true if the branch is active
83 public boolean isActive() {
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
96 public static GitBranch
current(Project project
, VirtualFile root
) throws VcsException
{
97 GitSimpleHandler h
= new GitSimpleHandler(project
, root
, GitHandler
.BRANCH
);
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
)) {
108 return new GitBranch(line
.substring(2), true, false);
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
,
129 final Collection
<String
> branches
) throws VcsException
{
130 if (!local
&& !remote
) {
131 // no need to run handler
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");
141 handler
.addParameters("-r");
143 for (String line
: handler
.run().split("\n")) {
144 if (line
.length() == 0 || line
.endsWith(NO_BRANCH_NAME
)) {
147 branches
.add(line
.substring(2));
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
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
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
,
199 final boolean remote
,
200 final Collection
<GitBranch
> branches
) throws VcsException
{
201 ArrayList
<String
> temp
= new ArrayList
<String
>();
203 listAsStrings(project
, root
, false, true, temp
);
204 for (String b
: temp
) {
205 branches
.add(new GitBranch(b
, false, false));
210 listAsStrings(project
, root
, true, false, temp
);
211 for (String b
: temp
) {
212 branches
.add(new GitBranch(b
, false, true));
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());
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) {
263 String branch
= getTrackedBranchName(project
, root
);
264 if (branch
== null) {
267 branch
= branch
.substring(REFS_HEADS_PREFIX
.length());
269 if (!".".equals(remote
)) {
270 branch
= remote
+ "/" + branch
;
276 return new GitBranch(branch
, false, remoteFlag
);