Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Nittka2020-01-04 19:31:15 +0000
committerThomas Wolf2020-02-25 07:14:02 +0000
commit1205b4b3e62d5622378c20576e1582f9155c677c (patch)
tree2e076c0dd3991f6109bf052e9c91e10f3c7d9c81
parent97385df3e09c3351760e6f6ca415438ca1dba786 (diff)
downloadegit-1205b4b3e62d5622378c20576e1582f9155c677c.tar.gz
egit-1205b4b3e62d5622378c20576e1582f9155c677c.tar.xz
egit-1205b4b3e62d5622378c20576e1582f9155c677c.zip
Create branch from repository group
Allow creating a new branch for a mixed selections of repositories and/or repository groups. The branch is created from the current head. Except for the branch name no further configuration is possible. Bug: 558561 Change-Id: Ic6dccb6d9813ee568c70997d997f92121de46752 Signed-off-by: Alexander Nittka <alex@nittka.de> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/actions/SwitchToMenuTest.java20
-rw-r--r--org.eclipse.egit.ui/plugin.xml6
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java9
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SwitchToMenu.java121
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties3
5 files changed, 145 insertions, 14 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/actions/SwitchToMenuTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/actions/SwitchToMenuTest.java
index 7448f0bc80..6e10462354 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/actions/SwitchToMenuTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/actions/SwitchToMenuTest.java
@@ -209,13 +209,15 @@ public class SwitchToMenuTest extends LocalRepositoryTestCase {
mockMultiProjectSelection(PROJ1, PROJ2);
MenuItem[] items = fillMenu();
- assertTextEquals("change/15", items[0]);
- assertTextEquals("change/16", items[1]);
- assertTextEquals("change/17", items[2]);
- assertTextEquals("change/18", items[3]);
- assertTextEquals("change/19", items[4]);
- assertTextEquals("master", items[5]);
- assertTextEquals("stable", items[6]);
+ assertTextEquals(UIText.SwitchToMenu_NewBranchMenuLabel, items[0]);
+ // item[1] is separator
+ assertTextEquals("change/15", items[2]);
+ assertTextEquals("change/16", items[3]);
+ assertTextEquals("change/17", items[4]);
+ assertTextEquals("change/18", items[5]);
+ assertTextEquals("change/19", items[6]);
+ assertTextEquals("master", items[7]);
+ assertTextEquals("stable", items[8]);
}
@Test
@@ -273,7 +275,9 @@ public class SwitchToMenuTest extends LocalRepositoryTestCase {
mockMultiProjectSelection(PROJ1, PROJ2);
MenuItem[] items = fillMenu();
- assertTextEquals(UIText.SwitchToMenu_NoCommonBranchesFound, items[0]);
+ assertTextEquals(UIText.SwitchToMenu_NewBranchMenuLabel, items[0]);
+ // item[1] is separator
+ assertTextEquals(UIText.SwitchToMenu_NoCommonBranchesFound, items[2]);
// delete reflog again to not confuse other tests
new File(gitOne, Constants.LOGS + "/" + Constants.HEAD).delete();
diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml
index 7a60e571c3..4f75930cb6 100644
--- a/org.eclipse.egit.ui/plugin.xml
+++ b/org.eclipse.egit.ui/plugin.xml
@@ -4251,6 +4251,9 @@
<and>
<or>
<instanceof
+ value="org.eclipse.egit.ui.internal.repository.tree.RepositoryGroupNode">
+ </instanceof>
+ <instanceof
value="org.eclipse.egit.ui.internal.repository.tree.RepositoryNode">
</instanceof>
<instanceof
@@ -4263,6 +4266,9 @@
<test property="GitRepository.isBare" value="false" />
</and>
</iterate>
+ <test
+ property="GitSelection.selectionMultipleRepositories" value="false">
+ </test>
</and>
</visibleWhen>
</menu>
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
index 45edd1c697..c1612b7231 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
@@ -2808,6 +2808,15 @@ public class UIText extends NLS {
public static String CreateBranchWizard_NewBranchTitle;
/** */
+ public static String CreateBranchBulkDialog_Title;
+
+ /** */
+ public static String CreateBranchBulkDialog_Description;
+
+ /** */
+ public static String CreateBranchBulkDialog_Error;
+
+ /** */
public static String CreateRepositoryCommand_CreateButtonLabel;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SwitchToMenu.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SwitchToMenu.java
index 82ed542a38..f4261578de 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SwitchToMenu.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SwitchToMenu.java
@@ -16,6 +16,7 @@ package org.eclipse.egit.ui.internal.actions;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@@ -25,17 +26,23 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.egit.core.RepositoryUtil;
+import org.eclipse.egit.core.internal.Utils;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.CommonUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.branch.BranchOperationUI;
+import org.eclipse.egit.ui.internal.components.BranchNameNormalizer;
import org.eclipse.egit.ui.internal.dialogs.CheckoutDialog;
import org.eclipse.egit.ui.internal.history.CommitSelectionDialog;
import org.eclipse.egit.ui.internal.repository.CreateBranchWizard;
import org.eclipse.egit.ui.internal.selection.SelectionUtils;
import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
@@ -46,10 +53,15 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.util.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.handlers.IHandlerService;
@@ -113,12 +125,18 @@ public class SwitchToMenu extends ContributionItem implements
private void createDynamicMenu(Menu menu, final Repository[] repositories) {
+ boolean showCreateBranchItem = true;
if (!isMultipleSelection(repositories)) {
Repository repository = repositories[0];
createNewBranchMenuItem(menu, repository);
- if (hasBranches(repository)) {
- createSeparator(menu);
- }
+ } else if (canBulkCreateNewBranch(repositories)) {
+ createBulkNewBranchMenuItem(menu, repositories);
+ } else {
+ showCreateBranchItem = false;
+ }
+ if (showCreateBranchItem
+ && Arrays.stream(repositories).anyMatch(this::hasBranches)) {
+ createSeparator(menu);
}
int itemCount = createMostActiveBranchesMenuItems(menu, repositories);
@@ -138,6 +156,99 @@ public class SwitchToMenu extends ContributionItem implements
}
}
+ private boolean canBulkCreateNewBranch(Repository[] repositories) {
+ for (Repository repo : repositories) {
+ if (!hasBranches(repo)) {
+ return false;
+ }
+ if (repo.isBare()) {
+ return false;
+ }
+ if (repo.getRepositoryState() != RepositoryState.SAFE) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void createBulkNewBranchMenuItem(Menu menu,
+ final Repository[] repositories) {
+ MenuItem newBranch = getNewBranchMenuItem(menu);
+ newBranch.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ InputDialog dialog = new InputDialog(e.display.getActiveShell(),
+ UIText.CreateBranchBulkDialog_Title,
+ UIText.CreateBranchBulkDialog_Description, "", //$NON-NLS-1$
+ new IInputValidator() {
+ @Override
+ public String isValid(String newBranchName) {
+ return validateNewBulkBranchName(newBranchName,
+ repositories);
+ }
+ }) {
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Control result = super.createDialogArea(parent);
+ BranchNameNormalizer normalizer = new BranchNameNormalizer(
+ getText());
+ normalizer.setVisible(false);
+ return result;
+ }
+ };
+ if (dialog.open() == Window.OK) {
+ String name = dialog.getValue();
+ try {
+ for (Repository repository : repositories) {
+ Ref headRef = repository.exactRef(Constants.HEAD);
+ if (headRef != null) {
+ ObjectId headId = headRef.getLeaf()
+ .getObjectId();
+ RevCommit head = repository.parseCommit(headId);
+ CreateLocalBranchOperation op = new CreateLocalBranchOperation(
+ repository, name, head);
+ op.execute(null);
+ }
+ }
+ BranchOperationUI.checkout(repositories, name).start();
+ } catch (Exception exception) {
+ Activator.handleError(
+ UIText.CreateBranchBulkDialog_Error, exception,
+ true);
+ }
+ }
+ }
+ });
+ }
+
+ private MenuItem getNewBranchMenuItem(Menu parentMenu) {
+ MenuItem newBranch = new MenuItem(parentMenu, SWT.PUSH);
+ newBranch.setText(UIText.SwitchToMenu_NewBranchMenuLabel);
+ newBranch.setImage(newBranchImage);
+ return newBranch;
+ }
+
+ private String validateNewBulkBranchName(String newBranchName,
+ Repository[] repositories) {
+ if (StringUtils.isEmptyOrNull(newBranchName)
+ || newBranchName.trim().isEmpty()) {
+ return UIText.CreateBranchPage_ChooseNameMessage;
+ }
+ for (Repository repo : repositories) {
+ IStatus status = Utils.validateNewRefName(newBranchName, repo,
+ Constants.R_HEADS, true);
+ if (status.getException() != null) {
+ Activator.handleStatus(status, false);
+ }
+ if (!status.isOK()) {
+ return Activator.getDefault().getRepositoryUtil()
+ .getRepositoryName(repo) + ": " + status.getMessage(); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
private boolean hasBranches(Repository repository) {
try {
return !repository.getRefDatabase()
@@ -150,9 +261,7 @@ public class SwitchToMenu extends ContributionItem implements
}
private void createNewBranchMenuItem(Menu menu, Repository repository) {
- MenuItem newBranch = new MenuItem(menu, SWT.PUSH);
- newBranch.setText(UIText.SwitchToMenu_NewBranchMenuLabel);
- newBranch.setImage(newBranchImage);
+ MenuItem newBranch = getNewBranchMenuItem(menu);
newBranch.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
index badc3ca884..872cbe05cd 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
@@ -944,6 +944,9 @@ CreateBranchPage_SourceTooltip=The new branch will start at this point
CreateBranchPage_Title=Create a new branch in repository {0}
CreateBranchWizard_CreationFailed=Branch could not be created
CreateBranchWizard_NewBranchTitle=Create Branch
+CreateBranchBulkDialog_Title=Create Branch in Multiple Repositories
+CreateBranchBulkDialog_Description=Enter the name of a new branch to be created from HEAD in all selected repositories:
+CreateBranchBulkDialog_Error=Error during bulk branch creation
CreateRepositoryCommand_CreateButtonLabel=&Create
CreateRepositoryPage_BareCheckbox=&Create as bare repository
CreateRepositoryPage_BrowseButton=&Browse...

Back to the top