Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Hohenegger2015-04-30 05:48:23 -0400
committerMatthias Sohn2015-05-15 17:04:42 -0400
commit9904bd578ea60f3d28f38fec69af0456af805b12 (patch)
tree1ff9f0de63f988efae28eb2815cfb8772fce54cb
parent12a6299909b1bda6a3a4957aa0d6e2c89869c18f (diff)
downloadegit-9904bd578ea60f3d28f38fec69af0456af805b12.tar.gz
egit-9904bd578ea60f3d28f38fec69af0456af805b12.tar.xz
egit-9904bd578ea60f3d28f38fec69af0456af805b12.zip
Extend EGit to allow use of git-flow
Initial implementation: - Operations for all commonly used git flow commands without optional parameters - Menu contributions in the repository and history view, as well as the team menu on projects - Added new feature as incubation project to update site - Non-UI tests (see launch config) CQ: 9662 Bug: 348610 Change-Id: I215ed28e6434a789fa7260d7072532b402a1e714 Signed-off-by: Max Hohenegger <eclipse@hohenegger.eu> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.egit.core/META-INF/MANIFEST.MF19
-rw-r--r--org.eclipse.egit.gitflow-feature/.gitignore1
-rw-r--r--org.eclipse.egit.gitflow-feature/.project17
-rw-r--r--org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.gitflow-feature/.settings/org.eclipse.m2e.core.prefs4
-rw-r--r--org.eclipse.egit.gitflow-feature/build.properties4
-rw-r--r--org.eclipse.egit.gitflow-feature/epl-v10.html261
-rw-r--r--org.eclipse.egit.gitflow-feature/feature.properties158
-rw-r--r--org.eclipse.egit.gitflow-feature/feature.xml46
-rw-r--r--org.eclipse.egit.gitflow-feature/license.html106
-rw-r--r--org.eclipse.egit.gitflow-feature/pom.xml28
-rw-r--r--org.eclipse.egit.gitflow.test/.classpath7
-rw-r--r--org.eclipse.egit.gitflow.test/.project28
-rw-r--r--org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.core.prefs393
-rw-r--r--org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.ui.prefs61
-rw-r--r--org.eclipse.egit.gitflow.test/.settings/org.eclipse.m2e.core.prefs4
-rw-r--r--org.eclipse.egit.gitflow.test/META-INF/MANIFEST.MF11
-rw-r--r--org.eclipse.egit.gitflow.test/build.properties3
-rw-r--r--org.eclipse.egit.gitflow.test/org.eclipse.egit.gitflow--All-Tests.launch48
-rw-r--r--org.eclipse.egit.gitflow.test/pom.xml59
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/BranchNameValidatorTest.java70
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryConfigTest.java49
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryTest.java124
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractDualRepositoryTestCase.java114
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperationTest.java23
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractGitFlowOperationTest.java79
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperationTest.java51
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperationTest.java69
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureFinishOperationTest.java48
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureListOperationTest.java45
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperationTest.java47
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureStartOperationTest.java42
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureTrackOperationTest.java63
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixFinishOperationTest.java113
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixStartOperationTest.java31
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/InitOperationTest.java61
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperationTest.java136
-rw-r--r--org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseStartOperationTest.java87
-rw-r--r--org.eclipse.egit.gitflow.ui/.classpath7
-rw-r--r--org.eclipse.egit.gitflow.ui/.project35
-rw-r--r--org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.core.prefs393
-rw-r--r--org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.ui.prefs61
-rw-r--r--org.eclipse.egit.gitflow.ui/.settings/org.eclipse.m2e.core.prefs4
-rw-r--r--org.eclipse.egit.gitflow.ui/META-INF/MANIFEST.MF32
-rw-r--r--org.eclipse.egit.gitflow.ui/about.html28
-rw-r--r--org.eclipse.egit.gitflow.ui/build.properties6
-rw-r--r--org.eclipse.egit.gitflow.ui/plugin.properties14
-rw-r--r--org.eclipse.egit.gitflow.ui/plugin.xml743
-rw-r--r--org.eclipse.egit.gitflow.ui/pom.xml36
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/Activator.java103
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/JobFamilies.java20
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/UIText.java128
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/AbstractPublishHandler.java51
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureCheckoutHandler.java114
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureFinishHandler.java45
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeaturePublishHandler.java21
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureRebaseHandler.java62
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureStartHandler.java53
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureTrackHandler.java83
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/GitFlowHandlerUtil.java40
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixFinishHandler.java47
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixPublishHandler.java21
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixStartHandler.java53
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/InitHandler.java38
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseFinishHandler.java47
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleasePublishHandler.java21
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseStartHandler.java103
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/dialog/AbstractGitFlowBranchSelectionDialog.java155
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/factories/GitFlowAdapterFactory.java48
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/selection/SelectionPropertyTester.java65
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/uitext.properties41
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/BranchNameInputValidator.java44
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/FeatureNameValidator.java32
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/HotfixNameValidator.java32
-rw-r--r--org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/ReleaseNameValidator.java32
-rw-r--r--org.eclipse.egit.gitflow/.classpath7
-rw-r--r--org.eclipse.egit.gitflow/.project34
-rw-r--r--org.eclipse.egit.gitflow/.settings/.api_filters27
-rw-r--r--org.eclipse.egit.gitflow/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.gitflow/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.core.prefs393
-rw-r--r--org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.ui.prefs61
-rw-r--r--org.eclipse.egit.gitflow/.settings/org.eclipse.m2e.core.prefs4
-rw-r--r--org.eclipse.egit.gitflow/META-INF/MANIFEST.MF21
-rw-r--r--org.eclipse.egit.gitflow/about.html28
-rw-r--r--org.eclipse.egit.gitflow/build.properties5
-rw-r--r--org.eclipse.egit.gitflow/pom.xml36
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/Activator.java82
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/BranchNameValidator.java93
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowConfig.java310
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowDefaults.java34
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowRepository.java284
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/WrongGitFlowStateException.java37
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/CoreText.java100
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/coretext.properties31
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperation.java53
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractHotfixOperation.java48
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractReleaseOperation.java48
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractVersionFinishOperation.java89
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperation.java96
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperation.java49
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureFinishOperation.java51
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureListOperation.java105
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperation.java62
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureStartOperation.java56
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureTrackOperation.java126
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/GitFlowOperation.java174
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixFinishOperation.java77
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixStartOperation.java33
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/InitOperation.java141
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperation.java56
-rw-r--r--org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseStartOperation.java101
-rw-r--r--org.eclipse.egit.repository/category.xml3
-rw-r--r--org.eclipse.egit.ui/META-INF/MANIFEST.MF8
-rw-r--r--pom.xml12
120 files changed, 8354 insertions, 12 deletions
diff --git a/org.eclipse.egit.core/META-INF/MANIFEST.MF b/org.eclipse.egit.core/META-INF/MANIFEST.MF
index 45a883341..9e5c13831 100644
--- a/org.eclipse.egit.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.core/META-INF/MANIFEST.MF
@@ -11,18 +11,27 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)",
org.eclipse.equinox.security;bundle-version="[1.0.0,2.0.0)"
-Export-Package: org.eclipse.egit.core;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.ui.test,org.eclipse.egit.mylyn.ui",
- org.eclipse.egit.core.internal;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.import",
+Export-Package: org.eclipse.egit.core;version="4.0.0";
+ x-friends:="org.eclipse.egit.ui,
+ org.eclipse.egit.ui.test,
+ org.eclipse.egit.mylyn.ui,
+ org.eclipse.egit.gitflow.test",
+ org.eclipse.egit.core.internal;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.import,org.eclipse.egit.gitflow.ui",
org.eclipse.egit.core.internal.gerrit;version="4.0.0";x-friends:="org.eclipse.egit.ui",
org.eclipse.egit.core.internal.indexdiff;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.ui.test",
- org.eclipse.egit.core.internal.job;version="4.0.0";x-friends:="org.eclipse.egit.ui",
+ org.eclipse.egit.core.internal.job;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.gitflow.ui,org.eclipse.egit.gitflow",
org.eclipse.egit.core.internal.merge;version="4.0.0";x-internal:=true,
org.eclipse.egit.core.internal.rebase;version="4.0.0";x-friends:="org.eclipse.egit.ui",
org.eclipse.egit.core.internal.storage;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.core.test",
org.eclipse.egit.core.internal.trace;version="4.0.0";x-internal:=true,
org.eclipse.egit.core.internal.util;version="4.0.0";x-friends:="org.eclipse.egit.ui",
- org.eclipse.egit.core.op;version="4.0.0";x-friends:="org.eclipse.egit.ui.test,org.eclipse.egit.ui",
- org.eclipse.egit.core.project;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.ui.test",
+ org.eclipse.egit.core.op;version="4.0.0";
+ x-friends:="org.eclipse.egit.ui.test,
+ org.eclipse.egit.ui,
+ org.eclipse.egit.gitflow,
+ org.eclipse.egit.gitflow.test,
+ org.eclipse.egit.gitflow.ui",
+ org.eclipse.egit.core.project;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.ui.test,org.eclipse.egit.gitflow.ui",
org.eclipse.egit.core.securestorage;version="4.0.0";x-friends:="org.eclipse.egit.ui",
org.eclipse.egit.core.storage;version="4.0.0";uses:="org.eclipse.core.runtime,org.eclipse.jgit.lib,org.eclipse.core.resources",
org.eclipse.egit.core.synchronize;version="4.0.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.ui.test",
diff --git a/org.eclipse.egit.gitflow-feature/.gitignore b/org.eclipse.egit.gitflow-feature/.gitignore
new file mode 100644
index 000000000..b83d22266
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/org.eclipse.egit.gitflow-feature/.project b/org.eclipse.egit.gitflow-feature/.project
new file mode 100644
index 000000000..65486b95c
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.gitflow-feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..d4ff695e8
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:03 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..dfc3779a1
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:53 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.egit.gitflow-feature/build.properties b/org.eclipse.egit.gitflow-feature/build.properties
new file mode 100644
index 000000000..9ce9b4ff6
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/build.properties
@@ -0,0 +1,4 @@
+bin.includes = feature.xml,\
+ feature.properties,\
+ epl-v10.html,\
+ license.html
diff --git a/org.eclipse.egit.gitflow-feature/epl-v10.html b/org.eclipse.egit.gitflow-feature/epl-v10.html
new file mode 100644
index 000000000..6d5bbe86f
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/epl-v10.html
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>&quot;Contribution&quot; means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>&quot;Contributor&quot; means any person or entity that distributes
+the Program.</p>
+
+<p>&quot;Licensed Patents&quot; mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>&quot;Program&quot; means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>&quot;Recipient&quot; means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+(&quot;Commercial Contributor&quot;) hereby agrees to defend and
+indemnify every other Contributor (&quot;Indemnified Contributor&quot;)
+against any losses, damages and costs (collectively &quot;Losses&quot;)
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+</body>
+
+</html>
diff --git a/org.eclipse.egit.gitflow-feature/feature.properties b/org.eclipse.egit.gitflow-feature/feature.properties
new file mode 100644
index 000000000..693c47a7e
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/feature.properties
@@ -0,0 +1,158 @@
+###############################################################################
+# Copyright (c) 2000, 2010 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+featureName=Eclipse EGit GitFlow
+providerName=Eclipse EGit GitFlow
+
+updateSiteName=Eclipse EGit GitFlow Update Site
+
+# description property - text of the "Feature Descrption"
+description=\
+A GitFlow extension to Eclipse Git Team provider.\n
+################ end of description property ##################################
+
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2015 Max Hohenegger.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 9, 2014\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+ 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+ the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+ extending or updating the functionality of an Eclipse-based product.\n\
+ 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+ Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+ 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+ govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+ Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+ with the Specification. Such Installable Software Agreement must inform the user of the\n\
+ terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+ the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+ indication of agreement by the user, the provisioning Technology will complete installation\n\
+ of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
+
diff --git a/org.eclipse.egit.gitflow-feature/feature.xml b/org.eclipse.egit.gitflow-feature/feature.xml
new file mode 100644
index 000000000..a499882ae
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/feature.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.egit.gitflow.feature"
+ label="%featureName"
+ version="4.0.0.qualifier"
+ provider-name="%providerName"
+ plugin="org.eclipse.egit.gitflow">
+
+ <description url="http://www.eclipse.org/egit/">
+ %description
+ </description>
+
+ <copyright>
+ %copyright
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <url>
+ <update label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+ <discovery label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+ </url>
+
+ <requires>
+ <import feature="org.eclipse.jgit" version="4.0.0" match="equivalent"/>
+ <import plugin="org.eclipse.egit.core" version="4.0.0" match="equivalent"/>
+ <import plugin="org.eclipse.egit.ui" version="4.0.0" match="equivalent"/>
+ </requires>
+
+ <plugin
+ id="org.eclipse.egit.gitflow"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.egit.gitflow.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/org.eclipse.egit.gitflow-feature/license.html b/org.eclipse.egit.gitflow-feature/license.html
new file mode 100644
index 000000000..95ad95e77
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/license.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 9, 2014</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
+Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named "src" of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+ ("Specification").</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+ <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology
+ on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based
+ product.</li>
+ <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+ accessed and copied to the Target Machine.</li>
+ <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+ Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target
+ Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+ the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+ indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+
+
+</body></html> \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow-feature/pom.xml b/org.eclipse.egit.gitflow-feature/pom.xml
new file mode 100644
index 000000000..5c48d62bd
--- /dev/null
+++ b/org.eclipse.egit.gitflow-feature/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.egit</groupId>
+ <artifactId>egit-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.eclipse.egit.feature</groupId>
+ <artifactId>org.eclipse.egit.gitflow.feature</artifactId>
+ <packaging>eclipse-feature</packaging>
+
+ <name>Eclipse EGit Gitflow Feature</name>
+
+</project>
diff --git a/org.eclipse.egit.gitflow.test/.classpath b/org.eclipse.egit.gitflow.test/.classpath
new file mode 100644
index 000000000..46cec6ed2
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src/"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.egit.gitflow.test/.project b/org.eclipse.egit.gitflow.test/.project
new file mode 100644
index 000000000..8bd4bc87a
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.gitflow.test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..84e44d8d3
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:12 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..c8f089af7
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:45 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..f81872c06
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,393 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
+org.eclipse.jdt.core.compiler.problem.deadCode=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..c336cce6e
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_JGit Format
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.egit.gitflow.test/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.egit.gitflow.test/META-INF/MANIFEST.MF b/org.eclipse.egit.gitflow.test/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..2d418ec1b
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GitFlow Test
+Bundle-SymbolicName: org.eclipse.egit.gitflow.test;singleton:=true
+Bundle-Version: 4.0.0.qualifier
+Fragment-Host: org.eclipse.egit.gitflow
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Import-Package: org.eclipse.egit.core;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.test;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.junit;version="[4.0.0,4.1.0)",
+ org.junit;version="[4.3.0,5.0.0)"
diff --git a/org.eclipse.egit.gitflow.test/build.properties b/org.eclipse.egit.gitflow.test/build.properties
new file mode 100644
index 000000000..b107977f4
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/build.properties
@@ -0,0 +1,3 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .
diff --git a/org.eclipse.egit.gitflow.test/org.eclipse.egit.gitflow--All-Tests.launch b/org.eclipse.egit.gitflow.test/org.eclipse.egit.gitflow--All-Tests.launch
new file mode 100644
index 000000000..97ba42d78
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/org.eclipse.egit.gitflow--All-Tests.launch
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="append.args" value="true"/>
+<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="false"/>
+<booleanAttribute key="automaticValidate" value="true"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="false"/>
+<booleanAttribute key="includeOptional" value="false"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.egit.gitflow.test"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="com.mountainminds.eclemma.ui.launchGroup.coverage"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.egit.gitflow.test"/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.egit.gitflow.test"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.equinox.p2.director.app.product"/>
+<booleanAttribute key="run_in_ui_thread" value="false"/>
+<stringAttribute key="selected_target_plugins" value="com.ibm.icu@default:default,com.jcraft.jsch@default:default,javaewah@default:default,javax.xml@default:default,org.apache.log4j*1.2.15.v201012070815@default:default,org.eclipse.compare.core@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.java7@default:false,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources.win32.x86_64@default:false,org.eclipse.core.resources@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.security.win32.x86_64@default:false,org.eclipse.equinox.security@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.jdt.core@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.jdt.launching@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi@-1:true,org.eclipse.team.core@default:default,org.eclipse.text@default:default,org.hamcrest.core*1.3.0.v201303031735@default:default,org.hamcrest.integration*1.3.0.v201305210900@default:default,org.hamcrest.library*1.3.0.v201305281000@default:default,org.hamcrest.text@default:default,org.hamcrest@default:default,org.junit@default:default,org.mockito@default:default,org.objenesis@default:default,org.slf4j.api@default:default,org.slf4j.impl.log4j12@default:false"/>
+<stringAttribute key="selected_workspace_plugins" value="org.eclipse.egit.core.test@default:false,org.eclipse.egit.core@default:default,org.eclipse.egit.gitflow.test@default:false,org.eclipse.egit.gitflow@default:default,org.eclipse.egit@default:default,org.eclipse.jgit.junit@default:default,org.eclipse.jgit@default:default"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="false"/>
+</launchConfiguration>
diff --git a/org.eclipse.egit.gitflow.test/pom.xml b/org.eclipse.egit.gitflow.test/pom.xml
new file mode 100644
index 000000000..cc0161e68
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014, Max Hohenegger <eclipse@hohenegger.eu>
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.egit</groupId>
+ <artifactId>egit-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.egit.gitflow.test</artifactId>
+ <packaging>eclipse-test-plugin</packaging>
+
+ <name>GitFlow Test Plug-in</name>
+
+ <properties>
+ <coretest.vmparams></coretest.vmparams>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-surefire-plugin</artifactId>
+ <version>${tycho-version}</version>
+ <configuration>
+ <!--excludes> <exclude>**/Test*.class</exclude> </excludes -->
+ <useUIHarness>false</useUIHarness>
+ <useUIThread>false</useUIThread>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>target-platform-configuration</artifactId>
+ <configuration>
+ <dependency-resolution>
+ <extraRequirements>
+ <requirement>
+ <type>eclipse-feature</type>
+ <id>org.eclipse.egit</id>
+ <versionRange>0.0.0</versionRange>
+ </requirement>
+ </extraRequirements>
+ </dependency-resolution>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/BranchNameValidatorTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/BranchNameValidatorTest.java
new file mode 100644
index 000000000..1aed342b0
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/BranchNameValidatorTest.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import static org.eclipse.egit.gitflow.BranchNameValidator.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.egit.gitflow.op.AbstractGitFlowOperationTest;
+import org.eclipse.egit.gitflow.op.FeatureStartOperation;
+import org.eclipse.egit.gitflow.op.InitOperation;
+import org.eclipse.egit.gitflow.op.ReleaseStartOperation;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class BranchNameValidatorTest extends AbstractGitFlowOperationTest {
+
+ @Test
+ public void testFeatureExists() throws Exception {
+ testRepository
+ .createInitialCommit("testInitOperation\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+
+ assertTrue(featureExists(gfRepo, MY_FEATURE));
+ }
+
+ @Test
+ public void testReleaseExists() throws Exception {
+ testRepository
+ .createInitialCommit("testInitOperation\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ assertTrue(releaseExists(gfRepo, MY_RELEASE));
+ }
+
+ @Test
+ public void testBranchNotExists() throws Exception {
+ testRepository
+ .createInitialCommit("testInitOperation\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ assertFalse(releaseExists(gfRepo, "notThere"));
+ }
+
+ @Test
+ public void testBranchNameValid() throws Exception {
+ assertTrue(isBranchNameValid(MY_RELEASE));
+ assertTrue(isBranchNameValid(MY_FEATURE));
+ assertFalse(isBranchNameValid("/"));
+ assertFalse(isBranchNameValid(""));
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryConfigTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryConfigTest.java
new file mode 100644
index 000000000..c51b7e0fd
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryConfigTest.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.egit.gitflow.op.AbstractDualRepositoryTestCase;
+import org.eclipse.egit.gitflow.op.InitOperation;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class GitFlowRepositoryConfigTest extends AbstractDualRepositoryTestCase {
+ @Test
+ public void testIsInitialized() throws Exception {
+ repository1
+ .createInitialCommit("testIsInitialized\n\nfirst commit\n");
+
+ Repository repository = repository2.getRepository();
+ GitFlowConfig gitFlowConfig = new GitFlowConfig(repository);
+
+ assertFalse(gitFlowConfig.isInitialized());
+
+ new InitOperation(repository).execute(null);
+
+ assertTrue(gitFlowConfig.isInitialized());
+ }
+
+ @Test
+ public void testHasDefaultRemote() throws Exception {
+ repository1
+ .createInitialCommit("testHasDefaultRemote\n\nfirst commit\n");
+
+ Repository repository = repository1.getRepository();
+ GitFlowConfig gitFlowConfig = new GitFlowConfig(repository);
+
+ assertFalse(gitFlowConfig.hasDefaultRemote());
+
+ GitFlowConfig gitFlowConfig2 = new GitFlowConfig(repository2.getRepository());
+ assertTrue(gitFlowConfig2.hasDefaultRemote());
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryTest.java
new file mode 100644
index 000000000..62a8fab98
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/GitFlowRepositoryTest.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import static org.eclipse.egit.gitflow.GitFlowDefaults.DEVELOP;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.FEATURE_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.HOTFIX_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.RELEASE_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.VERSION_TAG;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.egit.gitflow.op.AbstractDualRepositoryTestCase;
+import org.eclipse.egit.gitflow.op.FeatureStartOperation;
+import org.eclipse.egit.gitflow.op.HotfixStartOperation;
+import org.eclipse.egit.gitflow.op.InitOperation;
+import org.eclipse.egit.gitflow.op.ReleaseFinishOperation;
+import org.eclipse.egit.gitflow.op.ReleaseStartOperation;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class GitFlowRepositoryTest extends AbstractDualRepositoryTestCase {
+ @Test
+ public void testIsMaster() throws Exception {
+ repository1.createInitialCommit("testIsMaster\n\nfirst commit\n");
+
+ Repository repository = repository2.getRepository();
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ assertTrue(gfRepo.isMaster());
+
+ new InitOperation(repository).execute(null);
+
+ assertFalse(gfRepo.isMaster());
+ }
+
+ @Test
+ public void testGetFeatureBranches() throws Exception {
+ repository1
+ .createInitialCommit("testGetFeatureBranches\n\nfirst commit\n");
+
+ Repository repository = repository1.getRepository();
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new InitOperation(repository).execute(null);
+
+ assertTrue(gfRepo.getFeatureBranches().isEmpty());
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+
+ assertEquals(R_HEADS + gfRepo.getConfig().getFeaturePrefix()
+ + MY_FEATURE, gfRepo.getFeatureBranches().get(0).getName());
+ }
+
+ @Test
+ public void testGetReleaseBranches() throws Exception {
+ repository1
+ .createInitialCommit("testGetReleaseBranches\n\nfirst commit\n");
+
+ Repository repository = repository1.getRepository();
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new InitOperation(repository).execute(null);
+
+ assertTrue(gfRepo.getReleaseBranches().isEmpty());
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ assertEquals(R_HEADS + gfRepo.getConfig().getReleasePrefix()
+ + MY_RELEASE, gfRepo.getReleaseBranches().get(0).getName());
+ }
+
+ @Test
+ public void testGetHotfixBranches() throws Exception {
+ repository1
+ .createInitialCommit("testGetHotfixBranches\n\nfirst commit\n");
+
+ Repository repository = repository1.getRepository();
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new InitOperation(repository).execute(null);
+
+ assertTrue(gfRepo.getHotfixBranches().isEmpty());
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ new ReleaseFinishOperation(gfRepo, MY_RELEASE).execute(null);
+ new HotfixStartOperation(gfRepo, MY_HOTFIX).execute(null);
+
+ assertEquals(
+ R_HEADS + gfRepo.getConfig().getHotfixPrefix() + MY_HOTFIX,
+ gfRepo.getHotfixBranches().get(0).getName());
+ }
+
+ @Test
+ public void testGetFeatureBranchName() throws Exception {
+ repository1
+ .createInitialCommit("testGetFeatureBranchName\n\nfirst commit\n");
+
+ Repository repository = repository1.getRepository();
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new InitOperation(repository, DEVELOP, GitFlowDefaults.MASTER,
+ FEATURE_PREFIX, RELEASE_PREFIX, HOTFIX_PREFIX, VERSION_TAG)
+ .execute(null);
+
+ assertTrue(gfRepo.getFeatureBranches().isEmpty());
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+
+ Ref actualFeatureRef = repository.getRef(R_HEADS
+ + gfRepo.getConfig().getFeaturePrefix() + MY_FEATURE);
+ assertEquals(MY_FEATURE, gfRepo.getFeatureBranchName(actualFeatureRef));
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractDualRepositoryTestCase.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractDualRepositoryTestCase.java
new file mode 100644
index 000000000..0d7bd1d9f
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractDualRepositoryTestCase.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.DOT_GIT;
+import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.core.op.CloneOperation;
+import org.eclipse.egit.core.test.DualRepositoryTestCase;
+import org.eclipse.egit.core.test.TestRepository;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.URIish;
+import org.junit.Before;
+
+public class AbstractDualRepositoryTestCase extends DualRepositoryTestCase {
+ protected static final String MY_FEATURE = "myFeature";
+
+ protected static final String MY_MASTER = "master";
+
+ protected static final String MY_RELEASE = "myRelease";
+
+ protected static final String MY_VERSION_TAG = "v";
+
+ protected static final String MY_HOTFIX = "myHotfix";
+
+ private File workdir;
+
+ private File workdir2;
+
+ String projectName = "FeaturePublishTest";
+
+ @Override
+ @Before
+ public void beforeTestCase() throws Exception {
+ workdir = testUtils.createTempDir("Repository1");
+ workdir2 = testUtils.createTempDir("Repository2");
+
+ repository1 = new TestRepository(new File(workdir, DOT_GIT));
+
+ repository1.createInitialCommit("setUp");
+
+ Repository repository = repository1.getRepository();
+ new InitOperation(repository).execute(null);
+
+ // now we create a project in repo1
+ IProject project = testUtils.createProjectInLocalFileSystem(workdir,
+ projectName);
+ testUtils.addFileToProject(project, "folder1/file1.txt", "Hello world");
+
+ repository1.connect(project);
+ repository1.trackAllFiles(project);
+ repository1.commit("Initial commit");
+
+ // let's get rid of the project
+ project.delete(false, false, null);
+
+ // let's clone repository1 to repository2
+ URIish uri = repository1.getUri();
+ CloneOperation clop = new CloneOperation(uri, true, null, workdir2,
+ R_HEADS + MY_MASTER, DEFAULT_REMOTE_NAME, 0);
+ clop.run(null);
+
+ Repository repo2 = Activator.getDefault().getRepositoryCache()
+ .lookupRepository(new File(workdir2, DOT_GIT));
+ repository2 = new TestRepository(repo2);
+ new InitOperation(repository).execute(null);
+ }
+
+ protected void assertCommitArrivedAtRemote(RevCommit branchCommit,
+ Repository remote) throws CoreException {
+ GitFlowRepository gfRepo = new GitFlowRepository(remote);
+ BranchOperation checkoutOperation = new BranchOperation(remote,
+ gfRepo.getConfig().getFullFeatureBranchName(MY_FEATURE));
+ checkoutOperation.execute(null);
+ RevCommit developHead = findHead(remote);
+ assertEquals(branchCommit, developHead);
+ }
+
+ protected RevCommit findHead(Repository repo) {
+ try (RevWalk walk = new RevWalk(repo)) {
+ try {
+ ObjectId head = repo.resolve(HEAD);
+ return walk.parseCommit(head);
+ } catch (RevisionSyntaxException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ protected String getRemoteName(GitFlowRepository gfRepo, String featureName) {
+ return gfRepo.getConfig().getRemoteName(featureName);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperationTest.java
new file mode 100644
index 000000000..5d2bc10b5
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperationTest.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Repository;
+
+abstract public class AbstractFeatureOperationTest extends
+ AbstractGitFlowOperationTest {
+
+ protected GitFlowRepository init(String initalCommit) throws Exception {
+ testRepository.createInitialCommit(initalCommit);
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ return new GitFlowRepository(repository);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractGitFlowOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractGitFlowOperationTest.java
new file mode 100644
index 000000000..bd89a7e55
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/AbstractGitFlowOperationTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.jgit.lib.Constants.DOT_GIT;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.egit.core.test.TestRepository;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.junit.After;
+import org.junit.Before;
+
+abstract public class AbstractGitFlowOperationTest extends GitTestCase {
+ protected TestRepository testRepository;
+
+ protected static final String MY_FEATURE = "myFeature";
+
+ protected static final String MY_RELEASE = "myRelease";
+
+ protected static final String MY_VERSION_TAG = "v";
+
+ protected static final String MY_MASTER = "master";
+
+ protected static final String MY_HOTFIX = "myHotfix";
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ gitDir = new File(project.getProject().getLocationURI().getPath(),
+ DOT_GIT);
+ testRepository = new TestRepository(gitDir);
+ testRepository.connect(project.getProject());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ testRepository.dispose();
+ super.tearDown();
+ }
+
+ protected Ref findBranch(Repository repository, String branchName)
+ throws IOException {
+ return repository.getRef(R_HEADS + branchName);
+ }
+
+ protected RevCommit parseCommit(Repository repo, AnyObjectId id)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ try (RevWalk revWalk = new RevWalk(repo)) {
+ return revWalk.parseCommit(id);
+ }
+ }
+
+ protected RevCommit addFileAndCommit(String fileName, String commitMessage)
+ throws Exception, UnsupportedEncodingException {
+ IFile file = project.createFile(fileName,
+ "Hello, world".getBytes("UTF-8"));
+ return testRepository.addAndCommit(project.project,
+ new File(file.getLocationURI()), commitMessage);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperationTest.java
new file mode 100644
index 000000000..97c0c5a42
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperationTest.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.egit.core.op.PushOperationResult;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PushResult;
+import org.junit.Test;
+
+public class CurrentBranchPublishOperationTest extends AbstractDualRepositoryTestCase {
+ @Test
+ public void testFeaturePublish() throws Exception {
+ new InitOperation(repository2.getRepository()).execute(null);
+ GitFlowRepository gfRepo2 = new GitFlowRepository(
+ repository2.getRepository());
+
+ new FeatureStartOperation(gfRepo2, MY_FEATURE).execute(null);
+ RevCommit branchCommit = repository2
+ .createInitialCommit("testFeaturePublish");
+ CurrentBranchPublishOperation featurePublishOperation = new CurrentBranchPublishOperation(
+ gfRepo2, 0);
+ featurePublishOperation.execute(null);
+ PushOperationResult result = featurePublishOperation
+ .getOperationResult();
+
+ assertTrue(result.isSuccessfulConnection(repository1.getUri()));
+ PushResult pushResult = result.getPushResult(repository1.getUri());
+ assertEquals(RefUpdate.Result.NEW, pushResult.getTrackingRefUpdates()
+ .iterator().next().getResult());
+
+ assertCommitArrivedAtRemote(branchCommit, repository1.getRepository());
+
+ // config updated?
+ assertEquals(DEFAULT_REMOTE_NAME, getRemoteName(gfRepo2, MY_FEATURE));
+ assertEquals(R_HEADS + gfRepo2.getConfig().getFeatureBranchName(MY_FEATURE),
+ gfRepo2.getUpstreamBranchName(MY_FEATURE));
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperationTest.java
new file mode 100644
index 000000000..1dba8b567
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperationTest.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.api.CheckoutResult.Status;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class FeatureCheckoutOperationTest extends AbstractFeatureOperationTest {
+ @Test
+ public void testFeatureCheckout() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureCheckout\n\nfirst commit\n");
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ new BranchOperation(repository, gfRepo.getConfig().getDevelop()).execute(null);
+
+ new FeatureCheckoutOperation(gfRepo, MY_FEATURE).execute(null);
+
+ assertEquals(gfRepo.getConfig().getFullFeatureBranchName(MY_FEATURE),
+ repository.getFullBranch());
+ }
+
+ @Test
+ public void testFeatureCheckoutConflicts() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureCheckoutConflicts\n\nfirst commit\n");
+
+ // setup something we can modify later
+ IFile file = testUtils.addFileToProject(project.getProject(),
+ "folder1/file1.txt", "Hello world");
+ testRepository.connect(project.getProject());
+ testRepository.trackAllFiles(project.getProject());
+ testRepository.commit("Initial commit");
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ // modify on first branch
+ testUtils.changeContentOfFile(project.getProject(), file,
+ "Hello Feature");
+ testRepository.addToIndex(file);
+ testRepository.commit("Feature commit");
+ new BranchOperation(repository, gfRepo.getConfig().getDevelop()).execute(null);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ // modify on second branch
+ testUtils.changeContentOfFile(project.getProject(), file,
+ "Hello Develop");
+ testRepository.addToIndex(file);
+
+ FeatureCheckoutOperation featureCheckoutOperation = new FeatureCheckoutOperation(
+ gfRepo, MY_FEATURE);
+ featureCheckoutOperation.execute(null);
+
+ assertEquals(Status.CONFLICTS, featureCheckoutOperation.getResult()
+ .getStatus());
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureFinishOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureFinishOperationTest.java
new file mode 100644
index 000000000..034c8ef7c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureFinishOperationTest.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class FeatureFinishOperationTest extends AbstractFeatureOperationTest {
+ @Test
+ public void testFeatureFinish() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureFinish\n\nfirst commit\n");
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ new FeatureFinishOperation(gfRepo).execute(null);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ String branchName = gfRepo.getConfig().getFeatureBranchName(MY_FEATURE);
+ RevCommit branchCommit = testRepository
+ .createInitialCommit("testFeatureFinish\n\nbranch commit\n");
+ assertEquals(findBranch(repository, branchName), null);
+
+ RevCommit developHead = gfRepo.findHead();
+ assertEquals(branchCommit, developHead);
+ }
+
+ @Test(expected = WrongGitFlowStateException.class)
+ public void testFeatureFinishFail() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureFinishFail\n\nfirst commit\n");
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ new BranchOperation(repository, gfRepo.getConfig().getDevelop()).execute(null);
+ new FeatureFinishOperation(gfRepo).execute(null);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureListOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureListOperationTest.java
new file mode 100644
index 000000000..1591bdab2
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureListOperationTest.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import static org.eclipse.jgit.lib.Constants.*;
+import org.eclipse.jgit.lib.Ref;
+import org.junit.Test;
+
+import static org.eclipse.egit.gitflow.op.AbstractFeatureOperation.*;
+
+public class FeatureListOperationTest extends AbstractDualRepositoryTestCase {
+ @Test
+ public void testFeatureList() throws Exception {
+ GitFlowRepository gfRepo1 = new GitFlowRepository(
+ repository1.getRepository());
+ GitFlowRepository gfRepo2 = new GitFlowRepository(
+ repository2.getRepository());
+ new FeatureStartOperation(gfRepo1, MY_FEATURE).execute(null);
+
+ FeatureListOperation featureListOperation = new FeatureListOperation(
+ gfRepo2, 0);
+ featureListOperation.execute(null);
+ String name = gfRepo2.getConfig().getFullFeatureBranchName(MY_FEATURE);
+ assertNotNull(featureListOperation.getOperationResult()
+ .getAdvertisedRef(name));
+ List<Ref> result = featureListOperation.getResult();
+ assertEquals(1, result.size());
+ assertEquals(
+ R_REMOTES + DEFAULT_REMOTE_NAME + SEP
+ + gfRepo2.getConfig().getFeatureBranchName(MY_FEATURE),
+ result.get(0).getName());
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperationTest.java
new file mode 100644
index 000000000..54199c3fb
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperationTest.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.*;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.api.RebaseResult;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class FeatureRebaseOperationTest extends AbstractFeatureOperationTest {
+ @Test
+ public void testFeatureRebase() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureRebase\n\nfirst commit\n");
+ RevCommit initialCommit = gfRepo.findHead();
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ String branchCommitMessage = "adding first file on feature branch";
+ addFileAndCommit("theFile.txt", branchCommitMessage);
+
+ testRepository.checkoutBranch(gfRepo.getConfig().getDevelop());
+ RevCommit developCommit = addFileAndCommit("theOtherFile.txt",
+ "adding second file on develop branch");
+
+ new FeatureCheckoutOperation(gfRepo, MY_FEATURE).execute(null);
+ assertEquals(initialCommit, gfRepo.findHead().getParent(0));
+ FeatureRebaseOperation featureRebaseOperation = new FeatureRebaseOperation(
+ gfRepo);
+ featureRebaseOperation.execute(null);
+
+ RebaseResult res = featureRebaseOperation.getOperationResult();
+ assertEquals(RebaseResult.Status.OK, res.getStatus());
+
+ assertEquals(branchCommitMessage, gfRepo.findHead().getShortMessage());
+ assertEquals(developCommit,
+ parseCommit(repository, repository.resolve("HEAD^")));
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureStartOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureStartOperationTest.java
new file mode 100644
index 000000000..55771a711
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureStartOperationTest.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class FeatureStartOperationTest extends AbstractFeatureOperationTest {
+ @Test
+ public void testFeatureStart() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureStart\n\nfirst commit\n");
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+
+ assertEquals(gfRepo.getConfig().getFullFeatureBranchName(MY_FEATURE),
+ repository.getFullBranch());
+ }
+
+ @Test(expected = CoreException.class)
+ public void testFeatureStartFail() throws Exception {
+ Repository repository = testRepository.getRepository();
+ GitFlowRepository gfRepo = init("testFeatureStart\n\nfirst commit\n");
+
+ BranchOperation branchOperation = new BranchOperation(repository,
+ MY_MASTER);
+ branchOperation.execute(null);
+
+ new FeatureStartOperation(gfRepo, MY_FEATURE).execute(null);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureTrackOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureTrackOperationTest.java
new file mode 100644
index 000000000..47cee9fcc
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/FeatureTrackOperationTest.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.FetchResult;
+import org.junit.Test;
+
+public class FeatureTrackOperationTest extends AbstractDualRepositoryTestCase {
+ @Test
+ public void testFeatureTrack() throws Exception {
+ GitFlowRepository gfRepo1 = new GitFlowRepository(
+ repository1.getRepository());
+ GitFlowRepository gfRepo2 = new GitFlowRepository(
+ repository2.getRepository());
+ new FeatureStartOperation(gfRepo1, MY_FEATURE).execute(null);
+ RevCommit branchCommit = repository1
+ .createInitialCommit("testFeatureTrack");
+
+ FeatureTrackOperation featureTrackOperation = new FeatureTrackOperation(
+ gfRepo2, getFirstRemoteFeatureRef(gfRepo2));
+ featureTrackOperation.execute(null);
+ FetchResult operationResult = featureTrackOperation
+ .getOperationResult();
+ assertNotNull(operationResult.getAdvertisedRef(gfRepo2
+ .getConfig().getFullFeatureBranchName(MY_FEATURE)));
+ assertEquals(gfRepo2.getConfig().getFeatureBranchName(MY_FEATURE),
+ repository2.getRepository().getBranch());
+ assertEquals(branchCommit, findHead(repository2.getRepository()));
+
+ RevCommit localCommit = repository2
+ .createInitialCommit("testFeatureTrack2");
+ new CurrentBranchPublishOperation(gfRepo2, 0).execute(null);
+ assertEquals(localCommit, findHead(repository2.getRepository()));
+
+ // config updated?
+ assertEquals(DEFAULT_REMOTE_NAME, getRemoteName(gfRepo2, MY_FEATURE));
+ assertEquals(R_HEADS + gfRepo2.getConfig().getFeatureBranchName(MY_FEATURE),
+ gfRepo2.getUpstreamBranchName(MY_FEATURE));
+ }
+
+ private Ref getFirstRemoteFeatureRef(GitFlowRepository gfRepo)
+ throws CoreException {
+ FeatureListOperation featureListOperation = new FeatureListOperation(
+ gfRepo, 0);
+ featureListOperation.execute(null);
+ return featureListOperation.getResult().get(0);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixFinishOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixFinishOperationTest.java
new file mode 100644
index 000000000..f7121845f
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixFinishOperationTest.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.GitFlowDefaults.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.io.File;
+
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.api.MergeResult;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class HotfixFinishOperationTest extends AbstractGitFlowOperationTest {
+ @Test
+ public void testHotfixFinish() throws Exception {
+ testRepository
+ .createInitialCommit("testHotfixFinish\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new HotfixStartOperation(gfRepo, MY_HOTFIX).execute(null);
+
+ RevCommit branchCommit = testRepository
+ .createInitialCommit("testHotfixFinish\n\nbranch commit\n");
+
+ new HotfixFinishOperation(gfRepo).execute(null);
+
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ String branchName = gfRepo.getConfig().getHotfixBranchName(MY_HOTFIX);
+
+ // tag created?
+ assertEquals(branchCommit, gfRepo.findCommitForTag(MY_HOTFIX));
+
+ // branch removed?
+ assertEquals(findBranch(repository, branchName), null);
+
+ RevCommit developHead = gfRepo.findHead(DEVELOP);
+ assertEquals(branchCommit, developHead);
+
+ RevCommit masterHead = gfRepo.findHead(MY_MASTER);
+ assertEquals(branchCommit, masterHead);
+ }
+
+ @Test
+ public void testMergeToDevelopFail() throws Exception {
+ testRepository
+ .createInitialCommit("testMergeToDevelopFail\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ // setup something we can modify later
+ File file = testRepository.createFile(project.getProject(),
+ "folder1/file1.txt");
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ testRepository.appendContentAndCommit(project.getProject(), file,
+ "Hello Release", "Release Commit");
+
+ new ReleaseFinishOperation(gfRepo).execute(null);
+
+ new HotfixStartOperation(gfRepo, MY_HOTFIX).execute(null);
+ // modify on first branch
+ RevCommit hotfixCommit = testRepository.appendContentAndCommit(
+ project.getProject(), file, "Hello Hotfix", "Hotfix Commit");
+ new BranchOperation(repository, gfRepo.getConfig().getDevelop()).execute(null);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ // modify on second branch
+ RevCommit developCommit = testRepository.appendContentAndCommit(
+ project.getProject(), file, "Hello Develop", "Develop Commit");
+
+ String branchName = gfRepo.getConfig().getHotfixBranchName(MY_HOTFIX);
+ new BranchOperation(repository, branchName).execute(null);
+ HotfixFinishOperation hotfixFinishOperation = new HotfixFinishOperation(
+ gfRepo);
+ hotfixFinishOperation.execute(null);
+
+ // tag not created?
+ assertNotEquals(hotfixCommit, gfRepo.findCommitForTag(MY_HOTFIX));
+
+ // branch not removed?
+ assertNotEquals(findBranch(repository, branchName), null);
+
+ // not merged on develop => conflict
+ RevCommit developHead = gfRepo.findHead(DEVELOP);
+ assertEquals(developCommit, developHead);
+ assertEquals(MergeResult.MergeStatus.CONFLICTING, hotfixFinishOperation
+ .getOperationResult().getMergeStatus());
+
+ // merged on master
+ RevCommit masterHead = gfRepo.findHead(MY_MASTER);
+ assertEquals(hotfixCommit, masterHead);
+
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixStartOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixStartOperationTest.java
new file mode 100644
index 000000000..77ea7da9e
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/HotfixStartOperationTest.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Test;
+
+public class HotfixStartOperationTest extends AbstractGitFlowOperationTest {
+ @Test
+ public void testHotfixStart() throws Exception {
+ testRepository.createInitialCommit("testHotfixStart\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new HotfixStartOperation(gfRepo, MY_HOTFIX).execute(null);
+
+ assertEquals(gfRepo.getConfig().getFullHotfixBranchName(MY_HOTFIX),
+ repository.getFullBranch());
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/InitOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/InitOperationTest.java
new file mode 100644
index 000000000..0f0d8f012
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/InitOperationTest.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.*;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+
+import static org.eclipse.egit.gitflow.GitFlowConfig.*;
+
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.junit.Test;
+
+public class InitOperationTest extends AbstractGitFlowOperationTest {
+
+ @Test
+ public void testInit() throws Exception {
+ testRepository
+ .createInitialCommit("testInitOperation\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ InitOperation initOperation = new InitOperation(repository);
+ initOperation.execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ assertEquals(FEATURE_PREFIX, getPrefix(repository, FEATURE_KEY));
+ assertEquals(RELEASE_PREFIX, getPrefix(repository, RELEASE_KEY));
+ assertEquals(HOTFIX_PREFIX, getPrefix(repository, HOTFIX_KEY));
+ assertEquals(VERSION_TAG, getPrefix(repository, VERSION_TAG_KEY));
+ assertEquals(DEVELOP, getBranch(repository, DEVELOP_KEY));
+ assertEquals(MASTER, getBranch(repository, MASTER_KEY));
+ }
+
+ private String getPrefix(Repository repository, String prefixName) {
+ StoredConfig config = repository.getConfig();
+ return config.getString(GITFLOW_SECTION, PREFIX_SECTION, prefixName);
+ }
+
+ private String getBranch(Repository repository, String branch) {
+ StoredConfig config = repository.getConfig();
+ return config.getString(GITFLOW_SECTION, BRANCH_SECTION, branch);
+ }
+
+ @Test
+ public void testInitEmptyRepository() throws Exception {
+ Repository repository = testRepository.getRepository();
+ InitOperation initOperation = new InitOperation(repository);
+ initOperation.execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperationTest.java
new file mode 100644
index 000000000..7637870c9
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperationTest.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.GitFlowDefaults.DEVELOP;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.FEATURE_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.HOTFIX_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.MASTER;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.RELEASE_PREFIX;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoHeadException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class ReleaseFinishOperationTest extends AbstractGitFlowOperationTest {
+ @Test
+ public void testReleaseFinish() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseFinish\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository, DEVELOP, MASTER, FEATURE_PREFIX,
+ RELEASE_PREFIX, HOTFIX_PREFIX, MY_VERSION_TAG).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ RevCommit branchCommit = testRepository
+ .createInitialCommit("testReleaseFinish\n\nbranch commit\n");
+ new ReleaseFinishOperation(gfRepo).execute(null);
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+
+ String branchName = gfRepo.getConfig().getReleaseBranchName(MY_RELEASE);
+ // tag created?
+ assertEquals(branchCommit,
+ gfRepo.findCommitForTag(MY_VERSION_TAG + MY_RELEASE));
+ // branch removed?
+ assertEquals(findBranch(repository, branchName), null);
+
+ RevCommit developHead = gfRepo.findHead();
+ assertEquals(branchCommit, developHead);
+
+ RevCommit masterHead = gfRepo.findHead(MY_MASTER);
+ assertEquals(branchCommit, masterHead);
+ }
+
+ @Test
+ public void testReleaseFinishFail() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseFinishFail\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ new BranchOperation(repository, gfRepo.getConfig().getDevelop()).execute(null);
+
+ try {
+ new ReleaseFinishOperation(gfRepo).execute(null);
+ fail();
+ } catch (WrongGitFlowStateException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testReleaseTagWithWrongReferenceExists() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseTagExists\n\nfirst commit\n");
+ testRepository
+ .createInitialCommit("testReleaseTagExists\n\nsecond commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ RevCommit next = getPreviousCommit(repository, 1);
+ ReleaseFinishOperation releaseFinishOperation = new ReleaseFinishOperation(
+ gfRepo);
+ releaseFinishOperation.createTag(null, next, MY_RELEASE, "irrelevant");
+
+ try {
+ releaseFinishOperation.execute(null);
+ fail();
+ } catch (CoreException e) {
+ assertFalse(e.getStatus().isOK());
+ }
+ }
+
+ @Test
+ public void testReleaseTagWithCorrectReferenceExists() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseTagExists\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ RevCommit next = getPreviousCommit(repository, 0);
+ ReleaseFinishOperation releaseFinishOperation = new ReleaseFinishOperation(
+ gfRepo);
+ releaseFinishOperation.createTag(null, next, MY_RELEASE, "irrelevant");
+ releaseFinishOperation.execute(null);
+ }
+
+ private RevCommit getPreviousCommit(Repository repository, int count)
+ throws GitAPIException, NoHeadException {
+ Iterable<RevCommit> logs = Git.wrap(repository).log().call();
+ Iterator<RevCommit> i = logs.iterator();
+ for (int j = 0; j < count; j++) {
+ i.next();
+ }
+ RevCommit next = i.next();
+ return next;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseStartOperationTest.java b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseStartOperationTest.java
new file mode 100644
index 000000000..53f9a0f2e
--- /dev/null
+++ b/org.eclipse.egit.gitflow.test/src/org/eclipse/egit/gitflow/op/ReleaseStartOperationTest.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.op.TagOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.TagBuilder;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class ReleaseStartOperationTest extends AbstractGitFlowOperationTest {
+ @Test
+ public void testReleaseBranchCreated() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseStart\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ assertEquals(gfRepo.getConfig().getFullReleaseBranchName(MY_RELEASE),
+ repository.getFullBranch());
+ }
+
+ @Test
+ public void testReleaseStartWithContent() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseStartWithContent\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ testUtils.addFileToProject(project.getProject(), "folder1/file1.txt",
+ "Hello world");
+ testRepository.connect(project.getProject());
+ testRepository.trackAllFiles(project.getProject());
+ RevCommit developCommit = testRepository.commit("Initial commit");
+
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+
+ RevCommit releaseHead = gfRepo.findHead(gfRepo
+ .getConfig().getReleaseBranchName(MY_RELEASE));
+ assertEquals(developCommit, releaseHead);
+ }
+
+ @Test
+ public void testReleaseStartFailed() throws Exception {
+ testRepository
+ .createInitialCommit("testReleaseStart\n\nfirst commit\n");
+
+ Repository repository = testRepository.getRepository();
+ new InitOperation(repository).execute(null);
+ GitFlowRepository gfRepo = new GitFlowRepository(repository);
+
+ createTag(gfRepo.findHead(), MY_RELEASE, "irrelevant", repository);
+
+ try {
+ new ReleaseStartOperation(gfRepo, MY_RELEASE).execute(null);
+ fail();
+ } catch (CoreException e) {
+ assertEquals(gfRepo.getConfig().getDevelopFull(), repository.getFullBranch());
+ }
+ }
+
+ protected void createTag(RevCommit head, String name, String message,
+ Repository repository) throws CoreException {
+ TagBuilder tag = new TagBuilder();
+ tag.setTag(name);
+ tag.setMessage(message);
+ tag.setObjectId(head);
+ new TagOperation(repository, tag, false).execute(null);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/.classpath b/org.eclipse.egit.gitflow.ui/.classpath
new file mode 100644
index 000000000..f2156e991
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.egit.gitflow.ui/.project b/org.eclipse.egit.gitflow.ui/.project
new file mode 100644
index 000000000..be30986ad
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.gitflow.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
+
diff --git a/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..99f26c020
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..dfc3779a1
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:53 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..448fcfd79
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,393 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
+org.eclipse.jdt.core.compiler.problem.deadCode=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..c336cce6e
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_JGit Format
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.egit.gitflow.ui/META-INF/MANIFEST.MF b/org.eclipse.egit.gitflow.ui/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..ba70137aa
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,32 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GitFlow UI
+Bundle-SymbolicName: org.eclipse.egit.gitflow.ui;singleton:=true
+Bundle-Version: 4.0.0.qualifier
+Bundle-Activator: org.eclipse.egit.gitflow.ui.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Bundle-Localization: plugin
+Import-Package: org.eclipse.egit.core;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.internal;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.internal.job;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.op;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.project;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.gitflow,
+ org.eclipse.egit.gitflow.op,
+ org.eclipse.egit.ui;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.ui.internal;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.ui.internal.branch;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.ui.internal.repository.tree;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.ui.internal.selection;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.api;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.api.errors;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.lib;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.revplot;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.revwalk;version="[4.0.0,4.1.0)"
+Require-Bundle: org.eclipse.core.jobs;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.team.ui;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.ui;bundle-version="[3.4.0,4.0.0)"
diff --git a/org.eclipse.egit.gitflow.ui/about.html b/org.eclipse.egit.gitflow.ui/about.html
new file mode 100644
index 000000000..a14d39be0
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>May 9, 2015</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.egit.gitflow.ui/build.properties b/org.eclipse.egit.gitflow.ui/build.properties
new file mode 100644
index 000000000..ff1f844c8
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ plugin.properties,\
+ about.html
diff --git a/org.eclipse.egit.gitflow.ui/plugin.properties b/org.eclipse.egit.gitflow.ui/plugin.properties
new file mode 100644
index 000000000..f10eb5d17
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/plugin.properties
@@ -0,0 +1,14 @@
+TeamGitFlowInit.name = Init Git Flow
+TeamGitFlowMenu.name = Git Flow
+TeamGitFlowFeatureStart.name = Start Feature
+TeamGitFlowFeatureFinish.name = Finish Feature
+TeamGitFlowReleaseStart.name = Start Release
+TeamGitFlowReleaseFinish.name = Finish Release
+TeamGitFlowFeaturePublish.name = Publish Feature
+TeamGitFlowReleasePublish.name = Publish Release
+TeamGitFlowHotfixPublish.name = Publish Hotfix
+TeamGitFlowFeatureTrack.name = Track Feature
+TeamGitFlowFeatureCheckout.name = Checkout Feature
+TeamGitFlowFeatureRebase.name = Rebase Feature
+TeamGitFlowHotfixStart.name = Start Hotfix
+TeamGitFlowHotfixFinish.name = Finish Hotfix
diff --git a/org.eclipse.egit.gitflow.ui/plugin.xml b/org.eclipse.egit.gitflow.ui/plugin.xml
new file mode 100644
index 000000000..e78a9159c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/plugin.xml
@@ -0,0 +1,743 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="popup:org.eclipse.egit.ui.RepositoriesView?before=group.open">
+ <separator
+ name="group.gitflow"
+ visible="true">
+ </separator>
+ </menuContribution>
+ </extension>
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="popup:org.eclipse.egit.ui.RepositoriesView?after=group.gitflow">
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.init"
+ label="%TeamGitFlowInit.name"
+ style="push">
+ <visibleWhen
+ checkEnabled="false">
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <not>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isInitialized">
+ </test>
+ </adapt>
+ </not>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.egit.ui.RepositoriesView?after=group.gitflow">
+ <menu
+ label="%TeamGitFlowMenu.name">
+ <visibleWhen
+ checkEnabled="false">
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isInitialized">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </visibleWhen>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureStart"
+ label="%TeamGitFlowFeatureStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureFinish"
+ label="%TeamGitFlowFeatureFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureRebase"
+ label="%TeamGitFlowFeatureRebase.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureCheckout"
+ label="%TeamGitFlowFeatureCheckout.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureTrack"
+ label="%TeamGitFlowFeatureTrack.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featurePublish"
+ label="%TeamGitFlowFeaturePublish.name"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.egit.gitflow.ui.separator1"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseStart"
+ label="%TeamGitFlowReleaseStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseFinish"
+ label="%TeamGitFlowReleaseFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releasePublish"
+ label="%TeamGitFlowReleasePublish.name"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.egit.gitflow.ui.separator2"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixStart"
+ label="%TeamGitFlowHotfixStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixFinish"
+ label="%TeamGitFlowHotfixFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixPublish"
+ label="%TeamGitFlowHotfixPublish.name"
+ style="push">
+ </command>
+ </menu>
+ </menuContribution>
+ <menuContribution
+ allPopups="false"
+ locationURI="popup:org.eclipse.egit.ui.historyPageContributions?after=additions">
+ <menu
+ label="%TeamGitFlowMenu.name">
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseStart"
+ label="%TeamGitFlowReleaseStart.name"
+ style="push">
+ </command>
+ </menu>
+ </menuContribution>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ categoryId="org.eclipse.egit.ui.commandCategory"
+ id="org.eclipse.egit.gitflow.ui.command.init"
+ name="%TeamGitFlowInit.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featureStart"
+ name="%TeamGitFlowFeatureStart.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featureFinish"
+ name="%TeamGitFlowFeatureFinish.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.releaseStart"
+ name="%TeamGitFlowReleaseStart.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.releaseFinish"
+ name="%TeamGitFlowReleaseFinish.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featurePublish"
+ name="%TeamGitFlowFeaturePublish.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.releasePublish"
+ name="%TeamGitFlowReleasePublish.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.hotfixPublish"
+ name="%TeamGitFlowHotfixPublish.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featureTrack"
+ name="%TeamGitFlowFeatureTrack.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featureCheckout"
+ name="%TeamGitFlowFeatureCheckout.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.featureRebase"
+ name="%TeamGitFlowFeatureRebase.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.hotfixStart"
+ name="%TeamGitFlowHotfixStart.name">
+ </command>
+ <command
+ id="org.eclipse.egit.gitflow.ui.command.hotfixFinish"
+ name="%TeamGitFlowHotfixFinish.name">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.init">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.InitHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <not>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isInitialized">
+ </test>
+ </adapt>
+ </not>
+ </and>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featureStart">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeatureStartHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isDevelop">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featureFinish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeatureFinishHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+
+ <and>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isFeature">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseStart">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.ReleaseStartHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <instanceof
+ value="org.eclipse.jgit.revwalk.RevCommit">
+ </instanceof>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isDevelop">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseFinish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.ReleaseFinishHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isRelease">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featurePublish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeaturePublishHandler">
+ </class>
+
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isFeature">
+ </test>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.hasDefaultRemote">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.releasePublish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.ReleasePublishHandler">
+ </class>
+
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isRelease">
+ </test>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.hasDefaultRemote">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixPublish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.HotfixPublishHandler">
+ </class>
+
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isHotfix">
+ </test>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.hasDefaultRemote">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featureTrack">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeatureTrackHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.hasDefaultRemote">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featureCheckout">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeatureCheckoutHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.featureRebase">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.FeatureRebaseHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isFeature">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixStart">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.HotfixStartHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isDevelop">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ <handler
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixFinish">
+ <class
+ class="org.eclipse.egit.gitflow.ui.internal.actions.HotfixFinishHandler">
+ </class>
+ <activeWhen>
+ <iterate>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.gitflow.ui.commandEnabled">
+ </reference>
+ </or>
+ </iterate>
+ </activeWhen>
+ <enabledWhen>
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <and>
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isHotfix">
+ </test>
+ </and>
+ </adapt>
+ </iterate>
+ </enabledWhen>
+ </handler>
+ </extension>
+ <extension
+ point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ class="org.eclipse.egit.gitflow.ui.internal.selection.SelectionPropertyTester"
+ id="org.eclipse.egit.gitflow.ui.propertyTester"
+ namespace="GitFlowRepository"
+ properties="isFeature,isRelease,isHotfix,isDevelop,isMaster,isInitialized,hasDefaultRemote"
+ type="org.eclipse.jgit.lib.Repository">
+ </propertyTester>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.expressions.definitions">
+ <definition
+ id="org.eclipse.egit.gitflow.ui.commandEnabled">
+ <or>
+ <instanceof
+ value="org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode">
+ </instanceof>
+ <instanceof
+ value="org.eclipse.core.resources.IResource">
+ </instanceof>
+ </or>
+ </definition>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.adapters">
+ <factory adaptableType="org.eclipse.core.resources.IResource"
+ class="org.eclipse.egit.gitflow.ui.internal.factories.GitFlowAdapterFactory">
+ <adapter type="org.eclipse.jgit.lib.Repository"/>
+ </factory>
+ </extension>
+
+
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="popup:team.main?after=group11">
+ <menu
+ label="%TeamGitFlowMenu.name">
+ <visibleWhen
+ checkEnabled="false">
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <instanceof
+ value="org.eclipse.core.resources.IProject">
+ </instanceof>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isInitialized">
+ </test>
+ </adapt>
+ </and>
+ </iterate>
+ </visibleWhen>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureStart"
+ label="%TeamGitFlowFeatureStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureFinish"
+ label="%TeamGitFlowFeatureFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureRebase"
+ label="%TeamGitFlowFeatureRebase.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureCheckout"
+ label="%TeamGitFlowFeatureCheckout.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featureTrack"
+ label="%TeamGitFlowFeatureTrack.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.featurePublish"
+ label="%TeamGitFlowFeaturePublish.name"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.egit.gitflow.ui.team.separator1"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseStart"
+ label="%TeamGitFlowReleaseStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releaseFinish"
+ label="%TeamGitFlowReleaseFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.releasePublish"
+ label="%TeamGitFlowReleasePublish.name"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.egit.gitflow.ui.team.separator2"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixStart"
+ label="%TeamGitFlowHotfixStart.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixFinish"
+ label="%TeamGitFlowHotfixFinish.name"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.hotfixPublish"
+ label="%TeamGitFlowHotfixPublish.name"
+ style="push">
+ </command>
+ </menu>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:team.main?after=group11">
+ <command
+ commandId="org.eclipse.egit.gitflow.ui.command.init"
+ label="%TeamGitFlowInit.name"
+ style="push">
+ <visibleWhen
+ checkEnabled="false">
+ <iterate
+ ifEmpty="false"
+ operator="and">
+ <and>
+ <instanceof
+ value="org.eclipse.core.resources.IProject">
+ </instanceof>
+ <not>
+ <adapt type="org.eclipse.jgit.lib.Repository">
+ <test
+ forcePluginActivation="true"
+ property="GitFlowRepository.isInitialized">
+ </test>
+ </adapt>
+ </not>
+ </and>
+ </iterate>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ </extension>
+</plugin>
diff --git a/org.eclipse.egit.gitflow.ui/pom.xml b/org.eclipse.egit.gitflow.ui/pom.xml
new file mode 100644
index 000000000..4dc6b7edd
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014, Max Hohenegger <eclipse@hohenegger.eu>
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.egit</groupId>
+ <artifactId>egit-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.egit.gitflow.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <name>Git Flow UI</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-source-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/Activator.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/Activator.java
new file mode 100644
index 000000000..e4c2c5204
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/Activator.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.statushandlers.StatusManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+ // The shared instance
+ private static Activator plugin;
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * @param message
+ * @param throwable
+ * @return Status constructed from parameters.
+ */
+ public static IStatus error(String message, Throwable throwable) {
+ return new Status(IStatus.ERROR, getPluginId(), 0, message, throwable);
+ }
+
+ /**
+ * @param message
+ * @return Status constructed from parameters.
+ */
+ public static IStatus error(String message) {
+ return new Status(IStatus.ERROR, getPluginId(), message);
+ }
+
+ /**
+ * @return the id of the egit ui plugin
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ /**
+ * Handle an error. The error is logged. If <code>show</code> is
+ * <code>true</code> the error is shown to the user.
+ *
+ * @param message a localized message
+ * @param throwable
+ * @param show
+ */
+ public static void handleError(String message, Throwable throwable,
+ boolean show) {
+ handleIssue(IStatus.ERROR, message, throwable, show);
+ }
+
+ /**
+ * Handle an issue. The issue is logged. If <code>show</code> is
+ * <code>true</code> the issue is shown to the user.
+ *
+ * @param severity
+ * status severity, use constants defined in {@link IStatus}
+ * @param message
+ * a localized message
+ * @param throwable
+ * @param show
+ */
+ public static void handleIssue(int severity, String message, Throwable throwable,
+ boolean show) {
+ IStatus status = new Status(severity, getPluginId(), message,
+ throwable);
+ int style = StatusManager.LOG;
+ if (show) {
+ style |= StatusManager.SHOW;
+ }
+ StatusManager.getManager().handle(status, style);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/JobFamilies.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/JobFamilies.java
new file mode 100644
index 000000000..ccd8b82d7
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/JobFamilies.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal;
+
+/**
+ * Job families of GitFlow jobs. May be used in tests to join job execution.
+ *
+ */
+public class JobFamilies {
+ /**
+ * Git Flow Jobs
+ */
+ public final static Object GITFLOW_FAMILY = new Object();
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/UIText.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/UIText.java
new file mode 100644
index 000000000..a43b81d76
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/UIText.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Text resources for the plugin. Strings here can be i18n-ed simpler and avoid
+ * duplicating strings.
+ */
+public class UIText extends NLS {
+
+ /**
+ * Do not in-line this into the static initializer as the
+ * "Find Broken Externalized Strings" tool will not be able to find the
+ * corresponding bundle file.
+ */
+ private static final String BUNDLE_NAME = "org.eclipse.egit.gitflow.ui.internal.uitext"; //$NON-NLS-1$
+
+ static {
+ initializeMessages(BUNDLE_NAME, UIText.class);
+ }
+
+ /** */
+ public static String FeatureFinishHandler_finishingFeature;
+
+ /** */
+ public static String FeatureRebaseHandler_conflicts;
+
+ /** */
+ public static String FeatureRebaseHandler_rebaseFailed;
+
+ /** */
+ public static String FeatureRebaseHandler_rebasingFeature;
+
+ /** */
+ public static String FeatureRebaseHandler_resolveConflictsManually;
+
+ /** */
+ public static String FeatureStartHandler_pleaseProvideANameForTheNewFeature;
+
+ /** */
+ public static String FeatureStartHandler_provideFeatureName;
+
+ /** */
+ public static String FeatureStartHandler_startingNewFeature;
+
+ /** */
+ public static String FeatureTrackHandler_fetchingRemoteFeatures;
+
+ /** */
+ public static String FeatureTrackHandler_noRemoteFeatures;
+
+ /** */
+ public static String FeatureTrackHandler_noRemoteFeaturesFoundOnTheConfiguredRemote;
+
+ /** */
+ public static String FeatureTrackHandler_remoteFeatures;
+
+ /** */
+ public static String FeatureTrackHandler_selectFeature;
+
+ /** */
+ public static String FeatureTrackHandler_trackingFeature;
+
+ /** */
+ public static String HotfixFinishHandler_finishingHotfix;
+
+ /** */
+ public static String HotfixStartHandler_pleaseProvideANameForTheNewHotfix;
+
+ /** */
+ public static String HotfixStartHandler_provideHotfixName;
+
+ /** */
+ public static String HotfixStartHandler_startingNewHotfix;
+
+ /** */
+ public static String InitHandler_initializing;
+
+ /** */
+ public static String ReleaseFinishHandler_finishingRelease;
+
+ /** */
+ public static String ReleaseStartHandler_provideANameForTheNewRelease;
+
+ /** */
+ public static String ReleaseStartHandler_provideReleaseName;
+
+ /** */
+ public static String ReleaseStartHandler_startingNewRelease;
+
+ /** */
+ public static String FeatureCheckoutHandler_checkingOutFeature;
+
+ /** */
+ public static String FeatureCheckoutHandler_localFeatures;
+
+ /** */
+ public static String FeatureCheckoutHandler_selectFeature;
+
+ /** */
+ public static String FeaturePublishHandler_publishingFeature;
+
+ /** */
+ public static String ReleasePublishHandler_publishingRelease;
+
+ /** */
+ public static String HotfixPublishHandler_publishingHotfix;
+
+ /** */
+ public static String NameValidator_invalidName;
+
+ /** */
+ public static String NameValidator_nameAlreadyExists;
+
+ /** */
+ public static String FeatureCheckoutHandler_cleanupDialog_title;
+
+ /** */
+ public static String FeatureCheckoutHandler_cleanupDialog_text;
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/AbstractPublishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/AbstractPublishHandler.java
new file mode 100644
index 000000000..8d3f25d4c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/AbstractPublishHandler.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.CurrentBranchPublishOperation;
+import org.eclipse.egit.gitflow.ui.Activator;
+import org.eclipse.egit.ui.JobFamilies;
+import org.eclipse.egit.ui.UIPreferences;
+
+/**
+ * git flow {feature,release,hotfix} finish
+ */
+public abstract class AbstractPublishHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ try {
+ int timeout = Activator.getDefault().getPreferenceStore()
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);
+ CurrentBranchPublishOperation featurePublishOperation = new CurrentBranchPublishOperation(
+ gfRepo, timeout);
+ JobUtil.scheduleUserWorkspaceJob(featurePublishOperation,
+ getProgressText(), JobFamilies.REBASE);
+ } catch (CoreException e) {
+ return error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+
+ /**
+ * @return Text to be shown when the operation is in progress
+ */
+ abstract protected String getProgressText();
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureCheckoutHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureCheckoutHandler.java
new file mode 100644
index 000000000..d237fc150
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureCheckoutHandler.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.FeatureCheckoutOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.egit.gitflow.ui.internal.dialog.AbstractGitFlowBranchSelectionDialog;
+import org.eclipse.egit.ui.internal.branch.CleanupUncomittedChangesDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jgit.api.CheckoutResult;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow feature checkout
+ */
+public class FeatureCheckoutHandler extends AbstractHandler {
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+ Repository repository = gfRepo.getRepository();
+
+ final List<Ref> refs = gfRepo.getFeatureBranches();
+
+ AbstractGitFlowBranchSelectionDialog<Ref> dialog = new AbstractGitFlowBranchSelectionDialog<Ref>(
+ HandlerUtil.getActiveShell(event), refs,
+ UIText.FeatureCheckoutHandler_selectFeature,
+ UIText.FeatureCheckoutHandler_localFeatures) {
+ @Override
+ protected String getPrefix() {
+ return R_HEADS + gfRepo.getConfig().getFeaturePrefix();
+ }
+ };
+ if (dialog.open() != Window.OK) {
+ return null;
+ }
+ final Ref ref = dialog.getSelectedNode();
+
+ try {
+ String featureName = gfRepo.getFeatureBranchName(ref);
+ // TODO: consider using BranchOperationUI because checkout can take
+ // a long time on large repositories
+ FeatureCheckoutOperation checkoutOperation = new FeatureCheckoutOperation(
+ gfRepo, featureName);
+ JobUtil.scheduleUserWorkspaceJob(checkoutOperation,
+ UIText.FeatureCheckoutHandler_checkingOutFeature,
+ JobFamilies.GITFLOW_FAMILY);
+ CheckoutResult result = checkoutOperation.getResult();
+ if (!CheckoutResult.Status.OK.equals(result.getStatus())) {
+ Shell shell = HandlerUtil.getActiveShell(event);
+ if (!handleUncommittedFiles(gfRepo.getRepository(), shell,
+ repository.getWorkTree().getName())) {
+ return Status.CANCEL_STATUS;
+ } else {
+ JobUtil.scheduleUserWorkspaceJob(checkoutOperation,
+ UIText.FeatureCheckoutHandler_checkingOutFeature,
+ JobFamilies.GITFLOW_FAMILY);
+ }
+ }
+ } catch (GitAPIException e) {
+ throw new RuntimeException(e);
+ }
+
+ return null;
+ }
+
+ private boolean handleUncommittedFiles(Repository repo, Shell shell,
+ String repoName) throws GitAPIException {
+ try (Git git = new Git(repo)) {
+ org.eclipse.jgit.api.Status status = git.status().call();
+
+ if (status.hasUncommittedChanges()) {
+ List<String> files = new ArrayList<String>(
+ status.getUncommittedChanges());
+ Collections.sort(files);
+ CleanupUncomittedChangesDialog cleanupUncomittedChangesDialog = new CleanupUncomittedChangesDialog(
+ shell,
+ MessageFormat
+ .format(UIText.FeatureCheckoutHandler_cleanupDialog_title,
+ repoName),
+ UIText.FeatureCheckoutHandler_cleanupDialog_text,
+ repo, files);
+ cleanupUncomittedChangesDialog.open();
+ return cleanupUncomittedChangesDialog.shouldContinue();
+ } else {
+ return true;
+ }
+ }
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureFinishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureFinishHandler.java
new file mode 100644
index 000000000..69fcc8b2a
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureFinishHandler.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.op.FeatureFinishOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow feature finish
+ */
+public class FeatureFinishHandler extends AbstractHandler {
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ try {
+ FeatureFinishOperation operation = new FeatureFinishOperation(gfRepo);
+ JobUtil.scheduleUserWorkspaceJob(operation,
+ UIText.FeatureFinishHandler_finishingFeature,
+ JobFamilies.GITFLOW_FAMILY);
+ } catch (WrongGitFlowStateException | CoreException | IOException e) {
+ return error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeaturePublishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeaturePublishHandler.java
new file mode 100644
index 000000000..0bcc05254
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeaturePublishHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow feature finish
+ */
+public class FeaturePublishHandler extends AbstractPublishHandler {
+ @Override
+ protected String getProgressText() {
+ return UIText.FeaturePublishHandler_publishingFeature;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureRebaseHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureRebaseHandler.java
new file mode 100644
index 000000000..d21127a3c
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureRebaseHandler.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.FeatureRebaseOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jgit.api.RebaseResult;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow feature rebase
+ */
+public class FeatureRebaseHandler extends AbstractHandler {
+ private static final String INTERACTIVE_REBASE_VIEW_ID = "org.eclipse.egit.ui.InteractiveRebaseView"; //$NON-NLS-1$
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ FeatureRebaseOperation featureRebaseOperation = new FeatureRebaseOperation(gfRepo);
+ JobUtil.scheduleUserWorkspaceJob(featureRebaseOperation,
+ UIText.FeatureRebaseHandler_rebasingFeature,
+ JobFamilies.GITFLOW_FAMILY);
+
+ RebaseResult.Status status = featureRebaseOperation
+ .getOperationResult().getStatus();
+ if (RebaseResult.Status.FAILED.equals(status)) {
+ return error(UIText.FeatureRebaseHandler_rebaseFailed);
+ }
+ if (!RebaseResult.Status.CONFLICTS.equals(status)) {
+ return null;
+ }
+ MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
+ UIText.FeatureRebaseHandler_conflicts,
+ UIText.FeatureRebaseHandler_resolveConflictsManually);
+ try {
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getActivePage().showView(INTERACTIVE_REBASE_VIEW_ID);
+ } catch (PartInitException e) {
+ return error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureStartHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureStartHandler.java
new file mode 100644
index 000000000..d55055a46
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureStartHandler.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.FeatureStartOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.egit.gitflow.ui.internal.validation.FeatureNameValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow feature start
+ */
+public class FeatureStartHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ InputDialog inputDialog = new InputDialog(
+ HandlerUtil.getActiveShell(event),
+ UIText.FeatureStartHandler_provideFeatureName,
+ UIText.FeatureStartHandler_pleaseProvideANameForTheNewFeature,
+ "", //$NON-NLS-1$
+ new FeatureNameValidator(gfRepo));
+
+ if (inputDialog.open() != Window.OK) {
+ return null;
+ }
+
+ final String featureName = inputDialog.getValue();
+ FeatureStartOperation featureStartOperation = new FeatureStartOperation(
+ gfRepo, featureName);
+ JobUtil.scheduleUserWorkspaceJob(featureStartOperation,
+ UIText.FeatureStartHandler_startingNewFeature,
+ JobFamilies.GITFLOW_FAMILY);
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureTrackHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureTrackHandler.java
new file mode 100644
index 000000000..80f714809
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/FeatureTrackHandler.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.op.GitFlowOperation.SEP;
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_REMOTES;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.FeatureListOperation;
+import org.eclipse.egit.gitflow.op.FeatureTrackOperation;
+import org.eclipse.egit.gitflow.ui.Activator;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.egit.gitflow.ui.internal.dialog.AbstractGitFlowBranchSelectionDialog;
+import org.eclipse.egit.ui.UIPreferences;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow feature track
+ */
+public class FeatureTrackHandler extends AbstractHandler {
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+ final List<Ref> refs = new ArrayList<Ref>();
+ Shell activeShell = HandlerUtil.getActiveShell(event);
+
+ int timeout = Activator.getDefault().getPreferenceStore()
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);
+ FeatureListOperation featureListOperation = new FeatureListOperation(
+ gfRepo, timeout);
+ JobUtil.scheduleUserWorkspaceJob(featureListOperation,
+ UIText.FeatureTrackHandler_fetchingRemoteFeatures, JobFamilies.GITFLOW_FAMILY);
+ List<Ref> remoteFeatures = featureListOperation.getResult();
+ if (remoteFeatures.isEmpty()) {
+ MessageDialog.openInformation(activeShell, UIText.FeatureTrackHandler_noRemoteFeatures,
+ UIText.FeatureTrackHandler_noRemoteFeaturesFoundOnTheConfiguredRemote);
+ }
+ refs.addAll(remoteFeatures);
+
+ AbstractGitFlowBranchSelectionDialog<Ref> dialog = new AbstractGitFlowBranchSelectionDialog<Ref>(
+ activeShell, refs,
+ UIText.FeatureTrackHandler_selectFeature,
+ UIText.FeatureTrackHandler_remoteFeatures) {
+ @Override
+ protected String getPrefix() {
+ return R_REMOTES + DEFAULT_REMOTE_NAME + SEP
+ + gfRepo.getConfig().getFeaturePrefix();
+ }
+ };
+ if (dialog.open() != Window.OK) {
+ return Status.CANCEL_STATUS;
+ }
+
+ Ref ref = dialog.getSelectedNode();
+ FeatureTrackOperation featureTrackOperation = new FeatureTrackOperation(
+ gfRepo, ref);
+ JobUtil.scheduleUserWorkspaceJob(featureTrackOperation,
+ UIText.FeatureTrackHandler_trackingFeature, JobFamilies.GITFLOW_FAMILY);
+
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/GitFlowHandlerUtil.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/GitFlowHandlerUtil.java
new file mode 100644
index 000000000..d368c22ff
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/GitFlowHandlerUtil.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.egit.core.internal.Utils;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ *
+ */
+public class GitFlowHandlerUtil {
+ /**
+ * @param event
+ * @return Selected GitFlowRepository
+ */
+ public static GitFlowRepository getRepository(ExecutionEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) HandlerUtil
+ .getCurrentSelection(event);
+ PlatformObject firstElement = (PlatformObject) selection
+ .getFirstElement();
+ Repository repository = Utils.getAdapter(firstElement,
+ Repository.class);
+ if (repository == null) {
+ return null;
+ }
+ return new GitFlowRepository(repository);
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixFinishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixFinishHandler.java
new file mode 100644
index 000000000..487fb319f
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixFinishHandler.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.op.HotfixFinishOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow hotfix finish
+ */
+public class HotfixFinishHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ HotfixFinishOperation hotfixFinishOperation;
+ try {
+ hotfixFinishOperation = new HotfixFinishOperation(gfRepo);
+ JobUtil.scheduleUserWorkspaceJob(hotfixFinishOperation,
+ UIText.HotfixFinishHandler_finishingHotfix,
+ JobFamilies.GITFLOW_FAMILY);
+ } catch (WrongGitFlowStateException | CoreException | IOException e) {
+ return error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixPublishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixPublishHandler.java
new file mode 100644
index 000000000..a04b10333
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixPublishHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow hotfix finish
+ */
+public class HotfixPublishHandler extends AbstractPublishHandler {
+ @Override
+ protected String getProgressText() {
+ return UIText.HotfixPublishHandler_publishingHotfix;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixStartHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixStartHandler.java
new file mode 100644
index 000000000..552be9150
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/HotfixStartHandler.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.HotfixStartOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.egit.gitflow.ui.internal.validation.HotfixNameValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow hotfix start
+ */
+public class HotfixStartHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ InputDialog inputDialog = new InputDialog(
+ HandlerUtil.getActiveShell(event),
+ UIText.HotfixStartHandler_provideHotfixName,
+ UIText.HotfixStartHandler_pleaseProvideANameForTheNewHotfix,
+ "", //$NON-NLS-1$
+ new HotfixNameValidator(gfRepo));
+
+ if (inputDialog.open() != Window.OK) {
+ return null;
+ }
+
+ final String hotfixName = inputDialog.getValue();
+ HotfixStartOperation hotfixStartOperation = new HotfixStartOperation(
+ gfRepo, hotfixName);
+ JobUtil.scheduleUserWorkspaceJob(hotfixStartOperation,
+ UIText.HotfixStartHandler_startingNewHotfix,
+ JobFamilies.GITFLOW_FAMILY);
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/InitHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/InitHandler.java
new file mode 100644
index 000000000..c75294438
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/InitHandler.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.op.InitOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow feature init
+ */
+public class InitHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+ if (gfRepo == null) {
+ return null;
+ }
+
+ InitOperation initOperation = new InitOperation(gfRepo.getRepository());
+ JobUtil.scheduleUserWorkspaceJob(initOperation,
+ UIText.InitHandler_initializing, JobFamilies.GITFLOW_FAMILY);
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseFinishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseFinishHandler.java
new file mode 100644
index 000000000..b24f9f9d1
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseFinishHandler.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.op.ReleaseFinishOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow release finish
+ */
+public class ReleaseFinishHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+
+ ReleaseFinishOperation releaseFinishOperation;
+ try {
+ releaseFinishOperation = new ReleaseFinishOperation(gfRepo);
+ JobUtil.scheduleUserWorkspaceJob(releaseFinishOperation,
+ UIText.ReleaseFinishHandler_finishingRelease,
+ JobFamilies.GITFLOW_FAMILY);
+ } catch (WrongGitFlowStateException | CoreException | IOException e) {
+ return error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleasePublishHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleasePublishHandler.java
new file mode 100644
index 000000000..f05002b1b
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleasePublishHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+
+/**
+ * git flow release finish
+ */
+public class ReleasePublishHandler extends AbstractPublishHandler {
+ @Override
+ protected String getProgressText() {
+ return UIText.ReleasePublishHandler_publishingRelease;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseStartHandler.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseStartHandler.java
new file mode 100644
index 000000000..7c48aee1b
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/actions/ReleaseStartHandler.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.actions;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.egit.core.internal.Utils;
+import org.eclipse.egit.core.internal.job.JobUtil;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.op.ReleaseStartOperation;
+import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.egit.gitflow.ui.internal.validation.ReleaseNameValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revplot.PlotCommit;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.team.ui.history.IHistoryView;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * git flow release start
+ */
+public class ReleaseStartHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
+ final String startCommitSha1 = getStartCommit(event);
+
+ InputDialog inputDialog = new InputDialog(
+ HandlerUtil.getActiveShell(event),
+ UIText.ReleaseStartHandler_provideReleaseName,
+ UIText.ReleaseStartHandler_provideANameForTheNewRelease, "", //$NON-NLS-1$
+ new ReleaseNameValidator(gfRepo));
+
+ if (inputDialog.open() != Window.OK) {
+ return null;
+ }
+
+ final String releaseName = inputDialog.getValue();
+
+ ReleaseStartOperation releaseStartOperation = new ReleaseStartOperation(
+ gfRepo, startCommitSha1, releaseName);
+ JobUtil.scheduleUserWorkspaceJob(releaseStartOperation,
+ UIText.ReleaseStartHandler_startingNewRelease,
+ JobFamilies.GITFLOW_FAMILY);
+
+ return null;
+ }
+
+ private String getStartCommit(ExecutionEvent event)
+ throws ExecutionException {
+ IStructuredSelection selection = (IStructuredSelection) HandlerUtil
+ .getCurrentSelection(event);
+ if (selection.getFirstElement() instanceof PlotCommit) {
+ RevCommit plotCommit = (RevCommit) selection.getFirstElement();
+ return plotCommit.getName();
+ } else {
+ GitFlowRepository gitFlowRepository = new GitFlowRepository(getRepository(event));
+ RevCommit head;
+ try {
+ head = gitFlowRepository.findHead();
+ } catch (WrongGitFlowStateException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ return head.getName();
+ }
+ }
+
+ private Repository getRepository(ExecutionEvent event)
+ throws ExecutionException {
+ PlatformObject firstElement;
+ IStructuredSelection selection = (IStructuredSelection) HandlerUtil
+ .getCurrentSelection(event);
+ if (selection.getFirstElement() instanceof PlotCommit) {
+ IWorkbenchPart ap = HandlerUtil.getActivePartChecked(event);
+ if (ap instanceof IHistoryView) {
+ firstElement = (PlatformObject) ((IHistoryView) ap)
+ .getHistoryPage().getInput();
+ } else {
+ // This is unexpected
+ return null;
+ }
+
+ } else {
+ firstElement = (PlatformObject) selection.getFirstElement();
+ }
+ return Utils.getAdapter(firstElement, Repository.class);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/dialog/AbstractGitFlowBranchSelectionDialog.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/dialog/AbstractGitFlowBranchSelectionDialog.java
new file mode 100644
index 000000000..43a5ac731
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/dialog/AbstractGitFlowBranchSelectionDialog.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.dialog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.egit.ui.internal.CommonUtils;
+import org.eclipse.egit.ui.internal.GitLabelProvider;
+import static org.eclipse.jface.dialogs.IDialogConstants.*;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Select Git Flow branches.
+ *
+ * @param <T>
+ */
+public abstract class AbstractGitFlowBranchSelectionDialog<T> extends MessageDialog {
+
+ private final List<T> nodes;
+
+ private TableViewer branchesList;
+
+ private List<T> selected = new ArrayList<T>();
+
+ /**
+ * @param parentShell
+ * @param nodes
+ * @param title
+ * @param message
+ */
+ public AbstractGitFlowBranchSelectionDialog(Shell parentShell, List<T> nodes,
+ String title, String message) {
+ super(parentShell, title, null, message, MessageDialog.QUESTION,
+ new String[] { OK_LABEL, CANCEL_LABEL }, 0);
+ this.nodes = nodes;
+ }
+
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ @Override
+ protected Control createCustomArea(Composite parent) {
+ Composite area = new Composite(parent, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, true).span(2, 1)
+ .applyTo(area);
+ area.setLayout(new GridLayout(1, false));
+ branchesList = new TableViewer(area, SWT.SINGLE | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, true)
+ .applyTo(branchesList.getControl());
+ branchesList.setContentProvider(ArrayContentProvider.getInstance());
+ branchesList.setLabelProvider(createLabelProvider());
+ branchesList.setComparator(new ViewerComparator(
+ CommonUtils.STRING_ASCENDING_COMPARATOR));
+ branchesList.setInput(nodes);
+ branchesList
+ .addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ checkPage();
+ }
+ });
+ branchesList.addDoubleClickListener(new IDoubleClickListener() {
+ @Override
+ public void doubleClick(DoubleClickEvent event) {
+ buttonPressed(OK);
+ }
+ });
+
+ branchesList.addFilter(createFilter());
+ return area;
+ }
+
+ private ViewerFilter createFilter() {
+ return new ViewerFilter() {
+ @Override
+ public boolean select(Viewer viewer, Object parentElement,
+ Object element) {
+ return true;
+ }
+ };
+ }
+
+ private IBaseLabelProvider createLabelProvider() {
+ final String prefix = getPrefix();
+ return new GitLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return super.getText(element).substring(prefix.length());
+ }
+ };
+ }
+
+ /**
+ * @return Git Flow prefix for this dialog. E.g. feature, release, hotfix
+ */
+ abstract protected String getPrefix();
+
+ private void checkPage() {
+ getButton(OK).setEnabled(!branchesList.getSelection().isEmpty());
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == OK) {
+ selected = ((IStructuredSelection) branchesList.getSelection())
+ .toList();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ @Override
+ public void create() {
+ super.create();
+ getButton(OK).setEnabled(false);
+ }
+
+ /**
+ * @return the selected entry (single mode)
+ */
+ public T getSelectedNode() {
+ if (selected.isEmpty()) {
+ return null;
+ }
+ return selected.get(0);
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/factories/GitFlowAdapterFactory.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/factories/GitFlowAdapterFactory.java
new file mode 100644
index 000000000..1609d64e3
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/factories/GitFlowAdapterFactory.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.factories;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.egit.core.internal.Utils;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Get JGit repository for element selected in Git Flow UI.
+ */
+public class GitFlowAdapterFactory implements IAdapterFactory {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ Repository repository = null;
+ if (adaptableObject instanceof IResource) {
+ IResource resource = (IResource) adaptableObject;
+ RepositoryMapping repositoryMapping = RepositoryMapping
+ .getMapping(resource.getProject());
+ repository = repositoryMapping.getRepository();
+ } else if (adaptableObject instanceof PlatformObject) {
+ PlatformObject platformObject = (PlatformObject) adaptableObject;
+ repository = Utils.getAdapter(platformObject, Repository.class);
+ } else {
+ throw new IllegalStateException();
+ }
+
+ return repository;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class[] getAdapterList() {
+ return new Class[] { IResource.class, RepositoryTreeNode.class };
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/selection/SelectionPropertyTester.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/selection/SelectionPropertyTester.java
new file mode 100644
index 000000000..2043fa144
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/selection/SelectionPropertyTester.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.selection;
+
+import static org.eclipse.egit.gitflow.ui.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.egit.gitflow.Activator;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Testing Git Flow states.
+ */
+public class SelectionPropertyTester extends PropertyTester {
+ private static final String IS_MASTER = "isMaster"; //$NON-NLS-1$
+
+ private static final String IS_DEVELOP = "isDevelop"; //$NON-NLS-1$
+
+ private static final String IS_HOTFIX = "isHotfix"; //$NON-NLS-1$
+
+ private static final String IS_RELEASE = "isRelease"; //$NON-NLS-1$
+
+ private static final String IS_INITIALIZED = "isInitialized"; //$NON-NLS-1$
+
+ private static final String IS_FEATURE = "isFeature"; //$NON-NLS-1$
+
+ private static final String HAS_DEFAULT_REMOTE = "hasDefaultRemote"; //$NON-NLS-1$
+
+ @Override
+ public boolean test(Object receiver, String property, Object[] args,
+ Object expectedValue) {
+ Repository repository = (Repository) receiver;
+
+ GitFlowRepository gitFlowRepository = new GitFlowRepository(repository);
+ try {
+ if (IS_INITIALIZED.equals(property)) {
+ return gitFlowRepository.getConfig().isInitialized();
+ } else if (IS_FEATURE.equals(property)) {
+ return gitFlowRepository.isFeature();
+ } else if (IS_RELEASE.equals(property)) {
+ return gitFlowRepository.isRelease();
+ } else if (IS_HOTFIX.equals(property)) {
+ return gitFlowRepository.isHotfix();
+ } else if (IS_DEVELOP.equals(property)) {
+ return gitFlowRepository.isDevelop();
+ } else if (IS_MASTER.equals(property)) {
+ return gitFlowRepository.isMaster();
+ } else if (HAS_DEFAULT_REMOTE.equals(property)) {
+ return gitFlowRepository.getConfig().hasDefaultRemote();
+ }
+ } catch (IOException e) {
+ Activator.getDefault().getLog().log(error(e.getMessage(), e));
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/uitext.properties b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/uitext.properties
new file mode 100644
index 000000000..340dc57bd
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/uitext.properties
@@ -0,0 +1,41 @@
+###############################################################################
+# Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+FeatureFinishHandler_finishingFeature=Finishing feature...
+FeatureRebaseHandler_conflicts=Conflicts
+FeatureRebaseHandler_rebaseFailed=Rebase failed.
+FeatureRebaseHandler_rebasingFeature=Rebasing feature...
+FeatureRebaseHandler_resolveConflictsManually=There are conflicts that need to be resolve manually. Add your changes and continue rebase when you are finished.
+FeatureStartHandler_pleaseProvideANameForTheNewFeature=Please provide a name for the new feature.
+FeatureStartHandler_provideFeatureName=Provide feature name
+FeatureStartHandler_startingNewFeature=Starting new Feature...
+FeatureTrackHandler_fetchingRemoteFeatures=Fetching remote features...
+FeatureTrackHandler_noRemoteFeatures=No remote features
+FeatureTrackHandler_noRemoteFeaturesFoundOnTheConfiguredRemote=No features were found on the configured remote.
+FeatureTrackHandler_remoteFeatures=Remote features:
+FeatureTrackHandler_selectFeature=Select Feature
+FeatureTrackHandler_trackingFeature=Tracking feature...
+HotfixFinishHandler_finishingHotfix=Finishing hotfix...
+HotfixStartHandler_pleaseProvideANameForTheNewHotfix=Please provide a name for the new hotfix.
+HotfixStartHandler_provideHotfixName=Provide hotfix name
+HotfixStartHandler_startingNewHotfix=Starting new Hotfix...
+InitHandler_initializing=Initializing...
+ReleaseFinishHandler_finishingRelease=Finishing release...
+ReleaseStartHandler_provideANameForTheNewRelease=Please provide a name for the new release.
+ReleaseStartHandler_provideReleaseName=Provide release name
+ReleaseStartHandler_startingNewRelease=Starting new Release...
+FeatureCheckoutHandler_checkingOutFeature=Checking out feature...
+FeatureCheckoutHandler_localFeatures=Local features:
+FeatureCheckoutHandler_selectFeature=Select Feature
+FeaturePublishHandler_publishingFeature=Publishing feature...
+ReleasePublishHandler_publishingRelease=Publishing release...
+HotfixPublishHandler_publishingHotfix=Publishing hotfix...
+NameValidator_invalidName='%s' is not a valid name. None of the following characters is allowed: '%s'
+NameValidator_nameAlreadyExists=Name '%s' already exists
+FeatureCheckoutHandler_cleanupDialog_title=Cannot Rebase Repository ''{0}''
+FeatureCheckoutHandler_cleanupDialog_text=You have uncommitted changes. Either commit the changes, stash the changes, or discard the changes by resetting the current branch.
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/BranchNameInputValidator.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/BranchNameInputValidator.java
new file mode 100644
index 000000000..2e0d337c5
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/BranchNameInputValidator.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.validation;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.BranchNameValidator;
+import org.eclipse.egit.gitflow.ui.internal.UIText;
+import org.eclipse.jface.dialogs.IInputValidator;
+
+/**
+ * Validates Git Flow branch names.
+ */
+abstract public class BranchNameInputValidator implements IInputValidator {
+ @Override
+ public String isValid(String newText) {
+ try {
+ if (branchExists(newText)) {
+ return String.format(UIText.NameValidator_nameAlreadyExists,
+ newText);
+ }
+ if (!BranchNameValidator.isBranchNameValid(newText)) {
+ return String.format(UIText.NameValidator_invalidName, newText,
+ BranchNameValidator.ILLEGAL_CHARS);
+ }
+ } catch (CoreException e) {
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * @param newText
+ * @return Whether or not newText corresponds to an existing branch.
+ * @throws CoreException
+ */
+ abstract protected boolean branchExists(String newText)
+ throws CoreException;
+} \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/FeatureNameValidator.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/FeatureNameValidator.java
new file mode 100644
index 000000000..d12951bb4
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/FeatureNameValidator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.validation;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.BranchNameValidator;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+
+/**
+ * Validate feature branch name.
+ */
+public class FeatureNameValidator extends BranchNameInputValidator {
+ private final GitFlowRepository repository;
+
+ /**
+ * @param gfRepo
+ */
+ public FeatureNameValidator(GitFlowRepository gfRepo) {
+ this.repository = gfRepo;
+ }
+
+ @Override
+ protected boolean branchExists(String newText) throws CoreException {
+ return BranchNameValidator.featureExists(repository, newText);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/HotfixNameValidator.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/HotfixNameValidator.java
new file mode 100644
index 000000000..75ffdbb36
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/HotfixNameValidator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.validation;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.BranchNameValidator;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+
+/**
+ * Validate name of hotfix branch.
+ */
+public class HotfixNameValidator extends BranchNameInputValidator {
+ private final GitFlowRepository repository;
+
+ /**
+ * @param repository
+ */
+ public HotfixNameValidator(GitFlowRepository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ protected boolean branchExists(String newText) throws CoreException {
+ return BranchNameValidator.hotfixExists(repository, newText);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/ReleaseNameValidator.java b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/ReleaseNameValidator.java
new file mode 100644
index 000000000..c371413a2
--- /dev/null
+++ b/org.eclipse.egit.gitflow.ui/src/org/eclipse/egit/gitflow/ui/internal/validation/ReleaseNameValidator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.ui.internal.validation;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.BranchNameValidator;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+
+/**
+ * Validate release branch name.
+ */
+public class ReleaseNameValidator extends BranchNameInputValidator {
+ private final GitFlowRepository repository;
+
+ /**
+ * @param gfRepo
+ */
+ public ReleaseNameValidator(GitFlowRepository gfRepo) {
+ this.repository = gfRepo;
+ }
+
+ @Override
+ protected boolean branchExists(String newText) throws CoreException {
+ return BranchNameValidator.releaseExists(repository, newText);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.gitflow/.classpath b/org.eclipse.egit.gitflow/.classpath
new file mode 100644
index 000000000..f2156e991
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.egit.gitflow/.project b/org.eclipse.egit.gitflow/.project
new file mode 100644
index 000000000..aafb928c5
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.gitflow</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.gitflow/.settings/.api_filters b/org.eclipse.egit.gitflow/.settings/.api_filters
new file mode 100644
index 000000000..0b505599d
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/.api_filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.egit.gitflow" version="2">
+ <resource path="src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperation.java" type="org.eclipse.egit.gitflow.op.CurrentBranchPublishOperation">
+ <filter id="643842064">
+ <message_arguments>
+ <message_argument value="PushOperationResult"/>
+ <message_argument value="CurrentBranchPublishOperation"/>
+ <message_argument value="getOperationResult()"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/egit/gitflow/op/GitFlowOperation.java" type="org.eclipse.egit.gitflow.op.GitFlowOperation">
+ <filter id="576725006">
+ <message_arguments>
+ <message_argument value="IEGitOperation"/>
+ <message_argument value="GitFlowOperation"/>
+ </message_arguments>
+ </filter>
+ <filter id="643842064">
+ <message_arguments>
+ <message_argument value="CreateLocalBranchOperation"/>
+ <message_argument value="GitFlowOperation"/>
+ <message_argument value="createBranchFromHead(String, RevCommit)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/org.eclipse.egit.gitflow/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.gitflow/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..d4ff695e8
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:03 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.gitflow/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.gitflow/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..dfc3779a1
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:53 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..448fcfd79
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,393 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
+org.eclipse.jdt.core.compiler.problem.deadCode=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..c336cce6e
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_JGit Format
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.egit.gitflow/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.egit.gitflow/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/org.eclipse.egit.gitflow/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.egit.gitflow/META-INF/MANIFEST.MF b/org.eclipse.egit.gitflow/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..8f9d00abf
--- /dev/null
+++ b/org.eclipse.egit.gitflow/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Gitflow
+Bundle-SymbolicName: org.eclipse.egit.gitflow
+Bundle-Version: 4.0.0.qualifier
+Bundle-Activator: org.eclipse.egit.gitflow.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.core.resources
+Export-Package: org.eclipse.egit.gitflow;version="4.0.0",
+ org.eclipse.egit.gitflow.op;version="4.0.0"
+Import-Package: org.eclipse.egit.core;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.internal.job;version="[4.0.0,4.1.0)",
+ org.eclipse.egit.core.op;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.api;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.errors;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.lib;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.revwalk;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.api.errors;version="[4.0.0,4.1.0)",
+ org.eclipse.jgit.transport;version="[4.0.0,4.1.0)"
diff --git a/org.eclipse.egit.gitflow/about.html b/org.eclipse.egit.gitflow/about.html
new file mode 100644
index 000000000..a14d39be0
--- /dev/null
+++ b/org.eclipse.egit.gitflow/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>May 9, 2015</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.egit.gitflow/build.properties b/org.eclipse.egit.gitflow/build.properties
new file mode 100644
index 000000000..a6790b8bf
--- /dev/null
+++ b/org.eclipse.egit.gitflow/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+bin.includes = META-INF/,\
+ .,\
+ build.properties,\
+ about.html
diff --git a/org.eclipse.egit.gitflow/pom.xml b/org.eclipse.egit.gitflow/pom.xml
new file mode 100644
index 000000000..d86f8cf4d
--- /dev/null
+++ b/org.eclipse.egit.gitflow/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014, Max Hohenegger <eclipse@hohenegger.eu>
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.egit</groupId>
+ <artifactId>egit-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.egit.gitflow</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <name>Git Flow</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-source-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/Activator.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/Activator.java
new file mode 100644
index 000000000..b7c7d8015
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/Activator.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ *
+ * @since 4.0
+ */
+public class Activator extends Plugin {
+
+ private static Plugin instance;
+
+ private static BundleContext context;
+
+ static BundleContext getContext() {
+ return context;
+ }
+
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ Activator.context = bundleContext;
+ instance = this;
+ }
+
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ Activator.context = null;
+ }
+
+ /**
+ * @param message
+ * @param throwable
+ * @return Status constructed from parameters.
+ */
+ public static IStatus error(String message, Throwable throwable) {
+ return new Status(IStatus.ERROR, getPluginId(), 0, message, throwable);
+ }
+
+ /**
+ * @param throwable
+ * @return Status constructed from parameters.
+ */
+ public static IStatus error(Throwable throwable) {
+ return error(throwable.getMessage(), throwable);
+ }
+
+ /**
+ * @param message
+ * @return Status constructed from parameters.
+ */
+ public static IStatus error(String message) {
+ return new Status(IStatus.ERROR, getPluginId(), message);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Plugin getDefault() {
+ return instance;
+ }
+
+ /**
+ * @return the id of the gitflow plugin
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/BranchNameValidator.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/BranchNameValidator.java
new file mode 100644
index 000000000..8745328f1
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/BranchNameValidator.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+
+/**
+ * Checks if name is valid and branch does not exist.
+ *
+ * @since 4.0
+ */
+public class BranchNameValidator {
+ /**
+ * Characters not allowed in git flow branches.
+ */
+ public static final String ILLEGAL_CHARS = "/ "; //$NON-NLS-1$
+
+ /**
+ * @param repository
+ * @param featureName
+ * @return Whether featureName corresponds to existing branch.
+ * @throws CoreException
+ */
+ public static boolean featureExists(GitFlowRepository repository,
+ String featureName) throws CoreException {
+ return branchExists(repository,
+ repository.getConfig().getFullFeatureBranchName(featureName));
+ }
+
+ /**
+ * @param repository
+ * @param hotfixName
+ * @return Whether hotfixName corresponds to existing branch.
+ * @throws CoreException
+ */
+ public static boolean hotfixExists(GitFlowRepository repository,
+ String hotfixName) throws CoreException {
+ return branchExists(repository,
+ repository.getConfig().getFullHotfixBranchName(hotfixName));
+ }
+
+ /**
+ * @param repository
+ * @param releaseName
+ * @return Whether releaseName corresponds to existing branch.
+ * @throws CoreException
+ */
+ public static boolean releaseExists(GitFlowRepository repository,
+ String releaseName) throws CoreException {
+ return branchExists(repository,
+ repository.getConfig().getFullReleaseBranchName(releaseName));
+ }
+
+ private static boolean branchExists(GitFlowRepository repository,
+ String fullBranchName) throws CoreException {
+ List<Ref> branches;
+ try {
+ branches = Git.wrap(repository.getRepository()).branchList().call();
+ } catch (GitAPIException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+ for (Ref ref : branches) {
+ if (fullBranchName.equals(ref.getTarget().getName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param name
+ * @return Whether or not name would be a valid name for a branch.
+ */
+ public static boolean isBranchNameValid(String name) {
+ return Repository.isValidRefName(Constants.R_HEADS + name);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowConfig.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowConfig.java
new file mode 100644
index 000000000..c544677c2
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowConfig.java
@@ -0,0 +1,310 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import static org.eclipse.egit.gitflow.GitFlowDefaults.DEVELOP;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.FEATURE_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.HOTFIX_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.RELEASE_PREFIX;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.VERSION_TAG;
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.RemoteConfig;
+
+/**
+ * Wrapper for JGit repository.
+ *
+ * @since 4.0
+ */
+public class GitFlowConfig {
+ /** Key for .git/config */
+ public static final String MASTER_KEY = "master"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String DEVELOP_KEY = "develop"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String HOTFIX_KEY = "hotfix"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String RELEASE_KEY = "release"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String FEATURE_KEY = "feature"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String VERSION_TAG_KEY = "versiontag"; //$NON-NLS-1$
+
+ /** Name of .git/config section. */
+ public static final String USER_SECTION = "user"; //$NON-NLS-1$
+
+ /** Name of .git/config section. */
+ public static final String BRANCH_SECTION = "branch"; //$NON-NLS-1$
+
+ /** Name of .git/config section. */
+ public static final String PREFIX_SECTION = "prefix"; //$NON-NLS-1$
+
+ /** Name of .git/config section. */
+ public static final String GITFLOW_SECTION = "gitflow"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String REMOTE_KEY = "remote"; //$NON-NLS-1$
+
+ /** Key for .git/config */
+ public static final String MERGE_KEY = "merge"; //$NON-NLS-1$
+
+ private Repository repository;
+
+ /**
+ * @param repository
+ */
+ public GitFlowConfig(Repository repository) {
+ Assert.isNotNull(repository);
+ this.repository = repository;
+ }
+
+ /**
+ * @return git init done?
+ * @throws IOException
+ */
+ public boolean isInitialized() throws IOException {
+ StoredConfig config = repository.getConfig();
+ Set<String> sections = config.getSections();
+ return sections.contains(GITFLOW_SECTION);
+ }
+
+ /**
+ * @return Local user of this repository.
+ */
+ public String getUser() {
+ StoredConfig config = repository.getConfig();
+ String userName = config.getString(USER_SECTION, null, "name"); //$NON-NLS-1$
+ String email = config.getString(USER_SECTION, null, "email"); //$NON-NLS-1$
+ return String.format("%s <%s>", userName, email); //$NON-NLS-1$
+ }
+
+ /**
+ * @return feature prefix configured for this repository.
+ */
+ public String getFeaturePrefix() {
+ return getPrefix(FEATURE_KEY, FEATURE_PREFIX);
+ }
+
+ /**
+ * @return release prefix configured for this repository.
+ */
+ public String getReleasePrefix() {
+ return getPrefix(RELEASE_KEY, RELEASE_PREFIX);
+ }
+
+ /**
+ * @return hotfix prefix configured for this repository.
+ */
+ public String getHotfixPrefix() {
+ return getPrefix(HOTFIX_KEY, HOTFIX_PREFIX);
+ }
+
+ /**
+ * @return version prefix configured for this repository, that is used in
+ * tags.
+ */
+ public String getVersionTagPrefix() {
+ return getPrefix(VERSION_TAG_KEY, VERSION_TAG);
+ }
+
+ /**
+ * @return name of develop configured for this repository.
+ */
+ public String getDevelop() {
+ return getBranch(DEVELOP_KEY, DEVELOP);
+ }
+
+ /**
+ * @return full name of develop configured for this repository.
+ */
+ public String getDevelopFull() {
+ return R_HEADS + getDevelop();
+ }
+
+ /**
+ * @return name of master configured for this repository.
+ */
+ public String getMaster() {
+ return getBranch(MASTER_KEY, GitFlowDefaults.MASTER);
+ }
+
+ /**
+ * @param prefixName
+ * @param defaultPrefix
+ * @return value for key prefixName from .git/config or default
+ */
+ public String getPrefix(String prefixName, String defaultPrefix) {
+ StoredConfig config = repository.getConfig();
+ String result = config.getString(GITFLOW_SECTION, PREFIX_SECTION,
+ prefixName);
+ return (result == null) ? defaultPrefix : result;
+ }
+
+ /**
+ * @param branch
+ * @param defaultBranch
+ * @return value for key branch from .git/config or default
+ */
+ public String getBranch(String branch, String defaultBranch) {
+ StoredConfig config = repository.getConfig();
+ String result = config.getString(GITFLOW_SECTION, BRANCH_SECTION,
+ branch);
+ return (result == null) ? defaultBranch : result;
+ }
+
+ /**
+ * Set prefix in .git/config
+ *
+ * @param prefixName
+ * @param value
+ */
+ public void setPrefix(String prefixName, String value) {
+ StoredConfig config = repository.getConfig();
+ config.setString(GITFLOW_SECTION, PREFIX_SECTION, prefixName, value);
+ }
+
+ /**
+ * Set branchName in .git/config
+ *
+ * @param branchName
+ * @param value
+ */
+ public void setBranch(String branchName, String value) {
+ StoredConfig config = repository.getConfig();
+ config.setString(GITFLOW_SECTION, BRANCH_SECTION, branchName, value);
+ }
+
+ /**
+ * @param featureName
+ * @return full name of branch featureName
+ */
+ public String getFullFeatureBranchName(String featureName) {
+ return R_HEADS + getFeatureBranchName(featureName);
+ }
+
+ /**
+ * @param featureName
+ * @return name of branch featureName
+ */
+ public String getFeatureBranchName(String featureName) {
+ return getFeaturePrefix() + featureName;
+ }
+
+ /**
+ * @param hotfixName
+ * @return name of branch hotfixName
+ */
+ public String getHotfixBranchName(String hotfixName) {
+ return getHotfixPrefix() + hotfixName;
+ }
+
+ /**
+ * @param hotfixName
+ * @return full name of branch hotfixName
+ */
+ public String getFullHotfixBranchName(String hotfixName) {
+ return R_HEADS + getHotfixBranchName(hotfixName);
+ }
+
+ /**
+ * @param releaseName
+ * @return full name of branch releaseName
+ */
+ public String getFullReleaseBranchName(String releaseName) {
+ return R_HEADS + getReleaseBranchName(releaseName);
+ }
+
+ /**
+ * @param releaseName
+ * @return name of branch releaseName
+ */
+ public String getReleaseBranchName(String releaseName) {
+ return getReleasePrefix() + releaseName;
+ }
+
+ /**
+ * @return Configured origin.
+ */
+ public RemoteConfig getDefaultRemoteConfig() {
+ StoredConfig rc = repository.getConfig();
+ RemoteConfig result;
+ try {
+ result = new RemoteConfig(rc, DEFAULT_REMOTE_NAME);
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ return result;
+ }
+
+ /**
+ * @return Whether or not there is a default remote configured.
+ */
+ public boolean hasDefaultRemote() {
+ RemoteConfig config = getDefaultRemoteConfig();
+ return !config.getURIs().isEmpty();
+ }
+
+ /**
+ * @param featureName
+ * @param value
+ * @throws IOException
+ */
+ public void setRemote(String featureName, String value) throws IOException {
+ setBranchValue(featureName, value, REMOTE_KEY);
+ }
+
+ /**
+ * @param featureName
+ * @param value
+ * @throws IOException
+ */
+ public void setUpstreamBranchName(String featureName, String value) throws IOException {
+ setBranchValue(featureName, value, MERGE_KEY);
+ }
+
+ /**
+ * @param featureName
+ * @return Upstream branch name
+ */
+ public String getUpstreamBranchName(String featureName) {
+ StoredConfig config = repository.getConfig();
+ return config.getString(BRANCH_SECTION,
+ getFeatureBranchName(featureName), MERGE_KEY);
+ }
+
+ private void setBranchValue(String featureName, String value,
+ String mergeKey) throws IOException {
+ StoredConfig config = repository.getConfig();
+ config.setString(BRANCH_SECTION, featureName, mergeKey, value);
+ config.save();
+ }
+
+ /**
+ * @param featureName
+ * @return remote tracking branch
+ */
+ public String getRemoteName(String featureName) {
+ StoredConfig config = repository.getConfig();
+ return config.getString(BRANCH_SECTION,
+ getFeatureBranchName(featureName), REMOTE_KEY);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowDefaults.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowDefaults.java
new file mode 100644
index 000000000..b37077a32
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowDefaults.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+/**
+ * Git flow branch names and prefixes.
+ */
+public final class GitFlowDefaults {
+ // TODO: this must be configurable
+
+ /** */
+ public static final String MASTER = "master"; //$NON-NLS-1$
+
+ /** */
+ public static final String DEVELOP = "develop"; //$NON-NLS-1$
+
+ /** */
+ public static final String FEATURE_PREFIX = "feature/"; //$NON-NLS-1$
+
+ /** */
+ public static final String RELEASE_PREFIX = "release/"; //$NON-NLS-1$
+
+ /** */
+ public static final String HOTFIX_PREFIX = "hotfix/"; //$NON-NLS-1$
+
+ /** */
+ public static final String VERSION_TAG = ""; //$NON-NLS-1$
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowRepository.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowRepository.java
new file mode 100644
index 000000000..753988232
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/GitFlowRepository.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.eclipse.jgit.lib.Constants.R_TAGS;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Wrapper for JGit repository.
+ *
+ * @since 4.0
+ */
+public class GitFlowRepository {
+
+ private Repository repository;
+
+ private GitFlowConfig config;
+
+ /**
+ * @param repository
+ */
+ public GitFlowRepository(Repository repository) {
+ Assert.isNotNull(repository);
+ this.repository = repository;
+ this.config = new GitFlowConfig(repository);
+ }
+
+ /**
+ * @return Whether or not this repository has branches.
+ */
+ public boolean hasBranches() {
+ List<Ref> branches;
+ try {
+ branches = Git.wrap(repository).branchList().call();
+ return !branches.isEmpty();
+ } catch (GitAPIException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param branch
+ * @return Whether or not branch exists in this repository.
+ * @throws GitAPIException
+ */
+ public boolean hasBranch(String branch) throws GitAPIException {
+ String fullBranchName = R_HEADS + branch;
+ List<Ref> branchList = Git.wrap(repository).branchList().call();
+ for (Ref ref : branchList) {
+ if (fullBranchName.equals(ref.getTarget().getName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param branchName
+ * @return Ref for branchName.
+ * @throws IOException
+ */
+ public Ref findBranch(String branchName) throws IOException {
+ return repository.getRef(R_HEADS + branchName);
+ }
+
+ /**
+ * @return current branch has feature-prefix?
+ * @throws IOException
+ */
+ public boolean isFeature() throws IOException {
+ return repository.getBranch()
+ .startsWith(getConfig().getFeaturePrefix());
+ }
+
+ /**
+ * @return branch name has name "develop"?
+ * @throws IOException
+ */
+ public boolean isDevelop() throws IOException {
+ return repository.getBranch().equals(getConfig().getDevelop());
+ }
+
+ /**
+ * @return branch name has name "master"?
+ * @throws IOException
+ */
+ public boolean isMaster() throws IOException {
+ return repository.getBranch().equals(getConfig().getMaster());
+ }
+
+ /**
+ * @return current branchs has release-prefix?
+ * @throws IOException
+ */
+ public boolean isRelease() throws IOException {
+ return repository.getBranch().startsWith(getConfig().getReleasePrefix());
+ }
+
+ /**
+ * @return current branchs has hotfix-prefix?
+ * @throws IOException
+ */
+ public boolean isHotfix() throws IOException {
+ return repository.getBranch().startsWith(getConfig().getHotfixPrefix());
+ }
+
+ /**
+ * @return HEAD commit
+ * @throws WrongGitFlowStateException
+ */
+ public RevCommit findHead() throws WrongGitFlowStateException {
+ try (RevWalk walk = new RevWalk(repository)) {
+ try {
+ ObjectId head = repository.resolve(HEAD);
+ return walk.parseCommit(head);
+ } catch (MissingObjectException e) {
+ throw new WrongGitFlowStateException(CoreText.GitFlowRepository_gitFlowRepositoryMayNotBeEmpty);
+ } catch (RevisionSyntaxException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * @param branchName
+ * @return HEAD commit on branch branchName
+ */
+ public RevCommit findHead(String branchName) {
+ try (RevWalk walk = new RevWalk(repository)) {
+ try {
+ ObjectId head = repository.resolve(R_HEADS + branchName);
+ return walk.parseCommit(head);
+ } catch (RevisionSyntaxException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * @param sha1
+ * @return Commit for SHA1
+ */
+ public RevCommit findCommit(String sha1) {
+ try (RevWalk walk = new RevWalk(repository)) {
+ try {
+ ObjectId head = repository.resolve(sha1);
+ return walk.parseCommit(head);
+ } catch (RevisionSyntaxException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ /**
+ * @return JGit repository
+ */
+ public Repository getRepository() {
+ return repository;
+ }
+
+ /**
+ * @return git flow feature branches
+ */
+ public List<Ref> getFeatureBranches() {
+ return getPrefixBranches(R_HEADS + getConfig().getFeaturePrefix());
+ }
+
+ /**
+ * @return git flow release branches
+ */
+ public List<Ref> getReleaseBranches() {
+ return getPrefixBranches(R_HEADS + getConfig().getReleasePrefix());
+ }
+
+ /**
+ * @return git flow hotfix branches
+ */
+ public List<Ref> getHotfixBranches() {
+ return getPrefixBranches(R_HEADS + getConfig().getHotfixPrefix());
+ }
+
+ private List<Ref> getPrefixBranches(String prefix) {
+ try {
+ List<Ref> branches = Git.wrap(repository).branchList().call();
+ List<Ref> prefixBranches = new ArrayList<Ref>();
+ for (Ref ref : branches) {
+ if (ref.getName().startsWith(prefix)) {
+ prefixBranches.add(ref);
+ }
+ }
+
+ return prefixBranches;
+ } catch (GitAPIException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param ref
+ * @return branch name for ref
+ */
+ public String getFeatureBranchName(Ref ref) {
+ return ref.getName().substring(
+ (R_HEADS + getConfig().getFeaturePrefix()).length());
+ }
+
+ /**
+ * @param tagName
+ * @return commit tag tagName points to
+ * @throws MissingObjectException
+ * @throws IncorrectObjectTypeException
+ * @throws IOException
+ */
+ public RevCommit findCommitForTag(String tagName)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ try (RevWalk revWalk = new RevWalk(repository)) {
+ Ref tagRef = repository.getRef(R_TAGS + tagName);
+ if (tagRef == null) {
+ return null;
+ }
+ return revWalk.parseCommit(tagRef.getObjectId());
+ }
+ }
+
+ /**
+ * @param featureName
+ * @param value
+ * @throws IOException
+ */
+ public void setRemote(String featureName, String value) throws IOException {
+ getConfig().setRemote(featureName, value);
+ }
+
+ /**
+ * @param featureName
+ * @param value
+ * @throws IOException
+ */
+ public void setUpstreamBranchName(String featureName, String value) throws IOException {
+ getConfig().setUpstreamBranchName(featureName, value);
+ }
+
+ /**
+ * @param featureName
+ * @return Upstream branch name
+ */
+ public String getUpstreamBranchName(String featureName) {
+ return getConfig().getUpstreamBranchName(featureName);
+ }
+
+ /**
+ * @return the configuration of this repository
+ */
+ public GitFlowConfig getConfig() {
+ return this.config;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/WrongGitFlowStateException.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/WrongGitFlowStateException.java
new file mode 100644
index 000000000..c0ca76325
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/WrongGitFlowStateException.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow;
+
+/**
+ * Signifies that a git flow operation was performed on a git repository state,
+ * this operation is not intended for.
+ *
+ * @since 4.0
+ */
+public class WrongGitFlowStateException extends Exception {
+
+ /**
+ * @generated
+ */
+ private static final long serialVersionUID = 3091117695421525438L;
+
+ /**
+ * @param e
+ */
+ public WrongGitFlowStateException(Exception e) {
+ super(e);
+ }
+
+ /**
+ * @param string
+ */
+ public WrongGitFlowStateException(String string) {
+ super(string);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/CoreText.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/CoreText.java
new file mode 100644
index 000000000..dc64e8993
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/CoreText.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Visible strings for the GitFlow plugin.
+ */
+public class CoreText extends NLS {
+
+ /**
+ * Do not in-line this into the static initializer as the
+ * "Find Broken Externalized Strings" tool will not be able to find the
+ * corresponding bundle file.
+ */
+ private static final String BUNDLE_NAME = "org.eclipse.egit.gitflow.internal.coretext"; //$NON-NLS-1$
+
+ /** */
+
+ static {
+ initializeMessages(BUNDLE_NAME, CoreText.class);
+ }
+
+ /** */
+ public static String AbstractFeatureOperation_notOnAFeautreBranch;
+
+ /** */
+ public static String AbstractHotfixOperation_notOnAHotfixBranch;
+
+ /** */
+ public static String AbstractReleaseOperation_notOnAReleaseBranch;
+
+ /** */
+ public static String AbstractVersionFinishOperation_tagNameExists;
+
+ /** */
+ public static String FeatureListOperation_unableToParse;
+
+ /** */
+ public static String pushToRemoteFailed;
+
+ /** */
+ public static String unableToStoreGitConfig;
+
+ /** */
+ public static String FeatureRebaseOperation_notOnAFeatureBranch;
+
+ /** */
+ public static String FeatureStartOperation_notOn;
+
+ /** */
+ public static String FeatureTrackOperation_checkoutReturned;
+
+ /** */
+ public static String FeatureTrackOperation_localBranchExists;
+
+ /** */
+ public static String FeatureTrackOperation_unableToStoreGitConfig;
+
+ /** */
+ public static String GitFlowOperation_branchMissing;
+
+ /** */
+ public static String GitFlowOperation_branchNotFound;
+
+ /** */
+ public static String GitFlowOperation_unableToCheckout;
+
+ /** */
+ public static String GitFlowRepository_gitFlowRepositoryMayNotBeEmpty;
+
+ /** */
+ public static String HotfixFinishOperation_hotfix;
+
+ /** */
+ public static String HotfixFinishOperation_mergeFromHotfixToMasterFailed;
+
+ /** */
+ public static String InitOperation_initialCommit;
+
+ /** */
+ public static String ReleaseFinishOperation_releaseOf;
+
+ /** */
+ public static String ReleaseStartOperation_notOn;
+
+ /** */
+ public static String ReleaseStartOperation_releaseNameAlreadyExists;
+
+ /** */
+ public static String ReleaseStartOperation_unableToFindCommit;
+
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/coretext.properties b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/coretext.properties
new file mode 100644
index 000000000..1dfe4a386
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/internal/coretext.properties
@@ -0,0 +1,31 @@
+###############################################################################
+# Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+AbstractFeatureOperation_notOnAFeautreBranch=Not on a feature branch.
+AbstractHotfixOperation_notOnAHotfixBranch=Not on a hotfix branch.
+AbstractReleaseOperation_notOnAReleaseBranch=Not on a release branch.
+AbstractVersionFinishOperation_tagNameExists=Tag with name '%s' already exists\!
+FeatureListOperation_unableToParse=Unable to parse: {0}
+pushToRemoteFailed=Push to remote repository failed: {0}
+unableToStoreGitConfig=Unable to store git config.
+FeatureRebaseOperation_notOnAFeatureBranch=Not on a feature branch.
+FeatureStartOperation_notOn=Not on {0}
+FeatureTrackOperation_checkoutReturned=Trying checkout '%s' returned: %s
+FeatureTrackOperation_localBranchExists=Local branch '%s' already exists.
+FeatureTrackOperation_unableToStoreGitConfig=Unable to store git config.
+GitFlowOperation_branchMissing=Branch %s missing
+GitFlowOperation_branchNotFound=No branch '%s' found.
+GitFlowOperation_unableToCheckout=Unable to checkout '%s': %s
+GitFlowRepository_gitFlowRepositoryMayNotBeEmpty=Git flow repository may not be empty.
+HotfixFinishOperation_hotfix=Hotifx {0}
+HotfixFinishOperation_mergeFromHotfixToMasterFailed=Merge from Hotfix to Master branch failed. This shouldn't happen in GitFlow.
+InitOperation_initialCommit=Git Flow inital commit
+ReleaseFinishOperation_releaseOf=Release of {0}
+ReleaseStartOperation_notOn=Not on {0}
+ReleaseStartOperation_releaseNameAlreadyExists=The release name '%s' already exists.
+ReleaseStartOperation_unableToFindCommit=Unable to find commit {0}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperation.java
new file mode 100644
index 000000000..e9ea8c7b4
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractFeatureOperation.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+
+/**
+ * Common logic for feature branch operations.
+ */
+abstract public class AbstractFeatureOperation extends GitFlowOperation {
+ /** */
+ protected String featureName;
+
+ /**
+ * @param repository
+ * @param featureName
+ */
+ public AbstractFeatureOperation(GitFlowRepository repository,
+ String featureName) {
+ super(repository);
+ this.featureName = featureName;
+ }
+
+ /**
+ * @param repository
+ * @return current feature branch name
+ * @throws WrongGitFlowStateException
+ * @throws CoreException
+ * @throws IOException
+ */
+ protected static String getFeatureName(GitFlowRepository repository)
+ throws WrongGitFlowStateException, CoreException, IOException {
+ if (!repository.isFeature()) {
+ throw new WrongGitFlowStateException(
+ CoreText.AbstractFeatureOperation_notOnAFeautreBranch);
+ }
+ String currentBranch = repository.getRepository().getBranch();
+ return currentBranch.substring(repository.getConfig()
+ .getFeaturePrefix().length());
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractHotfixOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractHotfixOperation.java
new file mode 100644
index 000000000..3fdb3b41d
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractHotfixOperation.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+
+/**
+ * Common logic for hotfix branch operations.
+ */
+abstract public class AbstractHotfixOperation extends
+ AbstractVersionFinishOperation {
+ /**
+ * @param repository
+ * @param hotfixName
+ */
+ public AbstractHotfixOperation(GitFlowRepository repository,
+ String hotfixName) {
+ super(repository, hotfixName);
+ }
+
+ /**
+ * @param repository
+ * @return current hotfix branch name
+ * @throws WrongGitFlowStateException
+ * @throws CoreException
+ * @throws IOException
+ */
+ protected static String getHotfixName(GitFlowRepository repository)
+ throws WrongGitFlowStateException, CoreException, IOException {
+ if (!repository.isHotfix()) {
+ throw new WrongGitFlowStateException(
+ CoreText.AbstractHotfixOperation_notOnAHotfixBranch);
+ }
+ String currentBranch = repository.getRepository().getBranch();
+ return currentBranch.substring(repository.getConfig().getHotfixPrefix().length());
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractReleaseOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractReleaseOperation.java
new file mode 100644
index 000000000..40c972be5
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractReleaseOperation.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+
+/**
+ * Common logic for release branch operations.
+ */
+abstract public class AbstractReleaseOperation extends
+ AbstractVersionFinishOperation {
+ /**
+ * @param repository
+ * @param releaseName
+ */
+ public AbstractReleaseOperation(GitFlowRepository repository,
+ String releaseName) {
+ super(repository, releaseName);
+ }
+
+ /**
+ * @param repository
+ * @return current release branch name
+ * @throws WrongGitFlowStateException
+ * @throws CoreException
+ * @throws IOException
+ */
+ protected static String getReleaseName(GitFlowRepository repository)
+ throws WrongGitFlowStateException, CoreException, IOException {
+ if (!repository.isRelease()) {
+ throw new WrongGitFlowStateException(
+ CoreText.AbstractReleaseOperation_notOnAReleaseBranch);
+ }
+ String currentBranch = repository.getRepository().getBranch();
+ return currentBranch.substring(repository.getConfig().getReleasePrefix().length());
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractVersionFinishOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractVersionFinishOperation.java
new file mode 100644
index 000000000..bfc5cdccf
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/AbstractVersionFinishOperation.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static java.lang.String.format;
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.TagOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.lib.TagBuilder;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * common logic for git flow * finish
+ */
+abstract public class AbstractVersionFinishOperation extends GitFlowOperation {
+ /** */
+ protected String versionName;
+
+ /**
+ * @param repository
+ * @param versionName
+ */
+ public AbstractVersionFinishOperation(GitFlowRepository repository,
+ String versionName) {
+ super(repository);
+ this.versionName = versionName;
+ }
+
+ /**
+ * Check if tag exists before trying to create it.
+ *
+ * @param monitor
+ * @param tagName
+ * @param tagMessage
+ * @throws CoreException
+ */
+ protected void safeCreateTag(IProgressMonitor monitor, String tagName,
+ String tagMessage) throws CoreException {
+ RevCommit head;
+ try {
+ head = repository.findHead();
+ } catch (WrongGitFlowStateException e) {
+ throw new CoreException(error(e));
+ }
+ RevCommit commitForTag;
+ try {
+ commitForTag = repository.findCommitForTag(versionName);
+ if (commitForTag == null) {
+ createTag(monitor, head, tagName, tagMessage);
+ } else if (!head.equals(commitForTag)) {
+ throw new CoreException(error(format(
+ CoreText.AbstractVersionFinishOperation_tagNameExists,
+ versionName)));
+ }
+ } catch (IOException e) {
+ throw new CoreException(error(e));
+ }
+ }
+
+ /**
+ * @param monitor
+ * @param head
+ * @param name
+ * @param message
+ * @throws CoreException
+ */
+ protected void createTag(IProgressMonitor monitor, RevCommit head,
+ String name, String message) throws CoreException {
+ TagBuilder tag = new TagBuilder();
+ tag.setTag(name);
+ tag.setMessage(message);
+ tag.setObjectId(head);
+ new TagOperation(repository.getRepository(), tag, false)
+ .execute(monitor);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperation.java
new file mode 100644
index 000000000..e7ac5888d
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/CurrentBranchPublishOperation.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.egit.core.op.PushOperation;
+import org.eclipse.egit.core.op.PushOperationResult;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * git flow * publish
+ */
+public class CurrentBranchPublishOperation extends GitFlowOperation {
+ private PushOperationResult operationResult;
+
+ private int timeout;
+
+ /**
+ * publish given branch
+ *
+ * @param repository
+ * @param timeout
+ * @throws CoreException
+ */
+ public CurrentBranchPublishOperation(GitFlowRepository repository,
+ int timeout) throws CoreException {
+ super(repository);
+ this.timeout = timeout;
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ PushOperation pushOperation = new PushOperation(
+ repository.getRepository(), DEFAULT_REMOTE_NAME, false,
+ //TODO: check if multiple remotes exist? There is no explicit refspec?
+ timeout);
+ pushOperation.run(monitor);
+ operationResult = pushOperation.getOperationResult();
+
+ if (!operationResult.isSuccessfulConnectionForAnyURI()) {
+ String errorMessage = NLS.bind(CoreText.pushToRemoteFailed,
+ operationResult.getErrorStringForAllURis());
+ throw new CoreException(error(errorMessage));
+ }
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ throw new CoreException(error(targetException.getMessage(),
+ targetException));
+ }
+
+ String newLocalBranch = getCurrentBranchhName();
+ try {
+ repository.setRemote(newLocalBranch, DEFAULT_REMOTE_NAME);
+ repository.setUpstreamBranchName(newLocalBranch, repository.getRepository().getFullBranch());
+ } catch (IOException e) {
+ throw new CoreException(error(CoreText.unableToStoreGitConfig, e));
+ }
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public PushOperationResult getOperationResult() {
+ return operationResult;
+ }
+
+ private String getCurrentBranchhName() {
+ try {
+ return repository.getRepository().getBranch();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public ISchedulingRule getSchedulingRule() {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperation.java
new file mode 100644
index 000000000..7302f03aa
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureCheckoutOperation.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.jgit.api.CheckoutResult;
+
+/**
+ * git flow feature checkout
+ */
+public final class FeatureCheckoutOperation extends AbstractFeatureOperation {
+ private CheckoutResult result;
+
+ /**
+ * @param repository
+ * @param featureName
+ */
+ public FeatureCheckoutOperation(GitFlowRepository repository,
+ String featureName) {
+ super(repository, featureName);
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String branchName = repository.getConfig().getFeatureBranchName(featureName);
+
+ boolean dontCloseProjects = false;
+ BranchOperation branchOperation = new BranchOperation(
+ repository.getRepository(), branchName, dontCloseProjects);
+ branchOperation.execute(null);
+ result = branchOperation.getResult();
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public CheckoutResult getResult() {
+ return result;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureFinishOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureFinishOperation.java
new file mode 100644
index 000000000..bf023a84f
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureFinishOperation.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+
+/**
+ * git flow feature finish
+ */
+public final class FeatureFinishOperation extends AbstractFeatureOperation {
+ /**
+ * Finish given feautre.
+ *
+ * @param repository
+ * @param featureName
+ */
+ public FeatureFinishOperation(GitFlowRepository repository,
+ String featureName) {
+ super(repository, featureName);
+ }
+
+ /**
+ * Finish current feature.
+ *
+ * @param repository
+ * @throws CoreException
+ * @throws WrongGitFlowStateException
+ * @throws IOException
+ */
+ public FeatureFinishOperation(GitFlowRepository repository)
+ throws CoreException, WrongGitFlowStateException, IOException {
+ this(repository, getFeatureName(repository));
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ finish(monitor, repository.getConfig().getFeatureBranchName(featureName));
+ }
+
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureListOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureListOperation.java
new file mode 100644
index 000000000..40605c152
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureListOperation.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_REMOTES;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.egit.core.op.ListRemoteOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * List feature branches.
+ */
+public final class FeatureListOperation extends GitFlowOperation {
+ private static final String FILE = "file:///"; //$NON-NLS-1$
+
+ private static final String REMOTE_ORIGIN_FEATURE_PREFIX = R_REMOTES
+ + DEFAULT_REMOTE_NAME + SEP;
+
+ private List<Ref> result = new ArrayList<Ref>();
+
+ private int timeout;
+
+ private FetchResult operationResult;
+
+ /**
+ * @param repository
+ * @param timeout
+ */
+ public FeatureListOperation(GitFlowRepository repository, int timeout) {
+ super(repository);
+ this.timeout = timeout;
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String uriString = FILE
+ + repository.getRepository().getDirectory().getPath();
+ try {
+ operationResult = fetch(monitor);
+
+ URIish uri = new URIish(uriString);
+ ListRemoteOperation listRemoteOperation = new ListRemoteOperation(
+ repository.getRepository(), uri, timeout);
+ listRemoteOperation.run(monitor);
+ Collection<Ref> remoteRefs = listRemoteOperation.getRemoteRefs();
+ for (Ref ref : remoteRefs) {
+ if (ref.getName().startsWith(
+ REMOTE_ORIGIN_FEATURE_PREFIX
+ + repository.getConfig().getFeaturePrefix())) {
+ result.add(ref);
+ }
+ }
+ } catch (URISyntaxException e) {
+ String message = NLS.bind(CoreText.FeatureListOperation_unableToParse, uriString);
+ throw new CoreException(error(message, e));
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ throw new CoreException(error(targetException.getMessage(),
+ targetException));
+ } catch (InterruptedException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public FetchResult getOperationResult() {
+ return operationResult;
+ }
+
+ /**
+ * @return list of feature branches
+ */
+ public List<Ref> getResult() {
+ return result;
+ }
+
+ @Override
+ public ISchedulingRule getSchedulingRule() {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperation.java
new file mode 100644
index 000000000..650003409
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureRebaseOperation.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.RebaseOperation;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.api.RebaseResult;
+
+/**
+ * git flow feature rebase
+ */
+public final class FeatureRebaseOperation extends GitFlowOperation {
+ private RebaseResult operationResult;
+
+ /**
+ * @param repository
+ */
+ public FeatureRebaseOperation(GitFlowRepository repository) {
+ super(repository);
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ if (!repository.isFeature()) {
+ throw new WrongGitFlowStateException(
+ CoreText.FeatureRebaseOperation_notOnAFeatureBranch);
+ }
+
+ RebaseOperation op = new RebaseOperation(
+ repository.getRepository(), repository.getRepository()
+ .getRef(repository.getConfig().getDevelopFull()));
+ op.execute(null);
+
+ operationResult = op.getResult();
+ } catch (WrongGitFlowStateException | IOException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public RebaseResult getOperationResult() {
+ return operationResult;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureStartOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureStartOperation.java
new file mode 100644
index 000000000..6f7d2e568
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureStartOperation.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * git flow feature start
+ */
+public final class FeatureStartOperation extends AbstractFeatureOperation {
+ /**
+ * @param repository
+ * @param featureName
+ */
+ public FeatureStartOperation(GitFlowRepository repository,
+ String featureName) {
+ super(repository, featureName);
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String branchName = repository.getConfig().getFeatureBranchName(featureName);
+
+ try {
+ if (!repository.isDevelop()) {
+ throw new CoreException(
+ error(NLS.bind(CoreText.FeatureStartOperation_notOn, repository.getConfig().getDevelop())));
+ }
+ } catch (IOException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+ RevCommit head;
+ try {
+ head = repository.findHead();
+ } catch (WrongGitFlowStateException e) {
+ throw new CoreException(error(e));
+ }
+ start(monitor, branchName, head);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureTrackOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureTrackOperation.java
new file mode 100644
index 000000000..d3818eca0
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/FeatureTrackOperation.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.jgit.lib.Constants.DEFAULT_REMOTE_NAME;
+import static org.eclipse.jgit.lib.Constants.R_REMOTES;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation.UpstreamConfig;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.api.CheckoutResult;
+import org.eclipse.jgit.api.CheckoutResult.Status;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.FetchResult;
+
+/**
+ * git flow feature track
+ */
+public final class FeatureTrackOperation extends AbstractFeatureOperation {
+ private static final String REMOTE_ORIGIN_FEATURE_PREFIX = R_REMOTES
+ + DEFAULT_REMOTE_NAME + SEP;
+
+ private Ref remoteFeature;
+
+ private FetchResult operationResult;
+
+ /**
+ * Track given ref, referencing a feature branch.
+ *
+ * @param repository
+ * @param ref
+ */
+ public FeatureTrackOperation(GitFlowRepository repository, Ref ref) {
+ this(repository, ref, ref.getName().substring(
+ (REMOTE_ORIGIN_FEATURE_PREFIX + repository.getConfig()
+ .getFeaturePrefix()).length()));
+ }
+
+ /**
+ * Track given feature branch locally as newLocalBranch.
+ *
+ * @param repository
+ * @param ref
+ * @param newLocalBranch
+ */
+ public FeatureTrackOperation(GitFlowRepository repository, Ref ref,
+ String newLocalBranch) {
+ super(repository, newLocalBranch);
+ this.remoteFeature = ref;
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ String newLocalBranch = repository
+ .getConfig().getFeatureBranchName(featureName);
+ operationResult = fetch(monitor);
+
+ if (repository.hasBranch(newLocalBranch)) {
+ String errorMessage = String.format(
+ CoreText.FeatureTrackOperation_localBranchExists,
+ newLocalBranch);
+ throw new CoreException(error(errorMessage));
+ }
+ CreateLocalBranchOperation createLocalBranchOperation = new CreateLocalBranchOperation(
+ repository.getRepository(), newLocalBranch, remoteFeature,
+ UpstreamConfig.MERGE);
+ createLocalBranchOperation.execute(monitor);
+
+ BranchOperation branchOperation = new BranchOperation(
+ repository.getRepository(), newLocalBranch);
+ branchOperation.execute(monitor);
+ CheckoutResult result = branchOperation.getResult();
+ if (!Status.OK.equals(result.getStatus())) {
+ String errorMessage = String.format(
+ CoreText.FeatureTrackOperation_checkoutReturned,
+ newLocalBranch, result.getStatus().name());
+ throw new CoreException(error(errorMessage));
+ }
+
+ try {
+ repository.setRemote(newLocalBranch, DEFAULT_REMOTE_NAME);
+ repository.setUpstreamBranchName(newLocalBranch,
+ repository.getConfig().getFullFeatureBranchName(featureName));
+ } catch (IOException e) {
+ throw new CoreException(error(
+ CoreText.FeatureTrackOperation_unableToStoreGitConfig,
+ e));
+ }
+ } catch (URISyntaxException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ throw new CoreException(error(targetException.getMessage(),
+ targetException));
+ } catch (GitAPIException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public FetchResult getOperationResult() {
+ return operationResult;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/GitFlowOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/GitFlowOperation.java
new file mode 100644
index 000000000..5a33c3c95
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/GitFlowOperation.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static java.lang.String.format;
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.egit.core.internal.job.RuleUtil;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
+import org.eclipse.egit.core.op.DeleteBranchOperation;
+import org.eclipse.egit.core.op.FetchOperation;
+import org.eclipse.egit.core.op.IEGitOperation;
+import org.eclipse.egit.core.op.MergeOperation;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.api.CheckoutResult;
+import org.eclipse.jgit.api.CheckoutResult.Status;
+import org.eclipse.jgit.api.MergeResult;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RemoteConfig;
+
+/**
+ * Common logic for Git Flow operations.
+ */
+abstract public class GitFlowOperation implements IEGitOperation {
+ /**
+ * git path separator
+ */
+ public static final String SEP = "/"; //$NON-NLS-1$
+
+ /**
+ * repository that is operated on.
+ */
+ protected GitFlowRepository repository;
+
+ /**
+ * @param repository
+ */
+ public GitFlowOperation(GitFlowRepository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ public ISchedulingRule getSchedulingRule() {
+ return RuleUtil.getRule(repository.getRepository());
+ }
+
+ /**
+ * @param branchName
+ * @param sourceCommit
+ * @return operation constructed from parameters
+ */
+ protected CreateLocalBranchOperation createBranchFromHead(
+ String branchName, RevCommit sourceCommit) {
+ return new CreateLocalBranchOperation(repository.getRepository(),
+ branchName, sourceCommit);
+ }
+
+ /**
+ * git flow * start
+ *
+ * @param monitor
+ * @param branchName
+ * @param sourceCommit
+ * @throws CoreException
+ */
+ protected void start(IProgressMonitor monitor, String branchName,
+ RevCommit sourceCommit) throws CoreException {
+ CreateLocalBranchOperation branchOperation = createBranchFromHead(
+ branchName, sourceCommit);
+ branchOperation.execute(monitor);
+ BranchOperation checkoutOperation = new BranchOperation(
+ repository.getRepository(), branchName);
+ checkoutOperation.execute(monitor);
+ }
+
+ /**
+ * git flow * finish
+ *
+ * @param monitor
+ * @param branchName
+ * @return result of merging back to develop branch
+ * @throws CoreException
+ */
+ protected MergeResult finish(IProgressMonitor monitor, String branchName)
+ throws CoreException {
+ try {
+ MergeResult mergeResult = mergeTo(monitor, branchName,
+ repository.getConfig().getDevelop());
+ if (!mergeResult.getMergeStatus().isSuccessful()) {
+ return mergeResult;
+ }
+
+ Ref branch = repository.findBranch(branchName);
+ if (branch == null) {
+ throw new IllegalStateException(String.format(
+ CoreText.GitFlowOperation_branchMissing, branchName));
+ }
+ new DeleteBranchOperation(repository.getRepository(), branch, false)
+ .execute(monitor);
+
+ return mergeResult;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param monitor
+ * @param branchName
+ * @param targetBranchName
+ * @return result of merging back to targetBranchName
+ * @throws CoreException
+ */
+ protected MergeResult mergeTo(IProgressMonitor monitor, String branchName,
+ String targetBranchName) throws CoreException {
+ try {
+ if (!repository.hasBranch(targetBranchName)) {
+ throw new RuntimeException(String.format(
+ CoreText.GitFlowOperation_branchNotFound,
+ targetBranchName));
+ }
+ boolean dontCloseProjects = false;
+ BranchOperation branchOperation = new BranchOperation(
+ repository.getRepository(), targetBranchName,
+ dontCloseProjects);
+ branchOperation.execute(monitor);
+ Status status = branchOperation.getResult().getStatus();
+ if (!CheckoutResult.Status.OK.equals(status)) {
+ throw new CoreException(error(format(
+ CoreText.GitFlowOperation_unableToCheckout, branchName,
+ status.toString())));
+ }
+ MergeOperation mergeOperation = new MergeOperation(
+ repository.getRepository(), branchName);
+ mergeOperation.execute(monitor);
+ return mergeOperation.getResult();
+ } catch (GitAPIException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param monitor
+ * @return resulting of fetching from remote
+ * @throws URISyntaxException
+ * @throws InvocationTargetException
+ */
+ protected FetchResult fetch(IProgressMonitor monitor)
+ throws URISyntaxException, InvocationTargetException {
+ RemoteConfig config = repository.getConfig().getDefaultRemoteConfig();
+ FetchOperation fetchOperation = new FetchOperation(
+ repository.getRepository(), config, 0, false);
+ fetchOperation.run(monitor);
+ return fetchOperation.getOperationResult();
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixFinishOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixFinishOperation.java
new file mode 100644
index 000000000..4feb2d419
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixFinishOperation.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.api.MergeResult;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * git flow hotfix finish
+ */
+public final class HotfixFinishOperation extends AbstractHotfixOperation {
+ private MergeResult mergeResult;
+
+ /**
+ * finish given hotfix branch
+ *
+ * @param repository
+ * @param hotfixName
+ */
+ public HotfixFinishOperation(GitFlowRepository repository, String hotfixName) {
+ super(repository, hotfixName);
+ }
+
+ /**
+ * finish current hotfix branch
+ *
+ * @param repository
+ * @throws WrongGitFlowStateException
+ * @throws CoreException
+ * @throws IOException
+ */
+ public HotfixFinishOperation(GitFlowRepository repository)
+ throws WrongGitFlowStateException, CoreException, IOException {
+ this(repository, getHotfixName(repository));
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String hotfixBranchName = repository.getConfig().getHotfixBranchName(versionName);
+ mergeResult = mergeTo(monitor, hotfixBranchName,
+ repository.getConfig().getMaster());
+ if (!mergeResult.getMergeStatus().isSuccessful()) {
+ throw new CoreException(
+ error(CoreText.HotfixFinishOperation_mergeFromHotfixToMasterFailed));
+ }
+
+ mergeResult = finish(monitor, hotfixBranchName);
+ if (!mergeResult.getMergeStatus().isSuccessful()) {
+ return;
+ }
+
+ safeCreateTag(monitor, versionName,
+ NLS.bind(CoreText.HotfixFinishOperation_hotfix, versionName));
+ }
+
+ /**
+ * @return result set after operation was executed
+ */
+ public MergeResult getOperationResult() {
+ return mergeResult;
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixStartOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixStartOperation.java
new file mode 100644
index 000000000..eca9834a7
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/HotfixStartOperation.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+
+/**
+ * git flow hotfix start
+ */
+public final class HotfixStartOperation extends AbstractHotfixOperation {
+ /**
+ * @param repository
+ * @param hotfixName
+ */
+ public HotfixStartOperation(GitFlowRepository repository, String hotfixName) {
+ super(repository, hotfixName);
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String branchName = repository.getConfig().getHotfixBranchName(versionName);
+
+ start(monitor, branchName, repository.findHead(repository.getConfig().getMaster()));
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/InitOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/InitOperation.java
new file mode 100644
index 000000000..26ec3f044
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/InitOperation.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.core.op.CommitOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+import static org.eclipse.egit.gitflow.GitFlowDefaults.*;
+
+import org.eclipse.egit.gitflow.GitFlowConfig;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+
+import static org.eclipse.egit.gitflow.GitFlowConfig.*;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * git flow init
+ */
+public final class InitOperation extends GitFlowOperation {
+ private String develop;
+
+ private String master;
+
+ private String feature;
+
+ private String release;
+
+ private String hotfix;
+
+ private String versionTag;
+
+ /**
+ * @param jGitRepository
+ * @param develop
+ * @param master
+ * @param feature
+ * @param release
+ * @param hotfix
+ * @param versionTag
+ */
+ public InitOperation(Repository jGitRepository, String develop,
+ String master, String feature, String release, String hotfix,
+ String versionTag) {
+ super(new GitFlowRepository(jGitRepository));
+ this.develop = develop;
+ this.master = master;
+ this.feature = feature;
+ this.release = release;
+ this.hotfix = hotfix;
+ this.versionTag = versionTag;
+ }
+
+ /**
+ * use default prefixes and names
+ *
+ * @param repository
+ */
+ public InitOperation(Repository repository) {
+ this(repository, DEVELOP, MASTER, FEATURE_PREFIX, RELEASE_PREFIX,
+ HOTFIX_PREFIX);
+ }
+
+ /**
+ * @param repository
+ * @param develop
+ * @param master
+ * @param featurePrefix
+ * @param releasePrefix
+ * @param hotfixPrefix
+ */
+ public InitOperation(Repository repository, String develop, String master,
+ String featurePrefix, String releasePrefix, String hotfixPrefix) {
+ this(repository, develop, master, featurePrefix, releasePrefix,
+ hotfixPrefix, VERSION_TAG);
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ setPrefixes(feature, release, hotfix, versionTag);
+ setBranches(develop, master);
+ repository.getRepository().getConfig().save();
+ } catch (IOException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+
+ if (!repository.hasBranches()) {
+ new CommitOperation(repository.getRepository(),
+ repository.getConfig().getUser(), repository.getConfig().getUser(),
+ CoreText.InitOperation_initialCommit).execute(monitor);
+ }
+
+ try {
+ RevCommit head = repository.findHead();
+ if (!repository.hasBranch(develop)) {
+ CreateLocalBranchOperation branchFromHead = createBranchFromHead(
+ develop, head);
+ branchFromHead.execute(monitor);
+ BranchOperation checkoutOperation = new BranchOperation(
+ repository.getRepository(), develop);
+ checkoutOperation.execute(monitor);
+ }
+ } catch (WrongGitFlowStateException e) {
+ throw new CoreException(error(e));
+ } catch (GitAPIException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+ }
+
+ private void setPrefixes(String feature, String release, String hotfix,
+ String versionTag) {
+ GitFlowConfig config = repository.getConfig();
+ config.setPrefix(FEATURE_KEY, feature);
+ config.setPrefix(RELEASE_KEY, release);
+ config.setPrefix(HOTFIX_KEY, hotfix);
+ config.setPrefix(VERSION_TAG_KEY, versionTag);
+ }
+
+ private void setBranches(String develop, String master) {
+ GitFlowConfig config = repository.getConfig();
+ config.setBranch(DEVELOP_KEY, develop);
+ config.setBranch(MASTER_KEY, master);
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperation.java
new file mode 100644
index 000000000..4fcdc1c55
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseFinishOperation.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * git flow release finish
+ */
+public final class ReleaseFinishOperation extends AbstractReleaseOperation {
+ /**
+ * finish given release
+ *
+ * @param repository
+ * @param releaseName
+ */
+ public ReleaseFinishOperation(GitFlowRepository repository,
+ String releaseName) {
+ super(repository, releaseName);
+ }
+
+ /**
+ * finish current release
+ *
+ * @param repository
+ * @throws WrongGitFlowStateException
+ * @throws CoreException
+ * @throws IOException
+ */
+ public ReleaseFinishOperation(GitFlowRepository repository)
+ throws WrongGitFlowStateException, CoreException, IOException {
+ this(repository, getReleaseName(repository));
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String releaseBranchName = repository.getConfig().getReleaseBranchName(versionName);
+ mergeTo(monitor, releaseBranchName, repository.getConfig().getMaster());
+ finish(monitor, releaseBranchName);
+ safeCreateTag(monitor, repository.getConfig().getVersionTagPrefix() + versionName,
+ NLS.bind(CoreText.ReleaseFinishOperation_releaseOf, versionName));
+ }
+}
diff --git a/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseStartOperation.java b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseStartOperation.java
new file mode 100644
index 000000000..f61664e13
--- /dev/null
+++ b/org.eclipse.egit.gitflow/src/org/eclipse/egit/gitflow/op/ReleaseStartOperation.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.gitflow.op;
+
+import java.io.IOException;
+
+import static java.lang.String.format;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import static org.eclipse.egit.gitflow.Activator.error;
+import static org.eclipse.jgit.lib.Constants.*;
+
+import org.eclipse.egit.gitflow.GitFlowRepository;
+import org.eclipse.egit.gitflow.WrongGitFlowStateException;
+import org.eclipse.egit.gitflow.internal.CoreText;
+import org.eclipse.jgit.errors.AmbiguousObjectException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * git flow release start
+ */
+public final class ReleaseStartOperation extends AbstractReleaseOperation {
+ private String startCommitSha1;
+
+ /**
+ * start release from given commit
+ *
+ * @param repository
+ * @param startCommitSha1
+ * @param releaseName
+ */
+ public ReleaseStartOperation(GitFlowRepository repository,
+ String startCommitSha1, String releaseName) {
+ super(repository, releaseName);
+ this.startCommitSha1 = startCommitSha1;
+ }
+
+ /**
+ * start release from HEAD
+ *
+ * @param repository
+ * @param releaseName
+ * @throws WrongGitFlowStateException
+ */
+ public ReleaseStartOperation(GitFlowRepository repository,
+ String releaseName) throws WrongGitFlowStateException {
+ super(repository, releaseName);
+ this.startCommitSha1 = repository.findHead().getName();
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ String branchName = repository.getConfig().getReleaseBranchName(versionName);
+
+ try {
+ if (releaseExists()) {
+ throw new CoreException(
+ error(format(
+ CoreText.ReleaseStartOperation_releaseNameAlreadyExists,
+ versionName)));
+ }
+ if (!repository.isDevelop()) {
+ throw new CoreException(
+ error(NLS.bind(CoreText.ReleaseStartOperation_notOn, repository.getConfig().getDevelop())));
+ }
+ } catch (IOException e) {
+ throw new CoreException(error(e.getMessage(), e));
+ }
+
+ RevCommit commit = repository.findCommit(startCommitSha1);
+ if (commit == null) {
+ throw new IllegalStateException(NLS.bind(CoreText.ReleaseStartOperation_unableToFindCommit, commit));
+ }
+ start(monitor, branchName, commit);
+ }
+
+ /**
+ * @return whether or not the given versionName exists
+ * @throws RevisionSyntaxException
+ * @throws AmbiguousObjectException
+ * @throws IncorrectObjectTypeException
+ * @throws IOException
+ */
+ public boolean releaseExists()
+ throws RevisionSyntaxException, AmbiguousObjectException,
+ IncorrectObjectTypeException, IOException {
+ return null != repository.getRepository().resolve(
+ R_TAGS + repository.getConfig().getVersionTagPrefix() + versionName);
+ }
+}
diff --git a/org.eclipse.egit.repository/category.xml b/org.eclipse.egit.repository/category.xml
index 0b312848b..3d129eacc 100644
--- a/org.eclipse.egit.repository/category.xml
+++ b/org.eclipse.egit.repository/category.xml
@@ -27,6 +27,9 @@
<feature url="features/org.eclipse.jgit.http.apache_0.0.0.qualifier.jar" id="org.eclipse.jgit.http.apache" version="0.0.0">
<category name="JGit"/>
</feature>
+ <feature url="features/org.eclipse.egit.gitflow.feature_0.0.0.qualifier.jar" id="org.eclipse.egit.gitflow.feature" version="0.0.0">
+ <category name="Eclipse Git Team Provider - experimental features (incubation)"/>
+ </feature>
<bundle id="org.eclipse.egit.ui.importer" version="0.0.1.qualifier">
<category name="Eclipse Git Team Provider - experimental features (incubation)"/>
</bundle>
diff --git a/org.eclipse.egit.ui/META-INF/MANIFEST.MF b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
index dd27a74d9..131b52a5b 100644
--- a/org.eclipse.egit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
@@ -71,11 +71,11 @@ Import-Package: org.eclipse.egit.core;version="[4.0.0,4.1.0)",
org.eclipse.jgit.treewalk.filter;version="[4.0.0,4.1.0)",
org.eclipse.jgit.util;version="[4.0.0,4.1.0)",
org.eclipse.jgit.util.io;version="[4.0.0,4.1.0)"
-Export-Package: org.eclipse.egit.ui;version="4.0.0";x-friends:="org.eclipse.egit.mylyn.ui",
- org.eclipse.egit.ui.internal;version="4.0.0";x-friends:="org.eclipse.egit.import",
+Export-Package: org.eclipse.egit.ui;version="4.0.0";x-friends:="org.eclipse.egit.mylyn.ui,org.eclipse.egit.gitflow.ui",
+ org.eclipse.egit.ui.internal;version="4.0.0";x-friends:="org.eclipse.egit.import,org.eclipse.egit.gitflow.ui",
org.eclipse.egit.ui.internal.actions;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.blame;version="4.0.0";x-internal:=true,
- org.eclipse.egit.ui.internal.branch;version="4.0.0";x-internal:=true,
+ org.eclipse.egit.ui.internal.branch;version="4.0.0";x-friends:="org.eclipse.egit.gitflow.ui",
org.eclipse.egit.ui.internal.clean;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.clone;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.commands;version="4.0.0";x-internal:=true,
@@ -104,7 +104,7 @@ Export-Package: org.eclipse.egit.ui;version="4.0.0";x-friends:="org.eclipse.egit
org.eclipse.egit.ui.internal.reflog;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.reflog.command;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.repository;version="4.0.0";x-internal:=true,
- org.eclipse.egit.ui.internal.repository.tree;version="4.0.0";x-internal:=true,
+ org.eclipse.egit.ui.internal.repository.tree;version="4.0.0";x-friends:="org.eclipse.egit.gitflow.ui",
org.eclipse.egit.ui.internal.repository.tree.command;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.revision;version="4.0.0";x-internal:=true,
org.eclipse.egit.ui.internal.search;version="4.0.0";x-internal:=true,
diff --git a/pom.xml b/pom.xml
index 5e03eb70c..97e882ca5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -293,13 +293,19 @@
<module>org.eclipse.egit.doc</module>
<module>org.eclipse.egit-feature</module>
- <module>org.eclipse.egit.core.test</module>
- <module>org.eclipse.egit.ui.test</module>
- <module>org.eclipse.egit.mylyn.ui.test</module>
+ <module>org.eclipse.egit.gitflow-feature</module>
+ <module>org.eclipse.egit.gitflow</module>
+ <module>org.eclipse.egit.gitflow.ui</module>
+ <module>org.eclipse.egit.gitflow.test</module>
<module>org.eclipse.egit.source-feature</module>
<module>org.eclipse.egit.repository</module>
+
+ <module>org.eclipse.egit.core.test</module>
+ <module>org.eclipse.egit.ui.test</module>
+ <module>org.eclipse.egit.mylyn.ui.test</module>
+
</modules>
<pluginRepositories>

Back to the top