PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/jgit-flow-core/src/main/java/com/atlassian/jgitflow/core/AbstractGitFlowCommand.java

https://bitbucket.org/ronsmits/jgit-flow
Java | 227 lines | 134 code | 27 blank | 66 comment | 14 complexity | 8f1a472f2c57d7500ebe3a12555e60a1 MD5 | raw file
  1. package com.atlassian.jgitflow.core;
  2. import java.io.IOException;
  3. import java.util.List;
  4. import java.util.concurrent.Callable;
  5. import com.atlassian.jgitflow.core.exception.*;
  6. import com.atlassian.jgitflow.core.util.GitHelper;
  7. import org.eclipse.jgit.api.Git;
  8. import org.eclipse.jgit.lib.ObjectId;
  9. import org.eclipse.jgit.lib.Ref;
  10. import org.eclipse.jgit.revwalk.RevCommit;
  11. import org.eclipse.jgit.revwalk.RevWalk;
  12. import org.eclipse.jgit.revwalk.filter.RevFilter;
  13. import static com.atlassian.jgitflow.core.util.Preconditions.checkNotNull;
  14. /**
  15. * The base class for all JGitFlow commands.
  16. * <p>
  17. * Most commands should extend this class as it provides common helper methods
  18. * and methods to ensure valid state.
  19. * </p>
  20. * @param <T> The return type of the call() method
  21. */
  22. public abstract class AbstractGitFlowCommand<T> implements Callable<T>
  23. {
  24. protected final Git git;
  25. protected final GitFlowConfiguration gfConfig;
  26. protected AbstractGitFlowCommand(Git git, GitFlowConfiguration gfConfig)
  27. {
  28. checkNotNull(git);
  29. checkNotNull(gfConfig);
  30. this.git = git;
  31. this.gfConfig = gfConfig;
  32. }
  33. /**
  34. * Requires that git flow has been initialized for the project represented by the internal {Git} instance
  35. * @throws NotInitializedException
  36. * @throws JGitFlowGitAPIException
  37. */
  38. protected void requireGitFlowInitialized() throws NotInitializedException, JGitFlowGitAPIException
  39. {
  40. if (!gfConfig.gitFlowIsInitialized())
  41. {
  42. throw new NotInitializedException("Git flow is not initialized in " + git.getRepository().getWorkTree().getPath());
  43. }
  44. }
  45. /**
  46. * Requires that a local branch with the given name does not yet exist
  47. * @param branch the name of the branch to test
  48. * @throws LocalBranchExistsException
  49. * @throws JGitFlowGitAPIException
  50. */
  51. protected void requireLocalBranchAbsent(String branch) throws LocalBranchExistsException, JGitFlowGitAPIException
  52. {
  53. if (GitHelper.localBranchExists(git, branch))
  54. {
  55. throw new LocalBranchExistsException("local branch '" + branch + "' already exists");
  56. }
  57. }
  58. /**
  59. * Requires that a local branch with the given name exists
  60. * @param branch The name of the branch to test
  61. * @throws LocalBranchMissingException
  62. * @throws JGitFlowGitAPIException
  63. */
  64. protected void requireLocalBranchExists(String branch) throws LocalBranchMissingException, JGitFlowGitAPIException
  65. {
  66. if (!GitHelper.localBranchExists(git, branch))
  67. {
  68. throw new LocalBranchMissingException("local branch " + branch + " does not exist");
  69. }
  70. }
  71. /**
  72. * Requires that a remote branch with the given name does not yet exist
  73. * @param branch The name of the branch to test
  74. * @throws RemoteBranchExistsException
  75. * @throws JGitFlowGitAPIException
  76. */
  77. protected void requireRemoteBranchAbsent(String branch) throws RemoteBranchExistsException, JGitFlowGitAPIException
  78. {
  79. if (GitHelper.remoteBranchExists(git, branch))
  80. {
  81. throw new RemoteBranchExistsException("remote branch '" + branch + "' already exists");
  82. }
  83. }
  84. /**
  85. * Requires that a remote branch with the given name exists
  86. * @param branch The name of the branch to test
  87. * @throws RemoteBranchMissingException
  88. * @throws JGitFlowGitAPIException
  89. */
  90. protected void requireRemoteBranchExists(String branch) throws RemoteBranchMissingException, JGitFlowGitAPIException
  91. {
  92. if (!GitHelper.remoteBranchExists(git, branch))
  93. {
  94. throw new RemoteBranchMissingException("remote branch " + branch + " does not exist");
  95. }
  96. }
  97. /**
  98. * Requires that a tag with the given name does not yet exist
  99. * @param name The name of the tag to test
  100. * @throws TagExistsException
  101. * @throws JGitFlowGitAPIException
  102. */
  103. protected void requireTagAbsent(String name) throws TagExistsException, JGitFlowGitAPIException
  104. {
  105. if (GitHelper.tagExists(git, name))
  106. {
  107. throw new TagExistsException("tag '" + name + "' already exists");
  108. }
  109. }
  110. /**
  111. * Requires that the local branch with the given name is not behind a remote brach with the same name
  112. * @param branch The name of the branch to test
  113. * @throws BranchOutOfDateException
  114. * @throws JGitFlowIOException
  115. */
  116. protected void requireLocalBranchNotBehindRemote(String branch) throws BranchOutOfDateException, JGitFlowIOException
  117. {
  118. final RevWalk walk = new RevWalk(git.getRepository());
  119. walk.setRetainBody(true);
  120. boolean behind = false;
  121. try
  122. {
  123. Ref remote = GitHelper.getRemoteBranch(git, branch);
  124. Ref local = GitHelper.getLocalBranch(git, branch);
  125. checkNotNull(remote);
  126. checkNotNull(local);
  127. ObjectId remoteId = git.getRepository().resolve(remote.getObjectId().getName());
  128. RevCommit remoteCommit = walk.parseCommit(remoteId);
  129. RevCommit localCommit = walk.parseCommit(local.getObjectId());
  130. if (!localCommit.equals(remoteCommit))
  131. {
  132. behind = true;
  133. walk.setRevFilter(RevFilter.MERGE_BASE);
  134. walk.markStart(localCommit);
  135. walk.markStart(remoteCommit);
  136. RevCommit base = walk.next();
  137. if (null != base)
  138. {
  139. walk.parseBody(base);
  140. //remote is behind
  141. if (remoteCommit.equals(base))
  142. {
  143. behind = false;
  144. }
  145. }
  146. }
  147. }
  148. catch (IOException e)
  149. {
  150. throw new JGitFlowIOException(e);
  151. }
  152. finally
  153. {
  154. walk.release();
  155. }
  156. if (behind)
  157. {
  158. throw new BranchOutOfDateException("local branch '" + branch + "' is behind the remote branch");
  159. }
  160. }
  161. /**
  162. * Requires that the local working tree has no un-committed changes
  163. * @throws DirtyWorkingTreeException
  164. * @throws JGitFlowIOException
  165. * @throws JGitFlowGitAPIException
  166. */
  167. protected void requireCleanWorkingTree() throws DirtyWorkingTreeException, JGitFlowIOException, JGitFlowGitAPIException
  168. {
  169. if (!GitHelper.workingTreeIsClean(git))
  170. {
  171. throw new DirtyWorkingTreeException("Working tree has uncommitted changes");
  172. }
  173. }
  174. /**
  175. * Requires that no release branches already exist
  176. * @throws ReleaseBranchExistsException
  177. * @throws JGitFlowGitAPIException
  178. */
  179. protected void requireNoExistingReleaseBranches() throws ReleaseBranchExistsException, JGitFlowGitAPIException
  180. {
  181. List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.RELEASE.configKey());
  182. if (!branches.isEmpty())
  183. {
  184. throw new ReleaseBranchExistsException("a release branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
  185. }
  186. }
  187. /**
  188. * Requires that no hotfix branches already exist
  189. * @throws HotfixBranchExistsException
  190. * @throws JGitFlowGitAPIException
  191. */
  192. protected void requireNoExistingHotfixBranches() throws HotfixBranchExistsException, JGitFlowGitAPIException
  193. {
  194. List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.HOTFIX.configKey());
  195. if (!branches.isEmpty())
  196. {
  197. throw new HotfixBranchExistsException("a hotfix branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
  198. }
  199. }
  200. }