mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
push dialog: mercurial implementation
* api created in dvcs-api module; * pushLog class implements complex tree ui with editor and renderer; * push controller created a push repo-spec model and managed actions between ui and model
This commit is contained in:
Generated
+2
-1
@@ -47,7 +47,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" filepath="$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/dvcs/dvcs.iml" filepath="$PROJECT_DIR$/platform/dvcs/dvcs.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" filepath="$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" filepath="$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" group="platform"/>
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="util-rt" />
|
||||
<orderEntry type="module" module-name="vcs-log-graph-api" exported="" />
|
||||
<orderEntry type="module" module-name="core-api" />
|
||||
<orderEntry type="module" module-name="vcs-api" />
|
||||
<orderEntry type="module" module-name="extensions" />
|
||||
<orderEntry type="module" module-name="vcs-log-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Provider for outgoing commits
|
||||
*/
|
||||
public abstract class OutgoingCommitsProvider {
|
||||
|
||||
/**
|
||||
* Collect outgoing commits or errors for selected repo for specified {@link PushSpec} and store to {@link OutgoingResult}
|
||||
*
|
||||
* @param initial true for first commits loading, which identify that all inside actions should be silent
|
||||
* and do not ask user about smth, a.e authorization request
|
||||
*/
|
||||
@NotNull
|
||||
public abstract OutgoingResult getOutgoingCommits(@NotNull Repository repository,
|
||||
@NotNull PushSpec pushSpec, boolean initial);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OutgoingResult {
|
||||
@NotNull private final List<VcsError> myErrors;
|
||||
@NotNull private final List<? extends VcsFullCommitDetails> myCommits;
|
||||
|
||||
public OutgoingResult(@NotNull List<? extends VcsFullCommitDetails> commits, @NotNull List<VcsError> errors) {
|
||||
myCommits = commits;
|
||||
myErrors = errors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VcsError> getErrors() {
|
||||
return myErrors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<? extends VcsFullCommitDetails> getCommits() {
|
||||
return myCommits;
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return !myErrors.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
/**
|
||||
* Source to push from. For example, local branch for git or branch/bookmark for mercurial.
|
||||
*/
|
||||
public interface PushSource {
|
||||
String getPresentation();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Specified a push from-to settings for one repository
|
||||
*/
|
||||
public class PushSpec {
|
||||
|
||||
@NotNull private PushSource mySource;
|
||||
@Nullable private PushTarget myTarget;
|
||||
|
||||
public PushSpec(@NotNull PushSource source, @Nullable PushTarget target) {
|
||||
mySource = source;
|
||||
myTarget = target;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PushSource getSource() {
|
||||
return mySource;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PushTarget getTarget() {
|
||||
return myTarget;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import com.intellij.dvcs.repo.RepositoryManager;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Base class to provide vcs-specific info
|
||||
*/
|
||||
|
||||
public abstract class PushSupport {
|
||||
public static final ExtensionPointName<PushSupport> PUSH_SUPPORT_EP = ExtensionPointName.create("com.intellij.pushSupport");
|
||||
|
||||
@NotNull
|
||||
public abstract AbstractVcs getVcs();
|
||||
|
||||
@NotNull
|
||||
public abstract Pusher getPusher();
|
||||
|
||||
@NotNull
|
||||
public abstract OutgoingCommitsProvider getOutgoingCommitsProvider();
|
||||
|
||||
/**
|
||||
* @return Default push destination
|
||||
*/
|
||||
@Nullable
|
||||
public abstract PushTarget getDefaultTarget(@NotNull Repository repository);
|
||||
|
||||
/**
|
||||
* @return All remembered remote destinations used for completion
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Collection<String> getTargetNames(@NotNull Repository repository);
|
||||
|
||||
/**
|
||||
* @return current source(branch) for repository
|
||||
*/
|
||||
@NotNull
|
||||
public abstract PushSource getSource(@NotNull Repository repository);
|
||||
|
||||
/** Create destination target from user input string
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public abstract PushTarget createTarget(String targetName);
|
||||
|
||||
/**
|
||||
* @return RepositoryManager for vcs
|
||||
*/
|
||||
@NotNull
|
||||
public abstract RepositoryManager<? extends Repository> getRepositoryManager();
|
||||
|
||||
@Nullable
|
||||
public VcsPushOptionsPanel getVcsPushOptionsPanel(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* Destination for push action. (Remote for git or push-path for mercurial).
|
||||
*/
|
||||
public interface PushTarget {
|
||||
|
||||
@NotNull
|
||||
String getPresentation();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class to execute push command.
|
||||
*/
|
||||
public abstract class Pusher {
|
||||
/**
|
||||
* Perform push command for all repositories belonged to one vcs.
|
||||
*
|
||||
* @param pushSpecs specify push from and to params
|
||||
* @param vcsPushOptionValue specify additional options to push, null if not supported
|
||||
* @param force if true then execute force push
|
||||
*/
|
||||
public abstract void push(@NotNull Map<Repository, PushSpec> pushSpecs,
|
||||
@Nullable VcsPushOptionValue vcsPushOptionValue,
|
||||
boolean force);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public interface TreeNodeLinkListener {
|
||||
void onClick(@NotNull DefaultMutableTreeNode source);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class VcsError extends VcsLinkedText {
|
||||
public VcsError(@NotNull String text) {
|
||||
super(text, "");
|
||||
}
|
||||
|
||||
public VcsError(@NotNull String text, @NotNull String link) {
|
||||
super(text, link);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.util.List;
|
||||
|
||||
public class VcsLinkedText {
|
||||
@NotNull String myText;
|
||||
@NotNull String myHandledLink;
|
||||
|
||||
private final List<TreeNodeLinkListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
public VcsLinkedText(@NotNull String text, @NotNull String link) {
|
||||
myText = text;
|
||||
myHandledLink = link;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLinkText() {
|
||||
return myHandledLink;
|
||||
}
|
||||
|
||||
public void addClickListener(@NotNull TreeNodeLinkListener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
public void fireOnClick(@NotNull DefaultMutableTreeNode relatedNode) {
|
||||
for (TreeNodeLinkListener listener : myListeners) {
|
||||
listener.onClick(relatedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
public interface VcsPushOptionValue {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public abstract class VcsPushOptionsPanel extends JPanel {
|
||||
|
||||
public abstract VcsPushOptionValue getValue();
|
||||
|
||||
/**
|
||||
* @param listener handle valueChange event
|
||||
*/
|
||||
public abstract void addValueChangeListener(ActionListener listener);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
/**
|
||||
* Specify which references(tags) should be pushed
|
||||
*/
|
||||
|
||||
public enum VcsPushReferenceStrategy {
|
||||
none, // do not push references/tags
|
||||
follow, // push references only for selected sources
|
||||
all // push all references for all repositories
|
||||
}
|
||||
+4
@@ -17,6 +17,7 @@ package com.intellij.dvcs.repo;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -97,6 +98,9 @@ public interface Repository extends Disposable {
|
||||
@NotNull
|
||||
State getState();
|
||||
|
||||
@Nullable
|
||||
AbstractVcs getVcs();
|
||||
|
||||
/**
|
||||
* Returns the hash of the revision, which HEAD currently points to.
|
||||
* Returns null only in the case of a fresh repository, when no commit have been made.
|
||||
@@ -17,6 +17,8 @@
|
||||
<orderEntry type="module" module-name="vcs-log-api" />
|
||||
<orderEntry type="module" module-name="vcs-log-impl" />
|
||||
<orderEntry type="module" module-name="images" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="dvcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<idea-plugin>
|
||||
<extensionPoints>
|
||||
<extensionPoint name="pushSupport"
|
||||
interface="com.intellij.dvcs.push.PushSupport" area="IDEA_PROJECT"/>
|
||||
</extensionPoints>
|
||||
<actions>
|
||||
<!--<action id="Vcs.Push" class="">-->
|
||||
<!--<keyboard-shortcut first-keystroke="control shift K" keymap="$default"/>-->
|
||||
<!--</action>-->
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
|
||||
+19
@@ -39,6 +39,8 @@ import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.vcs.log.TimedVcsCommit;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.VcsLogProvider;
|
||||
import org.intellij.images.editor.ImageFileEditor;
|
||||
@@ -55,6 +57,8 @@ import java.util.List;
|
||||
*/
|
||||
public class DvcsUtil {
|
||||
|
||||
private static final int SHORT_HASH_LENGTH = 8;
|
||||
|
||||
public static void installStatusBarWidget(@NotNull Project project, @NotNull StatusBarWidget widget) {
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
|
||||
if (statusBar != null) {
|
||||
@@ -183,4 +187,19 @@ public class DvcsUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getShortHash(@NotNull String hash) {
|
||||
if (hash.length() == 0) return "";
|
||||
if (hash.length() == 40) return hash.substring(0, SHORT_HASH_LENGTH);
|
||||
if (hash.length() > 40) // revision string encoded with date too
|
||||
{
|
||||
return hash.substring(hash.indexOf("[") + 1, SHORT_HASH_LENGTH);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getDateString(@NotNull TimedVcsCommit commit) {
|
||||
return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp()) + " ";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
public class MoreCommitsLink extends VcsLinkedText {
|
||||
MoreCommitsLink() {
|
||||
super("", "...");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.dvcs.push.ui.*;
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import com.intellij.dvcs.repo.RepositoryManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class PushController implements Disposable {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final List<PushSupport> myPushSupports;
|
||||
@NotNull private final PushLog myPushLog;
|
||||
private boolean mySingleRepoProject;
|
||||
private static final int DEFAULT_CHILDREN_PRESENTATION_NUMBER = 20;
|
||||
private final Map<PushSupport, MyPushOptionValueModel> myAdditionalValuesMap;
|
||||
|
||||
private final Map<RepositoryNode, MyRepoModel> myView2Model = new HashMap<RepositoryNode, MyRepoModel>();
|
||||
|
||||
|
||||
public PushController(@NotNull Project project,
|
||||
@NotNull VcsPushDialog dialog,
|
||||
@NotNull List<? extends Repository> preselectedRepositories) {
|
||||
myProject = project;
|
||||
//todo what would be in case of null
|
||||
myPushSupports = Arrays.asList(Extensions.getExtensions(PushSupport.PUSH_SUPPORT_EP, myProject));
|
||||
CheckedTreeNode rootNode = new CheckedTreeNode(null);
|
||||
mySingleRepoProject = createTreeModel(rootNode, preselectedRepositories);
|
||||
myPushLog = new PushLog(myProject, rootNode);
|
||||
myAdditionalValuesMap = new HashMap<PushSupport, MyPushOptionValueModel>();
|
||||
startLoadingCommits();
|
||||
Disposer.register(dialog.getDisposable(), this);
|
||||
}
|
||||
|
||||
private void startLoadingCommits() {
|
||||
Map<RepositoryNode, MyRepoModel> priorityLoading = new HashMap<RepositoryNode, MyRepoModel>();
|
||||
Map<RepositoryNode, MyRepoModel> others = new HashMap<RepositoryNode, MyRepoModel>();
|
||||
for (Map.Entry<RepositoryNode, MyRepoModel> entry : myView2Model.entrySet()) {
|
||||
MyRepoModel model = entry.getValue();
|
||||
if (model.isSelected()) {
|
||||
priorityLoading.put(entry.getKey(), model);
|
||||
}
|
||||
else {
|
||||
others.put(entry.getKey(), model);
|
||||
}
|
||||
}
|
||||
loadCommitsFromMap(priorityLoading);
|
||||
loadCommitsFromMap(others);
|
||||
}
|
||||
|
||||
private void loadCommitsFromMap(@NotNull Map<RepositoryNode, MyRepoModel> items) {
|
||||
for (Map.Entry<RepositoryNode, MyRepoModel> entry : items.entrySet()) {
|
||||
RepositoryNode node = entry.getKey();
|
||||
myPushLog.startLoading(node);
|
||||
loadCommits(entry.getValue(), node, true);
|
||||
}
|
||||
}
|
||||
|
||||
//return is single repository project or not
|
||||
private boolean createTreeModel(@NotNull CheckedTreeNode rootNode, @NotNull List<? extends Repository> preselectedRepositories) {
|
||||
if (myPushSupports.isEmpty()) return true;
|
||||
|
||||
boolean isSingleRepositoryProject = myPushSupports.size() == 1;
|
||||
for (final PushSupport support : myPushSupports) {
|
||||
RepositoryManager<? extends Repository> repositoryManager = support.getRepositoryManager();
|
||||
List<? extends Repository> repositories = repositoryManager.getRepositories();
|
||||
isSingleRepositoryProject = isSingleRepositoryProject && repositories.size() == 1;
|
||||
for (Repository repository : repositories) {
|
||||
PushTarget target = support.getDefaultTarget(repository);
|
||||
final MyRepoModel model = new MyRepoModel(repository, support, preselectedRepositories.contains(repository),
|
||||
new PushSpec(support.getSource(repository),
|
||||
target),
|
||||
DEFAULT_CHILDREN_PRESENTATION_NUMBER);
|
||||
RepositoryWithBranchPanel repoPanel = new RepositoryWithBranchPanel(myProject, DvcsUtil.getShortRepositoryName(repository),
|
||||
support.getSource(repository).getPresentation(),
|
||||
target == null ? "" : target.getPresentation(),
|
||||
support.getTargetNames(repository));
|
||||
final RepositoryNode repoNode =
|
||||
isSingleRepositoryProject ? new SingleRepositoryNode(repoPanel) : new RepositoryNode(repoPanel);
|
||||
myView2Model.put(repoNode, model);
|
||||
repoNode.setChecked(model.isSelected());
|
||||
repoNode.addRepoNodeListener(new RepositoryNodeListener() {
|
||||
@Override
|
||||
public void onTargetChanged(String newValue) {
|
||||
myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(newValue)));
|
||||
myPushLog.startLoading(repoNode);
|
||||
loadCommits(model, repoNode, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(boolean isSelected) {
|
||||
myView2Model.get(repoNode).setSelected(isSelected);
|
||||
}
|
||||
});
|
||||
rootNode.add(repoNode);
|
||||
}
|
||||
}
|
||||
return isSingleRepositoryProject;
|
||||
}
|
||||
|
||||
private void loadCommits(@NotNull final MyRepoModel model,
|
||||
@NotNull final RepositoryNode node,
|
||||
final boolean initial) {
|
||||
node.stopLoading();
|
||||
final ProgressIndicator indicator = node.startLoading();
|
||||
final PushSupport support = model.getSupport();
|
||||
final AtomicReference<OutgoingResult> result = new AtomicReference<OutgoingResult>();
|
||||
Task.Backgroundable task = new Task.Backgroundable(myProject, "Loading Commits", true) {
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
node.stopLoading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
OutgoingResult outgoing = result.get();
|
||||
if (outgoing.hasErrors()) {
|
||||
myPushLog.setChildren(node, ContainerUtil.map(outgoing.getErrors(), new Function<VcsError, DefaultMutableTreeNode>() {
|
||||
@Override
|
||||
public DefaultMutableTreeNode fun(VcsError error) {
|
||||
return new TextWithLinkNode(error);
|
||||
}
|
||||
}), model.isSelected());
|
||||
}
|
||||
else {
|
||||
model.setLoadedCommits(outgoing.getCommits());
|
||||
myPushLog.setChildren(node,
|
||||
getPresentationForCommits(PushController.this.myProject, model.getLoadedCommits(),
|
||||
model.getNumberOfShownCommits()), model.isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
OutgoingResult outgoing = support.getOutgoingCommitsProvider()
|
||||
.getOutgoingCommits(model.getRepository(), model.getSpec(), initial);
|
||||
result.compareAndSet(null, outgoing);
|
||||
}
|
||||
};
|
||||
|
||||
ProgressManagerImpl.runProcessWithProgressAsynchronously(task, indicator, null, ModalityState.any());
|
||||
}
|
||||
|
||||
|
||||
public PushLog getPushPanelInfo() {
|
||||
return myPushLog;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
//todo implement
|
||||
return false;
|
||||
}
|
||||
|
||||
public void push(final boolean force) {
|
||||
Task.Backgroundable task = new Task.Backgroundable(myProject, "Pushing...", false) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
for (PushSupport support : myPushSupports) {
|
||||
MyPushOptionValueModel additionalOptionsModel = myAdditionalValuesMap.get(support);
|
||||
support.getPusher()
|
||||
.push(collectPushInfoForVcs(support), additionalOptionsModel == null ? null : additionalOptionsModel.getCurrentValue(), force);
|
||||
}
|
||||
}
|
||||
};
|
||||
task.queue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<Repository, PushSpec> collectPushInfoForVcs(@NotNull final PushSupport pushSupport) {
|
||||
Map<Repository, PushSpec> pushSpecs = new HashMap<Repository, PushSpec>();
|
||||
Collection<MyRepoModel> repositoriesInformation = getSelectedRepoNode();
|
||||
for (MyRepoModel repoModel : repositoriesInformation) {
|
||||
if (repoModel.getSupport().equals(pushSupport)) {
|
||||
pushSpecs.put(repoModel.getRepository(), repoModel.getSpec());
|
||||
}
|
||||
}
|
||||
return pushSpecs;
|
||||
}
|
||||
|
||||
public Collection<MyRepoModel> getSelectedRepoNode() {
|
||||
if (mySingleRepoProject) {
|
||||
return myView2Model.values();
|
||||
}
|
||||
return ContainerUtil.filter(myView2Model.values(), new Condition<MyRepoModel>() {
|
||||
@Override
|
||||
public boolean value(MyRepoModel model) {
|
||||
return model.isSelected();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
for (RepositoryNode node : myView2Model.keySet()) {
|
||||
node.stopLoading();
|
||||
}
|
||||
}
|
||||
|
||||
private void addMoreCommits(RepositoryNode repositoryNode) {
|
||||
MyRepoModel repoModel = myView2Model.get(repositoryNode);
|
||||
repoModel.increaseShownCommits();
|
||||
myPushLog.setChildren(repositoryNode,
|
||||
getPresentationForCommits(
|
||||
myProject,
|
||||
repoModel.getLoadedCommits(),
|
||||
repoModel.getNumberOfShownCommits()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public List<DefaultMutableTreeNode> getPresentationForCommits(@NotNull final Project project,
|
||||
@NotNull List<? extends VcsFullCommitDetails> commits,
|
||||
int commitsNum) {
|
||||
Function<VcsFullCommitDetails, DefaultMutableTreeNode> commitToNode = new Function<VcsFullCommitDetails, DefaultMutableTreeNode>() {
|
||||
@Override
|
||||
public DefaultMutableTreeNode fun(VcsFullCommitDetails commit) {
|
||||
return new VcsFullCommitDetailsNode(project, commit);
|
||||
}
|
||||
};
|
||||
List<DefaultMutableTreeNode> childrenToShown = new ArrayList<DefaultMutableTreeNode>();
|
||||
for (int i = 0; i < commits.size(); ++i) {
|
||||
if (i >= commitsNum) {
|
||||
final MoreCommitsLink moreCommitsLink = new MoreCommitsLink();
|
||||
moreCommitsLink.addClickListener(new TreeNodeLinkListener() {
|
||||
@Override
|
||||
public void onClick(@NotNull DefaultMutableTreeNode source) {
|
||||
TreeNode parentNode = source.getParent();
|
||||
if (parentNode instanceof RepositoryNode) {
|
||||
addMoreCommits((RepositoryNode)parentNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
childrenToShown.add(new TextWithLinkNode(moreCommitsLink));
|
||||
break;
|
||||
}
|
||||
childrenToShown.add(commitToNode.fun(commits.get(i)));
|
||||
}
|
||||
return childrenToShown;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<VcsPushOptionsPanel> getAdditionalPanels() {
|
||||
List<VcsPushOptionsPanel> additionalPanels = new ArrayList<VcsPushOptionsPanel>();
|
||||
for (final PushSupport support : myPushSupports) {
|
||||
final VcsPushOptionsPanel panel = support.getVcsPushOptionsPanel();
|
||||
if (panel != null) {
|
||||
additionalPanels.add(panel);
|
||||
myAdditionalValuesMap.put(support, new MyPushOptionValueModel(panel.getValue()));
|
||||
panel.addValueChangeListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myAdditionalValuesMap.get(support).setCurrentValue(panel.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return additionalPanels;
|
||||
}
|
||||
|
||||
private static class MyRepoModel {
|
||||
final Repository myRepository;
|
||||
private PushSupport mySupport;
|
||||
|
||||
PushSpec mySpec;
|
||||
int myNumberOfShownCommits;
|
||||
|
||||
List<? extends VcsFullCommitDetails> myLoadedCommits;
|
||||
boolean myIsSelected;
|
||||
|
||||
public MyRepoModel(Repository repository, PushSupport supportForRepo, boolean isSelected, PushSpec spec, int num) {
|
||||
myRepository = repository;
|
||||
mySupport = supportForRepo;
|
||||
myIsSelected = isSelected;
|
||||
mySpec = spec;
|
||||
myNumberOfShownCommits = num;
|
||||
}
|
||||
|
||||
public Repository getRepository() {
|
||||
return myRepository;
|
||||
}
|
||||
|
||||
public PushSupport getSupport() {
|
||||
return mySupport;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return myIsSelected;
|
||||
}
|
||||
|
||||
public AbstractVcs<?> getVcs() {
|
||||
return myRepository.getVcs();
|
||||
}
|
||||
|
||||
public PushSpec getSpec() {
|
||||
return mySpec;
|
||||
}
|
||||
|
||||
public void setSpec(PushSpec spec) {
|
||||
mySpec = spec;
|
||||
}
|
||||
|
||||
public void setSelected(boolean isSelected) {
|
||||
myIsSelected = isSelected;
|
||||
}
|
||||
|
||||
public int getNumberOfShownCommits() {
|
||||
return myNumberOfShownCommits;
|
||||
}
|
||||
|
||||
public void increaseShownCommits() {
|
||||
myNumberOfShownCommits *= 2;
|
||||
}
|
||||
|
||||
public List<? extends VcsFullCommitDetails> getLoadedCommits() {
|
||||
return myLoadedCommits;
|
||||
}
|
||||
|
||||
public void setLoadedCommits(List<? extends VcsFullCommitDetails> loadedCommits) {
|
||||
myLoadedCommits = loadedCommits;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyPushOptionValueModel {
|
||||
@NotNull private VcsPushOptionValue myCurrentValue;
|
||||
|
||||
public MyPushOptionValueModel(@NotNull VcsPushOptionValue currentValue) {
|
||||
myCurrentValue = currentValue;
|
||||
}
|
||||
|
||||
public void setCurrentValue(@NotNull VcsPushOptionValue currentValue) {
|
||||
myCurrentValue = currentValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VcsPushOptionValue getCurrentValue() {
|
||||
return myCurrentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push;
|
||||
|
||||
public interface RepositoryNodeListener {
|
||||
|
||||
void onTargetChanged(String newValue);
|
||||
|
||||
void onSelectionChanged(boolean isSelected);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
interface CustomRenderedTreeNode {
|
||||
|
||||
void render(@NotNull ColoredTreeCellRenderer renderer);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.push.VcsPushReferenceStrategy;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class DvcsStrategyPanel extends JPanel {
|
||||
|
||||
private ComboBox myReferenceStrategyCombobox;
|
||||
|
||||
public DvcsStrategyPanel() {
|
||||
setLayout(new BorderLayout());
|
||||
myReferenceStrategyCombobox = new ComboBox();
|
||||
DefaultComboBoxModel comboModel = new DefaultComboBoxModel(VcsPushReferenceStrategy.values());
|
||||
myReferenceStrategyCombobox.setModel(comboModel);
|
||||
JPanel bottomPanel = new JPanel(new FlowLayout());
|
||||
JLabel referenceStrategyLabel = new JLabel("Push Reference Strategy: ");
|
||||
bottomPanel.add(referenceStrategyLabel, FlowLayout.LEFT);
|
||||
bottomPanel.add(myReferenceStrategyCombobox);
|
||||
add(bottomPanel, BorderLayout.WEST);
|
||||
}
|
||||
|
||||
public VcsPushReferenceStrategy getStrategy() {
|
||||
return (VcsPushReferenceStrategy)myReferenceStrategyCombobox.getSelectedItem();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.push.RepositoryNodeListener;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface EditableTreeNode extends CustomRenderedTreeNode {
|
||||
void addRepoNodeListener(@NotNull RepositoryNodeListener listener);
|
||||
|
||||
void fireOnChange(@NotNull String value);
|
||||
|
||||
void fireOnSelectionChange(boolean isSelected);
|
||||
|
||||
void stopLoading();
|
||||
|
||||
ProgressIndicator startLoading();
|
||||
|
||||
String getValue();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.net.URL;
|
||||
|
||||
public class LoadingTreeNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode {
|
||||
@NotNull protected ImageIcon myLoadingIcon;
|
||||
private static final String LOADING_ICON = "loadingSimpleIcon.gif";
|
||||
private static final String LOADING_DARK_ICON = "loadingSimpleDarkIcon.gif";
|
||||
|
||||
@NotNull
|
||||
public ImageIcon getIcon() {
|
||||
return myLoadingIcon;
|
||||
}
|
||||
|
||||
public LoadingTreeNode() {
|
||||
super(null, false);
|
||||
URL loadingIconPath = getClass().getResource(UIUtil.isUnderDarcula() ? LOADING_DARK_ICON : LOADING_ICON);
|
||||
myLoadingIcon = new ImageIcon(loadingIconPath.getPath());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
renderer.setIcon(myLoadingIcon);
|
||||
renderer.append("Loading Commits...", new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, JBColor.GRAY));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
class NodeImageObserver implements ImageObserver {
|
||||
JTree tree;
|
||||
DefaultTreeModel model;
|
||||
TreeNode node;
|
||||
|
||||
NodeImageObserver(JTree tree, TreeNode node) {
|
||||
this.tree = tree;
|
||||
this.model = (DefaultTreeModel)tree.getModel();
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
|
||||
if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
|
||||
TreePath path = new TreePath(model.getPathToRoot(node));
|
||||
Rectangle rect = tree.getPathBounds(path);
|
||||
if (rect != null) {
|
||||
tree.repaint(rect);
|
||||
}
|
||||
}
|
||||
return (flags & (ALLBITS | ABORT)) == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.openapi.actionSystem.CommonShortcuts;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.DataSink;
|
||||
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
|
||||
import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CellEditorListener;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EventObject;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class PushLog extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
private final ReentrantReadWriteLock TREE_CONSTRUCTION_LOCK = new ReentrantReadWriteLock();
|
||||
|
||||
private static final String START_EDITING = "startEditing";
|
||||
private final ChangesBrowser myChangesBrowser;
|
||||
private final CheckboxTree myTree;
|
||||
private final CheckedTreeNode myRootNode;
|
||||
private final MyTreeCellRenderer myTreeCellRenderer;
|
||||
|
||||
public PushLog(Project project, CheckedTreeNode root) {
|
||||
myRootNode = root;
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel(myRootNode);
|
||||
treeModel.nodeStructureChanged(myRootNode);
|
||||
myTreeCellRenderer = new MyTreeCellRenderer();
|
||||
myTree = new CheckboxTree(myTreeCellRenderer, myRootNode) {
|
||||
|
||||
public boolean isPathEditable(TreePath path) {
|
||||
return isEditable() && path.getLastPathComponent() instanceof DefaultMutableTreeNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeStateChanged(CheckedTreeNode node) {
|
||||
if (node instanceof EditableTreeNode) {
|
||||
((EditableTreeNode)node).fireOnSelectionChange(node.isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText(MouseEvent event) {
|
||||
final TreePath path = myTree.getPathForLocation(event.getX(), event.getY());
|
||||
if (path == null) {
|
||||
return "";
|
||||
}
|
||||
Object node = path.getLastPathComponent();
|
||||
if (node == null || (!(node instanceof DefaultMutableTreeNode))) {
|
||||
return "";
|
||||
}
|
||||
if (node instanceof TooltipNode) {
|
||||
return ((TooltipNode)node).getTooltip();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
myTree.setEditable(true);
|
||||
MyTreeCellEditor treeCellEditor = new MyTreeCellEditor(new JBTextField());
|
||||
myTree.setCellEditor(treeCellEditor);
|
||||
treeCellEditor.addCellEditorListener(new CellEditorListener() {
|
||||
@Override
|
||||
public void editingStopped(ChangeEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editingCanceled(ChangeEvent e) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent();
|
||||
if (node != null && node instanceof EditableTreeNode) {
|
||||
//todo restore from appropriate editor
|
||||
((EditableTreeNode)node).fireOnChange(((EditableTreeNode)node).getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
myTree.setRootVisible(false);
|
||||
TreeUtil.expandAll(myTree);
|
||||
final VcsBranchEditorListener linkMouseListener = new VcsBranchEditorListener(myTreeCellRenderer);
|
||||
linkMouseListener.installOn(myTree);
|
||||
|
||||
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
||||
myTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath[] nodes = myTree.getSelectionPaths();
|
||||
if (nodes != null) {
|
||||
ArrayList<Change> changes = new ArrayList<Change>();
|
||||
for (TreePath node : nodes) {
|
||||
Object nodeInfo = ((DefaultMutableTreeNode)node.getLastPathComponent()).getUserObject();
|
||||
if (nodeInfo instanceof VcsFullCommitDetails) {
|
||||
changes.addAll(((VcsFullCommitDetails)nodeInfo).getChanges());
|
||||
}
|
||||
}
|
||||
myChangesBrowser.getViewer().setEmptyText("No differences");
|
||||
myChangesBrowser.setChangesToDisplay(CommittedChangesTreeBrowser.zipChanges(changes));
|
||||
return;
|
||||
}
|
||||
setDefaultEmptyText();
|
||||
myChangesBrowser.setChangesToDisplay(Collections.<Change>emptyList());
|
||||
}
|
||||
});
|
||||
myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), START_EDITING);
|
||||
myTree.setRowHeight(0);
|
||||
ToolTipManager.sharedInstance().registerComponent(myTree);
|
||||
|
||||
myChangesBrowser =
|
||||
new ChangesBrowser(project, null, Collections.<Change>emptyList(), null, false, true, null, ChangesBrowser.MyUseCase.LOCAL_CHANGES,
|
||||
null);
|
||||
myChangesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myTree);
|
||||
setDefaultEmptyText();
|
||||
|
||||
Splitter splitter = new Splitter(false, 0.7f);
|
||||
splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree));
|
||||
splitter.setSecondComponent(myChangesBrowser);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(splitter);
|
||||
}
|
||||
|
||||
private void setDefaultEmptyText() {
|
||||
myChangesBrowser.getViewer().setEmptyText("No commits selected");
|
||||
}
|
||||
|
||||
// Make changes available for diff action
|
||||
@Override
|
||||
public void calcData(DataKey key, DataSink sink) {
|
||||
if (VcsDataKeys.CHANGES.equals(key)) {
|
||||
DefaultMutableTreeNode[] selectedNodes = myTree.getSelectedNodes(DefaultMutableTreeNode.class, null);
|
||||
if (selectedNodes.length == 0) {
|
||||
return;
|
||||
}
|
||||
Object object = selectedNodes[0].getUserObject();
|
||||
if (object instanceof VcsFullCommitDetails) {
|
||||
sink.put(key, ArrayUtil.toObjectArray(((VcsFullCommitDetails)object).getChanges(), Change.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER && myTree.isEditing()) {
|
||||
myTree.cancelEditing();
|
||||
return true;
|
||||
}
|
||||
return super.processKeyBinding(ks, e, condition, pressed);
|
||||
}
|
||||
|
||||
public void startLoading(DefaultMutableTreeNode parentNode) {
|
||||
LoadingTreeNode loading = new LoadingTreeNode();
|
||||
loading.getIcon().setImageObserver(new NodeImageObserver(myTree, loading));
|
||||
setChildren(parentNode, Collections.singleton(loading));
|
||||
}
|
||||
|
||||
private class MyTreeCellEditor extends DefaultCellEditor {
|
||||
|
||||
public MyTreeCellEditor(JTextField field) {
|
||||
super(field);
|
||||
setClickCountToStart(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
|
||||
final Object node = ((DefaultMutableTreeNode)value).getUserObject();
|
||||
editorComponent =
|
||||
(JComponent)((RepositoryWithBranchPanel)node).getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true);
|
||||
return editorComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(EventObject anEvent) {
|
||||
if (anEvent instanceof MouseEvent) {
|
||||
MouseEvent me = ((MouseEvent)anEvent);
|
||||
final TreePath path = myTree.getClosestPathForLocation(me.getX(), me.getY());
|
||||
final int row = myTree.getRowForLocation(me.getX(), me.getY());
|
||||
myTree.getCellRenderer().getTreeCellRendererComponent(myTree, path.getLastPathComponent(), false, false, true, row, true);
|
||||
Object tag = me.getClickCount() >= clickCountToStart
|
||||
? PushLogTreeUtil.getTagAtForRenderer(myTreeCellRenderer, me)
|
||||
: null;
|
||||
return tag instanceof EditorTextField;
|
||||
}
|
||||
//if keyboard event - then anEvent will be null =( See BasicTreeUi
|
||||
Object treeNode = myTree.getAnchorSelectionPath().getLastPathComponent();
|
||||
return treeNode instanceof EditableTreeNode;
|
||||
}
|
||||
|
||||
//Implement the one CellEditor method that AbstractCellEditor doesn't.
|
||||
public Object getCellEditorValue() {
|
||||
return ((RepositoryWithBranchPanel)editorComponent).getRemoteTargetName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
|
||||
|
||||
@Override
|
||||
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (!(value instanceof DefaultMutableTreeNode)) {
|
||||
return;
|
||||
}
|
||||
if (value instanceof RepositoryNode) {
|
||||
//todo simplify, remove instance of
|
||||
myCheckbox.setVisible(((RepositoryNode)value).isCheckboxVisible());
|
||||
}
|
||||
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
|
||||
ColoredTreeCellRenderer renderer = getTextRenderer();
|
||||
renderer.setBorder(null);
|
||||
if (value instanceof CustomRenderedTreeNode) {
|
||||
((CustomRenderedTreeNode)value).render(renderer);
|
||||
}
|
||||
else {
|
||||
renderer.append(userObject == null ? "" : userObject.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setChildren(DefaultMutableTreeNode parentNode, @NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes) {
|
||||
setChildren(parentNode, childrenNodes, true);
|
||||
}
|
||||
|
||||
public void setChildren(DefaultMutableTreeNode parentNode,
|
||||
@NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes,
|
||||
boolean shouldExpand) {
|
||||
try {
|
||||
TREE_CONSTRUCTION_LOCK.writeLock().lock();
|
||||
parentNode.removeAllChildren();
|
||||
for (DefaultMutableTreeNode child : childrenNodes) {
|
||||
parentNode.add(child);
|
||||
}
|
||||
final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel());
|
||||
model.nodeStructureChanged(parentNode);
|
||||
TreePath path = TreeUtil.getPathFromRoot(parentNode);
|
||||
if (shouldExpand) {
|
||||
myTree.expandPath(path);
|
||||
}
|
||||
else {
|
||||
myTree.collapsePath(path);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
TREE_CONSTRUCTION_LOCK.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.ui.CheckboxTree;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class PushLogTreeUtil {
|
||||
|
||||
@Nullable
|
||||
public static Object getTagAtForRenderer(CheckboxTree.CheckboxTreeCellRenderer renderer, MouseEvent e) {
|
||||
JTree tree = (JTree)e.getSource();
|
||||
Object tag = null;
|
||||
final TreePath path = tree.getPathForLocation(e.getX(), e.getY());
|
||||
if (path != null) {
|
||||
final Rectangle rectangle = tree.getPathBounds(path);
|
||||
assert rectangle != null;
|
||||
int dx = e.getX() - rectangle.x;
|
||||
final TreeNode treeNode = (TreeNode)path.getLastPathComponent();
|
||||
final int row = tree.getRowForLocation(e.getX(), e.getY());
|
||||
tree.getCellRenderer().getTreeCellRendererComponent(tree, treeNode, false, false, true, row, true);
|
||||
if (treeNode instanceof RepositoryNode) {
|
||||
RepositoryNode repositoryNode = (RepositoryNode)treeNode;
|
||||
int checkBoxWidth = repositoryNode.isCheckboxVisible() ? renderer.getCheckbox().getWidth() : 0;
|
||||
tag = renderer.getTextRenderer().getFragmentTagAt(dx - checkBoxWidth);
|
||||
}
|
||||
else {
|
||||
tag = renderer.getTextRenderer().getFragmentTagAt(dx);
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.push.RepositoryNodeListener;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode {
|
||||
protected final static String ENTER_REMOTE = "Enter Remote";
|
||||
|
||||
private RepositoryWithBranchPanel myRepositoryPanel;
|
||||
private ProgressIndicator myCurrentIndicator;
|
||||
private final List<RepositoryNodeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
|
||||
super(repositoryPanel);
|
||||
myRepositoryPanel = repositoryPanel;
|
||||
}
|
||||
|
||||
public boolean isCheckboxVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
String repositoryPath = myRepositoryPanel.getRepositoryName();
|
||||
renderer.append(repositoryPath, SimpleTextAttributes.GRAY_ATTRIBUTES);
|
||||
renderer.appendFixedTextFragmentWidth(120);
|
||||
renderer
|
||||
.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
renderer
|
||||
.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
|
||||
String targetName = myRepositoryPanel.getRemoteTargetName();
|
||||
if (StringUtil.isEmptyOrSpaces(targetName)) {
|
||||
renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, textField);
|
||||
}
|
||||
else {
|
||||
renderer.append(targetName, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, textField);
|
||||
}
|
||||
Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
|
||||
renderer.setBorder(new EmptyBorder(insets));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getValue() {
|
||||
return myRepositoryPanel.getRemoteTargetName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRepoNodeListener(@NotNull RepositoryNodeListener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireOnChange(@NotNull String newValue) {
|
||||
for (RepositoryNodeListener listener : myListeners) {
|
||||
listener.onTargetChanged(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireOnSelectionChange(boolean isSelected) {
|
||||
for (RepositoryNodeListener listener : myListeners) {
|
||||
listener.onSelectionChanged(isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLoading() {
|
||||
if (myCurrentIndicator != null && myCurrentIndicator.isRunning()) {
|
||||
myCurrentIndicator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgressIndicator startLoading() {
|
||||
return myCurrentIndicator = new EmptyProgressIndicator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletion;
|
||||
import com.intellij.ui.TextFieldWithAutoCompletionListProvider;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.util.Collection;
|
||||
|
||||
public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCellRenderer {
|
||||
|
||||
private final JBCheckBox myRepositoryCheckbox;
|
||||
private final TextFieldWithAutoCompletion myDestBranchTextField;
|
||||
private final JBLabel myLocalBranch;
|
||||
private final JLabel myArrowLabel;
|
||||
private final JLabel myRepositoryLabel;
|
||||
private final ColoredTreeCellRenderer myTextRenderer;
|
||||
|
||||
public RepositoryWithBranchPanel(Project project, @NotNull String repoName,
|
||||
@NotNull String sourceName, String targetName, @NotNull Collection<String> targetVariants) {
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
myRepositoryCheckbox = new JBCheckBox();
|
||||
myRepositoryCheckbox.setOpaque(false);
|
||||
myRepositoryCheckbox.setEnabled(false); //may be return editor depends on focus
|
||||
myRepositoryLabel = new JLabel(repoName);
|
||||
myLocalBranch = new JBLabel(sourceName);
|
||||
myArrowLabel = new JLabel(" -> ");
|
||||
TextFieldWithAutoCompletionListProvider<String> provider =
|
||||
new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null);
|
||||
myDestBranchTextField = new TextFieldWithAutoCompletion<String>(project, provider, true, targetName) {
|
||||
|
||||
@Override
|
||||
public boolean shouldHaveBorder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateBorder(@NotNull final EditorEx editor) {
|
||||
}
|
||||
};
|
||||
myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());//getTextFieldBorder());
|
||||
myDestBranchTextField.setOneLineMode(true);
|
||||
myDestBranchTextField.setOpaque(true);
|
||||
myDestBranchTextField.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
myDestBranchTextField.selectAll();
|
||||
}
|
||||
});
|
||||
|
||||
myTextRenderer = new ColoredTreeCellRenderer() {
|
||||
public void customizeCellRenderer(@NotNull JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
|
||||
}
|
||||
};
|
||||
myTextRenderer.setOpaque(false);
|
||||
layoutComponents();
|
||||
}
|
||||
|
||||
private void layoutComponents() {
|
||||
add(myRepositoryCheckbox, BorderLayout.WEST);
|
||||
JPanel panel = new NonOpaquePanel(new BorderLayout());
|
||||
panel.add(myTextRenderer, BorderLayout.WEST);
|
||||
panel.add(myDestBranchTextField, BorderLayout.CENTER);
|
||||
add(panel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getRepositoryName() {
|
||||
return myRepositoryLabel.getText();
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return myLocalBranch.getText();
|
||||
}
|
||||
|
||||
public String getArrow() {
|
||||
return myArrowLabel.getText();
|
||||
}
|
||||
|
||||
public TextFieldWithAutoCompletion<String> getRemoteTextFiled() {
|
||||
return myDestBranchTextField;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getRemoteTargetName() {
|
||||
return myDestBranchTextField.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
Rectangle bounds = tree.getPathBounds(tree.getPathForRow(row));
|
||||
invalidate();
|
||||
if (!(value instanceof SingleRepositoryNode)) {
|
||||
RepositoryNode node = (RepositoryNode)value;
|
||||
myRepositoryCheckbox.setSelected(node.isChecked());
|
||||
myRepositoryCheckbox.setVisible(true);
|
||||
myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
myTextRenderer.append(getRepositoryName(), SimpleTextAttributes.GRAY_ATTRIBUTES);
|
||||
myTextRenderer.appendFixedTextFragmentWidth(120);
|
||||
}
|
||||
else {
|
||||
myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
myRepositoryCheckbox.setVisible(false);
|
||||
}
|
||||
myTextRenderer.append(getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
myTextRenderer.append(getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
if (bounds != null) {
|
||||
setPreferredSize(new Dimension(tree.getWidth() - bounds.x, bounds.height));
|
||||
}
|
||||
revalidate();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
|
||||
public class SingleRepositoryNode extends RepositoryNode {
|
||||
private RepositoryWithBranchPanel myRepositoryPanel;
|
||||
|
||||
public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
|
||||
super(repositoryPanel);
|
||||
myRepositoryPanel = repositoryPanel;
|
||||
}
|
||||
|
||||
public boolean isCheckboxVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
renderer
|
||||
.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
renderer
|
||||
.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
|
||||
String targetName = myRepositoryPanel.getRemoteTargetName();
|
||||
if (StringUtil.isEmptyOrSpaces(targetName)) {
|
||||
renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, textField);
|
||||
}
|
||||
else {
|
||||
renderer.append(targetName, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, textField);
|
||||
}
|
||||
Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
|
||||
renderer.setBorder(new EmptyBorder(insets));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
|
||||
import com.intellij.dvcs.push.VcsLinkedText;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class TextWithLinkNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode {
|
||||
|
||||
@NotNull protected VcsLinkedText myLinkedText;
|
||||
|
||||
public TextWithLinkNode(@NotNull VcsLinkedText linkedText) {
|
||||
myLinkedText = linkedText;
|
||||
}
|
||||
|
||||
|
||||
public void fireOnClick(@NotNull TextWithLinkNode relatedNode) {
|
||||
myLinkedText.fireOnClick(relatedNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
renderer.append(myLinkedText.getText(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
String linkedText = myLinkedText.getLinkText();
|
||||
if (!StringUtil.isEmptyOrSpaces(linkedText)) {
|
||||
renderer.append(" ");
|
||||
renderer.append(myLinkedText.getLinkText(), SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
public interface TooltipNode {
|
||||
|
||||
String getTooltip();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
|
||||
import com.intellij.ui.CheckboxTree;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class VcsBranchEditorListener extends LinkMouseListenerBase {
|
||||
private final CheckboxTree.CheckboxTreeCellRenderer myRenderer;
|
||||
|
||||
public VcsBranchEditorListener(final CheckboxTree.CheckboxTreeCellRenderer renderer) {
|
||||
myRenderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
Component component = (Component)e.getSource();
|
||||
Object tag = getTagAt(e);
|
||||
if (tag != null && tag instanceof EditorTextField) {
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
|
||||
}
|
||||
else if (tag != null && tag instanceof TextWithLinkNode) {
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
}
|
||||
else {
|
||||
component.setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Object getTagAt(@NotNull final MouseEvent e) {
|
||||
return PushLogTreeUtil.getTagAtForRenderer(myRenderer, e);
|
||||
}
|
||||
|
||||
protected void handleTagClick(@Nullable Object tag, @NotNull MouseEvent event) {
|
||||
if (tag instanceof TextWithLinkNode) {
|
||||
TextWithLinkNode textWithLink = (TextWithLinkNode)tag;
|
||||
textWithLink.fireOnClick(textWithLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class VcsFullCommitDetailsNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode, TooltipNode {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
private final VcsFullCommitDetails myCommit;
|
||||
|
||||
public VcsFullCommitDetailsNode(@NotNull Project project, VcsFullCommitDetails commit) {
|
||||
super(commit, false);
|
||||
myProject = project;
|
||||
myCommit = commit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull ColoredTreeCellRenderer renderer) {
|
||||
renderer
|
||||
.append(myCommit.getSubject(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, renderer.getForeground()));
|
||||
}
|
||||
|
||||
public String getTooltip() {
|
||||
return DvcsUtil.getShortHash(myCommit.getId().toString()) +
|
||||
" " +
|
||||
DvcsUtil.getDateString(myCommit) +
|
||||
" by " +
|
||||
myCommit.getAuthor().getName() +
|
||||
"\n\n" +
|
||||
IssueLinkHtmlRenderer.formatTextWithLinks(myProject, myCommit.getFullMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 com.intellij.dvcs.push.ui;
|
||||
|
||||
import com.intellij.dvcs.push.PushController;
|
||||
import com.intellij.dvcs.push.VcsPushOptionsPanel;
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.OptionAction;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VcsPushDialog extends DialogWrapper {
|
||||
|
||||
private final PushLog myListPanel;
|
||||
private final PushController myController;
|
||||
private final Action[] myExecutorActions = {new DvcsPushAction("&Force Push", true)};
|
||||
@NotNull private final JPanel myAdditionalOptionsFromVcsPanel;
|
||||
|
||||
private DvcsPushAction myPushAction;
|
||||
|
||||
public VcsPushDialog(@NotNull Project project, @NotNull List<? extends Repository> selectedRepositories) {
|
||||
super(project);
|
||||
myController = new PushController(project, this, selectedRepositories);
|
||||
myListPanel = myController.getPushPanelInfo();
|
||||
myAdditionalOptionsFromVcsPanel = new JPanel(new MigLayout("ins 0 0, flowx"));
|
||||
init();
|
||||
setOKButtonText("Push");
|
||||
setOKButtonMnemonic('P');
|
||||
setTitle("Push Dialog");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
|
||||
JComponent rootPanel = new JPanel(new BorderLayout(0, 15));
|
||||
rootPanel.add(myListPanel, BorderLayout.CENTER);
|
||||
for (VcsPushOptionsPanel panel : myController.getAdditionalPanels()) {
|
||||
myAdditionalOptionsFromVcsPanel.add(panel);
|
||||
}
|
||||
rootPanel.add(myAdditionalOptionsFromVcsPanel, BorderLayout.SOUTH);
|
||||
return rootPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDimensionServiceKey() {
|
||||
return VcsPushDialog.class.getName();
|
||||
}
|
||||
|
||||
protected void setOKActionEnabled(boolean isEnabled) {
|
||||
if (myPushAction != null) {
|
||||
myPushAction.setEnabled(isEnabled);
|
||||
}
|
||||
for (Action executorAction : myExecutorActions) {
|
||||
executorAction.setEnabled(isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected Action[] createActions() {
|
||||
final List<Action> actions = new ArrayList<Action>();
|
||||
myPushAction = new DvcsPushAction("&Push", false);
|
||||
myPushAction.putValue(DEFAULT_ACTION, Boolean.TRUE);
|
||||
actions.add(myPushAction);
|
||||
myPushAction.setOptions(myExecutorActions);
|
||||
actions.add(getCancelAction());
|
||||
actions.add(getHelpAction());
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Action getOKAction() {
|
||||
return new DvcsPushAction("&Push", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpId() {
|
||||
return "reference.mercurial.push.dialog";
|
||||
}
|
||||
|
||||
private class DvcsPushAction extends AbstractAction implements OptionAction {
|
||||
private Action[] myOptions = new Action[0];
|
||||
private final boolean myForce;
|
||||
|
||||
private DvcsPushAction(String title, boolean force) {
|
||||
super(title);
|
||||
myForce = force;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myController.push(myForce);
|
||||
close(OK_EXIT_CODE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Action[] getOptions() {
|
||||
return myOptions;
|
||||
}
|
||||
|
||||
public void setOptions(Action[] actions) {
|
||||
myOptions = actions;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
+4
-4
@@ -15,15 +15,15 @@
|
||||
*/
|
||||
package com.intellij.dvcs.test;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.components.BaseComponent;
|
||||
import org.picocontainer.PicoContainer;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.picocontainer.PicoContainer;
|
||||
|
||||
/**
|
||||
*
|
||||
+10
-2
@@ -371,6 +371,14 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
|
||||
public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task,
|
||||
@NotNull final ProgressIndicator progressIndicator,
|
||||
@Nullable final Runnable continuation) {
|
||||
return runProcessWithProgressAsynchronously(task, progressIndicator, continuation, ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task,
|
||||
@NotNull final ProgressIndicator progressIndicator,
|
||||
@Nullable final Runnable continuation,
|
||||
@NotNull final ModalityState modalityState) {
|
||||
if (progressIndicator instanceof Disposable) {
|
||||
Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator);
|
||||
}
|
||||
@@ -397,7 +405,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
|
||||
public void run() {
|
||||
task.onCancel();
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}, modalityState);
|
||||
}
|
||||
else {
|
||||
final Task.NotificationInfo notificationInfo = task.notifyFinished();
|
||||
@@ -412,7 +420,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
|
||||
public void run() {
|
||||
task.onSuccess();
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}, modalityState);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,5 +101,8 @@
|
||||
<xi:include href="/META-INF/vcs-log-graph.xml" xpointer="xpointer(/idea-plugin/*)">
|
||||
<xi:fallback/>
|
||||
</xi:include>
|
||||
<xi:include href="/META-INF/dvcs.xml" xpointer="xpointer(/idea-plugin/*)">
|
||||
<xi:fallback/>
|
||||
</xi:include>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
<xi:include href="/META-INF/vcs-log-graph.xml" xpointer="xpointer(/idea-plugin/*)">
|
||||
<xi:fallback/>
|
||||
</xi:include>
|
||||
<xi:include href="/META-INF/dvcs.xml" xpointer="xpointer(/idea-plugin/*)">
|
||||
<xi:fallback/>
|
||||
</xi:include>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="/META-INF/PlatformExtensionPoints.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
|
||||
<orderEntry type="module" module-name="dvcs" exported="" />
|
||||
<orderEntry type="module" module-name="dvcs-impl" exported="" />
|
||||
<orderEntry type="library" scope="TEST" name="cucumber-jvm" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="cucumber-java" level="project" />
|
||||
<orderEntry type="library" name="JSch" level="project" />
|
||||
@@ -58,6 +58,7 @@
|
||||
<orderEntry type="module" module-name="vcs-log-api" />
|
||||
<orderEntry type="module" module-name="vcs-log-impl" />
|
||||
<orderEntry type="module" module-name="vcs-log-graph" />
|
||||
<orderEntry type="module" module-name="dvcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<orderEntry type="module" module-name="idea-ui" />
|
||||
<orderEntry type="module" module-name="openapi" />
|
||||
<orderEntry type="module" module-name="vcs-impl" />
|
||||
<orderEntry type="module" module-name="dvcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -103,7 +104,7 @@ public class GitRevisionNumber implements ShortVcsRevisionNumber {
|
||||
*/
|
||||
@NotNull
|
||||
public String getShortRev() {
|
||||
return GitUtil.getShortHash(myRevisionHash);
|
||||
return DvcsUtil.getShortHash(myRevisionHash);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,7 +102,6 @@ public class GitUtil {
|
||||
public static final String DOT_GIT = ".git";
|
||||
|
||||
private final static Logger LOG = Logger.getInstance(GitUtil.class);
|
||||
private static final int SHORT_HASH_LENGTH = 8;
|
||||
|
||||
public static final Predicate<GitBranchTrackInfo> NOT_NULL_PREDICATE = new Predicate<GitBranchTrackInfo>() {
|
||||
@Override
|
||||
@@ -828,17 +827,6 @@ public class GitUtil {
|
||||
}, "\n");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getShortHash(@NotNull String hash) {
|
||||
if (hash.length() == 0) return "";
|
||||
if (hash.length() == 40) return hash.substring(0, SHORT_HASH_LENGTH);
|
||||
if (hash.length() > 40) // revision string encoded with date too
|
||||
{
|
||||
return hash.substring(hash.indexOf("[") + 1, SHORT_HASH_LENGTH);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String fileOrFolder(@NotNull VirtualFile file) {
|
||||
if (file.isDirectory()) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.actions;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
@@ -70,7 +71,7 @@ public class GitCompareWithBranchAction extends DumbAwareAction {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
LOG.assertTrue(currentRevision != null,
|
||||
"Current revision is null for " + repository + ". Compare with branch shouldn't be available for fresh repository");
|
||||
head = GitUtil.getShortHash(currentRevision);
|
||||
head = DvcsUtil.getShortHash(currentRevision);
|
||||
}
|
||||
else {
|
||||
head = currentBranch.getName();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.history;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -116,7 +117,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getPresentableName(@NotNull GitFileRevision revision) {
|
||||
return GitUtil.getShortHash(revision.getHash());
|
||||
return DvcsUtil.getShortHash(revision.getHash());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -301,7 +302,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil
|
||||
@NotNull private final GitFileRevision myParentRevision;
|
||||
|
||||
public ShowDiffWithParentAction(@NotNull FilePath filePath, @NotNull GitFileRevision rev, @NotNull GitFileRevision parent) {
|
||||
super(GitUtil.getShortHash(parent.getHash()));
|
||||
super(DvcsUtil.getShortHash(parent.getHash()));
|
||||
myFilePath = filePath;
|
||||
myRevision = rev;
|
||||
myParentRevision = parent;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.push;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -219,7 +220,7 @@ public class GitPushDialog extends DialogWrapper {
|
||||
private static String logMessageForCommits(GitCommitsByRepoAndBranch commitsToPush) {
|
||||
StringBuilder logMessage = new StringBuilder();
|
||||
for (GitCommit commit : commitsToPush.getAllCommits()) {
|
||||
logMessage.append(GitUtil.getShortHash(commit.getId().toString()));
|
||||
logMessage.append(DvcsUtil.getShortHash(commit.getId().toString()));
|
||||
}
|
||||
return logMessage.toString();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import git4idea.GitBranch;
|
||||
@@ -336,12 +335,12 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
@NotNull
|
||||
private static String getDateString(@NotNull GitCommit commit) {
|
||||
return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp()) + " ";
|
||||
return DvcsUtil.getDateString(commit);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getHashString(@NotNull GitCommit commit) {
|
||||
return GitUtil.getShortHash(commit.getId().toString());
|
||||
return DvcsUtil.getShortHash(commit.getId().toString());
|
||||
}
|
||||
|
||||
private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
|
||||
|
||||
@@ -19,11 +19,13 @@ import com.intellij.dvcs.repo.RepositoryImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.branch.GitBranchesCollection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -135,6 +137,12 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository {
|
||||
return myInfo.getState();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractVcs getVcs() {
|
||||
return GitVcs.getInstance(getProject());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return local and remote branches in this repository.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.reset;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
@@ -26,7 +27,6 @@ import com.intellij.util.ui.RadioButtonEnumModel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -127,7 +127,7 @@ public class GitNewResetDialog extends DialogWrapper {
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
assert currentRevision != null;
|
||||
String text = repository.getCurrentBranch() == null ?
|
||||
"HEAD (" + GitUtil.getShortHash(currentRevision) + ")" :
|
||||
"HEAD (" + DvcsUtil.getShortHash(currentRevision) + ")" :
|
||||
repository.getCurrentBranch().getName();
|
||||
return "<b>" + text + "</b>";
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.ui;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
@@ -28,7 +29,6 @@ import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitCommit;
|
||||
import git4idea.GitUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -198,7 +198,7 @@ public class GitCommitListPanel extends JPanel implements TypeSafeDataProvider {
|
||||
}
|
||||
|
||||
private static String getHash(GitCommit commit) {
|
||||
return GitUtil.getShortHash(commit.getId().toString());
|
||||
return DvcsUtil.getShortHash(commit.getId().toString());
|
||||
}
|
||||
|
||||
private static String getAuthor(GitCommit commit) {
|
||||
|
||||
@@ -38,9 +38,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.dvcs.DvcsUtil.getShortHash;
|
||||
import static com.intellij.openapi.vcs.Executor.overwrite;
|
||||
import static com.intellij.openapi.vcs.Executor.touch;
|
||||
import static git4idea.GitUtil.getShortHash;
|
||||
import static git4idea.test.GitExecutor.*;
|
||||
import static git4idea.test.GitTestUtil.USER_EMAIL;
|
||||
import static git4idea.test.GitTestUtil.USER_NAME;
|
||||
|
||||
@@ -3,6 +3,7 @@ package git4idea.log;
|
||||
import com.intellij.mock.MockVirtualFile;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.util.Function;
|
||||
@@ -283,6 +284,12 @@ public class GitRefManagerTest extends UsefulTestCase {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractVcs getVcs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getCurrentRevision() {
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="library" name="gson" level="project" />
|
||||
<orderEntry type="module" module-name="dvcs" />
|
||||
<orderEntry type="module" module-name="dvcs-impl" />
|
||||
<orderEntry type="module" module-name="dvcs-api" />
|
||||
<orderEntry type="module" module-name="testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="xml-openapi" />
|
||||
<orderEntry type="module" module-name="xml" />
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
<orderEntry type="module" module-name="vcs-impl" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="dvcs" />
|
||||
<orderEntry type="module" module-name="dvcs-impl" />
|
||||
<orderEntry type="module" module-name="vcs-log-api" />
|
||||
<orderEntry type="module" module-name="vcs-log-impl" />
|
||||
<orderEntry type="module" module-name="dvcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<vcs name="hg4idea" vcsClass="org.zmlx.hg4idea.HgVcs" displayName="Mercurial" administrativeAreaName=".hg"/>
|
||||
<checkoutProvider implementation="org.zmlx.hg4idea.provider.HgCheckoutProvider"/>
|
||||
<vcsRootChecker implementation="org.zmlx.hg4idea.roots.HgRootChecker"/>
|
||||
<pushSupport implementation="org.zmlx.hg4idea.push.HgPushSupport"/>
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
|
||||
<vcsPopupProvider implementation="org.zmlx.hg4idea.provider.HgQuickListProvider"/>
|
||||
<logProvider implementation="org.zmlx.hg4idea.log.HgLogProvider"/>
|
||||
|
||||
@@ -16,26 +16,18 @@
|
||||
package org.zmlx.hg4idea;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
|
||||
import org.zmlx.hg4idea.command.HgPushCommand;
|
||||
import org.zmlx.hg4idea.execution.HgCommandResult;
|
||||
import org.zmlx.hg4idea.execution.HgCommandResultHandler;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
import org.zmlx.hg4idea.ui.HgPushDialog;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -54,17 +46,17 @@ public class HgPusher {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void showDialogAndPush (@NotNull Collection<HgRepository> repositories,@Nullable final HgRepository selectedRepo) {
|
||||
/* public void showDialogAndPush(@NotNull List<? extends Repository> selectedRepositories) {
|
||||
|
||||
if (repositories.isEmpty()) {
|
||||
if (selectedRepositories.isEmpty()) {
|
||||
VcsBalloonProblemNotifier.showOverChangesView(myProject, "No Mercurial repositories in the project", MessageType.ERROR);
|
||||
return;
|
||||
}
|
||||
final AtomicReference<HgPushCommand> pushCommand = new AtomicReference<HgPushCommand>();
|
||||
final HgPushDialog dialog = new HgPushDialog(myProject, repositories, selectedRepo);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
pushCommand.set(preparePushCommand(myProject, dialog));
|
||||
if (d2.isOK()) {
|
||||
pushCommand.set(preparePushCommand(myProject, dialog));
|
||||
new Task.Backgroundable(myProject, "Pushing...", false) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
@@ -74,9 +66,9 @@ public class HgPusher {
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private static void push(final Project project, HgPushCommand command) {
|
||||
public static void push(final Project project, HgPushCommand command) {
|
||||
final VirtualFile repo = command.getRepo();
|
||||
command.execute(new HgCommandResultHandler() {
|
||||
@Override
|
||||
@@ -91,9 +83,11 @@ public class HgPusher {
|
||||
String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum),
|
||||
repo.getPresentableName());
|
||||
VcsNotifier.getInstance(project).notifySuccess(successTitle, successDescription);
|
||||
} else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
|
||||
}
|
||||
else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
|
||||
VcsNotifier.getInstance(project).notifySuccess("Nothing to push");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
new HgCommandResultNotifier(project).notifyError(result, "Push failed",
|
||||
"Failed to push to [" + repo.getPresentableName() + "]");
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
abstract class HgAbstractGlobalAction extends AnAction {
|
||||
@@ -48,12 +50,17 @@ abstract class HgAbstractGlobalAction extends AnAction {
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
|
||||
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
|
||||
HgRepository repo = file != null ? repositoryManager.getRepositoryForFile(file): HgUtil.getCurrentRepository(project);
|
||||
VirtualFile[] files = event.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
|
||||
final HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
|
||||
List<HgRepository> repositories = repositoryManager.getRepositories();
|
||||
if (!repositories.isEmpty()) {
|
||||
execute(project, repositories, repo);
|
||||
List<HgRepository> selectedRepositories = (files == null || files.length == 0)
|
||||
?
|
||||
Collections.singletonList(HgUtil.getCurrentRepository(project))
|
||||
: HgActionUtil.collectRepositoriesFromFiles(repositoryManager,
|
||||
Arrays.asList(files));
|
||||
|
||||
execute(project, repositories, selectedRepositories);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +73,7 @@ abstract class HgAbstractGlobalAction extends AnAction {
|
||||
|
||||
protected abstract void execute(@NotNull Project project,
|
||||
@NotNull Collection<HgRepository> repositories,
|
||||
@Nullable HgRepository selectedRepo);
|
||||
@NotNull List<HgRepository> selectedRepositories);
|
||||
|
||||
public static void handleException(@Nullable Project project, @NotNull Exception e) {
|
||||
handleException(project, "Error", e);
|
||||
@@ -102,16 +109,4 @@ abstract class HgAbstractGlobalAction extends AnAction {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
|
||||
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
|
||||
return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.zmlx.hg4idea.action;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class HgAbstractGlobalSingleRepoAction extends HgAbstractGlobalAction {
|
||||
|
||||
public HgAbstractGlobalSingleRepoAction(Icon icon) {
|
||||
super(icon);
|
||||
}
|
||||
|
||||
public HgAbstractGlobalSingleRepoAction() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull Project project,
|
||||
@NotNull Collection<HgRepository> repositories,
|
||||
@NotNull List<HgRepository> selectedRepositories) {
|
||||
execute(project, repositories, selectedRepositories.isEmpty() ? null : selectedRepositories.get(0));
|
||||
}
|
||||
|
||||
protected abstract void execute(@NotNull Project project,
|
||||
@NotNull Collection<HgRepository> repositories,
|
||||
@Nullable HgRepository selectedRepo);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.zmlx.hg4idea.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
import org.zmlx.hg4idea.repo.HgRepositoryManager;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class HgActionUtil {
|
||||
|
||||
@NotNull
|
||||
public static List<HgRepository> collectRepositoriesFromFiles(@NotNull final HgRepositoryManager repositoryManager,
|
||||
@NotNull Collection<VirtualFile> files) {
|
||||
return ContainerUtil.mapNotNull(files, new Function<VirtualFile, HgRepository>() {
|
||||
@Override
|
||||
public HgRepository fun(VirtualFile file) {
|
||||
return repositoryManager.getRepositoryForFile(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
|
||||
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
|
||||
return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.zmlx.hg4idea.repo.HgRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgBranchesAction extends HgAbstractGlobalAction {
|
||||
public class HgBranchesAction extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgCreateTagAction extends HgAbstractGlobalAction {
|
||||
public class HgCreateTagAction extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
public void execute(@NotNull final Project project,
|
||||
@NotNull Collection<HgRepository> repositories,
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.zmlx.hg4idea.ui.HgMergeDialog;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgMerge extends HgAbstractGlobalAction {
|
||||
public class HgMerge extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull final Project project,
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.zmlx.hg4idea.action;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
|
||||
public abstract class HgProcessRebaseAction extends HgAbstractGlobalAction {
|
||||
public abstract class HgProcessRebaseAction extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
protected static boolean isRebasing(AnActionEvent e) {
|
||||
HgRepository repository = HgAbstractGlobalAction.getSelectedRepositoryFromEvent(e);
|
||||
HgRepository repository = HgActionUtil.getSelectedRepositoryFromEvent(e);
|
||||
return repository != null && repository.getState() == HgRepository.State.REBASING;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.zmlx.hg4idea.ui.HgPullDialog;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgPullAction extends HgAbstractGlobalAction {
|
||||
public class HgPullAction extends HgAbstractGlobalSingleRepoAction {
|
||||
public HgPullAction() {
|
||||
super(AllIcons.Actions.CheckOut);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
// limitations under the License.
|
||||
package org.zmlx.hg4idea.action;
|
||||
|
||||
import com.intellij.dvcs.push.ui.VcsPushDialog;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.HgPusher;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class HgPushAction extends HgAbstractGlobalAction {
|
||||
public HgPushAction() {
|
||||
@@ -29,7 +29,7 @@ public class HgPushAction extends HgAbstractGlobalAction {
|
||||
@Override
|
||||
public void execute(@NotNull final Project project,
|
||||
@NotNull Collection<HgRepository> repositories,
|
||||
@Nullable final HgRepository selectedRepo) {
|
||||
new HgPusher(project).showDialogAndPush(repositories, selectedRepo);
|
||||
@NotNull final List<HgRepository> selectedRepositories) {
|
||||
new VcsPushDialog(project, selectedRepositories).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgRunConflictResolverAction extends HgAbstractGlobalAction {
|
||||
public class HgRunConflictResolverAction extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HgUpdateToAction extends HgAbstractGlobalAction {
|
||||
public class HgUpdateToAction extends HgAbstractGlobalSingleRepoAction {
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public class HgIdentifyCommand {
|
||||
public HgCommandResult execute(@NotNull ModalityState state) {
|
||||
final List<String> arguments = new LinkedList<String>();
|
||||
arguments.add(source);
|
||||
final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state);
|
||||
final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state, false);
|
||||
executor.setSilent(true);
|
||||
return executor.executeInCurrentThread(null, "identify", arguments);
|
||||
}
|
||||
|
||||
@@ -12,11 +12,19 @@
|
||||
// limitations under the License.
|
||||
package org.zmlx.hg4idea.command;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.execution.HgCommandResult;
|
||||
import org.zmlx.hg4idea.execution.HgRemoteCommandExecutor;
|
||||
import org.zmlx.hg4idea.log.HgHistoryUtil;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class HgOutgoingCommand extends HgRemoteChangesetsCommand {
|
||||
|
||||
public HgOutgoingCommand(Project project) {
|
||||
@@ -27,4 +35,22 @@ public class HgOutgoingCommand extends HgRemoteChangesetsCommand {
|
||||
protected String getRepositoryUrl(VirtualFile root) {
|
||||
return HgUtil.getRepositoryDefaultPushPath(project, root);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HgCommandResult execute(@NotNull VirtualFile repo,
|
||||
@NotNull String template,
|
||||
@NotNull String source,
|
||||
@NotNull String destination,
|
||||
boolean doNotShowAuthorizationRequest) {
|
||||
|
||||
List<String> arguments = new LinkedList<String>();
|
||||
arguments.add("--template");
|
||||
arguments.add(template);
|
||||
arguments.add(HgHistoryUtil.prepareParameter("rev", source));
|
||||
arguments.add(destination);
|
||||
HgRemoteCommandExecutor commandExecutor =
|
||||
new HgRemoteCommandExecutor(project, destination, ModalityState.any(), doNotShowAuthorizationRequest);
|
||||
commandExecutor.setOutputAlwaysSuppressed(true);
|
||||
return commandExecutor.executeInCurrentThread(repo, "outgoing", arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,13 @@ class HgCommandAuthenticator {
|
||||
private GetPasswordRunnable myGetPassword;
|
||||
private final Project myProject;
|
||||
private boolean myForceAuthorization;
|
||||
//todo replace silent mode and/or force authorization
|
||||
private boolean mySilentMode;
|
||||
|
||||
public HgCommandAuthenticator(Project project, boolean forceAuthorization) {
|
||||
public HgCommandAuthenticator(Project project, boolean forceAuthorization, boolean silent) {
|
||||
myProject = project;
|
||||
myForceAuthorization = forceAuthorization;
|
||||
mySilentMode = silent;
|
||||
}
|
||||
|
||||
public void saveCredentials() {
|
||||
@@ -71,7 +74,7 @@ class HgCommandAuthenticator {
|
||||
}
|
||||
|
||||
public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) {
|
||||
GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization);
|
||||
GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, mySilentMode);
|
||||
ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
|
||||
myGetPassword = runnable;
|
||||
return runnable.isOk();
|
||||
@@ -96,19 +99,27 @@ class HgCommandAuthenticator {
|
||||
@Nullable private String myURL;
|
||||
private boolean myRememberPassword;
|
||||
private boolean myForceAuthorization;
|
||||
private final boolean mySilent;
|
||||
|
||||
public GetPasswordRunnable(Project project, String proposedLogin, String uri, String path, boolean forceAuthorization) {
|
||||
public GetPasswordRunnable(Project project,
|
||||
String proposedLogin,
|
||||
String uri,
|
||||
String path,
|
||||
boolean forceAuthorization, boolean silent) {
|
||||
this.myProject = project;
|
||||
this.myProposedLogin = proposedLogin;
|
||||
this.myURL = uri + path;
|
||||
this.myForceAuthorization = forceAuthorization;
|
||||
mySilent = silent;
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
|
||||
// find if we've already been here
|
||||
final HgVcs vcs = HgVcs.getInstance(myProject);
|
||||
if (vcs == null) { return; }
|
||||
if (vcs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@NotNull final HgGlobalSettings hgGlobalSettings = vcs.getGlobalSettings();
|
||||
@Nullable String rememberedLoginsForUrl = null;
|
||||
@@ -128,11 +139,14 @@ class HgCommandAuthenticator {
|
||||
final String key = keyForUrlAndLogin(myURL, login);
|
||||
try {
|
||||
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
|
||||
password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
|
||||
if (password == null) {
|
||||
if (mySilent) {
|
||||
password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
|
||||
}
|
||||
else {
|
||||
password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key);
|
||||
}
|
||||
} catch (PasswordSafeException e) {
|
||||
}
|
||||
catch (PasswordSafeException e) {
|
||||
LOG.info("Couldn't get password for key [" + key + "]", e);
|
||||
}
|
||||
}
|
||||
@@ -146,7 +160,13 @@ class HgCommandAuthenticator {
|
||||
return;
|
||||
}
|
||||
|
||||
final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"), HgVcsMessages.message("hg4idea.dialog.login.description", myURL),
|
||||
if (mySilent) {
|
||||
ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"),
|
||||
HgVcsMessages.message("hg4idea.dialog.login.description", myURL),
|
||||
login, password, true);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
@@ -182,5 +202,4 @@ class HgCommandAuthenticator {
|
||||
private static String keyForUrlAndLogin(String stringUrl, String login) {
|
||||
return login + ":" + stringUrl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,16 +30,22 @@ import java.util.List;
|
||||
public class HgRemoteCommandExecutor extends HgCommandExecutor {
|
||||
|
||||
@Nullable private ModalityState myState;
|
||||
final boolean myIgnoreAuthorizationRequest;
|
||||
|
||||
public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination) {
|
||||
this(project, destination, null);
|
||||
this(project, destination, null, false);
|
||||
}
|
||||
|
||||
public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination, boolean ignoreAuthorizationRequest) {
|
||||
this(project, destination, null, ignoreAuthorizationRequest);
|
||||
}
|
||||
|
||||
public HgRemoteCommandExecutor(@NotNull Project project,
|
||||
@Nullable String destination,
|
||||
@Nullable ModalityState state) {
|
||||
@Nullable ModalityState state, boolean ignoreAuthorizationRequest) {
|
||||
super(project, destination);
|
||||
myState = state;
|
||||
myIgnoreAuthorizationRequest = ignoreAuthorizationRequest;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -48,7 +54,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
|
||||
|
||||
|
||||
HgCommandResult result = executeInCurrentThread(repo, operation, arguments, false);
|
||||
if (HgErrorUtil.isAuthorizationError(result)) {
|
||||
if (!myIgnoreAuthorizationRequest && HgErrorUtil.isAuthorizationError(result)) {
|
||||
if (HgErrorUtil.hasAuthorizationInDestinationPath(myDestination)) {
|
||||
new HgCommandResultNotifier(myProject)
|
||||
.notifyError(result, "Authorization failed", "Your hgrc file settings have wrong username or password in [paths].\n" +
|
||||
@@ -62,11 +68,11 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
|
||||
|
||||
@Nullable
|
||||
private HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo,
|
||||
@NotNull final String operation,
|
||||
@Nullable final List<String> arguments,
|
||||
boolean forceAuthorization) {
|
||||
@NotNull final String operation,
|
||||
@Nullable final List<String> arguments,
|
||||
boolean forceAuthorization) {
|
||||
|
||||
PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myState);
|
||||
PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myIgnoreAuthorizationRequest, myState);
|
||||
SocketServer passServer = new SocketServer(passReceiver);
|
||||
try {
|
||||
int passPort = passServer.start();
|
||||
@@ -109,11 +115,13 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
|
||||
private final Project myProject;
|
||||
private HgCommandAuthenticator myAuthenticator;
|
||||
private boolean myForceAuthorization;
|
||||
private boolean mySilentMode;
|
||||
@Nullable private ModalityState myState;
|
||||
|
||||
private PassReceiver(Project project, boolean forceAuthorization, @Nullable ModalityState state) {
|
||||
private PassReceiver(Project project, boolean forceAuthorization, boolean silent, @Nullable ModalityState state) {
|
||||
myProject = project;
|
||||
myForceAuthorization = forceAuthorization;
|
||||
mySilentMode = silent;
|
||||
myState = state;
|
||||
}
|
||||
|
||||
@@ -129,7 +137,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
|
||||
String path = new String(readDataBlock(dataInputStream));
|
||||
String proposedLogin = new String(readDataBlock(dataInputStream));
|
||||
|
||||
HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization);
|
||||
HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization, mySilentMode);
|
||||
boolean ok = authenticator.promptForAuthentication(myProject, proposedLogin, uri, path, myState);
|
||||
if (ok) {
|
||||
myAuthenticator = authenticator;
|
||||
|
||||
@@ -94,23 +94,33 @@ public class HgHistoryUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get & parse hg log detailed output with commits, their parents and their changes.</p>
|
||||
* <p>Get & parse hg log detailed output with commits, their parents and their changes.
|
||||
* For null destination return log command result</p>
|
||||
* <p/>
|
||||
* <p>Warning: this is method is efficient by speed, but don't query too much, because the whole log output is retrieved at once,
|
||||
* and it can occupy too much memory. The estimate is ~600Kb for 1000 commits.</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project, @NotNull final VirtualFile root, int limit,
|
||||
public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project,
|
||||
@NotNull final VirtualFile root,
|
||||
int limit,
|
||||
@NotNull List<String> parameters) throws VcsException {
|
||||
final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
|
||||
if (factory == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
HgVcs hgvcs = HgVcs.getInstance(project);
|
||||
assert hgvcs != null;
|
||||
final HgVersion version = hgvcs.getVersion();
|
||||
String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version);
|
||||
HgCommandResult result = getLogResult(project, root, version, limit, parameters, HgChangesetUtil.makeTemplate(templates));
|
||||
return createFullCommitsFromResult(project, root, result, version);
|
||||
}
|
||||
|
||||
public static List<? extends VcsFullCommitDetails> createFullCommitsFromResult(@NotNull Project project,
|
||||
@NotNull VirtualFile root,
|
||||
@Nullable HgCommandResult result,
|
||||
@NotNull HgVersion version) {
|
||||
final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
|
||||
if (factory == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<HgFileRevision> hgRevisions =
|
||||
getCommitRecords(project, result, new HgFileRevisionLogParser(project, getOriginalHgFile(project, root), version));
|
||||
List<VcsFullCommitDetails> vcsFullCommitDetailsList = new ArrayList<VcsFullCommitDetails>();
|
||||
@@ -331,4 +341,8 @@ public class HgHistoryUtil {
|
||||
}
|
||||
return branchHeads;
|
||||
}
|
||||
|
||||
public static String prepareParameter(String paramName, String value) {
|
||||
return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,11 +180,11 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
boolean atLeastOneBranchExists = false;
|
||||
for (String branchName : filterCollection.getBranchFilter().getBranchNames()) {
|
||||
if (branchName.equals(TIP_REFERENCE) || branchExists(repository, branchName)) {
|
||||
filterParameters.add(prepareParameter("branch", branchName));
|
||||
filterParameters.add(HgHistoryUtil.prepareParameter("branch", branchName));
|
||||
atLeastOneBranchExists = true;
|
||||
}
|
||||
else if (branchName.equals(HEAD_REFERENCE)) {
|
||||
filterParameters.add(prepareParameter("branch", "."));
|
||||
filterParameters.add(HgHistoryUtil.prepareParameter("branch", "."));
|
||||
filterParameters.add("-r");
|
||||
filterParameters.add("::."); //all ancestors for current revision;
|
||||
atLeastOneBranchExists = true;
|
||||
@@ -197,7 +197,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
if (filterCollection.getUserFilter() != null) {
|
||||
for (String authorName : filterCollection.getUserFilter().getUserNames(root)) {
|
||||
filterParameters.add(prepareParameter("user", authorName));
|
||||
filterParameters.add(HgHistoryUtil.prepareParameter("user", authorName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
if (filterCollection.getTextFilter() != null) {
|
||||
String textFilter = filterCollection.getTextFilter().getText();
|
||||
filterParameters.add(prepareParameter("keyword", textFilter));
|
||||
filterParameters.add(HgHistoryUtil.prepareParameter("keyword", textFilter));
|
||||
}
|
||||
|
||||
if (filterCollection.getStructureFilter() != null) {
|
||||
@@ -262,10 +262,6 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
return HgHistoryUtil.getDescendingHeadsOfBranches(myProject, root, commitHash);
|
||||
}
|
||||
|
||||
private static String prepareParameter(String paramName, String value) {
|
||||
return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
|
||||
}
|
||||
|
||||
private static boolean branchExists(@NotNull HgRepository repository, @NotNull String branchName) {
|
||||
return repository.getBranches().keySet().contains(branchName) ||
|
||||
HgUtil.getNamesWithoutHashes(repository.getBookmarks()).contains(branchName);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
package org.zmlx.hg4idea.provider.commit;
|
||||
|
||||
import com.intellij.dvcs.DvcsCommitAdditionalComponent;
|
||||
import com.intellij.dvcs.push.ui.VcsPushDialog;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -37,6 +38,7 @@ import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.*;
|
||||
import org.zmlx.hg4idea.action.HgActionUtil;
|
||||
import org.zmlx.hg4idea.command.*;
|
||||
import org.zmlx.hg4idea.execution.HgCommandException;
|
||||
import org.zmlx.hg4idea.execution.HgCommandExecutor;
|
||||
@@ -132,13 +134,12 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
|
||||
|
||||
// push if needed
|
||||
if (myNextCommitIsPushed && exceptions.isEmpty()) {
|
||||
final VirtualFile preselectedRepo = repositoriesMap.size() == 1 ? repositoriesMap.keySet().iterator().next() : null;
|
||||
final Set<VirtualFile> preselectedFiles = repositoriesMap.keySet();
|
||||
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(myProject);
|
||||
final HgRepository repo = preselectedRepo != null ? repositoryManager.getRepositoryForFile(preselectedRepo) : null;
|
||||
final Collection<HgRepository> repositories = repositoryManager.getRepositories();
|
||||
final List<HgRepository> preselectedRepositories = HgActionUtil.collectRepositoriesFromFiles(repositoryManager, preselectedFiles);
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
new HgPusher(myProject).showDialogAndPush(repositories, repo);
|
||||
new VcsPushDialog(myProject, preselectedRepositories).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user