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

forge: add HostedRepository.recentCommitComments #891

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -169,4 +169,9 @@ public Optional<CommitMetadata> commitMetadata(Hash commit) {
public List<Check> allChecks(Hash hash) {
return List.of();
}

@Override
public List<CommitComment> recentCommitComments() {
return List.of();
}
}
@@ -29,16 +29,28 @@
import java.nio.file.Path;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Supplier;

public class CommitComment extends Comment {
private final Hash commit;
private Hash commit;
private final Supplier<Hash> commitSupplier;
private final Path path;
private final int line;

public CommitComment(Hash commit, Path path, int line, String id, String body, HostUser author, ZonedDateTime createdAt, ZonedDateTime updatedAt) {
super(id, body, author, createdAt, updatedAt);

this.commit = commit;
this.commitSupplier = null;
this.path = path;
this.line = line;
}

public CommitComment(Supplier<Hash> commitSupplier, Path path, int line, String id, String body, HostUser author, ZonedDateTime createdAt, ZonedDateTime updatedAt) {
super(id, body, author, createdAt, updatedAt);

this.commit = null;
this.commitSupplier = commitSupplier;
this.path = path;
this.line = line;
}
@@ -47,6 +59,9 @@ public CommitComment(Hash commit, Path path, int line, String id, String body, H
* Returns the hash of the commit.
*/
public Hash commit() {
if (commit == null) {
commit = commitSupplier.get();
}
return commit;
}

@@ -68,6 +68,7 @@ PullRequest createPullRequest(HostedRepository target,
Hash branchHash(String ref);
List<HostedBranch> branches();
List<CommitComment> commitComments(Hash hash);
List<CommitComment> recentCommitComments();
void addCommitComment(Hash hash, String body);
Optional<CommitMetadata> commitMetadata(Hash hash);
List<Check> allChecks(Hash hash);
@@ -199,10 +199,21 @@ HostUser parseUserField(JSONValue json) {
}

HostUser parseUserObject(JSONValue json) {
return hostUser(json.get("id").asInt(), json.get("login").asString());
}

HostUser hostUser(int id, String username) {
return HostUser.builder()
.id(id)
.username(username)
.supplier(() -> user(username).orElseThrow())
.build();
}

HostUser hostUser(String username) {
return HostUser.builder()
.id(json.get("id").asInt())
.username(json.get("login").asString())
.supplier(() -> user(json.get("login").asString()).orElseThrow())
.username(username)
.supplier(() -> user(username).orElseThrow())
.build();
}

@@ -269,10 +280,10 @@ public Optional<HostUser> user(String username) {
return Optional.empty();
}

return Optional.of(asHostUser(details.asObject()));
return Optional.of(toHostUser(details.asObject()));
}

private static HostUser asHostUser(JSONObject details) {
private HostUser toHostUser(JSONObject details) {
// Always present
var login = details.get("login").asString();
var id = details.get("id").asInt();
@@ -302,7 +313,7 @@ public HostUser currentUser() {
// on Windows always return "PersonalAccessToken" as username.
// Query GitHub for the username instead.
var details = request.get("user").execute().asObject();
currentUser = asHostUser(details);
currentUser = toHostUser(details);
} else {
throw new IllegalStateException("No credentials present");
}
@@ -268,29 +268,80 @@ public List<HostedBranch> branches() {
.collect(Collectors.toList());
}

private CommitComment toCommitComment(JSONValue o) {
var hash = new Hash(o.get("commit_id").asString());
var line = o.get("line").isNull()? -1 : o.get("line").asInt();
var path = o.get("path").isNull()? null : Path.of(o.get("path").asString());
return new CommitComment(hash,
path,
line,
o.get("id").toString(),
o.get("body").asString(),
gitHubHost.parseUserField(o),
ZonedDateTime.parse(o.get("created_at").asString()),
ZonedDateTime.parse(o.get("updated_at").asString()));
}

@Override
public List<CommitComment> commitComments(Hash hash) {
return request.get("commits/" + hash.hex() + "/comments")
.execute()
.stream()
.map(JSONValue::asObject)
.map(o -> {
var line = o.get("line").isNull()? -1 : o.get("line").asInt();
var path = o.get("path").isNull()? null : Path.of(o.get("path").asString());
return new CommitComment(hash,
path,
line,
o.get("id").toString(),
o.get("body").asString(),
gitHubHost.parseUserField(o),
ZonedDateTime.parse(o.get("created_at").asString()),
ZonedDateTime.parse(o.get("updated_at").asString()));


})
.map(this::toCommitComment)
.collect(Collectors.toList());
}

@Override
public List<CommitComment> recentCommitComments() {
var parts = name().split("/");
var owner = parts[0];
var name = parts[1];

var query = String.join("\n", List.of(
"query {",
" repository(owner: \"" + owner + "\", name: \"" + name + "\") {",
" commitComments(last: 200) {",
" nodes {",
" createdAt",
" updatedAt",
" author { login }",
" databaseId",
" commit { oid }",
" body",
" }",
" }",
" }",
"}"
));

var data = gitHubHost.graphQL()
.post()
.body(JSON.object().put("query", query))
.execute()
.get("data");
return data.get("repository")
.get("commitComments")
.get("nodes")
.stream()
.map(o -> {
var hash = new Hash(o.get("commit").get("oid").asString());
var createdAt = ZonedDateTime.parse(o.get("createdAt").asString());
var updatedAt = ZonedDateTime.parse(o.get("updatedAt").asString());
var id = o.get("databaseId").asString();
var body = o.get("body").asString();
var user = gitHubHost.hostUser(o.get("login").asString());
return new CommitComment(hash,
null,
-1,
id,
body,
user,
createdAt,
updatedAt);
})
.collect(Collectors.toList());
}

@Override
public void addCommitComment(Hash hash, String body) {
var query = JSON.object().put("body", body);
@@ -22,6 +22,7 @@
*/
package org.openjdk.skara.forge.gitlab;

import org.openjdk.skara.host.HostUser;
import org.openjdk.skara.forge.*;
import org.openjdk.skara.json.*;
import org.openjdk.skara.network.*;
@@ -33,6 +34,7 @@
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@@ -290,27 +292,90 @@ public List<HostedBranch> branches() {
.collect(Collectors.toList());
}

private CommitComment toCommitComment(Hash hash, JSONValue o) {
var line = o.get("line").isNull()? -1 : o.get("line").asInt();
var path = o.get("path").isNull()? null : Path.of(o.get("path").asString());
// GitLab does not offer updated_at for commit comments
var createdAt = ZonedDateTime.parse(o.get("created_at").asString());
// GitLab does not offer an id for commit comments
var id = "";
return new CommitComment(hash,
path,
line,
id,
o.get("note").asString(),
gitLabHost.parseAuthorField(o),
createdAt,
createdAt);
}

@Override
public List<CommitComment> commitComments(Hash hash) {
return request.get("repository/commits/" + hash.hex() + "/comments")
.execute()
.stream()
.map(JSONValue::asObject)
.map(o -> toCommitComment(hash, o))
.collect(Collectors.toList());
}

private Hash commitWithComment(String commitTitle,
String commentBody,
ZonedDateTime commentCreatedAt,
HostUser author) {
var result = request.get("search")
.param("scope", "commits")
.param("search", commitTitle)
.execute()
.stream()
.filter(o -> o.get("title").asString().equals(commitTitle))
.map(o -> new Hash(o.get("id").asString()))
.collect(Collectors.toList());
if (result.isEmpty()) {
throw new IllegalArgumentException("No commit with title: " + commitTitle);
}
if (result.size() > 1) {
var filtered = result.stream()
.flatMap(hash -> commitComments(hash).stream()
.filter(c -> c.body().equals(commentBody))
.filter(c -> c.createdAt().equals(commentCreatedAt))
.filter(c -> c.author().equals(author)))
.map(c -> c.commit())
.collect(Collectors.toList());
if (filtered.isEmpty()) {
throw new IllegalStateException("No commit with title '" + commitTitle +
"' and comment '" + commentBody + "'");
}
if (filtered.size() > 1) {
var hashes = filtered.stream().map(Hash::hex).collect(Collectors.toList());
throw new IllegalStateException("Multiple commits with identical comment '" + commentBody + "': "
+ String.join(",", hashes));
}
return filtered.get(0);
}
return result.get(0);
}

@Override
public List<CommitComment> recentCommitComments() {
var twoDaysAgo = ZonedDateTime.now().minusDays(2);
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-DD");
return request.get("events")
.param("after", twoDaysAgo.format(formatter))
.execute()
.stream()
.filter(o -> o.contains("note") &&
o.get("note").contains("noteable_type") &&
o.get("note").get("noteable_type").asString().equals("Commit"))
.map(o -> {
var line = o.get("line").isNull()? -1 : o.get("line").asInt();
var path = o.get("path").isNull()? null : Path.of(o.get("path").asString());
// GitLab does not offer updated_at for commit comments
var createdAt = ZonedDateTime.parse(o.get("created_at").asString());
// GitLab does not offer an id for commit comments
var id = "";
return new CommitComment(hash,
path,
line,
id,
o.get("note").asString(),
gitLabHost.parseAuthorField(o),
createdAt,
createdAt);
var createdAt = ZonedDateTime.parse(o.get("note").get("created_at").asString());
var body = o.get("note").get("body").asString();
var user = gitLabHost.parseAuthorField(o);
var id = o.get("note").get("id").asString();
Supplier<Hash> hash = () -> commitWithComment(o.get("target_title").asString(),
body,
createdAt,
user);
return new CommitComment(hash, null, -1, id, body, user, createdAt, createdAt);
})
.collect(Collectors.toList());
}
@@ -211,6 +211,14 @@ public List<CommitComment> commitComments(Hash hash) {
return commitComments.get(hash);
}

@Override
public List<CommitComment> recentCommitComments() {
return commitComments.values()
.stream()
.flatMap(e -> e.stream())
.collect(Collectors.toList());
}

@Override
public void addCommitComment(Hash hash, String body) {
var id = nextCommitCommentId;