org.netbeans.modules.git.client.GitClient Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.modules.git.client;
import java.io.File;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.libs.git.GitBlameResult;
import org.netbeans.libs.git.GitBranch;
import org.netbeans.libs.git.GitCherryPickResult;
import org.netbeans.libs.git.GitClient.CherryPickOperation;
import org.netbeans.libs.git.GitClient.DiffMode;
import org.netbeans.libs.git.GitClient.RebaseOperationType;
import org.netbeans.libs.git.GitClient.ResetType;
import org.netbeans.libs.git.GitClientCallback;
import org.netbeans.libs.git.GitRepository;
import org.netbeans.libs.git.GitException;
import org.netbeans.libs.git.GitMergeResult;
import org.netbeans.libs.git.GitPullResult;
import org.netbeans.libs.git.GitPushResult;
import org.netbeans.libs.git.GitRebaseResult;
import org.netbeans.libs.git.GitRefUpdateResult;
import org.netbeans.libs.git.GitRemoteConfig;
import org.netbeans.libs.git.GitRepository.FastForwardOption;
import org.netbeans.libs.git.GitRepositoryState;
import org.netbeans.libs.git.GitRevertResult;
import org.netbeans.libs.git.GitRevisionInfo;
import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
import org.netbeans.libs.git.GitStatus;
import org.netbeans.libs.git.GitSubmoduleStatus;
import org.netbeans.libs.git.GitTag;
import org.netbeans.libs.git.GitTransportUpdate;
import org.netbeans.libs.git.GitUser;
import org.netbeans.libs.git.SearchCriteria;
import org.netbeans.libs.git.progress.NotificationListener;
import org.netbeans.libs.git.progress.ProgressMonitor;
import org.netbeans.modules.git.Git;
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
import org.netbeans.modules.git.utils.GitUtils;
import org.netbeans.modules.versioning.util.Utils;
import org.openide.util.NetworkSettings;
import org.openide.util.RequestProcessor;
/**
*
* @author ondra
*/
public final class GitClient {
private final org.netbeans.libs.git.GitClient delegate;
private final GitProgressSupport progressSupport;
private final boolean handleAuthenticationIssues;
private static final int CLEANUP_TIME = 15000;
private static final List unusedClients = new LinkedList();
private static final RequestProcessor.Task cleanTask = Git.getInstance().getRequestProcessor().create(new CleanTask());
/**
* Set of commands that do not need to run under repository lock
*/
private static final HashSet PARALLELIZABLE_COMMANDS = new HashSet(Arrays.asList("addNotificationListener", //NOI18N
"blame", //NOI18N
"catFile", //NOI18N
"catIndexEntry", //NOI18N
"exportCommit", //NOI18N
"exportDiff", //NOI18N
"getBranches", //NOI18N
"getCommonAncestor", //NOI18N
"getConflicts", //NOI18N
"getPreviousRevision", //NOI18N
"getStatus", //NOI18N
"getTags", //NOI18N
"getRemote", //NOI18N
"getRemotes", //NOI18N
"getRepositoryState", //NOI18N
"getSubmoduleStatus", //NOI18N
"getUser", //NOI18N
"listModifiedIndexEntries", //NOI18N
"listRemoteBranches", //NOI18N
"listRemoteTags", //NOI18N
"log", //NOI18N
"removeNotificationListener", //NOI18N
"removeRemote", //NOI18N - i guess there's no need to mke this an exclusive command
"setCallback", //NOI18N
"setRemote", //NOI18N - i guess there's no need to mke this an exclusive command
"stashList")); //NOI18N
/**
* Commands triggering last cached timestamp of the index file. This means that after every command that somehow modifies the index, we need to refresh the timestamp
* otherwise a FS event will come to Interceptor and trigger the full scan.
*/
private static final HashSet WORKING_TREE_READ_ONLY_COMMANDS = new HashSet(Arrays.asList("addNotificationListener", //NOI18N
"blame", //NOI18N
"catFile", //NOI18N
"catIndexEntry", //NOI18N
"createBranch", //NOI18N - does not update index or files in WT
"createTag", //NOI18N - does not update index or files in WT
"deleteBranch", //NOI18N - does not update index or files in WT
"deleteTag", //NOI18N - does not update index or files in WT
"fetch", //NOI18N - updates only metadata
"exportCommit", //NOI18N
"exportDiff", //NOI18N
"getBranches", //NOI18N
"getCommonAncestor", //NOI18N
"getConflicts", //NOI18N
"getPreviousRevision", //NOI18N
"getStatus", //NOI18N
"getRemote", //NOI18N
"getRemotes", //NOI18N
"getRepositoryState", //NOI18N
"getSubmoduleStatus", //NOI18N
"getTags", //NOI18N
"getUser", //NOI18N
"ignore", //NOI18N
"listModifiedIndexEntries", //NOI18N
"listRemoteBranches", //NOI18N
"listRemoteTags", //NOI18N
"log", //NOI18N
"unignore", //NOI18N
"updateReference", //NOI18N
"push", //NOI18N - does not manipulate with index
"removeNotificationListener", //NOI18N
"removeRemote", //NOI18N - does not update index or files in WT
"setCallback", //NOI18N
"setRemote", //NOI18N - does not update index or files in WT
"stashDrop", //NOI18N
"stashDropAll", //NOI18N
"stashList")); //NOI18N
/**
* Commands that will trigger repository information refresh, i.e. those that change HEAD, current branch, etc.
*/
private static final HashSet NEED_REPOSITORY_REFRESH_COMMANDS = new HashSet(Arrays.asList("add",//NOI18N // may change state, e.g. MERGING->MERGED
"checkout", //NOI18N
"checkoutRevision", //NOI18N // current head changes
"cherryPick", //NOI18N
"commit", //NOI18N
"createBranch", //NOI18N // should refresh set of known branches
"createTag", //NOI18N - should refresh set of available tags
"deleteBranch", //NOI18N - should refresh set of available branches
"deleteTag", //NOI18N - should refresh set of available tags
"fetch", //NOI18N - changes available remote heads or tags
"merge", //NOI18N // creates a new head
"pull", //NOI18N // creates a new head
"push", //NOI18N // usually updates remote branches
"rebase", //NOI18N // creates new head and branches
"remove", //NOI18N // may change state, e.g. MERGING->MERGED
"reset", //NOI18N
"removeRemote", //NOI18N - updates remotes
"revert", //NOI18N - creates a new head
"setRemote", //NOI18N - updates remotes
"setUpstreamBranch", //NOI18N - updates remotes
"updateReference", //NOI18N - updates branches
"updateSubmodules" //NOI18N - current head changes
));
/**
* Commands accessing a remote repository. For these NbAuthenticator must be switched off
*/
private static final HashSet NETWORK_COMMANDS = new HashSet(Arrays.asList(
"fetch", //NOI18N
"listRemoteBranches", //NOI18N
"listRemoteTags", //NOI18N
"pull", //NOI18N
"push", //NOI18N
"updateSubmodules" //NOI18N
));
private static final Logger LOG = Logger.getLogger(GitClient.class.getName());
private final File repositoryRoot;
private boolean released;
public GitClient (File repository, GitProgressSupport progressSupport, boolean handleAuthenticationIssues) throws GitException {
this.repositoryRoot = repository;
delegate = GitRepository.getInstance(repository).createClient();
this.progressSupport = progressSupport;
this.handleAuthenticationIssues = handleAuthenticationIssues;
}
public void add (final File[] roots, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.add(roots, monitor);
return null;
}
}, "add", roots); //NOI18N
}
public void addNotificationListener (NotificationListener listener) {
delegate.addNotificationListener(listener);
}
public GitBlameResult blame (final File file, final String revision, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public GitBlameResult call () throws Exception {
return delegate.blame(file, revision, monitor);
}
}, "blame"); //NOI18N
}
public boolean catFile (final File file, final String revision, final java.io.OutputStream out, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public Boolean call () throws Exception {
return delegate.catFile(file, revision, out, monitor);
}
}, "catFile"); //NOI18N
}
public boolean catIndexEntry (final File file, final int stage, final java.io.OutputStream out, final ProgressMonitor monitor) throws GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public Boolean call () throws Exception {
return delegate.catIndexEntry(file, stage, out, monitor);
}
}, "catIndexEntry"); //NOI18N
}
public void checkout (final File[] roots, final String revision, final boolean recursively, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.checkout(roots, revision, recursively, monitor);
return null;
}
}, "checkout", roots); //NOI18N
}
public void checkoutRevision (final String revision, final boolean failOnConflict, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.checkoutRevision(revision, failOnConflict, monitor);
return null;
}
}, "checkoutRevision", new File[] { repositoryRoot }); //NOI18N
}
public GitCherryPickResult cherryPick (final CherryPickOperation op, final String[] revisions, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public GitCherryPickResult call () throws Exception {
return delegate.cherryPick(op, revisions, monitor);
}
}, "cherryPick", new File[] { repositoryRoot }); //NOI18N
}
public void clean(final File[] roots, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.clean(roots, monitor);
return null;
}
}, "clean", roots); //NOI18N
}
public GitRevisionInfo commit (final File[] roots, final String commitMessage, final GitUser author, final GitUser commiter, final ProgressMonitor monitor) throws GitException {
return commit(roots, commitMessage, author, commiter, false, monitor);
}
public GitRevisionInfo commit (final File[] roots, final String commitMessage, final GitUser author, final GitUser commiter, final boolean amend, final ProgressMonitor monitor) throws GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public GitRevisionInfo call () throws Exception {
return delegate.commit(roots, commitMessage, author, commiter, amend, monitor);
}
}, "commit", roots); //NOI18N
}
public void copyAfter (final File source, final File target, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.copyAfter(source, target, monitor);
return null;
}
}, "copyAfter", new File[] { target }); //NOI18N
}
public GitBranch createBranch (final String branchName, final String revision, final ProgressMonitor monitor) throws GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public GitBranch call () throws Exception {
return delegate.createBranch(branchName, revision, monitor);
}
}, "createBranch"); //NOI18N
}
public GitTag createTag (final String tagName, final String taggedObject, final String message, final boolean signed, final boolean forceUpdate, final ProgressMonitor monitor) throws GitException {
return new CommandInvoker().runMethod(new Callable() {
@Override
public GitTag call () throws Exception {
return delegate.createTag(tagName, taggedObject, message, signed, forceUpdate, monitor);
}
}, "createTag"); //NOI18N
}
public void deleteBranch (final String branchName, final boolean forceDeleteUnmerged, final ProgressMonitor monitor) throws GitException.NotMergedException, GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.deleteBranch(branchName, forceDeleteUnmerged, monitor);
return null;
}
}, "deleteBranch"); //NOI18N
}
public void deleteTag (final String tagName, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.deleteTag(tagName, monitor);
return null;
}
}, "deleteTag"); //NOI18N
}
public void exportCommit (final String commit, final OutputStream out, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.exportCommit(commit, out, monitor);
return null;
}
}, "exportCommit"); //NOI18N
}
public void exportDiff (final File[] roots, final DiffMode mode, final OutputStream out, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.exportDiff(roots, mode, out, monitor);
return null;
}
}, "exportDiff", roots); //NOI18N
}
public void exportDiff (final File[] roots, final String base, final String other, final OutputStream out, final ProgressMonitor monitor) throws GitException {
new CommandInvoker().runMethod(new Callable() {
@Override
public Void call () throws Exception {
delegate.exportDiff(roots, base, other, out, monitor);
return null;
}
}, "exportDiff", roots); //NOI18N
}
public Map fetch (final String remote, final ProgressMonitor monitor) throws GitException.AuthorizationException, GitException {
return new CommandInvoker().runMethod(new Callable
© 2015 - 2025 Weber Informatics LLC | Privacy Policy