diff --git a/src/main/scala/net/numa08/genrelease/ReleaseNote.scala b/src/main/scala/net/numa08/genrelease/ReleaseNote.scala index 577995a..cab4437 100644 --- a/src/main/scala/net/numa08/genrelease/ReleaseNote.scala +++ b/src/main/scala/net/numa08/genrelease/ReleaseNote.scala @@ -1,11 +1,7 @@ package net.numa08.genrelease trait ReleaseNote { + val releases: Seq[Release] - val features: Seq[Feature] - - val fixes: Seq[Fix] - - val version: String - + val version: String } diff --git a/src/main/scala/net/numa08/genrelease/ReleaseType.scala b/src/main/scala/net/numa08/genrelease/ReleaseType.scala index 48a2384..11aaa57 100644 --- a/src/main/scala/net/numa08/genrelease/ReleaseType.scala +++ b/src/main/scala/net/numa08/genrelease/ReleaseType.scala @@ -1,22 +1,45 @@ package net.numa08.genrelease -trait ReleaseType{ +case class Scope(scope: String) - val scope: String +sealed trait ReleaseType { val subject: String - } -case class Feature(scope: String, subject: String) extends ReleaseType -case class Fix(scope: String, subject: String) extends ReleaseType + +case class Feature(subject: String) extends ReleaseType + +case class Fix(subject: String) extends ReleaseType object ReleaseType { - def apply(t: String, scope: String, subject: String): ReleaseType = t match { - case "fix" => Fix(scope, subject) - case "feat" => Feature(scope, subject) + def apply(t: String, subject: String): ReleaseType = t match { + case "fix" => Fix(subject) + case "feat" => Feature(subject) case _ => throw UnKnownTypeException(s"$t is unknown type") } + +} + +sealed trait Release {} + +case class Features(releases: Map[Scope, Seq[Feature]]) extends Release + +case class Fixes(releases: Map[Scope, Seq[Fix]]) extends Release + +case object Empty extends Release + +object Release { + + def apply[T <: ReleaseType](r: Map[Scope, Seq[T]]): Release = if (r.isEmpty) { + Empty + } else { + r.values.head.head match { + case Feature(_) => Features(r.asInstanceOf[Map[Scope, Seq[Feature]]]) + case Fix(_) => Fixes(r.asInstanceOf[Map[Scope, Seq[Fix]]]) + } + } + } case class UnKnownTypeException(message: String) extends RuntimeException(message) \ No newline at end of file diff --git a/src/main/scala/net/numa08/genrelease/git/GitLogParser.scala b/src/main/scala/net/numa08/genrelease/git/GitLogParser.scala index c7e014a..e6a9dd6 100644 --- a/src/main/scala/net/numa08/genrelease/git/GitLogParser.scala +++ b/src/main/scala/net/numa08/genrelease/git/GitLogParser.scala @@ -11,8 +11,10 @@ case class GitLogParser(configuration: Configuration) extends Parser { val parses = lines.zip(lines.map(GitLogParser.parseLine)) (new ReleaseNote { - override val fixes: Seq[Fix] = parses.collect { case (_, Right(f: Fix)) => f } - override val features: Seq[Feature] = parses.collect { case (_, Right(f: Feature)) => f } + override val releases: Seq[Release] = List( + Release(parses.collect { case (_, Right((s, f: Feature))) => (s, f) }.toSeq.groupBy { case (s, _) => s }.map { case (s, seq) => (s, seq.map { case (_, f) => f }) }), + Release(parses.collect { case (_, Right((s, f: Fix))) => (s, f) }.toSeq.groupBy { case (s, _) => s }.map { case (s, seq) => (s, seq.map { case (_, f) => f }) }) + ) override val version: String = configuration.version }, parses.collect { case (l, Left(e)) => ParseError(l, e) }) } @@ -21,7 +23,7 @@ case class GitLogParser(configuration: Configuration) extends Parser { object GitLogParser { - def parseLine(line: String): Either[Throwable, ReleaseType] = allCatch either { + def parseLine(line: String): Either[Throwable, (Scope, ReleaseType)] = allCatch either { def split(s: String, d: String): (String, String) = s.split(d).array match { case Array(x, y, _*) => (x, y) case _ => throw new RuntimeException(s"$s does not have $d") @@ -29,6 +31,6 @@ object GitLogParser { val (pre, subject) = split(line, ": ") val (_type, scope) = split(pre, "/") - ReleaseType(_type, scope, subject) + (Scope(scope), ReleaseType(_type, subject)) } } \ No newline at end of file diff --git a/src/main/scala/net/numa08/genrelease/markdown/MarkdownConverter.scala b/src/main/scala/net/numa08/genrelease/markdown/MarkdownConverter.scala index c8c60c6..b04e573 100644 --- a/src/main/scala/net/numa08/genrelease/markdown/MarkdownConverter.scala +++ b/src/main/scala/net/numa08/genrelease/markdown/MarkdownConverter.scala @@ -1,31 +1,32 @@ package net.numa08.genrelease.markdown -import net.numa08.genrelease.{NoteConverter, ReleaseNote, ReleaseType} +import net.numa08.genrelease._ class MarkdownConverter extends NoteConverter { - override def convert(note: ReleaseNote): String = { - val features = note.features.groupBy(_.scope) - val fixes = note.fixes.groupBy(_.scope) + override def convert(note: ReleaseNote): String = note.releases.map(makeMarkdown).mkString - def makeMarkdown(keys: Iterable[String], notes: Map[String, Seq[ReleaseType]]): String = { - (for (key <- keys) yield { - val indexes = notes(key).map(_.subject).mkString(" - ", "\n - ", "") - s""" - |### $key - | - |$indexes - |""".stripMargin - }).mkString("") - } - - - s""" - |## 新機能 - |${makeMarkdown(features.keys, features)} - |## 不具合修正 - |${makeMarkdown(fixes.keys, fixes)} - |""".stripMargin + def make(release: Map[Scope, Seq[ReleaseType]]): String = { + (for (k <- release.keys) yield { + val i = release(k).map(_.subject).mkString(" - ", "\n - ", "") + s""" + |### ${k.scope} + |$i + """.stripMargin + }).mkString } + def makeMarkdown(release: Release): String = release match { + case Empty => "" + case Features(r) => + s""" + |## 新機能 + |${make(r)} + """.stripMargin + case Fixes(r) => + s""" + |## 不具合修正 + |${make(r)} + """.stripMargin + } } diff --git a/src/test/scala/net/numa08/genrelease/git/GitLogParserSpec.scala b/src/test/scala/net/numa08/genrelease/git/GitLogParserSpec.scala index cf42947..dd28fdd 100644 --- a/src/test/scala/net/numa08/genrelease/git/GitLogParserSpec.scala +++ b/src/test/scala/net/numa08/genrelease/git/GitLogParserSpec.scala @@ -1,19 +1,21 @@ package net.numa08.genrelease.git -import net.numa08.genrelease.{Configuration, Feature, Fix, UnKnownTypeException} +import net.numa08.genrelease._ import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.{FlatSpec, Matchers} +import scala.collection.mutable.ArrayBuffer + @RunWith(classOf[JUnitRunner]) class GitLogParserSpec extends FlatSpec with Matchers{ "GitLogParser" should "parse line" in { val fixesLine = "fix/なんとか機能: どうしようもないクラッシュ問題を対応しました。" - assert(GitLogParser.parseLine(fixesLine) == Right(Fix("なんとか機能", "どうしようもないクラッシュ問題を対応しました。"))) + assert(GitLogParser.parseLine(fixesLine) == Right(Scope("なんとか機能"), Fix("どうしようもないクラッシュ問題を対応しました。"))) val featureLine = "feat/いつも使う機能: 誰もが驚く世紀の大発明を実施しました。" - assert(GitLogParser.parseLine(featureLine) == Right(Feature("いつも使う機能", "誰もが驚く世紀の大発明を実施しました。"))) + assert(GitLogParser.parseLine(featureLine) == Right(Scope("いつも使う機能"), Feature("誰もが驚く世紀の大発明を実施しました。"))) } "GitLogParse" should "not parse line" in { @@ -39,7 +41,9 @@ feat/ときどき使う機能: 驚天動地の新機能を実装しました。 assert(err.head.line == "ほげほげ") assert(note.version == "test") - assert(note.features == List(Feature("いつも使う機能", "誰もが驚く世紀の大発明を実施しました"), Feature("ときどき使う機能", "驚天動地の新機能を実装しました。"))) - assert(note.fixes == List(Fix("なんとか機能", "どうしようもないクラッシュ問題を対応しました。"), Fix("なんとか機能", "悲しみあふれる闇を取り払いました"))) + assert(note.releases == List( + Features(Map(Scope("ときどき使う機能") -> ArrayBuffer(Feature("驚天動地の新機能を実装しました。")), + Scope("いつも使う機能") -> ArrayBuffer(Feature("誰もが驚く世紀の大発明を実施しました")))), + Fixes(Map(Scope("なんとか機能") -> ArrayBuffer(Fix("どうしようもないクラッシュ問題を対応しました。"), Fix("悲しみあふれる闇を取り払いました")))))) } } \ No newline at end of file diff --git a/src/test/scala/net/numa08/genrelease/markdown/MarkdownConverterSpec.scala b/src/test/scala/net/numa08/genrelease/markdown/MarkdownConverterSpec.scala index 20ad851..c74ab1a 100644 --- a/src/test/scala/net/numa08/genrelease/markdown/MarkdownConverterSpec.scala +++ b/src/test/scala/net/numa08/genrelease/markdown/MarkdownConverterSpec.scala @@ -1,31 +1,43 @@ package net.numa08.genrelease.markdown -import net.numa08.genrelease.{Feature, Fix, ReleaseNote} +import net.numa08.genrelease._ import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.{FlatSpec, Matchers} +import scala.collection.immutable.Stream.Empty + @RunWith(classOf[JUnitRunner]) class MarkdownConverterSpec extends FlatSpec with Matchers { "MarkdownExporter" should "export markdown" in { val note = new ReleaseNote { - override val fixes: Seq[Fix] = List( - Fix("なんとか機能", "もうクラッシュなんてしない"), - Fix("ほげ機能", "今度こそ大丈夫"), - Fix("なんとか機能", "もう大丈夫") - ) + override val version: String = "test" - override val features: Seq[Feature] = List( - Feature("むっちゃ使う機能", "驚天動地の最新機能"), - Feature("微妙な機能", "いい感じやで"), - Feature("むっちゃ使う機能", "めっちゃ使いやすくなった") + override val releases: Seq[Release] = List( + Release( + Map((Scope("むっちゃ使う機能"), Feature("驚天動地の最新機能") :: Feature("めっちゃ使いやすくなった") :: Nil), + (Scope("微妙な機能"), Feature("いい感じやで") :: Nil)) + ), + Release( + Map((Scope("なんとか機能"), Fix("もうクラッシュなんてしない") :: Fix("もう大丈夫") :: Nil), + (Scope("ほげ機能"), Fix("今度こそ大丈夫") :: Nil)) + ) ) - override val version: String = "test" } val markdown = new MarkdownConverter().convert(note) println(markdown) } + + "Empty message" should "export empty markdown" in { + val note = new ReleaseNote { + override val releases: Seq[Release] = Empty + override val version: String = "test" + } + + val markdown = new MarkdownConverter().convert(note) + assert(markdown.isEmpty) + } }