(3);
+ String copyrightEnd = getGitLookup(document.getFile(), properties).getYearOfLastChange(document.getFile());
+ result.put(COPYRIGHT_LAST_YEAR_KEY, copyrightEnd);
+ final String copyrightYears;
+ if (inceptionYear.equals(copyrightEnd)) {
+ copyrightYears = inceptionYear;
+ } else {
+ copyrightYears = inceptionYear + "-" + copyrightEnd;
+ }
+ result.put(COPYRIGHT_YEARS_KEY, copyrightYears);
+ return Collections.unmodifiableMap(result);
+ } catch (NoHeadException e) {
+ throw new RuntimeException("Could not compute the year of the last git commit for file "
+ + document.getFile().getAbsolutePath(), e);
+ } catch (GitAPIException e) {
+ throw new RuntimeException("Could not compute the year of the last git commit for file "
+ + document.getFile().getAbsolutePath(), e);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not compute the year of the last git commit for file "
+ + document.getFile().getAbsolutePath(), e);
+ }
+ }
+
+ /**
+ * Lazily initializes #gitLookup assuming that all subsequent calls to this method will be related to the same
+ * git repository.
+ *
+ * @param file
+ * @return
+ * @throws IOException
+ */
+ private GitLookup getGitLookup(File file, Properties props) throws IOException {
+ if (gitLookup == null) {
+ synchronized (this) {
+ if (gitLookup == null) {
+ String dateSourceString = props.getProperty(COPYRIGHT_LAST_YEAR_SOURCE_KEY,
+ DateSource.AUTHOR.name());
+ DateSource dateSource = DateSource.valueOf(dateSourceString.toUpperCase(Locale.US));
+ String checkCommitsCountString = props.getProperty(COPYRIGHT_LAST_YEAR_MAX_COMMITS_LOOKUP_KEY);
+ int checkCommitsCount = GitLookup.DEFAULT_COMMITS_COUNT;
+ if (checkCommitsCountString != null) {
+ checkCommitsCountString = checkCommitsCountString.trim();
+ checkCommitsCount = Integer.parseInt(checkCommitsCountString);
+ }
+ final TimeZone timeZone;
+ String tzString = props.getProperty(COPYRIGHT_LAST_YEAR_TIME_ZONE_KEY);
+ switch (dateSource) {
+ case COMMITER:
+ timeZone = tzString == null ? GitLookup.DEFAULT_ZONE : TimeZone.getTimeZone(tzString);
+ break;
+ case AUTHOR:
+ if (tzString != null) {
+ throw new RuntimeException(COPYRIGHT_LAST_YEAR_TIME_ZONE_KEY + " must not be set with "
+ + COPYRIGHT_LAST_YEAR_SOURCE_KEY + " = " + DateSource.AUTHOR.name()
+ + " because git author name already contrains time zone information.");
+ }
+ timeZone = null;
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + DateSource.class.getName() + " " + dateSource);
+ }
+ gitLookup = new GitLookup(file, dateSource, timeZone, checkCommitsCount);
+ }
+ }
+ }
+ return gitLookup;
+ }
+
+}
diff --git a/src/main/java/org/hawkular/build/license/GitLookup.java b/src/main/java/org/hawkular/build/license/GitLookup.java
new file mode 100644
index 0000000..c4c32e6
--- /dev/null
+++ b/src/main/java/org/hawkular/build/license/GitLookup.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.hawkular.build.license;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoHeadException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.revwalk.filter.MaxCountRevFilter;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+/**
+ * A jGit library wrapper to query the date of the last commit.
+ *
+ * @author Peter Palaga
+ */
+public class GitLookup {
+ public static final TimeZone DEFAULT_ZONE = TimeZone.getTimeZone("GMT");
+ public static final int DEFAULT_COMMITS_COUNT = 10;
+
+ public enum DateSource {
+ AUTHOR, COMMITER
+ }
+
+ private final int checkCommitsCount;
+ private final DateSource dateSource;
+ private final GitPathResolver pathResolver;
+ private final Repository repository;
+ private final TimeZone timeZone;
+
+ /**
+ * Creates a new {@link GitLookup} for a repository that is detected from the supplied {@code anyFile}.
+ *
+ * Note on time zones:
+ *
+ * @param anyFile
+ * - any path from the working tree of the git repository to consider in all subsequent calls to
+ * {@link #getYearOfLastChange(File)}
+ * @param dateSource
+ * where to read the comit dates from - committer date or author date
+ * @param timeZone
+ * the time zone if {@code dateSource} is {@link DateSource#COMMITER}; otherwise must be {@code null}.
+ * @param checkCommitsCount
+ * @throws IOException
+ */
+ public GitLookup(File anyFile, DateSource dateSource, TimeZone timeZone, int checkCommitsCount) throws IOException {
+ super();
+ this.repository = new FileRepositoryBuilder().findGitDir(anyFile).build();
+ this.pathResolver = new GitPathResolver(repository.getWorkTree().getAbsolutePath());
+ this.dateSource = dateSource;
+ switch (dateSource) {
+ case COMMITER:
+ this.timeZone = timeZone == null ? DEFAULT_ZONE : timeZone;
+ break;
+ case AUTHOR:
+ if (timeZone != null) {
+ throw new IllegalArgumentException("Time zone must be null with dateSource " + DateSource.AUTHOR.name()
+ + " because git author name already contrains time zone information.");
+ }
+ this.timeZone = null;
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + DateSource.class.getName() + " " + dateSource);
+ }
+ this.checkCommitsCount = checkCommitsCount;
+ }
+
+ /**
+ * Returns the year of the last change of the given {@code file} based on the history of the present git branch. The
+ * year is taken either from the committer date or from the author identity depending on how {@link #dateSource} was
+ * initialized.
+ *
+ * See also the note on time zones in {@link #GitLookup(File, DateSource, TimeZone, int)}.
+ *
+ * @param file
+ * @return
+ * @throws NoHeadException
+ * @throws GitAPIException
+ * @throws IOException
+ */
+ public String getYearOfLastChange(File file) throws NoHeadException, GitAPIException, IOException {
+ RevWalk walk = new RevWalk(repository);
+ String repoRelativePath = pathResolver.relativize(file);
+ walk.markStart(walk.parseCommit(repository.resolve(Constants.HEAD)));
+ walk.setTreeFilter(AndTreeFilter.create(PathFilter.create(repoRelativePath), TreeFilter.ANY_DIFF));
+ walk.setRevFilter(MaxCountRevFilter.create(checkCommitsCount));
+ walk.setRetainBody(false);
+
+ int commitYear = 0;
+ for (RevCommit commit : walk) {
+ int y;
+ switch (dateSource) {
+ case COMMITER:
+ int epochSeconds = commit.getCommitTime();
+ y = toYear(epochSeconds * 1000L, timeZone);
+ break;
+ case AUTHOR:
+ PersonIdent id = commit.getAuthorIdent();
+ Date date = id.getWhen();
+ y = toYear(date.getTime(), id.getTimeZone());
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + DateSource.class.getName() + " " + dateSource);
+ }
+ if (y > commitYear) {
+ commitYear = y;
+ }
+ }
+ walk.dispose();
+ return Integer.toString(commitYear);
+ }
+
+ private static int toYear(long epochMilliseconds, TimeZone timeZone) {
+ Calendar result = Calendar.getInstance(timeZone);
+ result.setTimeInMillis(epochMilliseconds);
+ return result.get(Calendar.YEAR);
+ }
+}
diff --git a/src/main/java/org/hawkular/build/license/GitPathResolver.java b/src/main/java/org/hawkular/build/license/GitPathResolver.java
new file mode 100644
index 0000000..0eb521c
--- /dev/null
+++ b/src/main/java/org/hawkular/build/license/GitPathResolver.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.hawkular.build.license;
+
+import java.io.File;
+
+/**
+ * A utility to transform native {@link File} paths to the form expected by jGit - i.e. relative to git working tree
+ * root directory and delimited by {@code '/'}.
+ *
+ * @author Peter Palaga
+ */
+public class GitPathResolver {
+
+ /** The path separator expected by jGit. */
+ private static final char CANONICAL_PATH_SEPARATOR = '/';
+
+ /** The file path separator used by the current platform, usually {@value File#separatorChar}. */
+ private final char nativePathSeparator;
+
+ /** The native path to the root directory of the current git repository working tree. */
+ private final String repositoryRootDir;
+
+ public GitPathResolver(String repositoryRootDir) {
+ this(repositoryRootDir, File.separatorChar);
+ }
+
+ /**
+ * Default visibility for testing purposes.
+ *
+ * @param repositoryRootDir
+ * @param nativePathSeparator
+ */
+ GitPathResolver(String repositoryRootDir, char nativePathSeparator) {
+ super();
+ this.repositoryRootDir = repositoryRootDir.charAt(repositoryRootDir.length() - 1) == nativePathSeparator ? repositoryRootDir
+ : repositoryRootDir + nativePathSeparator;
+ this.nativePathSeparator = nativePathSeparator;
+ }
+
+ /**
+ * With default visibility to be testable.
+ *
+ * @param absoluteNativePath
+ * @return
+ */
+ String relativize(String absoluteNativePath) {
+ if (!absoluteNativePath.startsWith(repositoryRootDir)) {
+ throw new RuntimeException("Cannot relativize path '" + absoluteNativePath + "' to directory '"
+ + repositoryRootDir + "'");
+ }
+ String result = absoluteNativePath.substring(repositoryRootDir.length());
+ if (nativePathSeparator != CANONICAL_PATH_SEPARATOR) {
+ result = result.replace(nativePathSeparator, CANONICAL_PATH_SEPARATOR);
+ }
+ return result;
+ }
+
+ /**
+ * Return a string representing the supplied {@code path} path relative to git working tree root directory and
+ * delimited by {@code '/'}.
+ *
+ * @param path the path to relativize
+ * @return the relativized path
+ */
+ public String relativize(File path) {
+ return relativize(path.getAbsolutePath());
+ }
+
+}
diff --git a/src/main/resources/META-INF/services/com.mycila.maven.plugin.license.PropertiesProvider b/src/main/resources/META-INF/services/com.mycila.maven.plugin.license.PropertiesProvider
new file mode 100644
index 0000000..4e53264
--- /dev/null
+++ b/src/main/resources/META-INF/services/com.mycila.maven.plugin.license.PropertiesProvider
@@ -0,0 +1 @@
+org.hawkular.build.license.CopyrightRangeProvider
\ No newline at end of file
diff --git a/src/main/resources/hawkular-checkstyle/checkstyle.xml b/src/main/resources/hawkular-checkstyle/checkstyle.xml
index 572e488..e9097d3 100644
--- a/src/main/resources/hawkular-checkstyle/checkstyle.xml
+++ b/src/main/resources/hawkular-checkstyle/checkstyle.xml
@@ -1,4 +1,22 @@
+
diff --git a/src/main/resources/hawkular-checkstyle/suppressions.xml b/src/main/resources/hawkular-checkstyle/suppressions.xml
index 086560f..b0c42f7 100644
--- a/src/main/resources/hawkular-checkstyle/suppressions.xml
+++ b/src/main/resources/hawkular-checkstyle/suppressions.xml
@@ -1,5 +1,22 @@
+
diff --git a/src/main/resources/hawkular-license/jboss-apache-2-template.txt b/src/main/resources/hawkular-license/jboss-apache-2-template.txt
new file mode 100644
index 0000000..e652c19
--- /dev/null
+++ b/src/main/resources/hawkular-license/jboss-apache-2-template.txt
@@ -0,0 +1,14 @@
+Copyright ${license.copyrightYears} Red Hat, Inc. and/or its affiliates
+and other contributors as indicated by the @author tags.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/src/test/java/org/hawkular/build/checkstyle/xml/XmlIndentCheckTest.java b/src/test/java/org/hawkular/build/checkstyle/xml/XmlIndentCheckTest.java
index 21b3e51..5ed0337 100644
--- a/src/test/java/org/hawkular/build/checkstyle/xml/XmlIndentCheckTest.java
+++ b/src/test/java/org/hawkular/build/checkstyle/xml/XmlIndentCheckTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.hawkular.build.checkstyle.xml;
import static org.junit.Assert.assertEquals;
@@ -26,6 +42,9 @@
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.Configuration;
+/**
+ * @author Peter Palaga
+ */
public class XmlIndentCheckTest {
protected static class SilentLogger extends DefaultLogger {
public SilentLogger(OutputStream out) {
diff --git a/src/test/java/org/hawkular/build/license/CopyrightRangeProviderTest.java b/src/test/java/org/hawkular/build/license/CopyrightRangeProviderTest.java
new file mode 100644
index 0000000..10e9279
--- /dev/null
+++ b/src/test/java/org/hawkular/build/license/CopyrightRangeProviderTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.hawkular.build.license;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import com.mycila.maven.plugin.license.document.Document;
+
+/**
+ * @author Peter Palaga
+ */
+public class CopyrightRangeProviderTest {
+
+ private static File gitRepoRoot;
+ private static TemporaryFolder tempFolder;
+
+ @Test
+ public void copyrightRange() {
+ CopyrightRangeProvider provider = new CopyrightRangeProvider();
+
+ assertRange(provider, "dir1/file1.txt", "2006", "1999-2006");
+ assertRange(provider, "dir2/file2.txt", "2007", "1999-2007");
+ assertRange(provider, "dir1/file3.txt", "2009", "1999-2009");
+ assertRange(provider, "dir2/file4.txt", "1999", "1999");
+
+ }
+
+ private static void assertRange(CopyrightRangeProvider provider, String path, String copyrightEnd, String copyrightRange) {
+ Properties props = new Properties();
+ props.put(CopyrightRangeProvider.INCEPTION_YEAR_KEY, "1999");
+
+ Document document = newDocument(path);
+ Map actual = provider.getAdditionalProperties(null, props, document);
+
+ HashMap expected = new HashMap();
+ expected.put(CopyrightRangeProvider.COPYRIGHT_LAST_YEAR_KEY, copyrightEnd);
+ expected.put(CopyrightRangeProvider.COPYRIGHT_YEARS_KEY, copyrightRange);
+ Assert.assertEquals("for file '"+ path +"': ", expected, actual);
+
+ }
+
+ private static Document newDocument(String relativePath) {
+ File file = new File(gitRepoRoot.getAbsolutePath() + File.separatorChar
+ + relativePath.replace('/', File.separatorChar));
+ return new Document(file, null, "utf-8", new String[0], null);
+ }
+
+ @BeforeClass
+ public static void beforeClass() throws FileNotFoundException, IOException {
+ tempFolder = new TemporaryFolder();
+ tempFolder.create();
+
+ URL url = GitLookupTest.class.getResource("git-test-repo.zip");
+ File unzipDestination = tempFolder.getRoot();
+ gitRepoRoot = new File(unzipDestination, "git-test-repo");
+
+ GitLookupTest.unzip(url, unzipDestination);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ tempFolder.delete();
+ }
+
+}
diff --git a/src/test/java/org/hawkular/build/license/GitLookupTest.java b/src/test/java/org/hawkular/build/license/GitLookupTest.java
new file mode 100644
index 0000000..544d7f6
--- /dev/null
+++ b/src/test/java/org/hawkular/build/license/GitLookupTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.hawkular.build.license;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.TimeZone;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoHeadException;
+import org.hawkular.build.license.GitLookup.DateSource;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * @author Peter Palaga
+ */
+public class GitLookupTest {
+
+ private static File gitRepoRoot;
+ private static TemporaryFolder tempFolder;
+
+ @BeforeClass
+ public static void beforeClass() throws FileNotFoundException, IOException {
+ tempFolder = new TemporaryFolder();
+ tempFolder.create();
+
+ URL url = GitLookupTest.class.getResource("git-test-repo.zip");
+ File unzipDestination = tempFolder.getRoot();
+ gitRepoRoot = new File(unzipDestination, "git-test-repo");
+
+ unzip(url, unzipDestination);
+ }
+
+ public static void unzip(URL url, File unzipDestination) throws FileNotFoundException, IOException {
+ ZipInputStream zipInputStream = null;
+ try {
+ zipInputStream = new ZipInputStream(new BufferedInputStream(url.openStream()));
+ ZipEntry entry;
+ byte[] buffer = new byte[2048];
+ while ((entry = zipInputStream.getNextEntry()) != null) {
+
+ String fileName = entry.getName();
+ File unzippedFile = new File(unzipDestination.getAbsolutePath() + File.separatorChar + fileName);
+ if (entry.isDirectory()) {
+ unzippedFile.mkdirs();
+ } else {
+ unzippedFile.getParentFile().mkdirs();
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(unzippedFile), 2048);
+ int len;
+ while ((len = zipInputStream.read(buffer)) != -1) {
+ out.write(buffer, 0, len);
+ }
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ }
+ }
+ } finally {
+ if (zipInputStream != null) {
+ zipInputStream.close();
+ }
+ }
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ tempFolder.delete();
+ }
+
+ @Test
+ public void modified() throws NoHeadException, GitAPIException, IOException {
+ assertLastChange(newAuthorLookup(), "dir1/file1.txt", "2006");
+ assertLastChange(newCommitterLookup(), "dir1/file1.txt", "2006");
+ }
+
+ @Test
+ public void justCreated() throws NoHeadException, GitAPIException, IOException {
+ assertLastChange(newAuthorLookup(), "dir2/file2.txt", "2007");
+ assertLastChange(newCommitterLookup(), "dir2/file2.txt", "2007");
+ }
+
+ @Test
+ public void moved() throws NoHeadException, GitAPIException, IOException {
+ assertLastChange(newAuthorLookup(), "dir1/file3.txt", "2009");
+ assertLastChange(newCommitterLookup(), "dir1/file3.txt", "2010");
+ }
+
+ @Test
+ public void reuseProvider() throws NoHeadException, GitAPIException, IOException {
+ GitLookup provider = newAuthorLookup();
+ assertLastChange(provider, "dir1/file1.txt", "2006");
+ assertLastChange(provider, "dir2/file2.txt", "2007");
+ assertLastChange(provider, "dir1/file3.txt", "2009");
+ }
+
+ @Test
+ public void timezone() throws NoHeadException, GitAPIException, IOException {
+ try {
+ new GitLookup(gitRepoRoot, DateSource.AUTHOR, TimeZone.getTimeZone("GMT"), 10);
+ Assert.fail("RuntimeException expected");
+ } catch (RuntimeException e) {
+ if (e.getMessage().startsWith("Time zone must be null with dateSource " + DateSource.AUTHOR.name() + "")) {
+ /* expected */
+ } else {
+ throw e;
+ }
+ }
+
+ /* null is GMT */
+ GitLookup nullTzLookup = new GitLookup(gitRepoRoot, DateSource.COMMITER, null, 10);
+ assertLastChange(nullTzLookup, "dir1/file3.txt", "2010");
+
+ /* explicit GMT */
+ GitLookup gmtLookup = new GitLookup(gitRepoRoot, DateSource.COMMITER, TimeZone.getTimeZone("GMT"), 10);
+ assertLastChange(gmtLookup, "dir1/file3.txt", "2010");
+
+ /*
+ * explicit non-GMT zome. Note that the relevant commit's (GMT) time stamp is 2010-12-31T23:30:00 which yealds
+ * 2011 in the CET (+01:00) time zone
+ */
+ GitLookup cetLookup = new GitLookup(gitRepoRoot, DateSource.COMMITER, TimeZone.getTimeZone("CET"), 10);
+ assertLastChange(cetLookup, "dir1/file3.txt", "2011");
+
+ }
+
+ private GitLookup newAuthorLookup() throws IOException {
+ return new GitLookup(gitRepoRoot, DateSource.AUTHOR, null, 10);
+ }
+
+ private GitLookup newCommitterLookup() throws IOException {
+ return new GitLookup(gitRepoRoot, DateSource.COMMITER, null, 10);
+ }
+
+ private void assertLastChange(GitLookup provider, String relativePath, String expected) throws NoHeadException,
+ GitAPIException, IOException {
+ String actual = provider.getYearOfLastChange(new File(gitRepoRoot.getAbsolutePath() + File.separatorChar
+ + relativePath.replace('/', File.separatorChar)));
+ assertEquals(expected, actual);
+ }
+
+}
diff --git a/src/test/java/org/hawkular/build/license/GitPathResolverTest.java b/src/test/java/org/hawkular/build/license/GitPathResolverTest.java
new file mode 100644
index 0000000..ecff5fc
--- /dev/null
+++ b/src/test/java/org/hawkular/build/license/GitPathResolverTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014-2015 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.hawkular.build.license;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Peter Palaga
+ */
+public class GitPathResolverTest {
+ @Test
+ public void relativize() throws Exception {
+ /* *nix-like */
+ assertRelativized("/path/to/my/git/repo", '/', "/path/to/my/git/repo/dir/file.txt", "dir/file.txt");
+ assertRelativized("/path/to/my/git/repo/", '/', "/path/to/my/git/repo/dir/file.txt", "dir/file.txt");
+
+ assertFail("/path/to/my/git/repo/", '/', "/path/to/other/git/repo/dir/file.txt");
+
+ /* Windows */
+ assertRelativized("c:\\path\\to\\my\\repo", '\\', "c:\\path\\to\\my\\repo\\dir\\file.txt", "dir/file.txt");
+ assertRelativized("c:\\path\\to\\my\\repo\\", '\\', "c:\\path\\to\\my\\repo\\dir\\file.txt", "dir/file.txt");
+ assertRelativized("\\\\path\\to\\my\\repo", '\\', "\\\\path\\to\\my\\repo\\dir\\file.txt", "dir/file.txt");
+ assertRelativized("\\\\path\\to\\my\\repo\\", '\\', "\\\\path\\to\\my\\repo\\dir\\file.txt", "dir/file.txt");
+
+ assertFail("c:\\path\\to\\my\\repo\\", '\\', "c:\\path\\to\\other\\repo\\dir\\file.txt");
+
+ }
+
+ private void assertRelativized(String repoRoot, char nativePathSepartor, String absoluteNativePath, String expected) {
+ GitPathResolver resolver = new GitPathResolver(repoRoot, nativePathSepartor);
+ String actual = resolver.relativize(absoluteNativePath);
+ assertEquals(expected, actual);
+ }
+
+ private void assertFail(String repoRoot, char nativePathSepartor, String absoluteNativePath) {
+ GitPathResolver resolver = new GitPathResolver(repoRoot, nativePathSepartor);
+ try {
+ resolver.relativize(absoluteNativePath);
+ Assert.fail("RuntimeException expected");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().startsWith("Cannot relativize"));
+ }
+ }
+
+}
diff --git a/src/test/resources/org/hawkular/build/license/git-test-repo.zip b/src/test/resources/org/hawkular/build/license/git-test-repo.zip
new file mode 100644
index 0000000..f79d96f
Binary files /dev/null and b/src/test/resources/org/hawkular/build/license/git-test-repo.zip differ