├── NOTICE ├── project ├── build.properties ├── plugins.sbt └── sonatype.sbt ├── shell-prompt.sbt ├── .history ├── .scalafmt.conf ├── .gitignore ├── LICENSE ├── src ├── test │ └── scala │ │ └── ca │ │ └── aaronlevin │ │ └── gitrev │ │ └── GitRevTest.scala └── main │ └── scala │ └── ca │ └── aaronlevin │ └── gitrev │ ├── GitRun.scala │ └── package.scala └── README.md /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2016 aaronlevin 2 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version = 0.13.13 2 | -------------------------------------------------------------------------------- /shell-prompt.sbt: -------------------------------------------------------------------------------- 1 | shellPrompt.in(ThisBuild) := { state => 2 | val project = Project.extract(state).currentRef.project 3 | s"[$project]> " 4 | } 5 | -------------------------------------------------------------------------------- /.history: -------------------------------------------------------------------------------- 1 | 0.1.1 2 | ===== 3 | 4 | Minor revision to fix output redirection (https://github.com/aaronlevin/scala-gitrev/issues/2). 5 | 6 | 0.1.0 7 | ===== 8 | 9 | Initial release. 10 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | style = defaultWithAlign 2 | 3 | danglingParentheses = true 4 | indentOperator = spray 5 | rewrite.rules = [RedundantBraces, RedundantParens, SortImports] 6 | spaces.inImportCurlyBraces = true 7 | unindentTopLevelOperators = true 8 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.4.10") 2 | addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.5") 3 | addSbtPlugin("de.heikoseeberger" % "sbt-header" % "1.6.0") 4 | addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.4") 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sbt 2 | lib_managed 3 | project/project 4 | target 5 | 6 | # Worksheets (Eclipse or IntelliJ) 7 | *.sc 8 | 9 | # Eclipse 10 | .cache* 11 | .classpath 12 | .project 13 | .scala_dependencies 14 | .settings 15 | .target 16 | .worksheet 17 | 18 | # IntelliJ 19 | .idea 20 | 21 | # ENSIME 22 | .ensime 23 | .ensime_lucene 24 | .ensime_cache 25 | 26 | # Mac 27 | .DS_Store 28 | 29 | # Akka Persistence 30 | journal 31 | snapshots 32 | 33 | # Log files 34 | *.log 35 | -------------------------------------------------------------------------------- /project/sonatype.sbt: -------------------------------------------------------------------------------- 1 | sonatypeProfileName := "aaronlevin" 2 | 3 | // To sync with Maven central, you need to supply the following information: 4 | pomExtra in Global := { 5 | https://github.com/aaronlevin/scala-gitrev 6 | 7 | 8 | Apache 2 9 | http://www.apache.org/licenses/LICENSE-2.0.txt 10 | 11 | 12 | 13 | scm:git:git@github.com:aaronlevin/scala-gitrev.git 14 | scm:git:git@github.com:aaronlevin/scala-gitrev.git 15 | git@github.com:aaronlevin/scala-gitrev.git 16 | 17 | 18 | 19 | aaronlevin 20 | Aaron Levin 21 | aaronlevin.ca 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Aaron Levin 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /src/test/scala/ca/aaronlevin/gitrev/GitRevTest.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 aaronlevin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ca.aaronlevin.gitrev 18 | 19 | import org.scalatest._ 20 | import scala.sys.process._ 21 | 22 | class GitRevTest extends FlatSpec with Matchers { 23 | 24 | it should "create the same hash as 'git rev-parse HEAD'" in { 25 | val hashMacro = gitHash 26 | val computedHash = ("git rev-parse HEAD" !!).dropRight(1) 27 | 28 | hashMacro should be(computedHash) 29 | } 30 | 31 | it should "create the same hash as 'git rev-parse --short HEAD'" in { 32 | val hashShortMacro = gitHashShort 33 | val computedHashShort = ("git rev-parse --short HEAD" !!).dropRight(1) 34 | 35 | hashShortMacro should be(computedHashShort) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scala-gitrev # 2 | 3 | Welcome to `scala-gitrev`! Inspired by the [gitrev](https://hackage.haskell.org/package/gitrev) haskell library, **scala-gitrev** provides simple macros to capture git information at compile time. This will empower you to bundle compile-time git-info with your artifacts, which can be extremely useful for debugging. 4 | 5 | To use `scala-gitrev` in your scala project with SBT, simply add the following line to your `build.sbt` file: 6 | 7 | ```scala 8 | libraryDependencies += "ca.aaronlevin" %% "scala-gitrev" % "0.1.1" 9 | ``` 10 | 11 | Example usage: 12 | 13 | ```scala 14 | object MyCoolProject { 15 | 16 | import ca.aaronlevin.gitrev.gitHash 17 | 18 | val theGitHash: String = gitHash 19 | 20 | // ... other super cool code ... 21 | 22 | def main(args: Array[String]): Unit = { 23 | 24 | println(s"This artifact was compiled at revision $theGitHash") 25 | 26 | // ... do super cool stuff ... 27 | } 28 | } 29 | ``` 30 | 31 | ## Contribution policy ## 32 | 33 | Contributions via GitHub pull requests are gladly accepted from their original 34 | author. Along with any pull requests, please state that the contribution is your 35 | original work and that you license the work to the project under the project's 36 | open source license. Whether or not you state this explicitly, by submitting any 37 | copyrighted material via pull request, email, or other means you agree to 38 | license the material under the project's open source license and warrant that 39 | you have the legal authority to do so. 40 | 41 | ## License ## 42 | 43 | This code is open source software licensed under the 44 | [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) license. 45 | -------------------------------------------------------------------------------- /src/main/scala/ca/aaronlevin/gitrev/GitRun.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 aaronlevin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ca.aaronlevin.gitrev 18 | 19 | import sys.process.{ Process, ProcessLogger } 20 | 21 | /** 22 | * between Scala 2.10 and 2.11 the Process API changed. This small 23 | * module supports cross-compiling to 2.10 24 | */ 25 | object RunGit { 26 | 27 | /** 28 | * Small helper to run git commands and process the output 29 | * @param command the shell command to be run, as a list of strings 30 | * (space delimited). 31 | * @return Either an error or a string containing the output from stdout. 32 | */ 33 | def runGit(command: List[String]): Either[RunGitError, String] = { 34 | val procDecl = Process(s"git ${command.mkString(" ")}") 35 | var output: List[String] = Nil 36 | try { 37 | val process = 38 | procDecl.run( 39 | ProcessLogger(o => output = o.split("\n").toList, _ => Unit)) 40 | if (process.exitValue() == 0) { 41 | output match { 42 | case out :: Nil => Right(out) 43 | case _ => Left(BadExitValue(process.exitValue())) 44 | } 45 | } else { 46 | Left(UnexpectedGitOutput) 47 | } 48 | } catch { 49 | case _: java.io.IOException => Left(RuntimeFailure) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/ca/aaronlevin/gitrev/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 aaronlevin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ca.aaronlevin 18 | 19 | import macrocompat.bundle 20 | import scala.language.experimental.macros 21 | import scala.reflect.macros.whitebox 22 | 23 | package object gitrev { 24 | 25 | /** 26 | * A small sealed-trait hierarchy to capture errors while calling out to git 27 | */ 28 | sealed trait RunGitError 29 | case class BadExitValue(code: Int) extends RunGitError 30 | case object UnexpectedGitOutput extends RunGitError 31 | case object RuntimeFailure extends RunGitError 32 | 33 | @bundle // macro-compat addition 34 | class GitRevMacro(val c: whitebox.Context) { 35 | import c.universe._ 36 | import ca.aaronlevin.gitrev.RunGit.runGit 37 | 38 | def gitHash_impl: Tree = { 39 | val response = runGit(List("rev-parse", "HEAD")) match { 40 | case Right(r) => r 41 | case Left(_) => "UNKNOWN" 42 | } 43 | q""" $response """ 44 | } 45 | 46 | def gitHashShort_impl: Tree = { 47 | val response = 48 | runGit(List("rev-parse", "--short", "HEAD")) match { 49 | case Right(r) => r 50 | case Left(_) => "UNKNOWN" 51 | } 52 | q""" $response """ 53 | } 54 | 55 | } 56 | 57 | /** 58 | * A Macro to produce the shortened git hash (via `git rev-parse --short HEAD`) 59 | * @return a String containing the shortened git hash (or 'UNKNOWN' if a failure 60 | * is encountered) 61 | */ 62 | def gitHashShort: String = macro GitRevMacro.gitHashShort_impl 63 | 64 | /** 65 | * A Macro to produce the full git hash (via `git rev-parse HEAD`) 66 | * @return a String containing the full git hash (or 'UNKNOWN' if a failure 67 | * is encountered) 68 | */ 69 | def gitHash: String = macro GitRevMacro.gitHash_impl 70 | 71 | } 72 | --------------------------------------------------------------------------------