Skip to content

Commit

Permalink
Try to configure authentication for command from GitWithAuth (#884)
Browse files Browse the repository at this point in the history
**Motivation**

- Goes well with the name `GitWithAuth` which implies that authentication is done from the object implicitly
- We don't have to pass a `Consumer` around for each location where we want to execute a git command
  • Loading branch information
jrhee17 authored Sep 15, 2023
1 parent 61ecc9b commit 03540a1
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
Expand All @@ -38,9 +37,6 @@

import javax.annotation.Nullable;

import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.LsRemoteCommand;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.RemoteSetUrlCommand;
import org.eclipse.jgit.api.RemoteSetUrlCommand.UriType;
import org.eclipse.jgit.api.TransportCommand;
Expand Down Expand Up @@ -136,21 +132,21 @@ abstract class AbstractGitMirror extends AbstractMirror {
}
}

GitWithAuth openGit(File workDir, String jGitUri,
URIish remoteUri) throws IOException, URISyntaxException, GitAPIException {
GitWithAuth openGit(File workDir,
URIish remoteUri,
Consumer<TransportCommand<?, ?>> configurator) throws IOException, GitAPIException {
// Now create and open the repository.
final File repoDir = new File(
workDir,
CONSECUTIVE_UNDERSCORES.matcher(DISALLOWED_CHARS.matcher(
remoteRepoUri().toASCIIString()).replaceAll("_")).replaceAll("_"));
final GitWithAuth git = new GitWithAuth(this, repoDir, remoteUri);
final GitWithAuth git = new GitWithAuth(this, repoDir, remoteUri, configurator);
boolean success = false;
try {
// Set the remote URLs.
final URIish uri = new URIish(jGitUri);
final RemoteSetUrlCommand remoteSetUrl = git.remoteSetUrl();
remoteSetUrl.setRemoteName(Constants.DEFAULT_REMOTE_NAME);
remoteSetUrl.setRemoteUri(uri);
remoteSetUrl.setRemoteUri(remoteUri);

remoteSetUrl.setUriType(UriType.FETCH);
remoteSetUrl.call();
Expand All @@ -174,12 +170,11 @@ GitWithAuth openGit(File workDir, String jGitUri,
}

void mirrorLocalToRemote(
GitWithAuth git, int maxNumFiles, long maxNumBytes,
Consumer<TransportCommand<?, ?>> configurator) throws GitAPIException, IOException {
GitWithAuth git, int maxNumFiles, long maxNumBytes) throws GitAPIException, IOException {
// TODO(minwoox): Early return if the remote does not have any updates.
final Ref headBranchRef = getHeadBranchRef(git, configurator);
final Ref headBranchRef = getHeadBranchRef(git);
final String headBranchRefName = headBranchRef.getName();
final ObjectId headCommitId = fetchRemoteHeadAndGetCommitId(git, headBranchRefName, configurator);
final ObjectId headCommitId = fetchRemoteHeadAndGetCommitId(git, headBranchRefName);

final org.eclipse.jgit.lib.Repository gitRepository = git.getRepository();
try (ObjectReader reader = gitRepository.newObjectReader();
Expand Down Expand Up @@ -227,21 +222,19 @@ dirCache, new InsertText(mirrorStatePath.substring(1), // Strip the leading '/'.
updateRef(gitRepository, revWalk, headBranchRefName, nextCommitId);
}

final PushCommand push = git.push();
configurator.accept(push);
push.setRefSpecs(new RefSpec(headBranchRefName))
.setAtomic(true)
.setTimeout(GIT_TIMEOUT_SECS)
.call();
git.push()
.setRefSpecs(new RefSpec(headBranchRefName))
.setAtomic(true)
.setTimeout(GIT_TIMEOUT_SECS)
.call();
}

void mirrorRemoteToLocal(
GitWithAuth git, CommandExecutor executor, int maxNumFiles, long maxNumBytes,
Consumer<TransportCommand<?,?>> configurator) throws Exception {
GitWithAuth git, CommandExecutor executor, int maxNumFiles, long maxNumBytes) throws Exception {
final String summary;
final String detail;
final Map<String, Change<?>> changes = new HashMap<>();
final Ref headBranchRef = getHeadBranchRef(git, configurator);
final Ref headBranchRef = getHeadBranchRef(git);

final String mirrorStatePath = localPath() + MIRROR_STATE_FILE_NAME;
final Revision localRev = localRepo().normalizeNow(Revision.HEAD);
Expand All @@ -251,7 +244,7 @@ void mirrorRemoteToLocal(

// Update the head commit ID again because there's a chance a commit is pushed between the
// getHeadBranchRefName and fetchRemoteHeadAndGetCommitId calls.
final ObjectId headCommitId = fetchRemoteHeadAndGetCommitId(git, headBranchRef.getName(), configurator);
final ObjectId headCommitId = fetchRemoteHeadAndGetCommitId(git, headBranchRef.getName());
try (ObjectReader reader = git.getRepository().newObjectReader();
TreeWalk treeWalk = new TreeWalk(reader);
RevWalk revWalk = new RevWalk(reader)) {
Expand Down Expand Up @@ -369,17 +362,16 @@ private boolean needsFetch(Ref headBranchRef, String mirrorStatePath, Revision l
return true;
}

private Ref getHeadBranchRef(
GitWithAuth git, Consumer<TransportCommand<?,?>> configurator) throws GitAPIException {
private Ref getHeadBranchRef(GitWithAuth git) throws GitAPIException {
if (remoteBranch() != null) {
final String headBranchRefName = Constants.R_HEADS + remoteBranch();
final Collection<Ref> refs = lsRemote(git, configurator, true);
final Collection<Ref> refs = lsRemote(git, true);
return findHeadBranchRef(git, headBranchRefName, refs);
}

// Otherwise, we need to figure out which branch we should fetch.
// Fetch the remote reference list to determine the default branch.
final Collection<Ref> refs = lsRemote(git, configurator, false);
final Collection<Ref> refs = lsRemote(git, false);

// Find and resolve 'HEAD' reference, which leads us to the default branch.
final Optional<String> headRefNameOptional = refs.stream()
Expand All @@ -396,14 +388,13 @@ private Ref getHeadBranchRef(
return findHeadBranchRef(git, headBranchRefName, refs);
}

private static Collection<Ref> lsRemote(GitWithAuth git, Consumer<TransportCommand<?, ?>> configurator,
private static Collection<Ref> lsRemote(GitWithAuth git,
boolean setHeads) throws GitAPIException {
final LsRemoteCommand lsRemoteCommand = git.lsRemote();
configurator.accept(lsRemoteCommand);
return lsRemoteCommand.setTags(false)
.setTimeout(GIT_TIMEOUT_SECS)
.setHeads(setHeads)
.call();
return git.lsRemote()
.setTags(false)
.setTimeout(GIT_TIMEOUT_SECS)
.setHeads(setHeads)
.call();
}

private static Ref findHeadBranchRef(GitWithAuth git, String headBranchRefName, Collection<Ref> refs) {
Expand Down Expand Up @@ -461,15 +452,14 @@ private Revision remoteCurrentRevision(
}

private static ObjectId fetchRemoteHeadAndGetCommitId(
GitWithAuth git, String headBranchRefName,
Consumer<TransportCommand<?,?>> configurator) throws GitAPIException, IOException {
final FetchCommand fetch = git.fetch().setDepth(1);
configurator.accept(fetch);
final FetchResult fetchResult = fetch.setRefSpecs(new RefSpec(headBranchRefName))
.setRemoveDeletedRefs(true)
.setTagOpt(TagOpt.NO_TAGS)
.setTimeout(GIT_TIMEOUT_SECS)
.call();
GitWithAuth git, String headBranchRefName) throws GitAPIException, IOException {
final FetchResult fetchResult = git.fetch()
.setDepth(1)
.setRefSpecs(new RefSpec(headBranchRefName))
.setRemoveDeletedRefs(true)
.setTagOpt(TagOpt.NO_TAGS)
.setTimeout(GIT_TIMEOUT_SECS)
.call();
final ObjectId commitId = fetchResult.getAdvertisedRef(headBranchRefName).getObjectId();
final RefUpdate refUpdate = git.getRepository().updateRef(headBranchRefName);
refUpdate.setNewObjectId(commitId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ final class DefaultGitMirror extends AbstractGitMirror {

@Override
protected void mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumBytes) throws Exception {
try (GitWithAuth git = openGit(workDir)) {
mirrorLocalToRemote(git, maxNumFiles, maxNumBytes, transportCommandConfigurator());
try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
mirrorLocalToRemote(git, maxNumFiles, maxNumBytes);
}
}

Expand All @@ -80,12 +80,12 @@ protected void mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumByt
@Override
protected void mirrorRemoteToLocal(File workDir, CommandExecutor executor,
int maxNumFiles, long maxNumBytes) throws Exception {
try (GitWithAuth git = openGit(workDir)) {
mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes, transportCommandConfigurator());
try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes);
}
}

private GitWithAuth openGit(File workDir) throws Exception {
private GitWithAuth openGit(File workDir, Consumer<TransportCommand<?, ?>> configurator) throws Exception {
final String scheme = remoteRepoUri().getScheme();
final String jGitUri;
if (scheme.startsWith("git+")) {
Expand All @@ -94,6 +94,6 @@ private GitWithAuth openGit(File workDir) throws Exception {
} else {
jGitUri = remoteRepoUri().toASCIIString();
}
return openGit(workDir, jGitUri, new URIish(jGitUri));
return openGit(workDir, new URIish(jGitUri), configurator);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.GarbageCollectCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LsRemoteCommand;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.TransportCommand;
import org.eclipse.jgit.lib.EmptyProgressMonitor;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
Expand Down Expand Up @@ -70,12 +73,15 @@ private static Lock getLock(File repoDir) {
private final Lock lock;
private final URIish remoteUri;
private final Map<String, ProgressMonitor> progressMonitors = new HashMap<>();
private final Consumer<TransportCommand<?, ?>> configurator;

GitWithAuth(AbstractGitMirror mirror, File repoDir, URIish remoteUri) throws IOException {
GitWithAuth(AbstractGitMirror mirror, File repoDir, URIish remoteUri,
Consumer<TransportCommand<?, ?>> configurator) throws IOException {
super(repo(repoDir));
this.mirror = mirror;
lock = getLock(repoDir);
this.remoteUri = remoteUri;
this.configurator = configurator;
}

URIish remoteUri() {
Expand Down Expand Up @@ -122,12 +128,23 @@ private ProgressMonitor progressMonitor(String name) {

@Override
public FetchCommand fetch() {
return super.fetch().setProgressMonitor(progressMonitor("fetch"));
final FetchCommand command = super.fetch();
configurator.accept(command);
return command.setProgressMonitor(progressMonitor("fetch"));
}

@Override
public PushCommand push() {
return super.push().setProgressMonitor(progressMonitor("push"));
final PushCommand command = super.push();
configurator.accept(command);
return command.setProgressMonitor(progressMonitor("push"));
}

@Override
public LsRemoteCommand lsRemote() {
final LsRemoteCommand command = super.lsRemote();
configurator.accept(command);
return command;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Collection;
Expand Down Expand Up @@ -87,14 +88,17 @@ final class SshGitMirror extends AbstractGitMirror {

@Override
protected void mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumBytes) throws Exception {
final URIish remoteUri = remoteUri();
SshClient sshClient = null;
ClientSession session = null;
try (GitWithAuth git = openGit(workDir)) {
try {
sshClient = createSshClient();
session = createSession(sshClient, git);
session = createSession(sshClient, remoteUri);
final DefaultGitSshdSessionFactory sessionFactory =
new DefaultGitSshdSessionFactory(sshClient, session);
mirrorLocalToRemote(git, maxNumFiles, maxNumBytes, sessionFactory::configureCommand);
try (GitWithAuth git = openGit(workDir, remoteUri, sessionFactory::configureCommand)) {
mirrorLocalToRemote(git, maxNumFiles, maxNumBytes);
}
} finally {
try {
if (session != null) {
Expand All @@ -111,14 +115,17 @@ protected void mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumByt
@Override
protected void mirrorRemoteToLocal(File workDir, CommandExecutor executor,
int maxNumFiles, long maxNumBytes) throws Exception {
final URIish remoteUri = remoteUri();
SshClient sshClient = null;
ClientSession session = null;
try (GitWithAuth git = openGit(workDir)) {
try {
sshClient = createSshClient();
session = createSession(sshClient, git);
session = createSession(sshClient, remoteUri);
final DefaultGitSshdSessionFactory sessionFactory =
new DefaultGitSshdSessionFactory(sshClient, session);
mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes, sessionFactory::configureCommand);
try (GitWithAuth git = openGit(workDir, remoteUri, sessionFactory::configureCommand)) {
mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes);
}
} finally {
try {
if (session != null) {
Expand All @@ -132,7 +139,7 @@ protected void mirrorRemoteToLocal(File workDir, CommandExecutor executor,
}
}

private GitWithAuth openGit(File workDir) throws Exception {
private URIish remoteUri() throws URISyntaxException {
// Requires the username to be included in the URI.
final String username;
if (credential() instanceof PasswordMirrorCredential) {
Expand All @@ -151,7 +158,7 @@ private GitWithAuth openGit(File workDir) throws Exception {
} else {
jGitUri = "ssh://" + remoteRepoUri().getRawAuthority() + remoteRepoUri().getRawPath();
}
return openGit(workDir, jGitUri, new URIish(jGitUri));
return new URIish(jGitUri);
}

private SshClient createSshClient() {
Expand All @@ -168,9 +175,8 @@ private SshClient createSshClient() {
return client;
}

private static ClientSession createSession(SshClient sshClient, GitWithAuth git) {
private static ClientSession createSession(SshClient sshClient, URIish uri) {
try {
final URIish uri = git.remoteUri();
int port = uri.getPort();
if (port <= 0) {
port = 22; // Use the SSH default port it unspecified.
Expand Down

0 comments on commit 03540a1

Please sign in to comment.