Skip to content

Commit

Permalink
Merge pull request #168 from hughsimpson/support-git-worktrees
Browse files Browse the repository at this point in the history
  • Loading branch information
SethTisue authored Mar 15, 2022
2 parents 52b2eb0 + 1fa3ca5 commit ae227f6
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
11 changes: 9 additions & 2 deletions src/main/scala/com/typesafe/sbt/SbtGit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.typesafe.sbt

import sbt._
import Keys._
import git.{ConsoleGitRunner, DefaultReadableGit, GitRunner, JGitRunner, ReadableGit}
import git.{ConsoleGitReadableOnly, ConsoleGitRunner, DefaultReadableGit, GitRunner, JGitRunner, ReadableGit}
import sys.process.Process

/** This plugin has all the basic 'git' functionality for other plugins. */
Expand Down Expand Up @@ -40,6 +40,9 @@ object SbtGit {

// The remote repository we're using.
val gitRemoteRepo = SettingKey[String]("git-remote-repo", "The remote git repository associated with this project")

// Git worktree workaround
val useConsoleForROGit = SettingKey[Boolean]("console-ro-runner", "Whether to shell out to git for ro ops in the current build.")
}

object GitCommand {
Expand Down Expand Up @@ -110,7 +113,8 @@ object SbtGit {
// Build settings.
import GitKeys._
def buildSettings = Seq(
gitReader := new DefaultReadableGit(baseDirectory.value),
useConsoleForROGit := false,
gitReader := new DefaultReadableGit(baseDirectory.value, if (useConsoleForROGit.value) Some(new ConsoleGitReadableOnly(ConsoleGitRunner, file("."), ConsoleLogger())) else None),
gitRunner := ConsoleGitRunner,
gitHeadCommit := gitReader.value.withGit(_.headCommitSha),
gitHeadMessage := gitReader.value.withGit(_.headCommitMessage),
Expand Down Expand Up @@ -155,6 +159,9 @@ object SbtGit {
/** A Predefined setting to use JGit runner for git. */
def useJGit: Setting[_] = gitRunner in ThisBuild := JGitRunner

/** Setting to use console git for readable ops, to allow working with git worktrees */
def useReadableConsoleGit: Setting[_] = useConsoleForROGit in ThisBuild := true

/** Adapts the project prompt to show the current project name *and* the current git branch. */
def showCurrentGitBranch: Setting[_] =
shellPrompt := GitCommand.prompt
Expand Down
27 changes: 27 additions & 0 deletions src/main/scala/com/typesafe/sbt/git/ConsoleGitReadableOnly.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.typesafe.sbt.git

import scala.util.Try

import sbt.{File, Logger}

class ConsoleGitReadableOnly(git: GitRunner, cwd: File, log: Logger) extends GitReadonlyInterface {
def branch: String = git("rev-parse", "--abbrev-ref", "HEAD")(cwd, log)

def headCommitSha: Option[String] = Try(git("rev-parse", "HEAD")(cwd, log)).toOption

def headCommitDate: Option[String] = Try(git("log", """--pretty="%cI"""", "-n", "1")(cwd, log)).toOption

def currentTags: Seq[String] = git("tag", "--points-at", "HEAD")(cwd, log).split("\\s+")

def describedVersion: Option[String] = git("describe", "--tags")(cwd, log).split("\\s+").headOption

def hasUncommittedChanges: Boolean = git("status")(cwd, log).contains("nothing to commit, working tree clean")

def branches: Seq[String] = git("branch", "--list")(cwd, log).split("\\s+")

def remoteBranches: Seq[String] = git("branch", "-l", "--remotes")(cwd, log).split("\\s+")

def remoteOrigin: String = git("ls-remote", "--get-url", "origin")(cwd, log)

def headCommitMessage: Option[String] = Try(git("log", "--pretty=%s\n\n%b", "-n", "1")(cwd, log)).toOption
}
8 changes: 5 additions & 3 deletions src/main/scala/com/typesafe/sbt/git/ReadableGit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ trait GitReadonlyInterface {
}


/** Our default readable git uses JGit instead of a process-forking and reading, for speed/safety. */
final class DefaultReadableGit(base: sbt.File) extends ReadableGit {
/** Our default readable git uses JGit instead of a process-forking and reading, for speed/safety. However, we allow
* overriding, since JGit doesn't currently work with git worktrees
* */
final class DefaultReadableGit(base: sbt.File, gitOverride: Option[GitReadonlyInterface]) extends ReadableGit {
// TODO - Should we cache git, or just create on each request?
// For now, let's cache.
private[this] val git = JGit(base)
private[this] val git = gitOverride getOrElse JGit(base)
/** Use the git read-only interface. */
def withGit[A](f: GitReadonlyInterface => A): A =
// JGit has concurrency issues so we synchronize access to it.
Expand Down

0 comments on commit ae227f6

Please sign in to comment.