Commit 2156ff76 authored by Jonathan Doklovic's avatar Jonathan Doklovic

Merge branch 'release/1.0-m4'

parents 578237db 3077c1be
# JGit-Flow
**Current Version: 1.0-m2**
**Current Version: 1.0-m3**
**Issue Tracker Has Moved To: [https://ecosystem.atlassian.net/browse/MJF](https://ecosystem.atlassian.net/browse/MJF)**
......@@ -16,7 +16,7 @@ For more information and usage guide, [see the wiki](https://bitbucket.org/atlas
# Maven JGit-Flow Plugin
**Current Version: 1.0-m2**
**Current Version: 1.0-m3**
**The Issue Tracker Has Moved To: [https://ecosystem.atlassian.net/browse/MJF](https://ecosystem.atlassian.net/browse/MJF)**
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>external.atlassian.jgitflow</groupId>
<artifactId>jgitflow-parent</artifactId>
<version>1.0-m3</version>
<version>1.0-m4</version>
</parent>
<artifactId>jgit-flow-core</artifactId>
......
......@@ -189,6 +189,23 @@ public class JGitFlow
return initCommand.setDirectory(projectDir).setDefaultOriginUrl(defaultOriginUrl).setForce(true).setInitContext(context).call();
}
/**
* Initializes a project for use with git flow using a custom context overriding any existing configuration.
*
* @param projectDir
* @param context
* @return
* @throws com.atlassian.jgitflow.core.exception.JGitFlowIOException
* @throws com.atlassian.jgitflow.core.exception.AlreadyInitializedException
* @throws com.atlassian.jgitflow.core.exception.SameBranchException
* @throws com.atlassian.jgitflow.core.exception.JGitFlowGitAPIException
*/
public static JGitFlowInitCommand forceInitCommand(File projectDir, InitContext context) throws JGitFlowIOException, AlreadyInitializedException, SameBranchException, JGitFlowGitAPIException
{
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
return initCommand.setDirectory(projectDir).setForce(true).setInitContext(context);
}
/**
* Gets an existing git flow project and returns a JGitFlow instance
*
......
......@@ -66,6 +66,10 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
private InitContext context;
JGitFlowReporter reporter;
private String defaultOriginUrl;
private boolean allowRemote;
private boolean alwaysUpdateOrigin;
private boolean pullMaster;
private boolean pullDevelop;
/**
* Create a new init command instance.
......@@ -75,6 +79,11 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
public JGitFlowInitCommand()
{
this.force = false;
this.alwaysUpdateOrigin = false;
this.defaultOriginUrl = "";
this.pullMaster = false;
this.pullDevelop = false;
this.allowRemote = true;
this.reporter = new JGitFlowReporter();
}
......@@ -122,25 +131,14 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
try
{
String currentBranch = repo.getBranch();
StoredConfig gitConfig = git.getRepository().getConfig();
String originUrl = gitConfig.getString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "url");
String finalOriginUrl = setupOriginIfNeeded(git,gitConfig,originUrl);
//set origin if we need to
if (!Strings.isNullOrEmpty(defaultOriginUrl))
if(allowRemote && ! Strings.isNullOrEmpty(finalOriginUrl))
{
StoredConfig gitConfig = git.getRepository().getConfig();
String newOriginUrl = defaultOriginUrl;
if (defaultOriginUrl.startsWith("file://"))
{
File originFile = new File(defaultOriginUrl.substring(7));
newOriginUrl = "file://" + originFile.getCanonicalPath();
}
gitConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "url", newOriginUrl);
gitConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "fetch", "+refs/heads/*:refs/remotes/origin/*");
gitConfig.save();
gitConfig.load();
git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call();
}
if (!force && gfConfig.gitFlowIsInitialized())
......@@ -171,6 +169,14 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
gfConfig.setMaster(context.getMaster());
if(allowRemote && pullMaster && GitHelper.remoteBranchExists(git, context.getMaster(), reporter))
{
reporter.debugText("JgitFlowInitCommand", "pulling '" + context.getMaster());
reporter.flush();
git.checkout().setName(context.getMaster()).call();
git.pull().call();
}
//now setup develop
if (gfConfig.hasDevelopConfigured() && !force)
......@@ -188,6 +194,8 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
reporter.infoText(SHORT_NAME, "setting develop in config to '" + context.getDevelop() + "'");
gfConfig.setDevelop(context.getDevelop());
setupRemotesInConfig(gitConfig,finalOriginUrl);
//Creation of HEAD
walk = new RevWalk(repo);
ObjectId masterBranch = repo.resolve(Constants.R_HEADS + context.getMaster());
......@@ -242,8 +250,14 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
}
}
//don't do this as it breaks feature finish
//git.checkout().setName(context.getDevelop()).call();
if(allowRemote && pullDevelop && GitHelper.remoteBranchExists(git, context.getDevelop(), reporter))
{
reporter.debugText("JgitFlowInitCommand", "pulling '" + context.getDevelop());
reporter.flush();
git.checkout().setName(context.getDevelop()).call();
git.pull().call();
}
//setup prefixes
for (String prefixName : gfConfig.getPrefixNames())
......@@ -293,6 +307,65 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
return new JGitFlow(git, gfConfig, reporter);
}
private String setupOriginIfNeeded(Git git, StoredConfig gitConfig, String originUrl) throws IOException, ConfigInvalidException
{
String newOriginUrl = originUrl;
//set origin if we need to
if ((Strings.isNullOrEmpty(originUrl) || alwaysUpdateOrigin) && !Strings.isNullOrEmpty(defaultOriginUrl))
{
if (defaultOriginUrl.startsWith("file://"))
{
File originFile = new File(defaultOriginUrl.substring(7));
newOriginUrl = "file://" + originFile.getCanonicalPath();
}
gitConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "url", newOriginUrl);
gitConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "fetch", "+refs/heads/*:refs/remotes/origin/*");
gitConfig.save();
gitConfig.load();
}
return newOriginUrl;
}
private void setupRemotesInConfig(StoredConfig gitConfig, String originUrl) throws IOException, ConfigInvalidException
{
if (!Strings.isNullOrEmpty(originUrl))
{
if (Strings.isNullOrEmpty(gitConfig.getString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getMaster(), "remote")))
{
gitConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getMaster(), "remote", Constants.DEFAULT_REMOTE_NAME);
}
if (Strings.isNullOrEmpty(gitConfig.getString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getMaster(), "merge")))
{
gitConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getMaster(), "merge", Constants.R_HEADS + context.getMaster());
}
if (Strings.isNullOrEmpty(gitConfig.getString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getDevelop(), "remote")))
{
gitConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getDevelop(), "remote", Constants.DEFAULT_REMOTE_NAME);
}
if (Strings.isNullOrEmpty(gitConfig.getString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getDevelop(), "merge")))
{
gitConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, context.getDevelop(), "merge", Constants.R_HEADS + context.getDevelop());
}
if (Strings.isNullOrEmpty(gitConfig.getString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "fetch")))
{
gitConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, "fetch", "+refs/heads/*:refs/remotes/origin/*");
}
gitConfig.save();
gitConfig.load();
}
}
/**
* Sets the project root folder
......@@ -336,6 +409,30 @@ public class JGitFlowInitCommand implements Callable<JGitFlow>
return this;
}
public JGitFlowInitCommand setAlwaysUpdateOrigin(boolean update)
{
this.alwaysUpdateOrigin = update;
return this;
}
public JGitFlowInitCommand setPullMaster(boolean pull)
{
this.pullMaster = pull;
return this;
}
public JGitFlowInitCommand setPullDevelop(boolean pull)
{
this.pullDevelop = pull;
return this;
}
public JGitFlowInitCommand setAllowRemote(boolean allow)
{
this.allowRemote = allow;
return this;
}
private Git getOrInitGit(File folder) throws IOException, GitAPIException
{
reporter.debugMethod(SHORT_NAME, "getOrInitGit");
......
......@@ -32,7 +32,7 @@ public class JGitFlowReporter
public static final int PAD = 4;
private boolean wroteHeader;
private boolean logFileCreated;
private boolean clearLog;
private String header;
private File logDir;
......@@ -45,7 +45,7 @@ public class JGitFlowReporter
public JGitFlowReporter()
{
this.wroteHeader = false;
this.logFileCreated = false;
this.clearLog = false;
this.entries = newArrayList();
this.allEntries = newArrayList();
......@@ -56,7 +56,7 @@ public class JGitFlowReporter
indent = 0;
}
void setGitFlowConfiguration(Git git, GitFlowConfiguration config)
public void setGitFlowConfiguration(Git git, GitFlowConfiguration config)
{
this.logDir = git.getRepository().getDirectory();
this.header = generateHeader(git, config);
......@@ -108,6 +108,13 @@ public class JGitFlowReporter
return this;
}
public JGitFlowReporter clearLog()
{
this.clearLog = true;
return this;
}
public JGitFlowReporter endMethod()
{
indent -= PAD;
......@@ -163,7 +170,7 @@ public class JGitFlowReporter
Charset utf8 = Charset.forName("UTF-8");
try
{
if (!logFileCreated && null != logDir && logDir.exists())
if (clearLog && null != logDir && logDir.exists())
{
if (logFile.exists())
{
......@@ -171,7 +178,14 @@ public class JGitFlowReporter
}
Files.touch(logFile);
logFileCreated = true;
clearLog = false;
}
if(!clearLog && null == logDir || !logFile.exists())
{
logDir.mkdirs();
Files.touch(logFile);
}
if (!wroteHeader && null != header)
......
......@@ -142,8 +142,8 @@ public abstract class AbstractBranchMergingCommand<C, T> extends AbstractGitFlow
if (isPush() && GitHelper.remoteBranchExists(git, branchToDelete, reporter))
{
reporter.infoText(getCommandName(), "pushing deleted branch: " + branchToDelete);
RefSpec deleteSpec = new RefSpec(":" + Constants.R_HEADS + branchToDelete);
reporter.infoText(getCommandName(), "pushing deleted branch: :" + branchToDelete);
RefSpec deleteSpec = new RefSpec().setSource(null).setDestination(Constants.R_HEADS + branchToDelete);
git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(deleteSpec).call();
}
}
......
package com.atlassian.jgitflow.core.command;
import java.util.List;
import com.atlassian.jgitflow.core.GitFlowConfiguration;
import com.atlassian.jgitflow.core.JGitFlowConstants;
import com.atlassian.jgitflow.core.JGitFlowReporter;
......@@ -102,6 +104,7 @@ public class HotfixFinishCommand extends AbstractBranchMergingCommand<HotfixFini
MergeResult developResult = createEmptyMergeResult();
MergeResult masterResult = createEmptyMergeResult();
MergeResult releaseResult = createEmptyMergeResult();
try
{
doFetchIfNeeded(extension);
......@@ -137,6 +140,22 @@ public class HotfixFinishCommand extends AbstractBranchMergingCommand<HotfixFini
{
cleanupBranchesIfNeeded(gfConfig.getDevelop(), prefixedBranchName);
}
//Backmerge to release branch if needed
if(releaseBranchExists())
{
String releaseBranchName = getReleaseBranchName();
MergeProcessExtensionWrapper releaseExtension = new MergeProcessExtensionWrapper(extension.beforeReleaseCheckout(), extension.afterReleaseCheckout(), extension.beforeReleaseMerge(), extension.afterReleaseMerge());
releaseResult = doMerge(gfConfig.getMaster(), releaseBranchName, releaseExtension);
boolean releaseMergeSuccess = checkMergeResults(releaseResult);
if (releaseMergeSuccess)
{
doPushIfNeeded(extension, !noTag, releaseBranchName);
}
}
reporter.infoText(getCommandName(), "checking out '" + gfConfig.getDevelop() + "'");
git.checkout().setName(gfConfig.getDevelop()).call();
......@@ -156,6 +175,34 @@ public class HotfixFinishCommand extends AbstractBranchMergingCommand<HotfixFini
}
}
private boolean releaseBranchExists() throws JGitFlowGitAPIException
{
boolean exists = false;
List<Ref> branches = GitHelper.listBranchesWithPrefix(git, gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.RELEASE.configKey()), reporter);
if (!branches.isEmpty())
{
exists = true;
}
return exists;
}
private String getReleaseBranchName() throws JGitFlowGitAPIException
{
String branchName = "";
List<Ref> branches = GitHelper.listBranchesWithPrefix(git, gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.RELEASE.configKey()), reporter);
if (!branches.isEmpty())
{
branchName = branches.get(0).getName();
}
return branchName;
}
/**
* Set the commit message for the tag creation
*
......
package com.atlassian.jgitflow.core.extension;
public interface HotfixFinishExtension extends DevelopMergingExtension, MasterMergingExtension
public interface HotfixFinishExtension extends DevelopMergingExtension, MasterMergingExtension, ReleaseMergingExtension
{
}
package com.atlassian.jgitflow.core.extension;
public interface ReleaseMergingExtension extends BranchMergingExtension
{
Iterable<ExtensionCommand> beforeReleaseCheckout();
Iterable<ExtensionCommand> afterReleaseCheckout();
Iterable<ExtensionCommand> beforeReleaseMerge();
Iterable<ExtensionCommand> afterReleaseMerge();
}
......@@ -5,7 +5,7 @@ import java.util.Collections;
import com.atlassian.jgitflow.core.extension.ExtensionCommand;
import com.atlassian.jgitflow.core.extension.HotfixFinishExtension;
public class EmptyHotfixFinishExtension extends EmptyMasterAndDevelopMergingExtension implements HotfixFinishExtension
public class EmptyHotfixFinishExtension extends EmptyMasterAndDevelopAndReleaseMergingExtension implements HotfixFinishExtension
{
......
package com.atlassian.jgitflow.core.extension.impl;
import java.util.Arrays;
import java.util.List;
import com.atlassian.jgitflow.core.extension.ExtensionCommand;
import com.atlassian.jgitflow.core.extension.ReleaseMergingExtension;
import com.google.common.collect.Iterables;
import static com.google.common.collect.Lists.newArrayList;
public class EmptyMasterAndDevelopAndReleaseMergingExtension extends EmptyMasterAndDevelopMergingExtension implements ReleaseMergingExtension
{
private final List<ExtensionCommand> beforeReleaseCheckout;
private final List<ExtensionCommand> afterReleaseCheckout;
private final List<ExtensionCommand> beforeReleaseMerge;
private final List<ExtensionCommand> afterReleaseMerge;
protected EmptyMasterAndDevelopAndReleaseMergingExtension()
{
this.beforeReleaseCheckout = newArrayList();
this.afterReleaseCheckout = newArrayList();
this.beforeReleaseMerge = newArrayList();
this.afterReleaseMerge = newArrayList();
}
public void addBeforeReleaseCheckoutCommands(ExtensionCommand ... commands)
{
beforeReleaseCheckout.addAll(Arrays.asList(commands));
}
public void addAfterReleaseCheckoutCommands(ExtensionCommand ... commands)
{
afterReleaseCheckout.addAll(Arrays.asList(commands));
}
public void addBeforeReleaseMergeCommands(ExtensionCommand ... commands)
{
beforeReleaseMerge.addAll(Arrays.asList(commands));
}
public void addAfterReleaseMergeCommands(ExtensionCommand ... commands)
{
afterReleaseMerge.addAll(Arrays.asList(commands));
}
@Override
public Iterable<ExtensionCommand> beforeReleaseCheckout()
{
return Iterables.unmodifiableIterable(beforeReleaseCheckout);
}
@Override
public Iterable<ExtensionCommand> afterReleaseCheckout()
{
return Iterables.unmodifiableIterable(afterReleaseCheckout);
}
@Override
public Iterable<ExtensionCommand> beforeReleaseMerge()
{
return Iterables.unmodifiableIterable(beforeReleaseMerge);
}
@Override
public Iterable<ExtensionCommand> afterReleaseMerge()
{
return Iterables.unmodifiableIterable(afterReleaseMerge);
}
}
......@@ -159,6 +159,53 @@ public class HotfixFinishTest extends BaseGitFlowTest
assertTrue(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
}
@Test
public void finishHotfixWithNewCommitAndReleaseBranch() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
String releaseName = "release/1.0";
flow.git().checkout().setName("develop").call();
flow.hotfixStart("1.0.1").call();
//create a new commit
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//make sure develop doesn't report our commit yet
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//make sure release doesn't report our commit yet
assertFalse(GitHelper.isMergedInto(git, commit, releaseName));
//try to finish
flow.hotfixFinish("1.0.1").call();
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//hotfix branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "1.0.1");
assertNull(ref2check);
//the develop branch should have our commit
assertTrue(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//the master branch should have our commit
assertTrue(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
//the release branch should have our commit
assertTrue(GitHelper.isMergedInto(git, commit, releaseName));
}
@Test
public void finishHotfixKeepBranch() throws Exception
{
......
......@@ -28,6 +28,10 @@ public abstract class BaseExtensionForTests<T>
public static final String AFTER_MASTER_CHECKOUT = "afterMasterCheckout";
public static final String BEFORE_MASTER_MERGE = "beforeMasterMerge";
public static final String AFTER_MASTER_MERGE = "afterMasterMerge";
public static final String BEFORE_RELEASE_CHECKOUT = "beforeReleaseCheckout";
public static final String AFTER_RELEASE_CHECKOUT = "afterReleaseCheckout";
public static final String BEFORE_RELEASE_MERGE = "beforeReleaseMerge";
public static final String AFTER_RELEASE_MERGE = "afterReleaseMerge";
public static final String AFTER_TOPIC_CHECKOUT = "afterTopicCheckout";
public static final String BEFORE_TAG = "beforeTag";
public static final String AFTER_TAG = "afterTag";
......
......@@ -57,6 +57,30 @@ public class HotfixFinishExtensionForTests extends BaseExtensionForTests<Release
return Lists.<ExtensionCommand> newArrayList(createExtension(BaseExtensionForTests.AFTER_DEVELOP_MERGE));
}
@Override
public Iterable<ExtensionCommand> beforeReleaseCheckout()
{
return Lists.<ExtensionCommand> newArrayList(createExtension(BEFORE_RELEASE_CHECKOUT));
}
@Override
public Iterable<ExtensionCommand> afterReleaseCheckout()
{
return Lists.<ExtensionCommand> newArrayList(createExtension(AFTER_RELEASE_CHECKOUT));
}
@Override
public Iterable<ExtensionCommand> beforeReleaseMerge()
{
return Lists.<ExtensionCommand> newArrayList(createExtension(BEFORE_RELEASE_MERGE));
}
@Override
public Iterable<ExtensionCommand> afterReleaseMerge()
{
return Lists.<ExtensionCommand> newArrayList(createExtension(AFTER_RELEASE_MERGE));
}
@Override
public Iterable<ExtensionCommand> afterPush()
{
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>jgitflow-parent</artifactId>
<groupId>external.atlassian.jgitflow</groupId>
<version>1.0-m3</version>
<version>1.0-m4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>jgitflow-parent</artifactId>
<groupId>external.atlassian.jgitflow</groupId>
<version>1.0-m3</version>
<version>1.0-m4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>external.atlassian.jgitflow</groupId>
<artifactId>jgitflow-parent</artifactId>
<version>1.0-m3</version>
<version>1.0-m4</version>
</parent>
<artifactId>jgitflow-maven-plugin</artifactId>
......
import com.atlassian.jgitflow.core.JGitFlow
import com.atlassian.jgitflow.core.util.GitHelper
import com.atlassian.maven.plugins.jgitflow.it.FinishScriptHelper
import static org.junit.Assert.assertTrue
import static org.junit.Assert.assertFalse
try
{
helper = new FinishScriptHelper(basedir, localRepositoryPath, context)
flow = JGitFlow.getOrInit(basedir)
flow.git().checkout().setName("master").call()
......@@ -12,13 +13,13 @@ try
flow.git().checkout().setName("develop").call()
File junkFile = new File(basedir,"junk.txt")
File junkFile = new File(basedir, "junk.txt")
assertTrue(junkFile.exists())
//make sure hotfix delete was pushed
branch = "hotfix/1.0.1";
assertFalse("remote hotfix should not exist!", GitHelper.remoteBranchExists(flow.git(), branch, flow.getReporter()));
helper.comparePomFiles("expected-develop-pom.xml", "pom.xml")
}
catch (Exception e)
{