This is an automated email from the ASF dual-hosted git repository. mdedetrich pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/incubator-pekko-projection.git
commit 012d4ff3148b290d61066ddc671f5c75f1c2c670 Author: Matthew de Detrich <[email protected]> AuthorDate: Mon Apr 3 18:01:30 2023 +0200 Update CopyrightHeader to deal with Apache license headers --- .github/workflows/headers.yml | 30 ++++++++++ project/CopyrightHeader.scala | 128 ++++++++++++++++++++++++++++++------------ 2 files changed, 122 insertions(+), 36 deletions(-) diff --git a/.github/workflows/headers.yml b/.github/workflows/headers.yml new file mode 100644 index 0000000..5faf67d --- /dev/null +++ b/.github/workflows/headers.yml @@ -0,0 +1,30 @@ +name: Headers + +on: + pull_request: + +permissions: {} + +jobs: + check-headers: + name: Check headers + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Java 8 + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 11 + + - name: Cache Coursier cache + uses: coursier/[email protected] + + - name: Check headers + run: |- + sbt \ + -Dsbt.override.build.repos=false \ + -Dsbt.log.noformat=false \ + +headerCheckAll diff --git a/project/CopyrightHeader.scala b/project/CopyrightHeader.scala index 78595a4..99c96a1 100644 --- a/project/CopyrightHeader.scala +++ b/project/CopyrightHeader.scala @@ -1,53 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * license agreements; and to You under the Apache License, version 2.0: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * This file is part of the Apache Pekko project, derived from Akka. + */ + /* * Copyright (C) 2020-2021 Lightbend Inc. <https://www.lightbend.com> */ -import de.heikoseeberger.sbtheader.CommentCreator -import de.heikoseeberger.sbtheader.HeaderPlugin + +import de.heikoseeberger.sbtheader.HeaderPlugin.autoImport._ +import de.heikoseeberger.sbtheader.{ CommentCreator, HeaderPlugin, NewLine } +import org.apache.commons.lang3.StringUtils +import sbt.Keys._ import sbt._ -object CopyrightHeader extends AutoPlugin { - import HeaderPlugin.autoImport._ +trait CopyrightHeader extends AutoPlugin { + + override def requires: Plugins = HeaderPlugin - override def requires = HeaderPlugin - override def trigger = allRequirements + override def trigger: PluginTrigger = allRequirements - override def projectSettings = - Def.settings(Seq(Compile, Test).flatMap { config => + protected def headerMappingSettings: Seq[Def.Setting[_]] = + Seq(Compile, Test, IntegrationTest).flatMap { config => inConfig(config)( Seq( - headerLicense := Some(HeaderLicense.Custom(headerFor(CurrentYear))), + headerLicense := Some(HeaderLicense.Custom(apacheHeader)), headerMappings := headerMappings.value ++ Map( HeaderFileType.scala -> cStyleComment, - HeaderFileType.java -> cStyleComment))) - }) - - // We hard-code this so PR's created in year X will not suddenly fail in X+1. - // Of course we should remember to update it early in the year. - val CurrentYear = "2022" - val CopyrightPattern = "Copyright \\([Cc]\\) (\\d{4}(-\\d{4})?) (Lightbend|Typesafe) Inc. <.*>".r - val CopyrightHeaderPattern = s"(?s).*${CopyrightPattern}.*".r - - def headerFor(year: String): String = - s"Copyright (C) $year Lightbend Inc. <https://www.lightbend.com>" - - private def lightbendCommentCreator(commentCreator: CommentCreator) = new CommentCreator() { - - def updateLightbendHeader(header: String): String = header match { - case CopyrightHeaderPattern(years, null, _) => - if (years != CurrentYear) - CopyrightPattern.replaceFirstIn(header, headerFor(years + "-" + CurrentYear)) - else - CopyrightPattern.replaceFirstIn(header, headerFor(years)) - case CopyrightHeaderPattern(years, endYears, _) => - CopyrightPattern.replaceFirstIn(header, headerFor(years.replace(endYears, "-" + CurrentYear))) - case _ => - header + HeaderFileType.java -> cStyleComment, + HeaderFileType.conf -> hashLineComment, + HeaderFileType("template") -> cStyleComment))) + } + + override def projectSettings: Seq[Def.Setting[_]] = + Def.settings(headerMappingSettings, additional) ++ Defaults.itSettings ++ + headerSettings(IntegrationTest) + + def additional: Seq[Def.Setting[_]] = + Def.settings(Compile / compile := { + (Compile / headerCreate).value + (Compile / compile).value + }, + Test / compile := { + (Test / headerCreate).value + (Test / compile).value + }) + + def apacheHeader: String = + """Licensed to the Apache Software Foundation (ASF) under one or more + |license agreements; and to You under the Apache License, version 2.0: + | + | https://www.apache.org/licenses/LICENSE-2.0 + | + |This file is part of the Apache Pekko project, derived from Akka. + |""".stripMargin + + val apacheSpdxHeader: String = "SPDX-License-Identifier: Apache-2.0" + + val cStyleComment = HeaderCommentStyle.cStyleBlockComment.copy(commentCreator = new CommentCreator() { + + override def apply(text: String, existingText: Option[String]): String = { + val formatted = existingText match { + case Some(currentText) if isValidCopyrightAnnotated(currentText) => + currentText + case Some(currentText) if isLightbendCopyrighted(currentText) => + HeaderCommentStyle.cStyleBlockComment.commentCreator(text, existingText) + NewLine * 2 + currentText + case Some(currentText) => + throw new IllegalStateException(s"Unable to detect copyright for header:[${currentText}]") + case None => + HeaderCommentStyle.cStyleBlockComment.commentCreator(text, existingText) + } + formatted.trim } + }) + + val hashLineComment = HeaderCommentStyle.hashLineComment.copy(commentCreator = new CommentCreator() { + // deliberately hardcode use of apacheSpdxHeader and ignore input text override def apply(text: String, existingText: Option[String]): String = { - existingText.map(updateLightbendHeader).getOrElse(commentCreator(text, existingText)).trim + val formatted = existingText match { + case Some(currentText) if isApacheCopyrighted(currentText) => + currentText + case Some(currentText) => + HeaderCommentStyle.hashLineComment.commentCreator(apacheSpdxHeader, existingText) + NewLine * 2 + currentText + case None => + HeaderCommentStyle.hashLineComment.commentCreator(apacheSpdxHeader, existingText) + } + formatted.trim } + }) + + private def isApacheCopyrighted(text: String): Boolean = + StringUtils.containsIgnoreCase(text, "licensed to the apache software foundation (asf)") || + StringUtils.containsIgnoreCase(text, "www.apache.org/licenses/license-2.0") || + StringUtils.contains(text, "Apache-2.0") + + private def isLightbendCopyrighted(text: String): Boolean = + StringUtils.containsIgnoreCase(text, "lightbend inc.") + + private def isValidCopyrightAnnotated(text: String): Boolean = { + isApacheCopyrighted(text) } - val cStyleComment = HeaderCommentStyle.cStyleBlockComment - .copy(commentCreator = lightbendCommentCreator(HeaderCommentStyle.cStyleBlockComment.commentCreator)) } + +object CopyrightHeader extends CopyrightHeader --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
