mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
git: let plugins customize some parts of the push process
VCS-969
This commit is contained in:
@@ -235,5 +235,7 @@
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Git4Idea.GitHttpAuthDataProvider" interface="git4idea.remote.GitHttpAuthDataProvider"/>
|
||||
<extensionPoint qualifiedName="Git4Idea.gitRepositoryHostingService" interface="git4idea.remote.GitRepositoryHostingService"/>
|
||||
<extensionPoint qualifiedName="com.intellij.vcs.git.pushCustomizationFactory"
|
||||
interface="git4idea.push.GitPushProcessCustomizationFactory" />
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitCompoundResult;
|
||||
import git4idea.push.GitPushParamsImpl;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.ui.branch.GitMultiRootBranchConfig;
|
||||
@@ -162,7 +163,7 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation {
|
||||
|
||||
@NotNull
|
||||
private GitCommandResult pushDeletion(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String branchName) {
|
||||
return myGit.push(repository, remote, ":" + branchName, false, false, false, null);
|
||||
return myGit.push(repository, new GitPushParamsImpl(remote, ":" + branchName, false, false, false, null));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.branch.GitRebaseParams;
|
||||
import git4idea.push.GitPushParams;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.reset.GitResetMode;
|
||||
@@ -144,12 +145,7 @@ public interface Git {
|
||||
|
||||
@NotNull
|
||||
GitCommandResult push(@NotNull GitRepository repository,
|
||||
@NotNull GitRemote remote,
|
||||
@NotNull String spec,
|
||||
boolean force,
|
||||
boolean updateTracking,
|
||||
boolean skipHook,
|
||||
@Nullable String tagMode,
|
||||
@NotNull GitPushParams pushParams,
|
||||
GitLineHandlerListener... listeners);
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.vcsUtil.VcsFileUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.branch.GitRebaseParams;
|
||||
import git4idea.config.GitVersionSpecialty;
|
||||
import git4idea.push.GitPushParams;
|
||||
import git4idea.rebase.GitInteractiveRebaseEditorHandler;
|
||||
import git4idea.rebase.GitRebaseEditorHandler;
|
||||
import git4idea.rebase.GitRebaseEditorService;
|
||||
@@ -38,8 +39,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
import static git4idea.GitUtil.COMMENT_CHAR;
|
||||
@@ -399,14 +398,10 @@ public class GitImpl extends GitImplBase {
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult push(@NotNull GitRepository repository,
|
||||
@NotNull GitRemote remote,
|
||||
@NotNull String spec,
|
||||
boolean force,
|
||||
boolean updateTracking,
|
||||
boolean skipHook,
|
||||
@Nullable String tagMode,
|
||||
@NotNull GitPushParams pushParams,
|
||||
GitLineHandlerListener... listeners) {
|
||||
return doPush(repository, remote.getName(), remote.getPushUrls(), spec, force, updateTracking, skipHook, tagMode, listeners);
|
||||
return doPush(repository, pushParams.getRemote().getName(), pushParams.getRemote().getPushUrls(), pushParams.getSpec(),
|
||||
pushParams.isForce(), pushParams.shouldSetupTracking(), pushParams.shouldSkipHooks(), pushParams.getTagMode(), listeners);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -65,6 +65,7 @@ import static com.intellij.util.containers.ContainerUtil.filter;
|
||||
import static git4idea.commands.GitAuthenticationListener.GIT_AUTHENTICATION_SUCCESS;
|
||||
import static git4idea.push.GitPushNativeResult.Type.FORCED_UPDATE;
|
||||
import static git4idea.push.GitPushNativeResult.Type.NEW_REF;
|
||||
import static git4idea.push.GitPushProcessCustomizationFactory.GIT_PUSH_CUSTOMIZATION_FACTORY_EP;
|
||||
import static git4idea.push.GitPushRepoResult.Type.NOT_PUSHED;
|
||||
import static git4idea.push.GitPushRepoResult.Type.REJECTED_NO_FF;
|
||||
|
||||
@@ -92,6 +93,7 @@ public class GitPushOperation {
|
||||
private final ProgressIndicator myProgressIndicator;
|
||||
private final GitVcsSettings mySettings;
|
||||
private final GitRepositoryManager myRepositoryManager;
|
||||
@Nullable private final GitPushProcessCustomizationFactory.GitPushProcessCustomization myPushProcessCustomization;
|
||||
|
||||
public GitPushOperation(@NotNull Project project,
|
||||
@NotNull GitPushSupport pushSupport,
|
||||
@@ -121,6 +123,8 @@ public class GitPushOperation {
|
||||
currentHeads.put(repository, new GitRevisionNumber(head));
|
||||
}
|
||||
}
|
||||
|
||||
myPushProcessCustomization = findPushCustomization();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -188,6 +192,7 @@ public class GitPushOperation {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myPushProcessCustomization != null) myPushProcessCustomization.executeAfterPush(results);
|
||||
}
|
||||
finally {
|
||||
if (beforePushLabel != null) {
|
||||
@@ -200,6 +205,24 @@ public class GitPushOperation {
|
||||
return prepareCombinedResult(results, updatedRoots, preUpdatePositions, beforePushLabel, afterPushLabel);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GitPushProcessCustomizationFactory.GitPushProcessCustomization findPushCustomization() {
|
||||
List<GitPushProcessCustomizationFactory.GitPushProcessCustomization> customizations = StreamEx
|
||||
.of(GIT_PUSH_CUSTOMIZATION_FACTORY_EP.getExtensions())
|
||||
.map(factory -> factory.createCustomization(myProject, myPushSpecs, myForce)).toList();
|
||||
|
||||
if (customizations.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else if (customizations.size() > 1) {
|
||||
LOG.error("Only one GitPushProcessCustomization is allowed, but more are installed: " + customizations);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return customizations.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<GitRepository> getRootsToUpdate(@NotNull PushUpdateSettings updateSettings,
|
||||
@NotNull Set<GitRepository> rejectedRepositories) {
|
||||
@@ -303,6 +326,10 @@ public class GitPushOperation {
|
||||
results.put(repository, repoResult);
|
||||
}
|
||||
|
||||
if (myPushProcessCustomization != null) {
|
||||
return myPushProcessCustomization.executeAfterPushIteration(results);
|
||||
}
|
||||
|
||||
// fill other not-processed repositories as not-pushed
|
||||
for (GitRepository repository : repositories) {
|
||||
if (!results.containsKey(repository)) {
|
||||
@@ -358,8 +385,17 @@ public class GitPushOperation {
|
||||
|
||||
String spec = sourceBranch.getFullName() + ":" + targetBranch.getNameForRemoteOperations();
|
||||
GitRemote remote = targetBranch.getRemote();
|
||||
GitCommandResult res = myGit.push(repository, remote, spec, myForce, setUpstream, mySkipHook, tagMode, progressListener);
|
||||
if(res.success()){
|
||||
GitPushParamsImpl params = new GitPushParamsImpl(remote, spec, myForce, setUpstream, mySkipHook, tagMode);
|
||||
|
||||
GitCommandResult res;
|
||||
if (myPushProcessCustomization != null) {
|
||||
res = myPushProcessCustomization.runPushCommand(repository, pushSpec, params, progressListener);
|
||||
}
|
||||
else {
|
||||
res = myGit.push(repository, params, progressListener);
|
||||
}
|
||||
|
||||
if (res.success()) {
|
||||
BackgroundTaskUtil.syncPublisher(myProject, GIT_AUTHENTICATION_SUCCESS).authenticationSucceeded(repository, remote);
|
||||
}
|
||||
return new ResultWithOutput(res);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package git4idea.push;
|
||||
|
||||
import git4idea.repo.GitRemote;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface GitPushParams {
|
||||
@NotNull
|
||||
GitRemote getRemote();
|
||||
|
||||
@NotNull
|
||||
String getSpec();
|
||||
|
||||
boolean isForce();
|
||||
|
||||
boolean shouldSetupTracking();
|
||||
|
||||
boolean shouldSkipHooks();
|
||||
|
||||
@Nullable
|
||||
String getTagMode();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package git4idea.push;
|
||||
|
||||
import git4idea.repo.GitRemote;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GitPushParamsImpl implements GitPushParams {
|
||||
@NotNull private final GitRemote myRemote;
|
||||
@NotNull private final String mySpec;
|
||||
private final boolean myForce;
|
||||
private final boolean mySetupTracking;
|
||||
private final boolean mySkipHooks;
|
||||
@Nullable private final String myTagMode;
|
||||
|
||||
public GitPushParamsImpl(@NotNull GitRemote remote,
|
||||
@NotNull String spec,
|
||||
boolean force,
|
||||
boolean setupTracking,
|
||||
boolean skipHooks,
|
||||
@Nullable String tagMode) {
|
||||
|
||||
myRemote = remote;
|
||||
mySpec = spec;
|
||||
myForce = force;
|
||||
mySetupTracking = setupTracking;
|
||||
mySkipHooks = skipHooks;
|
||||
myTagMode = tagMode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GitRemote getRemote() {
|
||||
return myRemote;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getSpec() {
|
||||
return mySpec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForce() {
|
||||
return myForce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSetupTracking() {
|
||||
return mySetupTracking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipHooks() {
|
||||
return mySkipHooks;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTagMode() {
|
||||
return myTagMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package git4idea.push;
|
||||
|
||||
import com.intellij.dvcs.push.PushSpec;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitLineHandlerListener;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implement to customize some parts of the {@link GitPushOperation git push process}.
|
||||
* <br/><br/>
|
||||
* Note that only one customization can be installed: if several ones are found among installed plugins, none is being executed.
|
||||
*/
|
||||
public interface GitPushProcessCustomizationFactory {
|
||||
|
||||
ExtensionPointName<GitPushProcessCustomizationFactory> GIT_PUSH_CUSTOMIZATION_FACTORY_EP =
|
||||
ExtensionPointName.create("com.intellij.vcs.git.pushCustomizationFactory");
|
||||
|
||||
/**
|
||||
* Creates a push customization instance for a push session, if such customization is allowed in the given conditions.
|
||||
*/
|
||||
@Nullable
|
||||
GitPushProcessCustomization createCustomization(@NotNull Project project,
|
||||
@NotNull Map<GitRepository, PushSpec<GitPushSource, GitPushTarget>> pushSpecs,
|
||||
boolean forcePush);
|
||||
|
||||
interface GitPushProcessCustomization {
|
||||
|
||||
/**
|
||||
* Will be executed after one push iteration,
|
||||
* i.e. after all `git push` commands are called against all selected repositories,
|
||||
* but before the rebase/merge is proposed or a notification is shown.
|
||||
*
|
||||
* @param results Results of `git push` commands.
|
||||
* @return Adjusted results of the push process - these will be processed by the push process instead of the original ones.
|
||||
*/
|
||||
@NotNull
|
||||
Map<GitRepository, GitPushRepoResult> executeAfterPushIteration(@NotNull Map<GitRepository, GitPushRepoResult> results);
|
||||
|
||||
/**
|
||||
* Overrides the call to `git push`.
|
||||
*/
|
||||
@NotNull
|
||||
GitCommandResult runPushCommand(@NotNull GitRepository repository,
|
||||
@NotNull PushSpec<GitPushSource, GitPushTarget> pushSpec,
|
||||
@NotNull GitPushParams pushParams,
|
||||
@NotNull GitLineHandlerListener progressListener);
|
||||
|
||||
/**
|
||||
* Will be executed after the whole push procedure is finished, successfully or not.
|
||||
*/
|
||||
void executeAfterPush(@NotNull Map<GitRepository, GitPushRepoResult> results);
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,9 @@ import git4idea.commands.GitCommandResult
|
||||
import git4idea.commands.GitImpl
|
||||
import git4idea.commands.GitLineHandler
|
||||
import git4idea.commands.GitLineHandlerListener
|
||||
import git4idea.push.GitPushParams
|
||||
import git4idea.rebase.GitInteractiveRebaseEditorHandler
|
||||
import git4idea.rebase.GitRebaseEditorService
|
||||
import git4idea.repo.GitRemote
|
||||
import git4idea.repo.GitRepository
|
||||
import java.io.File
|
||||
|
||||
@@ -51,16 +51,10 @@ class TestGitImpl : GitImpl() {
|
||||
val plainTextEditor: ((String) -> String)?)
|
||||
|
||||
override fun push(repository: GitRepository,
|
||||
remote: GitRemote,
|
||||
spec: String,
|
||||
force: Boolean,
|
||||
updateTracking: Boolean,
|
||||
skipHook: Boolean,
|
||||
tagMode: String?,
|
||||
pushParams: GitPushParams,
|
||||
vararg listeners: GitLineHandlerListener): GitCommandResult {
|
||||
pushListener?.invoke(repository)
|
||||
return myPushHandler(repository) ?:
|
||||
super.push(repository, remote, spec, force, updateTracking, skipHook, tagMode, *listeners)
|
||||
return myPushHandler(repository) ?: super.push(repository, pushParams, *listeners)
|
||||
}
|
||||
|
||||
override fun branchDelete(repository: GitRepository,
|
||||
|
||||
Reference in New Issue
Block a user