LsRemoteCommand: apply url.*.insteadOf

If LsRemoteCommand is used without repository, the remote URI was not
translated. If the git user config contains e.g.

  [url "ssh://git@github.com/"]
    insteadOf = https://github.com/

and LsRemoteCommand is called with an HTTPS GitHub repository URL, the
command should actually rewrite this to an SSH URI and use the SSH
transport.

Actually this same problem may exist everywhere Transport is used with
an URIish instead of with a remote name. However, doing this translation
in Transport.open(URIish) and in Transport.open(Repository, URIish,
String) if no remote name is given would change the behavior and might
break assumptions made in existing clients. For instance, EGit's
PushOperation assumes that the URI obtained from PushResult.getURI()
was the same as was passed in to Transport.open(Repository, URIish).

URIs obtained from a RemoteConfig have this translation applied
transparently, and in Transport we cannot know for sure whether or
not a URI has already been translated, if needed. So doing this in
Transport might also lead to translating URIs twice.

Therefore this commit does the translation in LsRemoteCommand, where
we can be sure that it won't affect other use cases. If other cases
besides LsRemoteCommand are found where such a URI translation is
missing, it'll have to be done at higher levels, possibly even in
client code directly.

Bug: 544769
Change-Id: I5df54a925d30b55d98e21f37f2851fe79649b064
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
Thomas Wolf 2022-03-04 21:00:26 +01:00
parent c127a1a652
commit 2c1a8798ca
2 changed files with 30 additions and 6 deletions

View File

@ -21,6 +21,8 @@
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Test;
public class LsRemoteCommandTest extends RepositoryTestCase {
@ -106,6 +108,20 @@ public void testLsRemoteWithoutLocalRepository() throws Exception {
assertEquals(2, refs.size());
}
@Test
public void testLsRemoteWithoutLocalRepositoryUrlInsteadOf()
throws Exception {
String uri = fileUri();
StoredConfig userConfig = SystemReader.getInstance().getUserConfig();
userConfig.load();
userConfig.setString("url", uri, "insteadOf", "file:///foo");
userConfig.save();
Collection<Ref> refs = Git.lsRemoteRepository().setRemote("file:///foo")
.setHeads(true).call();
assertNotNull(refs);
assertEquals(2, refs.size());
}
@Test
public void testLsRemoteWithSymRefs() throws Exception {
File directory = createTempDirectory("testRepository");

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011, 2020 Christoph Brill <egore911@egore911.de> and others
* Copyright (C) 2011, 2022 Christoph Brill <egore911@egore911.de> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -9,6 +9,7 @@
*/
package org.eclipse.jgit.api;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
@ -20,8 +21,8 @@
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
@ -30,6 +31,8 @@
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UrlConfig;
import org.eclipse.jgit.util.SystemReader;
/**
* The ls-remote command
@ -153,7 +156,7 @@ private Map<String, Ref> execute() throws GitAPIException,
try (Transport transport = repo != null
? Transport.open(repo, remote)
: Transport.open(new URIish(remote))) {
: Transport.open(new URIish(translate(remote)))) {
transport.setOptionUploadPack(uploadPack);
configure(transport);
Collection<RefSpec> refSpecs = new ArrayList<>(1);
@ -185,11 +188,16 @@ private Map<String, Ref> execute() throws GitAPIException,
throw new JGitInternalException(
JGitText.get().exceptionCaughtDuringExecutionOfLsRemoteCommand,
e);
} catch (TransportException e) {
} catch (IOException | ConfigInvalidException e) {
throw new org.eclipse.jgit.api.errors.TransportException(
e.getMessage(),
e);
e.getMessage(), e);
}
}
private String translate(String uri)
throws IOException, ConfigInvalidException {
UrlConfig urls = new UrlConfig(
SystemReader.getInstance().getUserConfig());
return urls.replace(uri);
}
}