diff --git a/README.md b/README.md index c4db4a0..19b4de9 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,14 @@ Git is immensely popular and being able to publish to it as part of a build proc `gradle-git-publish` is a [Gradle](http://gradle.org) plugin, `org.ajoberstar.git-publish`, which publishes files to a remote Git repository's branch. -See [Grgit](https://github.com/ajoberstar/grgit) for details on the Git library used underneath, including -configuration for authentication. - ## Usage See the [Release Notes](https://github.com/ajoberstar/gradle-git-publish/releases) for updates on changes and compatibility with Java and Gradle versions. > [!NOTE] > As of 5.0.0, the plugin uses the Git CLI for all behavior. `git` binary must be on the `PATH`. +> +> If you relied on Grgit's authentication, such as `GRGIT_USER`, use the new `username` and `password` properties on the `GitPublication`. See the configuration documentation below. ### Applying the Plugin @@ -80,6 +79,11 @@ gitPublish { // for signing commits, omit to use the default from your gitconfig sign = false + + // if you need to provide credentials, set both of these + // use an external source, such as an environment variable + username = 'dont-harcode' + password = 'dont-hardcode' } ``` diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublication.java b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublication.java index f232b19..3b9a7cd 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublication.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublication.java @@ -21,6 +21,8 @@ public class GitPublication implements Named { private final Property sign; private final CopySpec contents; private final PatternFilterable preserve; + private final Property username; + private final Property password; public GitPublication(String name, Project project, ObjectFactory objectFactory) { this.name = name; @@ -35,6 +37,9 @@ public GitPublication(String name, Project project, ObjectFactory objectFactory) this.contents = project.copySpec(); this.preserve = new PatternSet(); this.preserve.include(".git/**/*"); + + this.username = objectFactory.property(String.class); + this.password = objectFactory.property(String.class); } @Override @@ -85,4 +90,12 @@ public PatternFilterable getPreserve() { public void preserve(Action action) { action.execute(preserve); } + + public Property getUsername() { + return username; + } + + public Property getPassword() { + return password; + } } diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishExtension.java b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishExtension.java index d87b30d..04e7efa 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishExtension.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishExtension.java @@ -70,4 +70,12 @@ public PatternFilterable getPreserve() { public void preserve(Action action) { publications.getByName("main").preserve(action); } + + public Property getUsername() { + return publications.getByName("main").getUsername(); + } + + public Property getPassword() { + return publications.getByName("main").getPassword(); + } } diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java index 46acb3c..d668b4c 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java @@ -58,6 +58,8 @@ private TaskProvider createResetTask(Project project, GitPublic task.getBranch().set(publication.getBranch()); task.getFetchDepth().set(publication.getFetchDepth()); task.setPreserve(publication.getPreserve()); + task.getUsername().set(publication.getUsername()); + task.getPassword().set(publication.getPassword()); }); } @@ -91,6 +93,8 @@ private TaskProvider createPushTask(Project project, GitPublicat task.setDescription("Pushes " + publication.getName() + " publication changes to git."); task.getRepoDir().set(publication.getRepoDir()); task.getBranch().set(publication.getBranch()); + task.getUsername().set(publication.getUsername()); + task.getPassword().set(publication.getPassword()); }); } diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishPush.java b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishPush.java index ae12108..7e97ed3 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishPush.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishPush.java @@ -26,6 +26,12 @@ public abstract class GitPublishPush extends DefaultTask { @Input public abstract Property getBranch(); + @Internal + public abstract Property getUsername(); + + @Internal + public abstract Property getPassword(); + @Inject protected abstract ExecOperations getExecOperations(); @@ -36,6 +42,12 @@ public void push() { getExecOperations().exec(spec -> { var refSpec = String.format("refs/heads/%s:refs/heads/%s", pubBranch, pubBranch); spec.commandLine("git", "push", "--porcelain", "--set-upstream", "origin", refSpec); + + if (getUsername().isPresent() && getPassword().isPresent()) { + spec.environment("GIT_USERNAME", getUsername().get()); + spec.environment("GIT_PASSWORD", getPassword().get()); + } + spec.workingDir(getRepoDir().get()); spec.setStandardOutput(output); }); diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java index 73aaf9a..c259084 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java @@ -58,6 +58,12 @@ public void setPreserve(PatternFilterable preserve) { this.preserve = preserve; } + @Internal + public abstract Property getUsername(); + + @Internal + public abstract Property getPassword(); + @Inject protected abstract ObjectFactory getObjectFactory(); @@ -78,6 +84,16 @@ public void reset() throws IOException { }); } + // (if credentials) set credential helper + if (getUsername().isPresent() && getPassword().isPresent()) { + getExecOperations().exec(spec -> { + var script = "!f() { echo username=$GIT_USERNAME; echo password=$GIT_PASSWORD; }; f"; + spec.commandLine("git", "config", "--local", "credential.helper", script); + spec.workingDir(repoDir); + spec.setStandardOutput(OutputStream.nullOutputStream()); + }); + } + // set origin try { getExecOperations().exec(spec -> { @@ -94,19 +110,25 @@ public void reset() throws IOException { }); } - // set alternate object store if reference used - if (getReferenceRepoUri().isPresent()) { + // set alternate object store if reference used and not using fetch depth + if (getReferenceRepoUri().isPresent() && !getFetchDepth().isPresent()) { Path repoObjectsPath = repoDir.toPath().resolve(".git").resolve("objects"); Path alternatesPath = repoObjectsPath.resolve("info").resolve("alternates"); Path referenceRepoPath = Path.of(getReferenceRepoUri().get()); + Path referenceRepoGitPath = referenceRepoPath.resolve(".git"); + if (Files.exists(referenceRepoGitPath)) { + // not a bare repo + referenceRepoPath = referenceRepoGitPath; + } - Path referenceRepoObjectsPath = referenceRepoPath.resolve(".git").resolve("objects"); - Path referenceBareRepoObjectsPath = referenceRepoPath.resolve("objects"); - if (Files.exists(referenceRepoObjectsPath)) { + Path referenceRepoShallowPath = referenceRepoPath.resolve("shallow"); + Path referenceRepoObjectsPath = referenceRepoPath.resolve("objects"); + + if (Files.exists(referenceRepoShallowPath)) { + getLogger().info("Reference repo is shallow. Cannot use as a reference."); + } else if (Files.exists(referenceRepoObjectsPath)) { Files.writeString(alternatesPath, referenceRepoObjectsPath + "\n", StandardCharsets.UTF_8); - } else if (Files.exists(referenceBareRepoObjectsPath)) { - Files.writeString(alternatesPath, referenceBareRepoObjectsPath + "\n", StandardCharsets.UTF_8); } else { getLogger().warn("Reference repo doesn't seem to have an objects database: {}", referenceRepoPath); } @@ -118,6 +140,12 @@ public void reset() throws IOException { getExecOperations().exec(spec -> { spec.commandLine("git", "ls-remote", "--exit-code", "origin", pubBranch); spec.workingDir(repoDir); + + if (getUsername().isPresent() && getPassword().isPresent()) { + spec.environment("GIT_USERNAME", getUsername().get()); + spec.environment("GIT_PASSWORD", getPassword().get()); + } + spec.setStandardOutput(OutputStream.nullOutputStream()); spec.setErrorOutput(OutputStream.nullOutputStream()); }); @@ -139,6 +167,11 @@ public void reset() throws IOException { spec.args("--no-tags"); spec.args("origin", refSpec); + if (getUsername().isPresent() && getPassword().isPresent()) { + spec.environment("GIT_USERNAME", getUsername().get()); + spec.environment("GIT_PASSWORD", getPassword().get()); + } + spec.workingDir(repoDir); spec.setStandardOutput(OutputStream.nullOutputStream()); });