PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/atlassian/jgit-flow
Java | 280 lines | 221 code | 37 blank | 22 comment | 21 complexity | 7c6ed47598bb3873f9a486e529937bdb MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.jgitflow.core.command;
  2. import java.util.concurrent.Callable;
  3. import com.atlassian.jgitflow.core.GitFlowConfiguration;
  4. import com.atlassian.jgitflow.core.JGitFlowConstants;
  5. import com.atlassian.jgitflow.core.JGitFlowReporter;
  6. import com.atlassian.jgitflow.core.exception.BranchOutOfDateException;
  7. import com.atlassian.jgitflow.core.exception.JGitFlowExtensionException;
  8. import com.atlassian.jgitflow.core.exception.JGitFlowGitAPIException;
  9. import com.atlassian.jgitflow.core.exception.JGitFlowIOException;
  10. import com.atlassian.jgitflow.core.extension.ExtensionCommand;
  11. import com.atlassian.jgitflow.core.extension.ExtensionFailStrategy;
  12. import com.atlassian.jgitflow.core.extension.JGitFlowExtension;
  13. import com.atlassian.jgitflow.core.util.GitHelper;
  14. import com.atlassian.jgitflow.core.util.RequirementHelper;
  15. import org.eclipse.jgit.api.Git;
  16. import org.eclipse.jgit.api.errors.GitAPIException;
  17. import org.eclipse.jgit.lib.Constants;
  18. import org.eclipse.jgit.lib.RefUpdate;
  19. import org.eclipse.jgit.transport.PushResult;
  20. import org.eclipse.jgit.transport.RefSpec;
  21. import org.eclipse.jgit.transport.RemoteRefUpdate;
  22. import org.eclipse.jgit.transport.TrackingRefUpdate;
  23. import org.slf4j.Logger;
  24. import org.slf4j.LoggerFactory;
  25. import static com.atlassian.jgitflow.core.util.Preconditions.checkNotNull;
  26. /**
  27. * The base class for all JGitFlow commands.
  28. * <p>
  29. * Most commands should extend this class as it provides common helper methods
  30. * and methods to ensure valid state.
  31. * </p>
  32. *
  33. * @param <T> The return type of the call() method
  34. */
  35. public abstract class AbstractGitFlowCommand<C, T> implements Callable<T>, JGitFlowCommand
  36. {
  37. private static final Logger log = LoggerFactory.getLogger(AbstractGitFlowCommand.class);
  38. protected final Git git;
  39. protected final GitFlowConfiguration gfConfig;
  40. protected final JGitFlowReporter reporter = JGitFlowReporter.get();
  41. protected final RequirementHelper requirementHelper;
  42. private boolean allowUntracked;
  43. private String scmMessagePrefix;
  44. private String scmMessageSuffix;
  45. private boolean fetch;
  46. private boolean push;
  47. private final String branchName;
  48. protected AbstractGitFlowCommand(String branchName, Git git, GitFlowConfiguration gfConfig)
  49. {
  50. checkNotNull(branchName);
  51. checkNotNull(git);
  52. checkNotNull(gfConfig);
  53. this.requirementHelper = new RequirementHelper(git, gfConfig, getCommandName());
  54. this.git = git;
  55. this.gfConfig = gfConfig;
  56. this.allowUntracked = false;
  57. this.scmMessagePrefix = "";
  58. this.scmMessageSuffix = "";
  59. this.fetch = false;
  60. this.push = false;
  61. this.branchName = branchName;
  62. }
  63. protected void doFetchIfNeeded(JGitFlowExtension fetchingExtension) throws GitAPIException, JGitFlowGitAPIException, JGitFlowExtensionException
  64. {
  65. if (fetch)
  66. {
  67. runExtensionCommands(fetchingExtension.beforeFetch());
  68. git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call();
  69. runExtensionCommands(fetchingExtension.afterFetch());
  70. }
  71. }
  72. protected void doPushIfNeeded(JGitFlowExtension pushExtension, boolean includeTags, String... branchesToPush) throws GitAPIException, JGitFlowGitAPIException, JGitFlowExtensionException
  73. {
  74. if (push)
  75. {
  76. reporter.infoText(getCommandName(), "pushing changes to origin...");
  77. for (String branchToPush : branchesToPush)
  78. {
  79. if (GitHelper.remoteBranchExists(git, branchToPush))
  80. {
  81. reporter.infoText(getCommandName(), "pushing '" + branchToPush + "'");
  82. RefSpec branchSpec = new RefSpec(branchToPush);
  83. Iterable<PushResult> i = git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(branchSpec).call();
  84. for (PushResult pr : i)
  85. {
  86. reporter.infoText(getCommandName(), "messages: '" + pr.getMessages() + "'");
  87. if(null != pr && null != pr.getRemoteUpdates() && !pr.getRemoteUpdates().isEmpty()) {
  88. for (RemoteRefUpdate update : pr.getRemoteUpdates()) {
  89. RemoteRefUpdate.Status trackingStatus = update.getStatus();
  90. if (failedResult(trackingStatus)) {
  91. if (pr.getMessages() != null && pr.getMessages().length() > 0) {
  92. throw new JGitFlowGitAPIException("error pushing to " + branchToPush + " - status: " + trackingStatus.name() + " - " + pr.getMessages());
  93. } else {
  94. throw new JGitFlowGitAPIException("error pushing to " + branchToPush + " - " + trackingStatus.name());
  95. }
  96. }
  97. }
  98. }
  99. else
  100. {
  101. throw new JGitFlowGitAPIException("error pushing to " + branchToPush + " - " + pr.getMessages());
  102. }
  103. }
  104. }
  105. }
  106. if (includeTags)
  107. {
  108. reporter.infoText(getCommandName(), "pushing tags");
  109. // TODO: check for errors or at least log error messages received
  110. git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setPushTags().call();
  111. }
  112. git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call();
  113. runExtensionCommands(pushExtension.afterPush());
  114. }
  115. }
  116. private boolean failedResult(RemoteRefUpdate.Status trackingStatus) {
  117. boolean isFailed = false;
  118. switch(trackingStatus)
  119. {
  120. case REJECTED_NONFASTFORWARD:
  121. case REJECTED_NODELETE:
  122. case REJECTED_REMOTE_CHANGED:
  123. case REJECTED_OTHER_REASON:
  124. isFailed = true;
  125. break;
  126. }
  127. return isFailed;
  128. }
  129. protected String runBeforeAndGetPrefixedBranchName(Iterable<ExtensionCommand> before, JGitFlowConstants.PREFIXES prefix) throws JGitFlowExtensionException
  130. {
  131. reporter.commandCall(getCommandName());
  132. runExtensionCommands(before);
  133. return gfConfig.getPrefixValue(prefix.configKey()) + branchName;
  134. }
  135. protected void ensureLocalBranchesNotBehindRemotes(String... branchesToTest) throws JGitFlowGitAPIException, BranchOutOfDateException, JGitFlowIOException
  136. {
  137. for (String branchToTest : branchesToTest)
  138. {
  139. if (GitHelper.remoteBranchExists(git, branchToTest))
  140. {
  141. enforcer().requireLocalBranchNotBehindRemote(branchToTest);
  142. }
  143. }
  144. }
  145. @Override
  146. public C setAllowUntracked(boolean allow)
  147. {
  148. this.allowUntracked = allow;
  149. return (C) this;
  150. }
  151. @Override
  152. public boolean isAllowUntracked()
  153. {
  154. return allowUntracked;
  155. }
  156. @Override
  157. public String getScmMessagePrefix()
  158. {
  159. return scmMessagePrefix;
  160. }
  161. @Override
  162. public C setScmMessagePrefix(String scmMessagePrefix)
  163. {
  164. this.scmMessagePrefix = scmMessagePrefix;
  165. return (C) this;
  166. }
  167. @Override
  168. public String getScmMessageSuffix()
  169. {
  170. return scmMessageSuffix;
  171. }
  172. @Override
  173. public C setScmMessageSuffix(String scmMessageSuffix)
  174. {
  175. this.scmMessageSuffix = scmMessageSuffix;
  176. return (C) this;
  177. }
  178. /**
  179. * Set whether to perform a git fetch of the remote branches before doing the merge
  180. *
  181. * @param fetch {@code true} to do the fetch, {@code false}(default) otherwise
  182. * @return {@code this}
  183. */
  184. @Override
  185. public C setFetch(boolean fetch)
  186. {
  187. this.fetch = fetch;
  188. return (C) this;
  189. }
  190. @Override
  191. public boolean isFetch()
  192. {
  193. return fetch;
  194. }
  195. /**
  196. * Set whether to push the changes to the remote repository
  197. *
  198. * @param push {@code true} to do the push, {@code false}(default) otherwise
  199. * @return {@code this}
  200. */
  201. @Override
  202. public C setPush(boolean push)
  203. {
  204. this.push = push;
  205. return (C) this;
  206. }
  207. @Override
  208. public boolean isPush()
  209. {
  210. return push;
  211. }
  212. @Override
  213. public String getBranchName()
  214. {
  215. return branchName;
  216. }
  217. protected abstract String getCommandName();
  218. protected void runExtensionCommands(Iterable<ExtensionCommand> commands) throws JGitFlowExtensionException
  219. {
  220. for (final ExtensionCommand command : commands)
  221. {
  222. try
  223. {
  224. command.execute(gfConfig, git, this);
  225. }
  226. catch (JGitFlowExtensionException e)
  227. {
  228. if (ExtensionFailStrategy.ERROR.equals(command.failStrategy()))
  229. {
  230. throw e;
  231. }
  232. else
  233. {
  234. log.warn("Error running JGitFlow Extension", e);
  235. }
  236. }
  237. }
  238. }
  239. protected RequirementHelper enforcer()
  240. {
  241. return requirementHelper;
  242. }
  243. }