Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Upgrade to Grgit 5
Browse files Browse the repository at this point in the history
Fixes #60
Fixes #70
Fixes #79
Fixes #85
ajoberstar committed Feb 10, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent d1e8dc9 commit b38668a
Showing 9 changed files with 127 additions and 168 deletions.
19 changes: 6 additions & 13 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -19,19 +19,20 @@ mavenCentral {
developerName.set("Andrew Oberstar")
developerEmail.set("[email protected]")
githubOwner.set("ajoberstar")
githubRepository.set("reckon")
githubRepository.set("gradle-git-publish")
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
languageVersion.set(JavaLanguageVersion.of(11))
}
}

dependencies {
// grgit
api("org.ajoberstar.grgit:grgit-core:[4.0,5.0[")
compatTestImplementation("org.ajoberstar.grgit:grgit-core:[4.0,5.0[")
api("org.ajoberstar.grgit:grgit-core:[5.0,6.0[")
api("org.ajoberstar.grgit:grgit-gradle:[5.0,6.0[")
compatTestImplementation("org.ajoberstar.grgit:grgit-core:[5.0,6.0[")

// testing
compatTestImplementation(gradleTestKit())
@@ -49,20 +50,12 @@ tasks.withType<Test> {
}

stutter {
val java8 by matrices.creating {
javaToolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
gradleVersions {
compatibleRange("5.0")
}
}
val java11 by matrices.creating {
javaToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
gradleVersions {
compatibleRange("5.0")
compatibleRange("7.0")
}
}
val java17 by matrices.creating {
9 changes: 5 additions & 4 deletions gradle.lockfile
Original file line number Diff line number Diff line change
@@ -2,13 +2,14 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
cglib:cglib-nodep:3.3.0=compatTestCompileClasspath,compatTestRuntimeClasspath
com.googlecode.javaewah:JavaEWAH:1.1.12=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.googlecode.javaewah:JavaEWAH:1.1.13=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.11.0=compatTestCompileClasspath,compatTestRuntimeClasspath
org.ajoberstar.grgit:grgit-core:4.1.1=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ajoberstar.grgit:grgit-core:5.0.0-rc.7=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ajoberstar.grgit:grgit-gradle:5.0.0-rc.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.0=compatTestCompileClasspath,compatTestRuntimeClasspath
org.assertj:assertj-core:3.16.1=compatTestCompileClasspath,compatTestRuntimeClasspath
org.codehaus.groovy:groovy:3.0.8=compatTestCompileClasspath,compatTestRuntimeClasspath
org.eclipse.jgit:org.eclipse.jgit:5.13.0.202109080827-r=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.codehaus.groovy:groovy:3.0.9=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jgit:org.eclipse.jgit:6.0.0.202111291000-r=compatTestCompileClasspath,compatTestRuntimeClasspath,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest:2.2=compatTestCompileClasspath,compatTestRuntimeClasspath
org.jetbrains:annotations:20.1.0=compatTestCompileClasspath,compatTestRuntimeClasspath
org.junit.platform:junit-platform-commons:1.7.2=compatTestCompileClasspath,compatTestRuntimeClasspath
Original file line number Diff line number Diff line change
@@ -318,7 +318,6 @@ gitPublish {
then:
result.task(':gitPublishPush').outcome == TaskOutcome.SUCCESS
remote.log().size() == 2
working.branch.list()*.name == ['gh-pages']
}

def 'when no git publish tasks are run, build completes successfully'() {
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.ajoberstar.gradle.git.publish;


import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.util.PatternFilterable;
import org.gradle.api.tasks.util.PatternSet;

import javax.inject.Inject;

public class GitPublishExtension {
private final DirectoryProperty repoDir;
private final Property<String> repoUri;
@@ -19,13 +21,14 @@ public class GitPublishExtension {
private final CopySpec contents;
private final PatternFilterable preserve;

public GitPublishExtension(Project project) {
this.repoDir = project.getObjects().directoryProperty();
this.repoUri = project.getObjects().property(String.class);
this.referenceRepoUri = project.getObjects().property(String.class);
this.branch = project.getObjects().property(String.class);
this.commitMessage = project.getObjects().property(String.class);
this.sign = project.getObjects().property(Boolean.class);
@Inject
public GitPublishExtension(Project project, ObjectFactory objectFactory) {
this.repoDir = objectFactory.directoryProperty();
this.repoUri = objectFactory.property(String.class);
this.referenceRepoUri = objectFactory.property(String.class);
this.branch = objectFactory.property(String.class);
this.commitMessage = objectFactory.property(String.class);
this.sign = objectFactory.property(Boolean.class);

this.contents = project.copySpec();
this.preserve = new PatternSet();
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package org.ajoberstar.gradle.git.publish;

import java.util.Optional;

import org.ajoberstar.gradle.git.publish.tasks.GitPublishCommit;
import org.ajoberstar.gradle.git.publish.tasks.GitPublishPush;
import org.ajoberstar.gradle.git.publish.tasks.GitPublishReset;
import org.ajoberstar.grgit.Grgit;
import org.ajoberstar.grgit.gradle.GrgitService;
import org.ajoberstar.grgit.gradle.GrgitServiceExtension;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.TaskProvider;

public class GitPublishPlugin implements Plugin<Project> {
static final String RESET_TASK = "gitPublishReset";
@@ -20,74 +20,77 @@ public class GitPublishPlugin implements Plugin<Project> {

@Override
public void apply(Project project) {
GitPublishExtension extension = project.getExtensions().create("gitPublish", GitPublishExtension.class, project);

extension.getCommitMessage().set("Generated by gradle-git-publish.");
var extension = project.getExtensions().create("gitPublish", GitPublishExtension.class, project);
configureExtensionDefaults(project, extension);

// if using the grgit plugin, default to the repo's origin
project.getPluginManager().withPlugin("org.ajoberstar.grgit", plugin -> {
// TODO should this be based on tracking branch instead of assuming origin?
Optional.ofNullable((Grgit) project.findProperty("grgit")).ifPresent(grgit -> {
extension.getRepoUri().set(getOriginUri(grgit));
extension.getReferenceRepoUri().set(grgit.getRepository().getRootDir().toURI().toString());
var grgitService = project.getGradle().getSharedServices().registerIfAbsent("git-publish-grgit", GrgitService.class, spec -> {
spec.parameters(parameters -> {
parameters.getDirectory().set(extension.getRepoDir());
parameters.getInitIfNotExists().set(true);
});
spec.getMaxParallelUsages().set(1);
});

extension.getRepoDir().set(project.getLayout().getBuildDirectory().dir("gitPublish"));
var reset = createResetTask(project, extension, grgitService);
var copy = createCopyTask(project, extension);
var commit = createCommitTask(project, extension, grgitService);
var push = createPushTask(project, extension, grgitService);

GitPublishReset reset = createResetTask(project, extension);
Task copy = createCopyTask(project, extension);
Task commit = createCommitTask(project, extension, reset.getGrgit());
Task push = createPushTask(project, extension, reset.getGrgit());
push.dependsOn(commit);
commit.dependsOn(copy);
copy.dependsOn(reset);
push.configure(t -> t.dependsOn(commit));
commit.configure(t -> t.dependsOn(copy));
copy.configure(t -> t.dependsOn(reset));
}

// always close the repo at the end of the build
project.getGradle().buildFinished(result -> {
project.getLogger().info("Closing Git publish repo: {}", extension.getRepoDir().get());
if (reset.getGrgit().isPresent()) {
reset.getGrgit().get().close();
}
private void configureExtensionDefaults(Project project, GitPublishExtension extension) {
extension.getCommitMessage().set("Generated by gradle-git-publish.");

// if using the grgit-service plugin, default to the repo's origin
project.getPluginManager().withPlugin("org.ajoberstar.grgit.service", plugin -> {
var grgitExt = project.getExtensions().getByType(GrgitServiceExtension.class);
// TODO should this be based on tracking branch instead of assuming origin?
extension.getRepoUri().set(grgitExt.getService().map(service -> getOriginUri(service.getGrgit())));
extension.getReferenceRepoUri().set(grgitExt.getService().map(service -> service.getGrgit().getRepository().getRootDir().toURI().toString()));
});

extension.getRepoDir().set(project.getLayout().getBuildDirectory().dir("gitPublish"));
}

private GitPublishReset createResetTask(Project project, GitPublishExtension extension) {
return project.getTasks().create(RESET_TASK, GitPublishReset.class, task -> {
private TaskProvider<GitPublishReset> createResetTask(Project project, GitPublishExtension extension, Provider<GrgitService> grgitService) {
return project.getTasks().register(RESET_TASK, GitPublishReset.class, task -> {
task.setGroup("publishing");
task.setDescription("Prepares a git repo for new content to be generated.");
task.getRepoDirectory().set(extension.getRepoDir());
task.getGrgitService().set(grgitService);
task.getRepoUri().set(extension.getRepoUri());
task.getReferenceRepoUri().set(extension.getReferenceRepoUri());
task.getBranch().set(extension.getBranch());
task.setPreserve(extension.getPreserve());
});
}

private Copy createCopyTask(Project project, GitPublishExtension extension) {
return project.getTasks().create(COPY_TASK, Copy.class, task -> {
private TaskProvider<Copy> createCopyTask(Project project, GitPublishExtension extension) {
return project.getTasks().register(COPY_TASK, Copy.class, task -> {
task.setGroup("publishing");
task.setDescription("Copy contents to be published to git.");
task.with(extension.getContents());
task.into(extension.getRepoDir());
});
}

private GitPublishCommit createCommitTask(Project project, GitPublishExtension extension, Provider<Grgit> grgitProvider) {
return project.getTasks().create(COMMIT_TASK, GitPublishCommit.class, task -> {
private TaskProvider<GitPublishCommit> createCommitTask(Project project, GitPublishExtension extension, Provider<GrgitService> grgitService) {
return project.getTasks().register(COMMIT_TASK, GitPublishCommit.class, task -> {
task.setGroup("publishing");
task.setDescription("Commits changes to be published to git.");
task.getGrgit().set(grgitProvider);
task.getGrgitService().set(grgitService);
task.getMessage().set(extension.getCommitMessage());
task.getSign().set(extension.getSign());
});
}

private GitPublishPush createPushTask(Project project, GitPublishExtension extension, Provider<Grgit> grgitProvider) {
return project.getTasks().create(PUSH_TASK, GitPublishPush.class, task -> {
private TaskProvider<GitPublishPush> createPushTask(Project project, GitPublishExtension extension, Provider<GrgitService> grgitService) {
return project.getTasks().register(PUSH_TASK, GitPublishPush.class, task -> {
task.setGroup("publishing");
task.setDescription("Pushes changes to git.");
task.getGrgit().set(grgitProvider);
task.getGrgitService().set(grgitService);
task.getBranch().set(extension.getBranch());
});
}
Original file line number Diff line number Diff line change
@@ -6,30 +6,28 @@

import javax.inject.Inject;

import org.ajoberstar.grgit.Grgit;
import org.ajoberstar.grgit.gradle.GrgitService;
import org.gradle.api.DefaultTask;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.*;

@UntrackedTask(because = "Git tracks the state")
public class GitPublishCommit extends DefaultTask {
private final Property<Grgit> grgit;
private final Property<GrgitService> grgitService;
private final Property<String> message;
private final Property<Boolean> sign;

@Inject
public GitPublishCommit(ObjectFactory objectFactory) {
this.grgit = objectFactory.property(Grgit.class);
this.grgitService = objectFactory.property(GrgitService.class);
this.message = objectFactory.property(String.class);
this.sign = objectFactory.property(Boolean.class);

// always consider this task out of date
this.getOutputs().upToDateWhen(t -> false);
}

@Internal
public Property<Grgit> getGrgit() {
return grgit;
public Property<GrgitService> getGrgitService() {
return grgitService;
}

@Input
@@ -43,14 +41,9 @@ public Property<Boolean> getSign() {
return sign;
}

@OutputDirectory
public File getRepoDirectory() {
return getGrgit().get().getRepository().getRootDir();
}

@TaskAction
public void commit() {
Grgit git = getGrgit().get();
var git = getGrgitService().get().getGrgit();
git.add(op -> {
op.setPatterns(Stream.of(".").collect(Collectors.toSet()));
});
@@ -68,5 +61,4 @@ public void commit() {
setDidWork(true);
}
}

}
Original file line number Diff line number Diff line change
@@ -5,29 +5,26 @@

import javax.inject.Inject;

import org.ajoberstar.grgit.BranchStatus;
import org.ajoberstar.grgit.Grgit;
import org.ajoberstar.grgit.gradle.GrgitService;
import org.gradle.api.DefaultTask;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.*;

@UntrackedTask(because = "Git tracks the state")
public class GitPublishPush extends DefaultTask {
private final Property<Grgit> grgit;
private final Property<GrgitService> grgitService;
private final Property<String> branch;

@Inject
public GitPublishPush(ObjectFactory objectFactory) {
this.grgit = objectFactory.property(Grgit.class);
this.grgitService = objectFactory.property(GrgitService.class);
this.branch = objectFactory.property(String.class);

// always consider this task out of date
this.getOutputs().upToDateWhen(t -> false);

this.onlyIf(t -> {
try {
Grgit git = getGrgit().get();
BranchStatus status = git.getBranch().status(op -> {
var git = getGrgitService().get().getGrgit();
var status = git.getBranch().status(op -> {
op.setName(getBranch().get());
});
return status.getAheadCount() > 0;
@@ -39,24 +36,19 @@ public GitPublishPush(ObjectFactory objectFactory) {
}

@Internal
public Property<Grgit> getGrgit() {
return grgit;
public Property<GrgitService> getGrgitService() {
return grgitService;
}

@Input
public Property<String> getBranch() {
return branch;
}

@OutputDirectory
public File getRepoDirectory() {
return getGrgit().get().getRepository().getRootDir();
}

@TaskAction
public void push() {
Grgit git = getGrgit().get();
String pubBranch = getBranch().get();
var git = getGrgitService().get().getGrgit();
var pubBranch = getBranch().get();
git.push(op -> {
op.setRefsOrSpecs(Arrays.asList(String.format("refs/heads/%s:refs/heads/%s", pubBranch, pubBranch)));
});
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@

import org.ajoberstar.grgit.Grgit;
import org.ajoberstar.grgit.Ref;
import org.ajoberstar.grgit.gradle.GrgitService;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.DirectoryProperty;
@@ -23,47 +25,35 @@
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.*;
import org.gradle.api.tasks.util.PatternFilterable;

@UntrackedTask(because = "Git tracks the state")
public class GitPublishReset extends DefaultTask {
private final Property<Grgit> grgit;
private final DirectoryProperty repoDirectory;
private final Property<GrgitService> grgitService;
private final Property<String> repoUri;
private final Property<String> referenceRepoUri;
private final Property<String> branch;
private PatternFilterable preserve;

@Inject
public GitPublishReset(ProjectLayout layout, ObjectFactory objectFactory) {
this.grgit = objectFactory.property(Grgit.class);
this.repoDirectory = getProject().getObjects().directoryProperty();
this.grgitService = objectFactory.property(GrgitService.class);
this.repoUri = objectFactory.property(String.class);
this.referenceRepoUri = objectFactory.property(String.class);
this.branch = objectFactory.property(String.class);

// always consider this task out of date
this.getOutputs().upToDateWhen(t -> false);
}

@Internal
public Property<Grgit> getGrgit() {
return grgit;
public Property<GrgitService> getGrgitService() {
return grgitService;
}

@Internal
public Property<String> getReferenceRepoUri() {
return referenceRepoUri;
}

@OutputDirectory
public DirectoryProperty getRepoDirectory() {
return repoDirectory;
}

@Input
public Property<String> getRepoUri() {
return repoUri;
@@ -84,11 +74,39 @@ public void setPreserve(PatternFilterable preserve) {
}

@TaskAction
public void reset() {
Grgit git = findExistingRepo().orElseGet(() -> freshRepo());
grgit.set(git);
public void reset() throws IOException {
var git = grgitService.get().getGrgit();

String pubBranch = getBranch().get();
if (!isRemoteUriMatch(git, "origin", repoUri.get())) {
git.getRemote().remove(op -> {
op.setName("origin");
});
git.getRemote().add(op -> {
op.setName("origin");
op.setUrl(repoUri.get());
});
}

if (referenceRepoUri.isPresent() && !isRemoteUriMatch(git, "reference", referenceRepoUri.get())) {
git.getRemote().remove(op -> {
op.setName("reference");
});

git.getRemote().add(op -> {
op.setName("reference");
op.setUrl(referenceRepoUri.get());
});
}

var pubBranch = getBranch().get();

if (!pubBranch.equals(git.getBranch().current().getName())) {
// create a new orphan branch
git.checkout(op -> {
op.setBranch(pubBranch);
op.setOrphan(true);
});
}

if (referenceRepoUri.isPresent()) {
Map<Ref, String> referenceBranches = git.lsremote(op -> {
@@ -142,12 +160,6 @@ public void reset() {
op.setCommit("origin/" + pubBranch);
op.setMode("hard");
});
} else {
// create a new orphan branch
git.checkout(op -> {
op.setBranch(pubBranch);
op.setOrphan(true);
});
}

// clean up unwanted files
@@ -177,55 +189,20 @@ public void visitFile(FileVisitDetails fileVisitDetails) {
});
}

private Optional<Grgit> findExistingRepo() {
try {
return Optional.of(Grgit.open(op -> op.setDir(repoDirectory.get().getAsFile())))
.filter(repo -> {
boolean valid = isRemoteUriMatch(repo, "origin", repoUri.get())
&& (!referenceRepoUri.isPresent() || isRemoteUriMatch(repo, "reference", referenceRepoUri.get()))
&& branch.get().equals(repo.getBranch().current().getName());
if (!valid) {
repo.close();
}
return valid;
});
} catch (Exception e) {
// missing, invalid, or corrupt repo
getProject().getLogger().debug("Failed to find existing Git publish repository.", e);
return Optional.empty();
}
}

private Grgit freshRepo() {
getProject().delete(repoDirectory.get().getAsFile());

Grgit repo = Grgit.init(op -> {
op.setDir(repoDirectory.get().getAsFile());
});
repo.getRemote().add(op -> {
op.setName("origin");
op.setUrl(repoUri.get());
});
if (referenceRepoUri.isPresent()) {
repo.getRemote().add(op -> {
op.setName("reference");
op.setUrl(referenceRepoUri.get());
});
}
return repo;
}

private boolean isRemoteUriMatch(Grgit grgit, String remoteName, String remoteUri) {
try {
String currentRemoteUri = grgit.getRemote().list().stream()
var maybeCurrentRemoteUri = grgit.getRemote().list().stream()
.filter(remote -> remote.getName().equals(remoteName))
.map(remote -> remote.getUrl())
.findAny()
.orElse(null);
.findAny();

// need to use the URIish to normalize them and ensure we support all Git compatible URI-ishs (URL
// is too limiting)
return new URIish(remoteUri).equals(new URIish(currentRemoteUri));
if (maybeCurrentRemoteUri.isPresent()) {
return new URIish(remoteUri).equals(new URIish(maybeCurrentRemoteUri.get()));
} else {
return false;
}
} catch (URISyntaxException e) {
throw new RuntimeException("Invalid URI.", e);
}
3 changes: 1 addition & 2 deletions stutter.lockfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# DO NOT MODIFY: Generated by Stutter plugin.
java11=5.0,5.6.4,6.0.1,6.9.2,7.0.2,7.4
java11=7.0.2,7.4
java17=7.3.3,7.4
java8=5.0,5.6.4,6.0.1,6.9.2,7.0.2,7.4

0 comments on commit b38668a

Please sign in to comment.