blob: 420a7c3fe5024624ea3ea6309a5c96d0311bd55d [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007, 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
* Copyright (C) 2010, Matthias Sohn <matthias.sohn@sap.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.egit.ui.internal.components;
import java.io.File;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.core.securestorage.UserPasswordCredentials;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.UIUtils.IPreviousValueProposalHandler;
import org.eclipse.egit.ui.internal.SecureStoreUtils;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.clone.GitUrlChecker;
import org.eclipse.egit.ui.internal.components.RemoteSelectionCombo.SelectionType;
import org.eclipse.egit.ui.internal.provisional.wizards.GitRepositoryInfo;
import org.eclipse.egit.ui.internal.provisional.wizards.IRepositorySearchResult;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FS;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
/**
* Wizard page that allows the user entering the location of a remote repository
* by specifying URL manually or selecting a preconfigured remote repository.
*/
public class RepositorySelectionPage extends WizardPage implements IRepositorySearchResult {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private final static String USED_URIS_PREF = "RepositorySelectionPage.UsedUris"; //$NON-NLS-1$
private final List<RemoteConfig> configuredRemotes;
private final boolean sourceSelection;
private final String presetUri;
private Group authGroup;
private Text uriText;
private Text hostText;
private Text pathText;
private Text userText;
private Text passText;
private Button storeCheckbox;
private Combo scheme;
private Text portText;
private int eventDepth;
private URIish uri;
private RemoteConfig remoteConfig;
private RepositorySelection selection;
private Composite remotePanel;
private Button remoteButton;
private RemoteSelectionCombo remoteCombo;
private Composite uriPanel;
private Button uriButton;
private IPreviousValueProposalHandler uriProposalHandler;
private String user = EMPTY_STRING;
private String password = EMPTY_STRING;
private boolean storeInSecureStore;
private String helpContext = null;
/**
* Transport protocol abstraction
*
* TODO rework this to become part of JGit API
*/
public static class Protocol {
/** Ordered list of all protocols **/
private static final TreeMap<String, Protocol> protocols = new TreeMap<>();
/** Git native transfer */
public static final Protocol GIT = new Protocol("git", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_git, true, true, false);
/** Git over SSH */
public static final Protocol SSH = new Protocol("ssh", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_ssh, true, true, true) {
@Override
public boolean handles(URIish uri) {
if (!uri.isRemote())
return false;
final String scheme = uri.getScheme();
if (getDefaultScheme().equals(scheme))
return true;
if ("ssh+git".equals(scheme)) //$NON-NLS-1$
return true;
if ("git+ssh".equals(scheme)) //$NON-NLS-1$
return true;
if (scheme == null && uri.getHost() != null
&& uri.getPath() != null)
return true;
return false;
}
};
/** Secure FTP */
public static final Protocol SFTP = new Protocol("sftp", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_sftp, true, true, true);
/** HTTP */
public static final Protocol HTTP = new Protocol("http", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_http, true, true, true);
/** Secure HTTP */
public static final Protocol HTTPS = new Protocol("https", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_https, true, true, true);
/** FTP */
public static final Protocol FTP = new Protocol("ftp", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_ftp, true, true, true);
/** Local repository */
public static final Protocol FILE = new Protocol("file", //$NON-NLS-1$
UIText.RepositorySelectionPage_tip_file, false, false, false) {
@Override
public boolean handles(URIish uri) {
if (getDefaultScheme().equals(uri.getScheme()))
return true;
if (uri.getHost() != null || uri.getPort() > 0
|| uri.getUser() != null || uri.getPass() != null
|| uri.getPath() == null)
return false;
if (uri.getScheme() == null)
return FS.DETECTED
.resolve(new File("."), uri.getPath()).isDirectory(); //$NON-NLS-1$
return false;
}
};
private final String defaultScheme;
private final String tooltip;
private final boolean hasHost;
private final boolean hasPort;
private final boolean canAuthenticate;
private Protocol(String defaultScheme, String tooltip,
boolean hasHost, boolean hasPort, boolean canAuthenticate) {
this.defaultScheme = defaultScheme;
this.tooltip = tooltip;
this.hasHost = hasHost;
this.hasPort = hasPort;
this.canAuthenticate = canAuthenticate;
protocols.put(defaultScheme, this);
}
/**
* @param uri
* URI to match against this protocol
* @return {@code true} if the uri is handled by this protocol
*/
public boolean handles(URIish uri) {
return getDefaultScheme().equals(uri.getScheme());
}
/**
* @return the default protocol scheme
*/
public String getDefaultScheme() {
return defaultScheme;
}
/**
* @return the tooltip text describing the protocol
*/
public String getTooltip() {
return tooltip;
}
/**
* @return true if protocol has host segment
*/
public boolean hasHost() {
return hasHost;
}
/**
* @return true if protocol has port
*/
public boolean hasPort() {
return hasPort;
}
/**
* @return true if protocol can authenticate
*/
public boolean canAuthenticate() {
return canAuthenticate;
}
/**
* @return all protocols
*/
public static Protocol[] values() {
return protocols.values().toArray(new Protocol[0]);
}
/**
* Lookup protocol supporting given default URL scheme
*
* @param scheme
* default scheme to lookup protocol for
* @return protocol matching scheme or null
*/
public static Protocol fromDefaultScheme(String scheme) {
return protocols.get(scheme);
}
/**
* Lookup protocol handling given URI
*
* @param uri URI to lookup protocol for
* @return protocol handling this URI
*/
public static Protocol fromUri(URIish uri) {
for (Protocol p : protocols.values())
if (p.handles(uri))
return p;
return null;
}
}
/**
* Create repository selection page, allowing user specifying URI or
* (optionally) choosing from preconfigured remotes list.
* <p>
* Wizard page is created without image, just with text description.
*
* @param sourceSelection
* true if dialog is used for source selection; false otherwise
* (destination selection). This indicates appropriate text
* messages.
* @param configuredRemotes
* list of configured remotes that user may select as an
* alternative to manual URI specification. Remotes appear in
* given order in GUI, with
* {@value Constants#DEFAULT_REMOTE_NAME} as the default choice.
* List may be null or empty - no remotes configurations appear
* in this case. Note that the provided list may be changed by
* this constructor.
* @param presetUri
* the pre-set URI, may be null
*/
public RepositorySelectionPage(final boolean sourceSelection,
final List<RemoteConfig> configuredRemotes, String presetUri) {
super(RepositorySelectionPage.class.getName());
this.uri = new URIish();
this.sourceSelection = sourceSelection;
String preset = presetUri;
if (presetUri == null) {
Clipboard clipboard = new Clipboard(Display.getCurrent());
try {
String text = (String) clipboard
.getContents(TextTransfer.getInstance());
if (text != null) {
text = GitUrlChecker.sanitizeAsGitUrl(text);
if (GitUrlChecker.isValidGitUrl(text)) {
preset = text;
}
}
} finally {
clipboard.dispose();
}
}
this.presetUri = preset;
this.configuredRemotes = getUsableConfigs(configuredRemotes);
selection = RepositorySelection.INVALID_SELECTION;
if (sourceSelection) {
setTitle(UIText.RepositorySelectionPage_sourceSelectionTitle);
setDescription(UIText.RepositorySelectionPage_sourceSelectionDescription);
} else {
setTitle(UIText.RepositorySelectionPage_destinationSelectionTitle);
setDescription(UIText.RepositorySelectionPage_destinationSelectionDescription);
}
storeInSecureStore = getPreferenceStore().getBoolean(
UIPreferences.CLONE_WIZARD_STORE_SECURESTORE);
}
/**
* Create repository selection page, allowing user specifying URI, with no
* preconfigured remotes selection.
*
* @param sourceSelection
* true if dialog is used for source selection; false otherwise
* (destination selection). This indicates appropriate text
* messages.
* @param presetUri
* the pre-set URI, may be null
*/
public RepositorySelectionPage(final boolean sourceSelection,
String presetUri) {
this(sourceSelection, null, presetUri);
}
/**
* No args constructor; needed because the page is provided by the extension
* point {@code org.eclipse.egit.ui.cloneSourceProvider}
*/
public RepositorySelectionPage() {
this(true, null);
}
/**
* @return repository selection representing current page state.
*/
public RepositorySelection getSelection() {
return selection;
}
/**
* Compare current repository selection set by user to provided one.
*
* @param s
* repository selection to compare.
* @return true if provided selection is equal to current page selection,
* false otherwise.
*/
public boolean selectionEquals(final RepositorySelection s) {
return selection.equals(s);
}
@Override
public void createControl(final Composite parent) {
final Composite panel = new Composite(parent, SWT.NULL);
panel.setLayout(new GridLayout());
if (configuredRemotes != null)
createRemotePanel(panel);
else
createRemoteNamePanel(panel);
createUriPanel(panel);
if (presetUri != null)
updateFields(presetUri);
updateRemoteAndURIPanels();
Dialog.applyDialogFont(panel);
setControl(panel);
checkPage();
}
private void createRemotePanel(final Composite parent) {
remoteButton = new Button(parent, SWT.RADIO);
remoteButton
.setText(UIText.RepositorySelectionPage_configuredRemoteChoice
+ ":"); //$NON-NLS-1$
remoteButton.setSelection(true);
remotePanel = new Composite(parent, SWT.NULL);
remotePanel.setLayout(new GridLayout());
final GridData gd = new GridData();
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
remotePanel.setLayoutData(gd);
SelectionType selectionType = sourceSelection ? SelectionType.FETCH : SelectionType.PUSH;
remoteCombo = new RemoteSelectionCombo(remotePanel, SWT.NULL, selectionType);
remoteConfig = remoteCombo.setItems(configuredRemotes);
remoteCombo.addRemoteSelectionListener(rc -> {
remoteConfig = rc;
checkPage();
});
}
/**
*
* @param panel
*/
protected void createRemoteNamePanel(Composite panel) {
// Only used by subclass
}
private void createUriPanel(final Composite parent) {
if (configuredRemotes != null) {
uriButton = new Button(parent, SWT.RADIO);
uriButton.setText(UIText.RepositorySelectionPage_uriChoice + ":"); //$NON-NLS-1$
uriButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// occurs either on selection or unselection event
updateRemoteAndURIPanels();
checkPage();
}
});
}
uriPanel = new Composite(parent, SWT.NULL);
uriPanel.setLayout(new GridLayout());
final GridData gd = new GridData();
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
uriPanel.setLayoutData(gd);
createLocationGroup(uriPanel);
createConnectionGroup(uriPanel);
authGroup = createAuthenticationGroup(uriPanel);
}
private void createLocationGroup(final Composite parent) {
final Group g = createGroup(parent,
UIText.RepositorySelectionPage_groupLocation);
g.setLayout(new GridLayout(4, false));
newLabel(g, UIText.RepositorySelectionPage_promptURI + ":"); //$NON-NLS-1$
uriText = new Text(g, SWT.BORDER);
if (presetUri != null) {
uriText.setText(presetUri);
uriText.selectAll();
}
uriText.setLayoutData(createFieldGridData());
uriText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
updateFields(uriText.getText());
}
});
uriProposalHandler = UIUtils.addPreviousValuesContentProposalToText(
uriText, USED_URIS_PREF);
Button browseLocalFolderButton = new Button(g, SWT.NULL);
if (!sourceSelection) {
GridDataFactory.fillDefaults().span(2, 1)
.applyTo(browseLocalFolderButton);
}
browseLocalFolderButton.setText(UIText.RepositorySelectionPage_BrowseLocalFolder);
browseLocalFolderButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
DirectoryDialog dialog = new DirectoryDialog(getShell());
if (sourceSelection) {
dialog.setMessage(
UIText.RepositorySelectionPage_sourceSelectionTitle);
} else {
dialog.setMessage(
UIText.RepositorySelectionPage_destinationSelectionTitle);
}
dialog.setFilterPath(getUriFilterPath());
String result = dialog.open();
if (result != null) {
uriText.setText(
Protocol.FILE.getDefaultScheme() + "://" + result); //$NON-NLS-1$
}
}
});
if (sourceSelection) {
Button browseLocalBundleFileButton = new Button(g, SWT.NULL);
browseLocalBundleFileButton.setText(UIText.RepositorySelectionPage_BrowseLocalBundleFile);
browseLocalBundleFileButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
FileDialog dialog = new FileDialog(getShell());
dialog.setText(UIText.RepositorySelectionPage_sourceSelectionTitle);
dialog.setFilterPath(getUriFilterPath());
String result = dialog.open();
if (result != null) {
uriText.setText(Protocol.FILE.getDefaultScheme()
+ "://" + result); //$NON-NLS-1$
}
}
});
}
newLabel(g, UIText.RepositorySelectionPage_promptHost + ":"); //$NON-NLS-1$
hostText = new Text(g, SWT.BORDER);
GridDataFactory.fillDefaults().span(3, 1).applyTo(hostText);
hostText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
setURI(uri.setHost(nullString(hostText.getText())));
}
});
newLabel(g, UIText.RepositorySelectionPage_promptPath + ":"); //$NON-NLS-1$
pathText = new Text(g, SWT.BORDER);
GridDataFactory.fillDefaults().span(3, 1).applyTo(pathText);
pathText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
setURI(uri.setPath(nullString(pathText.getText())));
}
});
}
private Group createAuthenticationGroup(final Composite parent) {
final Group g = createGroup(parent,
UIText.RepositorySelectionPage_groupAuthentication);
newLabel(g, UIText.RepositorySelectionPage_promptUser + ":"); //$NON-NLS-1$
userText = new Text(g, SWT.BORDER);
userText.setLayoutData(createFieldGridData());
userText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
Protocol protocol = getProtocol();
if (protocol != Protocol.HTTP && protocol != Protocol.HTTPS)
setURI(uri.setUser(nullString(userText.getText())));
user = userText.getText();
}
});
newLabel(g, UIText.RepositorySelectionPage_promptPassword + ":"); //$NON-NLS-1$
passText = new Text(g, SWT.BORDER | SWT.PASSWORD);
passText.setLayoutData(createFieldGridData());
passText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
setURI(uri.setPass(null));
password = passText.getText();
}
});
storeCheckbox = new Button(g, SWT.CHECK);
GridDataFactory.fillDefaults().span(2, 1).applyTo(storeCheckbox);
storeCheckbox
.setText(UIText.RepositorySelectionPage_storeInSecureStore);
storeCheckbox.setSelection(storeInSecureStore);
storeCheckbox.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
storeInSecureStore = storeCheckbox.getSelection();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
storeInSecureStore = storeCheckbox.getSelection();
}
});
return g;
}
private void createConnectionGroup(final Composite parent) {
final Group g = createGroup(parent,
UIText.RepositorySelectionPage_groupConnection);
newLabel(g, UIText.RepositorySelectionPage_promptScheme + ":"); //$NON-NLS-1$
scheme = new Combo(g, SWT.DROP_DOWN | SWT.READ_ONLY);
for (Protocol p : Protocol.values())
scheme.add(p.getDefaultScheme());
scheme.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final int idx = scheme.getSelectionIndex();
if (idx < 0) {
setURI(uri.setScheme(null));
scheme.setToolTipText(EMPTY_STRING);
} else {
setURI(uri.setScheme(nullString(scheme.getItem(idx))));
scheme.setToolTipText(Protocol.values()[idx].getTooltip());
}
updateGroups();
}
});
newLabel(g, UIText.RepositorySelectionPage_promptPort + ":"); //$NON-NLS-1$
portText = new Text(g, SWT.BORDER);
portText.addVerifyListener(new VerifyListener() {
final Pattern p = Pattern.compile("^(?:[1-9][0-9]*)?$"); //$NON-NLS-1$
@Override
public void verifyText(final VerifyEvent e) {
final String v = portText.getText();
e.doit = p.matcher(
v.substring(0, e.start) + e.text + v.substring(e.end))
.matches();
}
});
portText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
final String val = nullString(portText.getText());
if (val == null)
setURI(uri.setPort(-1));
else
try {
setURI(uri.setPort(Integer.parseInt(val)));
} catch (NumberFormatException err) {
// Ignore it for now.
}
}
});
}
private Group createGroup(final Composite parent, final String text) {
final Group g = new Group(parent, SWT.NONE);
final GridLayout layout = new GridLayout();
layout.numColumns = 2;
g.setLayout(layout);
g.setText(text);
final GridData gd = new GridData();
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
g.setLayoutData(gd);
return g;
}
private void newLabel(final Group g, final String text) {
new Label(g, SWT.NULL).setText(text);
}
private GridData createFieldGridData() {
return new GridData(SWT.FILL, SWT.CENTER, true, false);
}
private String nullString(final String value) {
if (value == null)
return null;
final String v = value.trim();
return v.length() == 0 ? null : v;
}
private void safeSet(final Text text, final String value) {
text.setText(value != null ? value : EMPTY_STRING);
}
private boolean isURISelected() {
return uriButton == null || uriButton.getSelection();
}
private void setURI(final URIish u) {
try {
eventDepth++;
if (eventDepth == 1) {
uri = u;
String oldUriText = uriText.getText();
String newUriText = uri.toString();
// avoid moving the cursor to the first position if there are no
// changes by this automatic update
if (!oldUriText.equals(newUriText)) {
uriText.setText(newUriText);
}
checkPage();
}
} finally {
eventDepth--;
}
}
private List<RemoteConfig> getUsableConfigs(final List<RemoteConfig> remotes) {
if (remotes == null)
return null;
List<RemoteConfig> result = new ArrayList<>();
for (RemoteConfig config : remotes)
if ((sourceSelection && !config.getURIs().isEmpty() || !sourceSelection
&& (!config.getPushURIs().isEmpty() || !config.getURIs()
.isEmpty())))
result.add(config);
if (!result.isEmpty())
return result;
return null;
}
/**
* Check the user input and set messages in case of invalid input.
*/
protected void checkPage() {
if (isURISelected()) {
assert uri != null;
if (uriText.getText().length() == 0) {
selectionIncomplete(null);
return;
} else if (uriText.getText().endsWith(" ")) { //$NON-NLS-1$
selectionIncomplete(UIText.RepositorySelectionPage_UriMustNotHaveTrailingSpacesMessage);
return;
}
try {
final URIish finalURI = new URIish(
GitUrlChecker.sanitizeAsGitUrl(uriText.getText()));
String proto = finalURI.getScheme();
if (proto == null && scheme.getSelectionIndex() >= 0)
proto = scheme.getItem(scheme.getSelectionIndex());
if (uri.getPath() == null) {
selectionIncomplete(NLS.bind(
UIText.RepositorySelectionPage_fieldRequired,
unamp(UIText.RepositorySelectionPage_promptPath),
proto));
return;
}
if (Protocol.FILE.handles(finalURI)) {
String badField = null;
if (uri.getHost() != null)
badField = UIText.RepositorySelectionPage_promptHost;
else if (uri.getUser() != null)
badField = UIText.RepositorySelectionPage_promptUser;
else if (uri.getPass() != null)
badField = UIText.RepositorySelectionPage_promptPassword;
if (badField != null) {
selectionIncomplete(NLS
.bind(
UIText.RepositorySelectionPage_fieldNotSupported,
unamp(badField), proto));
return;
}
final File d = FS.DETECTED.resolve(
new File("."), uri.getPath()); //$NON-NLS-1$
if (!d.exists()) {
selectionIncomplete(NLS.bind(
UIText.RepositorySelectionPage_fileNotFound,
d.getAbsolutePath()));
return;
}
selectionComplete(finalURI, null);
return;
}
if (uri.getHost() == null) {
selectionIncomplete(NLS.bind(
UIText.RepositorySelectionPage_fieldRequired,
unamp(UIText.RepositorySelectionPage_promptHost),
proto));
return;
}
if (Protocol.GIT.handles(finalURI)) {
String badField = null;
if (uri.getUser() != null)
badField = UIText.RepositorySelectionPage_promptUser;
else if (uri.getPass() != null)
badField = UIText.RepositorySelectionPage_promptPassword;
if (badField != null) {
selectionIncomplete(NLS
.bind(
UIText.RepositorySelectionPage_fieldNotSupported,
unamp(badField), proto));
return;
}
}
if (Protocol.HTTP.handles(finalURI)
|| Protocol.HTTPS.handles(finalURI)) {
UserPasswordCredentials credentials = SecureStoreUtils
.getCredentials(finalURI);
if (credentials != null) {
String u = credentials.getUser();
String p = credentials.getPassword();
String uriUser = finalURI.getUser();
if (uriUser == null) {
if (setSafeUser(u) && setSafePassword(p))
setStoreInSecureStore(true);
} else if (uriUser.length() != 0 && uriUser.equals(u)) {
if (setSafePassword(p))
setStoreInSecureStore(true);
}
}
}
selectionComplete(finalURI, null);
return;
} catch (URISyntaxException e) {
selectionIncomplete(e.getReason());
return;
} catch (Exception e) {
Activator.logError(NLS.bind(
UIText.RepositorySelectionPage_errorValidating,
getClass().getName()), e);
selectionIncomplete(UIText.RepositorySelectionPage_internalError);
return;
}
} else {
assert remoteButton.getSelection();
selectionComplete(null, remoteConfig);
return;
}
}
private boolean setSafePassword(String p) {
if ((password == null || password.length() == 0) && p != null
&& p.length() != 0) {
password = p;
passText.setText(p);
return true;
}
return false;
}
private boolean setSafeUser(String u) {
if ((user == null || user.length() == 0) && u != null
&& u.length() != 0) {
user = u;
userText.setText(u);
return true;
}
return false;
}
private void setStoreInSecureStore(boolean store) {
storeInSecureStore = store;
storeCheckbox.setSelection(store);
}
private String unamp(String s) {
return s.replace("&", EMPTY_STRING); //$NON-NLS-1$
}
private void selectionIncomplete(final String errorMessage) {
setExposedSelection(null, null);
setErrorMessage(errorMessage);
setPageComplete(false);
}
private void selectionComplete(final URIish u, final RemoteConfig rc) {
setExposedSelection(u, rc);
setErrorMessage(null);
setPageComplete(true);
}
private void setExposedSelection(final URIish u, final RemoteConfig rc) {
final RepositorySelection newSelection = new RepositorySelection(u, rc);
if (newSelection.equals(selection))
return;
selection = newSelection;
}
private void updateRemoteAndURIPanels() {
UIUtils.setEnabledRecursively(uriPanel, isURISelected());
if (uriPanel.getEnabled())
updateGroups();
if (configuredRemotes != null)
UIUtils.setEnabledRecursively(remotePanel, !isURISelected());
}
private void updateGroups() {
Protocol p = getProtocol();
if (p != null) {
hostText.setEnabled(p.hasHost());
if (!p.hasHost())
hostText.setText(EMPTY_STRING);
portText.setEnabled(p.hasPort());
if (!p.hasPort())
portText.setText(EMPTY_STRING);
UIUtils.setEnabledRecursively(authGroup, p.canAuthenticate());
if (!p.canAuthenticate()) {
userText.setText(EMPTY_STRING);
passText.setText(EMPTY_STRING);
storeCheckbox.setSelection(false);
}
}
}
private Protocol getProtocol() {
int idx = scheme.getSelectionIndex();
if (idx >= 0)
return Protocol.values()[idx];
return null;
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible)
uriText.setFocus();
}
/**
* Updates the proposal list for the URI field
*/
public void saveUriInPrefs() {
uriProposalHandler.updateProposals();
}
/**
* @return credentials
*/
public UserPasswordCredentials getCredentials() {
if ((user == null || user.length() == 0)
&& (password == null || password.length() == 0))
return null;
return new UserPasswordCredentials(user, password);
}
/**
* @return true if credentials should be stored
*/
public boolean getStoreInSecureStore() {
return this.storeInSecureStore;
}
/**
* Set the ID for context sensitive help
*
* @param id
* help context
*/
public void setHelpContext(String id) {
helpContext = id;
}
@Override
public void performHelp() {
PlatformUI.getWorkbench().getHelpSystem().displayHelp(helpContext);
}
private void updateFields(final String text) {
try {
eventDepth++;
if (eventDepth != 1)
return;
String strippedText = GitUrlChecker.sanitizeAsGitUrl(text);
final URIish u = new URIish(strippedText);
if (!text.equals(strippedText)) {
uriText.setText(strippedText);
}
safeSet(hostText, u.getHost());
safeSet(pathText, u.getPath());
safeSet(userText, u.getUser());
safeSet(passText, u.getPass());
if (u.getPort() > 0)
portText.setText(Integer.toString(u.getPort()));
else
portText.setText(EMPTY_STRING);
Protocol protocol = Protocol.fromUri(u);
if (protocol != null) {
scheme.select(scheme.indexOf(protocol.getDefaultScheme()));
scheme.notifyListeners(SWT.Selection, new Event());
}
updateGroups();
uri = u;
} catch (URISyntaxException err) {
// leave uriText as it is, but clean up underlying uri and
// decomposed fields
uri = new URIish();
hostText.setText(EMPTY_STRING);
pathText.setText(EMPTY_STRING);
userText.setText(EMPTY_STRING);
passText.setText(EMPTY_STRING);
portText.setText(EMPTY_STRING);
scheme.select(-1);
} finally {
eventDepth--;
}
checkPage();
}
private IPreferenceStore getPreferenceStore() {
return Activator.getDefault().getPreferenceStore();
}
@Override
public GitRepositoryInfo getGitRepositoryInfo() {
GitRepositoryInfo info = new GitRepositoryInfo(uri.toString());
info.setCredentials(user, password);
info.setShouldSaveCredentialsInSecureStore(storeInSecureStore);
uriProposalHandler.updateProposals();
return info;
}
private String getUriFilterPath() {
String filterPath = null;
// if a file was selected before, let's try to open
// the directory dialog on the same directory
if (!uriText.getText().isEmpty()) {
try {
// first we try if this is a simple file name
File testFile = new File(uriText.getText());
if (testFile.exists()) {
filterPath = testFile.getPath();
} else {
// this could still be a file URIish
URIish testUri = new URIish(uriText.getText());
if (Protocol.FILE.defaultScheme
.equals(testUri.getScheme())) {
testFile = new File(testUri.getPath());
if (testFile.exists()) {
filterPath = testFile.getPath();
}
}
}
} catch (IllegalArgumentException | URISyntaxException e) {
// ignore here, we just' don't set the directory in the
// browser
}
}
// if nothing else, we start the search from the default folder for repositories
if (filterPath == null || filterPath.isEmpty()) {
filterPath = RepositoryUtil.getDefaultRepositoryDir();
}
return filterPath;
}
}