Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --no-token flag to git-pr #270

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -100,28 +100,21 @@ private static String projectName(URI uri) {
return name;
}

private static HostedRepository getHostedRepositoryFor(URI uri, GitCredentials credentials) throws IOException {
var host = Forge.from(uri, new Credential(credentials.username(), credentials.password()));
if (System.getenv("GIT_TOKEN") == null) {
GitCredentials.approve(credentials);
}
if (host.isEmpty() || !host.get().isValid()) {
exit("error: failed to connect to host " + uri);
}
var remoteRepo = host.get().repository(projectName(uri)).orElseThrow(() ->
private static HostedRepository getHostedRepositoryFor(URI uri, Forge host) throws IOException {
var remoteRepo = host.repository(projectName(uri)).orElseThrow(() ->
new IOException("Could not find repository at: " + uri.toString())
);
var parentRepo = remoteRepo.parent();
var targetRepo = parentRepo.isPresent() ? parentRepo.get() : remoteRepo;
return targetRepo;
}

private static PullRequest getPullRequest(URI uri, GitCredentials credentials, Argument prId) throws IOException {
private static PullRequest getPullRequest(URI uri, Forge host, Argument prId) throws IOException {
if (!prId.isPresent()) {
exit("error: missing pull request identifier");
}

var pr = getHostedRepositoryFor(uri, credentials).pullRequest(prId.asString());
var pr = getHostedRepositoryFor(uri, host).pullRequest(prId.asString());
if (pr == null) {
exit("error: could not fetch PR information");
}
@@ -262,6 +255,10 @@ public static void main(String[] args) throws IOException, InterruptedException
.fullname("no-decoration")
.helptext("Hide any decorations when listing PRs")
.optional(),
Switch.shortcut("")
.fullname("no-token")
.helptext("Do not use a personal access token (PAT). Only works for read-only operations.")
.optional(),
Switch.shortcut("")
.fullname("mercurial")
.helptext("Force use of Mercurial (hg)")
@@ -313,13 +310,36 @@ public static void main(String[] args) throws IOException, InterruptedException
var username = arguments.contains("username") ? arguments.get("username").asString() : null;
var token = isMercurial ? System.getenv("HG_TOKEN") : System.getenv("GIT_TOKEN");
var uri = Remote.toWebURI(remotePullPath);
var credentials = GitCredentials.fill(uri.getHost(), uri.getPath(), username, token, uri.getScheme());
var host = Forge.from(uri, new Credential(credentials.username(), credentials.password()));
if (host.isEmpty() || !host.get().isValid()) {
exit("error: failed to connect to host " + uri);
var shouldUseToken = !arguments.contains("no-token");
var credentials = !shouldUseToken ?
null :
GitCredentials.fill(uri.getHost(), uri.getPath(), username, token, uri.getScheme());
var forgeURI = URI.create(uri.getScheme() + "://" + uri.getHost());
var forge = credentials == null ?
Forge.from(forgeURI) :
Forge.from(forgeURI, new Credential(credentials.username(), credentials.password()));
if (forge.isEmpty() || !forge.get().isValid()) {
if (!shouldUseToken) {
if (arguments.contains("verbose")) {
System.err.println("");
}
System.err.println("warning: using git-pr with --no-token may result in rate limiting from " + forgeURI);
if (!arguments.contains("verbose")) {
System.err.println(" Re-run git-pr with --verbose to see if you are being rate limited");
System.err.println("");
}
}
exit("error: failed to connect to host: " + forgeURI);
}
var host = forge.get();

var action = arguments.at(0).asString();
if (!shouldUseToken &&
!List.of("list", "fetch", "show", "checkout", "apply").contains(action)) {
System.err.println("error: --no-token can only be used with read-only operations");
System.exit(1);
}

if (action.equals("create")) {
if (isMercurial) {
var currentBookmark = repo.currentBookmark();
@@ -420,7 +440,7 @@ public static void main(String[] args) throws IOException, InterruptedException
System.exit(1);
}

var remoteRepo = host.get().repository(projectName(uri)).orElseThrow(() ->
var remoteRepo = host.repository(projectName(uri)).orElseThrow(() ->
new IOException("Could not find repository at " + uri.toString())
);
if (token == null) {
@@ -490,7 +510,7 @@ public static void main(String[] args) throws IOException, InterruptedException
if (arguments.contains("assignees")) {
var usernames = Arrays.asList(arguments.get("assignees").asString().split(","));
var assignees = usernames.stream()
.map(u -> host.get().user(u))
.map(u -> host.user(u))
.collect(Collectors.toList());
pr.setAssignees(assignees);
}
@@ -579,7 +599,7 @@ public static void main(String[] args) throws IOException, InterruptedException
System.exit(1);
}

var remoteRepo = host.get().repository(projectName(uri)).orElseThrow(() ->
var remoteRepo = host.repository(projectName(uri)).orElseThrow(() ->
new IOException("Could not find repository at " + uri.toString())
);
if (token == null) {
@@ -649,14 +669,14 @@ public static void main(String[] args) throws IOException, InterruptedException
if (arguments.contains("assignees")) {
var usernames = Arrays.asList(arguments.get("assignees").asString().split(","));
var assignees = usernames.stream()
.map(u -> host.get().user(u))
.map(u -> host.user(u))
.collect(Collectors.toList());
pr.setAssignees(assignees);
}
System.out.println(pr.webUrl().toString());
Files.deleteIfExists(file);
} else if (action.equals("integrate") || action.equals("approve")) {
var pr = getPullRequest(uri, credentials, arguments.at(1));
var pr = getPullRequest(uri, host, arguments.at(1));

if (action.equals("integrate")) {
pr.addComment("/integrate");
@@ -666,7 +686,7 @@ public static void main(String[] args) throws IOException, InterruptedException
throw new IllegalStateException("unexpected action: " + action);
}
} else if (action.equals("list")) {
var remoteRepo = getHostedRepositoryFor(uri, credentials);
var remoteRepo = getHostedRepositoryFor(uri, host);
var prs = remoteRepo.pullRequests();

var ids = new ArrayList<String>();
@@ -758,7 +778,7 @@ public static void main(String[] args) throws IOException, InterruptedException
exit("error: missing pull request identifier");
}

var remoteRepo = getHostedRepositoryFor(uri, credentials);
var remoteRepo = getHostedRepositoryFor(uri, host);
var pr = remoteRepo.pullRequest(prId.asString());
var repoUrl = remoteRepo.webUrl();
var prHeadRef = pr.sourceRef();
@@ -832,7 +852,7 @@ public static void main(String[] args) throws IOException, InterruptedException
exit("error: missing pull request identifier");
}

var remoteRepo = getHostedRepositoryFor(uri, credentials);
var remoteRepo = getHostedRepositoryFor(uri, host);
var pr = remoteRepo.pullRequest(prId.asString());
pr.setState(PullRequest.State.CLOSED);
} else if (action.equals("update")) {
@@ -841,12 +861,12 @@ public static void main(String[] args) throws IOException, InterruptedException
exit("error: missing pull request identifier");
}

var remoteRepo = getHostedRepositoryFor(uri, credentials);
var remoteRepo = getHostedRepositoryFor(uri, host);
var pr = remoteRepo.pullRequest(prId.asString());
if (arguments.contains("assignees")) {
var usernames = Arrays.asList(arguments.get("assignees").asString().split(","));
var assignees = usernames.stream()
.map(u -> host.get().user(u))
.map(u -> host.user(u))
.collect(Collectors.toList());
pr.setAssignees(assignees);
}
@@ -57,7 +57,7 @@ public GitHubHost(URI uri, GitHubApplication application, Pattern webUriPattern,
.build();

request = new RestRequest(baseApi, () -> Arrays.asList(
"Authorization", "token " + getInstallationToken(),
"Authorization", "token " + getInstallationToken().orElseThrow(),
"Accept", "application/vnd.github.machine-man-preview+json",
"Accept", "application/vnd.github.antiope-preview+json"));
}
@@ -75,7 +75,7 @@ public GitHubHost(URI uri, Credential pat, Pattern webUriPattern, String webUriR
.build();

request = new RestRequest(baseApi, () -> Arrays.asList(
"Authorization", "token " + pat.password()));
"Authorization", "token " + getInstallationToken().orElseThrow()));
}

GitHubHost(URI uri, Pattern webUriPattern, String webUriReplacement) {
@@ -114,12 +114,16 @@ URI getWebURI(String endpoint) {
return URIBuilder.base(matcher.replaceAll(webUriReplacement)).build();
}

String getInstallationToken() {
Optional<String> getInstallationToken() {
if (application != null) {
return application.getInstallationToken();
} else {
return pat.password();
return Optional.of(application.getInstallationToken());
}

if (pat != null) {
return Optional.of(pat.password());
}

return Optional.empty();
}

private String getFullName(String userName) {
@@ -49,12 +49,19 @@
.appendSubDomain("api")
.setPath("/repos/" + repository + "/")
.build();
request = new RestRequest(apiBase, () -> Arrays.asList(
"Authorization", "token " + gitHubHost.getInstallationToken(),
request = new RestRequest(apiBase, () -> {
var headers = new ArrayList<>(List.of(
"Accept", "application/vnd.github.machine-man-preview+json",
"Accept", "application/vnd.github.antiope-preview+json",
"Accept", "application/vnd.github.shadow-cat-preview+json",
"Accept", "application/vnd.github.comfort-fade-preview+json"));
var token = gitHubHost.getInstallationToken();
if (token.isPresent()) {
headers.add("Authorization");
headers.add("token " + token.get());
}
return headers;
});
json = gitHubHost.getProjectInfo(repository);
var urlPattern = gitHubHost.getWebURI("/" + repository + "/pull/").toString();
pullRequestPattern = Pattern.compile(urlPattern + "(\\d+)");
@@ -143,11 +150,13 @@ public String name() {

@Override
public URI url() {
return URIBuilder
.base(gitHubHost.getURI())
.setPath("/" + repository + ".git")
.setAuthentication("x-access-token:" + gitHubHost.getInstallationToken())
.build();
var builder = URIBuilder.base(gitHubHost.getURI())
.setPath("/" + repository + ".git");
var token = gitHubHost.getInstallationToken();
if (token.isPresent()) {
builder.setAuthentication("x-access-token:" + token.get());
}
return builder.build();
}

@Override
@@ -33,43 +33,11 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

class GitHubHostTests {
// This key was randomly generated for this test only
private String key = "-----BEGIN PRIVATE KEY-----\n" +
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAFzH+URXAvOoL\n" +
"0NSdIePQTTVsan13c+7D9tAilJAtRcxUjOz2lMZYBzrdsVYGbktfseEvF6o9dyoX\n" +
"X/py6DM0QqBNW/0uEv1ouS44po0VvykHVXrAq0u8E8HHFtr09VQSO/ceXrFd6haQ\n" +
"aCckbdp1TPn1q8w+U2bRkqUji7zzfwll6AaB4dhKZ1v5NFuff1PWmuk2x7b0u2yR\n" +
"uANLHLqmNB4ik7bUTiIyacXeVSZRZRFGwJjd+1WnyiybwV6QbQ0nndw6iaz2wGWt\n" +
"XDif7DJE0axMReUZVKJLqMagS5R5ra6FdlnUPw0nbJMwnDOLk9ofSfne0LTSTD6K\n" +
"/VZ26izbAgMBAAECggEBALF0vDq1reLgo1dHFSQUquFEcpY1yrMP5wQifyVzGb65\n" +
"PIrfpgomZxXrl/Y2XcKTIg7FxcI7moouDDSL9lMxMByXcIAG+14VLQYSDSFIvA3b\n" +
"C4w666wSk2Ss29eQxbaG7aPqweDMmg6osy+1CHQfCDJVapYKoCTz54i0cNrlvSk0\n" +
"FZ3o99uAvAcLtrsqbnXO57NXQVajoSH0bkMZd+TuZqEIX3CzHoNEVhzvqaKedqA6\n" +
"Cd22Y2m6cnW0H10Chko05FtskLYD+jw275LiUtInplBtG3n5/uDIamsOPo9XG8i0\n" +
"a4rxaJYsRqXYqDOEjLi/QCUrYBtJ+gqT/qMOTjAoKAECgYEA/VPdvc03vScjIu4T\n" +
"vNXjXxv81HZPm/IoTYTgvTvrEqErQ/CIwTQJer1XUJ9M43n+XkVZsMKkUIMlwt2+\n" +
"G0wBwYkDUgIXFEJhb170BVgwyZHE+Djr0E7NunbAv/oQu8AfQzk5HZpcQwxVg8w8\n" +
"Vj2ecLb4GK0D9iJ4zLwlsRw2RukCgYEAwh30AG7gq5y9Mj/BusuDvyNZZKjE/pJz\n" +
"HtC7a/OzOyr+Bpr2VBxVDeEFth22bd/a4ohv1QcwNAa2LzelNfQRQURq/vqpDmuj\n" +
"g0ESQavh3i3Tax2LXO582HWueuNL+8Ufyb6WDJDvYuz0F3WBJhxixP3I7VgMhPWV\n" +
"tK/wEEDDwyMCgYEArR3M4NIHDzpZppsv3dIE6ZAEvWSEjrtzk1YFBwyVXkvJd0o/\n" +
"Clj3SWtu6eeS8bkCfYXC/ypkg6i7+2jxa1ILuShanoZTI0Mhtqwa8jQMUxNMmZy8\n" +
"ecQAjzZsDkVjfgqS0quePn6oIiGhpsnBSeYeCkTfUm2Z0XBJQRAqadgvt1ECgYBK\n" +
"FAgzyhxvIUeKT45s7JGAdcr9gPJ8fAL2tY1wqvWxFL0QZD6w5ocG3uLBFyGxWIY9\n" +
"gPe8ghvBHvaTmlav+k5DbAqw95Ngb29c/Y4sBZ4SncZa0FGIy3JVYMOPHgK3OAjj\n" +
"gpncfcr9I5QbB7qbgqWmq3rsKHfOnbHd3G5upWiPpQKBgCaPW2vyT/nfCvfh0z//\n" +
"QSv0//4zy7pDdOolP5ZRsUo5cU4aiv4XgTSglR2jEJyr4bMYCN/+4tnqp0tIUzt1\n" +
"RWJhXLU1dm4QhCTccWMAyQgktn3SB5Ww3+qyLr1klUwkO+rx8kkNjv3rC/u5EzQ9\n" +
"q3DJ9in4wyYBNPVDB5kJom5i\n" +
"-----END PRIVATE KEY-----";


@Test
void webUriPatternReplacement() throws IOException, URISyntaxException {
try (var tempFolder = new TemporaryDirectory()) {
var app = new GitHubApplication(key, "y", "z");
var host = new GitHubHost(URIBuilder.base("http://www.example.com").build(),
app, Pattern.compile("^(http://www.example.com)/test/(.*)$"), "$1/another/$2");
Pattern.compile("^(http://www.example.com)/test/(.*)$"), "$1/another/$2");
assertEquals(new URI("http://www.example.com/another/hello"), host.getWebURI("/test/hello"));
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.