IDEA-67156 GitHub integration does not allow to manually type in project and does not show organization's projects

This commit is contained in:
Oleg Shpynov
2011-03-29 14:36:44 +04:00
parent ed643197b5
commit 9154af2743
8 changed files with 160 additions and 46 deletions
@@ -19,6 +19,7 @@ import com.intellij.ide.GeneralSettings;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vcs.CheckoutProvider;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -82,21 +83,32 @@ public class GithubCheckoutProvider implements CheckoutProvider {
}
// All the preliminary work is already done, go and clone the selected repository!
final RepositoryInfo selectedRepository = checkoutDialog.getSelectedRepository();
RepositoryInfo selectedRepository = checkoutDialog.getSelectedRepository();
// Check if selected repository exists
final String owner = selectedRepository.getOwner();
final String name = selectedRepository.getName();
if (selectedRepository instanceof UnknownRepositoryInfo) {
selectedRepository = GithubUtil.getDetailedRepositoryInfo(project, owner, name);
}
if (selectedRepository == null){
Messages.showErrorDialog(project, "Selected repository ''" + owner +"/" + name + "'' doesn't exist.", "Cannot clone repository");
return;
}
final boolean writeAccessAllowed = GithubUtil.isWriteAccessAllowed(project, selectedRepository);
if (!writeAccessAllowed){
Messages.showErrorDialog(project, "It seems that you have only read access to the selected repository.\n" +
"GitHub supports only https protocol for readonly access, which is not supported yet.\n" +
"As a workaround, please fork it and clone your forked repository instead.\n" +
"More details are available here: http://youtrack.jetbrains.net/issue/IDEA-55298", "Cannot clone this repository");
"More details are available here: http://youtrack.jetbrains.net/issue/IDEA-55298", "Cannot clone repository");
return;
}
final String host = writeAccessAllowed ? "git@" + settings.getHost() + ":" : "https://github.com" + settings.getHost() + "/";
final String selectedPath = checkoutDialog.getSelectedPath();
final VirtualFile selectedPathFile = LocalFileSystem.getInstance().findFileByPath(selectedPath);
final String projectName = checkoutDialog.getProjectName();
final String repositoryName = selectedRepository.getName();
final String repositoryOwner = selectedRepository.getOwner();
final String repositoryName = name;
final String repositoryOwner = owner;
final String checkoutUrl = host + repositoryOwner + "/" + repositoryName + ".git";
GitCheckoutProvider.checkout(project, listener, selectedPathFile, checkoutUrl, projectName, "origin", selectedPath);
}
@@ -106,7 +106,7 @@ public class GithubRebaseAction extends DumbAwareAction {
repoName = repoName.substring(0, repoName.length() - 4);
}
final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName);
final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, login, repoName);
if (repositoryInfo == null) {
Messages
.showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_PERFORM_GITHUB_REBASE);
@@ -182,9 +182,9 @@ public class GithubUtil {
}
@Nullable
public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String name) {
public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String owner, final String name) {
try {
final String request = "/repos/show/" + login + "/" + name;
final String request = "/repos/show/" + owner + "/" + name;
final HttpMethod method = doREST(url, login, password, request, false);
final InputStream stream = method.getResponseBodyAsStream();
final Element element = new SAXBuilder(false).build(stream).getRootElement();
@@ -302,7 +302,7 @@ public class GithubUtil {
* @return
*/
@Nullable
public static RepositoryInfo getDetailedRepositoryInfo(final Project project, final String name) {
public static RepositoryInfo getDetailedRepositoryInfo(final Project project, final String owner, final String name) {
final GithubSettings settings = GithubSettings.getInstance();
final boolean validCredentials;
try {
@@ -330,7 +330,7 @@ public class GithubUtil {
@Override
public RepositoryInfo compute() {
ProgressManager.getInstance().getProgressIndicator().setText("Extracting detailed info about repository ''" + name + "''");
return getDetailedRepoInfo(settings.getHost(), settings.getLogin(), settings.getPassword(), name);
return getDetailedRepoInfo(settings.getHost(), settings.getLogin(), settings.getPassword(), owner, name);
}
});
}
@@ -30,6 +30,10 @@ public class RepositoryInfo {
return myRepository.getChildText("parent");
}
public String getId() {
return getOwner() + "/" + getName();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RepositoryInfo)){
@@ -0,0 +1,52 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.github;
/**
* @author oleg
*/
public class UnknownRepositoryInfo extends RepositoryInfo {
private final String myId;
private final String myName;
private final String myOwner;
public UnknownRepositoryInfo(final String id) {
super(null);
myId = id;
myName = myId.substring(myId.lastIndexOf('/') + 1);
myOwner = myId.substring(0, myId.lastIndexOf('/'));
}
public String getName() {
return myName;
}
public String getOwner() {
return myOwner;
}
public boolean isFork() {
throw new UnsupportedOperationException("UnknownRepositoryInfo#isFork() shouldn't be called");
}
public String getParent() {
throw new UnsupportedOperationException("UnknownRepositoryInfo#isFork() shouldn't be called");
}
public String getId() {
return myId;
}
}
@@ -4,9 +4,14 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashMap;
import org.intellij.lang.annotations.Pattern;
import org.jetbrains.plugins.github.RepositoryInfo;
import org.jetbrains.plugins.github.UnknownRepositoryInfo;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@@ -14,14 +19,22 @@ import java.util.List;
*/
public class GithubCloneProjectDialog extends DialogWrapper {
private static final java.util.regex.Pattern PATTERN = java.util.regex.Pattern.compile("[\\w\\d-_]+/[\\w\\d-_]+");
private GithubCloneProjectPane myGithubCloneProjectPane;
private HashMap<String, RepositoryInfo> myRepositoryInfoHashMap;
public GithubCloneProjectDialog(final Project project, final List<RepositoryInfo> repos) {
super(project, true);
myGithubCloneProjectPane = new GithubCloneProjectPane(this);
setTitle("Select repository to clone");
setOKButtonText("Clone");
myGithubCloneProjectPane.setAvailableRepos(repos);
myRepositoryInfoHashMap = new HashMap<String, RepositoryInfo>();
for (RepositoryInfo repo : repos) {
myRepositoryInfoHashMap.put(repo.getId(), repo);
}
final ArrayList<String> ids = new ArrayList<String>(myRepositoryInfoHashMap.keySet());
Collections.sort(ids);
myGithubCloneProjectPane.setAvailableRepos(ids);
init();
setOKActionEnabled(false);
}
@@ -46,8 +59,9 @@ public class GithubCloneProjectDialog extends DialogWrapper {
}
public void updateOkButton() {
if (getSelectedRepository() == null){
setErrorText("No repository selected");
final String selectedRepositoryId = getSelectedRepositoryId();
if (!PATTERN.matcher(selectedRepositoryId).matches()){
setErrorText("Wrong repository format. owner/repository expected");
setOKActionEnabled(false);
return;
}
@@ -79,6 +93,11 @@ public class GithubCloneProjectDialog extends DialogWrapper {
}
public RepositoryInfo getSelectedRepository() {
final String id = getSelectedRepositoryId();
return myRepositoryInfoHashMap.containsKey(id) ? myRepositoryInfoHashMap.get(id) : new UnknownRepositoryInfo(id);
}
private String getSelectedRepositoryId() {
return myGithubCloneProjectPane.getSelectedRepository();
}
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="402" height="112"/>
<xy x="20" y="20" width="402" height="137"/>
</constraints>
<properties/>
<border type="none"/>
@@ -32,12 +32,6 @@
<text value="Directory &amp;Name:"/>
</properties>
</component>
<component id="7ac75" class="javax.swing.JComboBox" binding="mySelectRepositoryComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="f9011" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myTextFieldWithBrowseButton" custom-create="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
@@ -60,6 +54,12 @@
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="21a0c" class="com.intellij.openapi.ui.ComboBox" binding="myRepositoryComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</form>
@@ -1,11 +1,20 @@
package org.jetbrains.plugins.github.ui;
import com.intellij.ide.ui.ListCellRendererWrapper;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorComboBoxEditor;
import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.StringComboboxEditor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
@@ -26,31 +35,31 @@ import java.util.List;
*/
public class GithubCloneProjectPane {
private JPanel myPanel;
private JComboBox mySelectRepositoryComboBox;
private TextFieldWithBrowseButton myTextFieldWithBrowseButton;
private JTextField myProjectNameText;
private ComboBox myRepositoryComboBox;
private final GithubCloneProjectDialog myDialog;
public GithubCloneProjectPane(final GithubCloneProjectDialog dialog) {
myDialog = dialog;
mySelectRepositoryComboBox.setRenderer(new ListCellRendererWrapper<RepositoryInfo>(mySelectRepositoryComboBox.getRenderer()){
@Override
public void customize(final JList list, final RepositoryInfo value, final int index, final boolean selected, final boolean cellHasFocus) {
setText(value.getOwner() + "/" + value.getName());
}
});
mySelectRepositoryComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final RepositoryInfo repositoryInfo = (RepositoryInfo)e.getItem();
if (repositoryInfo != null) {
myProjectNameText.setText(repositoryInfo.getName());
myDialog.updateOkButton();
final EditorComboBoxEditor comboEditor = new StringComboboxEditor(ProjectManager.getInstance().getDefaultProject(), FileTypes.PLAIN_TEXT, myRepositoryComboBox);
myRepositoryComboBox.setEditor(comboEditor);
((EditorTextField) comboEditor.getEditorComponent()).addDocumentListener(
new DocumentAdapter() {
@Override
public void beforeDocumentChange(final com.intellij.openapi.editor.event.DocumentEvent e) {
updateControls();
}
}
});
final DocumentListener updateOkButtonListener = new DocumentListener() {
@Override
public void documentChanged(final com.intellij.openapi.editor.event.DocumentEvent e) {
updateControls();
}
});
myRepositoryComboBox.setRenderer(new EditorComboBoxRenderer(comboEditor));
myRepositoryComboBox.setEditable(true);
myProjectNameText.getDocument().addDocumentListener(new DocumentListener() {
// update Ok button state depending on the current state of the fields
public void insertUpdate(final DocumentEvent e) {
myDialog.updateOkButton();
@@ -63,9 +72,21 @@ public class GithubCloneProjectPane {
public void changedUpdate(final DocumentEvent e) {
myDialog.updateOkButton();
}
};
myProjectNameText.getDocument().addDocumentListener(updateOkButtonListener);
myTextFieldWithBrowseButton.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
});
myTextFieldWithBrowseButton.getChildComponent().getDocument().addDocumentListener(new DocumentListener() {
// update Ok button state depending on the current state of the fields
public void insertUpdate(final DocumentEvent e) {
myDialog.updateOkButton();
}
public void removeUpdate(final DocumentEvent e) {
myDialog.updateOkButton();
}
public void changedUpdate(final DocumentEvent e) {
myDialog.updateOkButton();
}
});
}
public JComponent getPanel() {
@@ -73,11 +94,11 @@ public class GithubCloneProjectPane {
}
public JComponent getPreferrableFocusComponent() {
return mySelectRepositoryComboBox;
return myRepositoryComboBox;
}
public RepositoryInfo getSelectedRepository(){
return (RepositoryInfo) mySelectRepositoryComboBox.getModel().getSelectedItem();
public String getSelectedRepository(){
return (String) myRepositoryComboBox.getEditor().getItem();
}
public String getSelectedPath(){
@@ -120,12 +141,18 @@ public class GithubCloneProjectPane {
});
}
public void setAvailableRepos(final List<RepositoryInfo> repos) {
mySelectRepositoryComboBox.setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(repos)));
final RepositoryInfo preselectedRepository = (RepositoryInfo)mySelectRepositoryComboBox.getSelectedItem();
public void setAvailableRepos(final List<String> repos) {
myRepositoryComboBox.setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(repos)));
updateControls();
}
private void updateControls() {
final String preselectedRepository = (String)myRepositoryComboBox.getEditor().getItem();
if (preselectedRepository != null) {
myProjectNameText.setText(preselectedRepository.getName());
final int i = preselectedRepository.lastIndexOf('/');
myProjectNameText.setText(i != -1 ? preselectedRepository.substring(i + 1) : "");
}
myDialog.updateOkButton();
}
public void setSelectedPath(final String path) {