Skip to content
Permalink
Browse files
Add ReadOnlyRepository.annotate(Tag t) method
Reviewed-by: rwestberg
  • Loading branch information
edvbld committed Nov 7, 2019
1 parent b1e3d87 commit e294ce92b738663b8b991eee71cbfa076ccad96b
@@ -239,4 +239,8 @@ public void addSubmodule(String pullPath, Path path) throws IOException {
public List<Submodule> submodules() throws IOException {
return null;
}

public Optional<Tag.Annotated> annotate(Tag tag) throws IOException {
return null;
}
}
@@ -95,4 +95,6 @@ static Optional<ReadOnlyRepository> get(Path p) throws IOException {
static boolean exists(Path p) throws IOException {
return Repository.exists(p);
}

Optional<Tag.Annotated> annotate(Tag tag) throws IOException;
}
@@ -24,8 +24,73 @@

import java.util.Objects;
import java.util.Optional;
import java.time.ZonedDateTime;

public class Tag {
public static class Annotated {
private final String name;
private final Hash target;
private final Author author;
private final ZonedDateTime date;
private final String message;

public Annotated(String name, Hash target, Author author, ZonedDateTime date, String message) {
this.name = name;
this.target = target;
this.author = author;
this.date = date;
this.message = message;
}

public String name() {
return name;
}

public Hash target() {
return target;
}

public Author author() {
return author;
}

public ZonedDateTime date() {
return date;
}

public String message() {
return message;
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

if (!(other instanceof Annotated)) {
return false;
}

var o = (Annotated) other;
return Objects.equals(name, o.name) &&
Objects.equals(target, o.target) &&
Objects.equals(author, o.author) &&
Objects.equals(date, o.date) &&
Objects.equals(message, o.message);
}

@Override
public int hashCode() {
return Objects.hash(name, target, author, date, message);
}

@Override
public String toString() {
return name + " -> " + target.hex();
}
}

private final String name;

public Tag(String name) {
@@ -1150,4 +1150,25 @@ public List<Submodule> submodules() throws IOException {

return modules;
}

@Override
public Optional<Tag.Annotated> annotate(Tag tag) throws IOException {
var ref = "refs/tags/" + tag.name();
var format = "%(refname:short)%0a%(*objectname)%0a%(taggername) %(taggeremail)%0a%(taggerdate:iso-strict)%0a%(contents)";
try (var p = capture("git", "for-each-ref", "--format", format, ref)) {
var lines = await(p).stdout();
if (lines.size() >= 4) {
var name = lines.get(0);
var target = new Hash(lines.get(1));
var author = Author.fromString(lines.get(2));

var formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
var date = ZonedDateTime.parse(lines.get(3), formatter);
var message = String.join("\n", lines.subList(4, lines.size()));

return Optional.of(new Tag.Annotated(name, target, author, date, message));
}
return Optional.empty();
}
}
}
@@ -1170,4 +1170,29 @@ public List<Submodule> submodules() throws IOException {

return modules;
}

@Override
public Optional<Tag.Annotated> annotate(Tag tag) throws IOException {
var hgtags = root().resolve(".hgtags");
if (!Files.exists(hgtags)) {
return Optional.empty();
}
try (var p = capture("hg", "annotate", hgtags.toString())) {
var reversed = new ArrayList<>(await(p).stdout());
Collections.reverse(reversed);
for (var line : reversed) {
var parts = line.split(" ");
var tagName = parts[2];
if (tagName.equals(tag.name())) {
var target = new Hash(parts[1]);
var rev = parts[0].substring(0, parts[0].length() - 1).trim(); // skip last ':' and ev. whitespace
var hash = resolve(rev).orElseThrow(IOException::new);
var commit = lookup(hash).orElseThrow(IOException::new);
var message = String.join("\n", commit.message()) + "\n";
return Optional.of(new Tag.Annotated(tagName, target, commit.author(), commit.date(), message));
}
}
}
return Optional.empty();
}
}
@@ -33,6 +33,7 @@
import java.net.URI;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

@@ -1894,4 +1895,53 @@ void testSubmodulesOnRepoWithSubmodule(VCS vcs) throws IOException {
assertEquals(pullPath, module.pullPath());
}
}

@ParameterizedTest
@EnumSource(VCS.class)
void testAnnotateTag(VCS vcs) throws IOException {
try (var dir = new TemporaryDirectory()) {
var repo = Repository.init(dir.path(), vcs);
var readme = repo.root().resolve("README");
var now = ZonedDateTime.now();
Files.writeString(readme, "Hello\n");
repo.add(readme);
var head = repo.commit("Added README", "duke", "duke@openjdk.org");
var tag = repo.tag(head, "1.0", "Added tag 1.0 for HEAD\n", "duke", "duke@openjdk.org");
var annotated = repo.annotate(tag).get();

assertEquals("1.0", annotated.name());
assertEquals(head, annotated.target());
assertEquals(new Author("duke", "duke@openjdk.org"), annotated.author());
assertEquals(now.getYear(), annotated.date().getYear());
assertEquals(now.getMonth(), annotated.date().getMonth());
assertEquals(now.getDayOfYear(), annotated.date().getDayOfYear());
assertEquals(now.getHour(), annotated.date().getHour());
assertEquals(now.getOffset(), annotated.date().getOffset());
assertEquals("Added tag 1.0 for HEAD\n", annotated.message());
}
}

@ParameterizedTest
@EnumSource(VCS.class)
void testAnnotateTagOnMissingTag(VCS vcs) throws IOException {
try (var dir = new TemporaryDirectory()) {
var repo = Repository.init(dir.path(), vcs);
var readme = repo.root().resolve("README");
var now = ZonedDateTime.now();
Files.writeString(readme, "Hello\n");
repo.add(readme);
var head = repo.commit("Added README", "duke", "duke@openjdk.org");

assertEquals(Optional.empty(), repo.annotate(new Tag("unknown")));
}
}

@ParameterizedTest
@EnumSource(VCS.class)
void testAnnotateTagOnEmptyRepo(VCS vcs) throws IOException {
try (var dir = new TemporaryDirectory()) {
var repo = Repository.init(dir.path(), vcs);
assertEquals(Optional.empty(), repo.annotate(new Tag("unknown")));
}
}
}

0 comments on commit e294ce9

Please sign in to comment.